Skip to content

Commit

Permalink
Add simulation snapshot panel interactions (#913)
Browse files Browse the repository at this point in the history
* add simulation dataset id to URL when choosing dataset or snapshot
* add filter button to simulation list and plan snapshot list
* add snapshot control bar to plan page
* make console affect layout
  • Loading branch information
duranb authored Oct 9, 2023
1 parent ef3c834 commit c8aa142
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 28 deletions.
12 changes: 4 additions & 8 deletions src/components/console/Console.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
<script lang="ts">
import ChevronDownIcon from '@nasa-jpl/stellar/icons/chevron_down.svg?component';
import ChevronUpIcon from '@nasa-jpl/stellar/icons/chevron_up.svg?component';
import { createEventDispatcher } from 'svelte';
import Tabs from '../ui/Tabs/Tabs.svelte';
import ConsoleDragHandle from './ConsoleDragHandle.svelte';
const consoleHeaderHeight: number = 36;
const dispatch = createEventDispatcher();
let consoleHeight: number = 0;
let consoleHeightString: string;
let consolePositionString: string;
let isOpen: boolean = false;
let previousConsoleHeight: number = 300;
$: {
consoleHeightString = `${consoleHeight + consoleHeaderHeight}px`;
consolePositionString = `${-consoleHeight}px`;
dispatch('resize', consoleHeightString);
}
function onSelectTab() {
Expand Down Expand Up @@ -44,12 +45,7 @@
</script>

<div class="console-container">
<div
class="console-expand-container"
class:expanded={isOpen}
style:height={consoleHeightString}
style:top={consolePositionString}
>
<div class="console-expand-container" class:expanded={isOpen} style:height={consoleHeightString}>
{#if isOpen}
<ConsoleDragHandle maxHeight="75%" rowHeight={consoleHeight} on:updateRowHeight={onUpdateRowHeight} />
{/if}
Expand Down
2 changes: 1 addition & 1 deletion src/components/modals/CreatePlanSnapshotModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,6 @@

<style>
.description {
padding: 0px 16px 0;
padding: 0px 16px;
}
</style>
1 change: 1 addition & 0 deletions src/components/modals/RestorePlanSnapshotModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<style>
.message {
font-weight: 500;
padding: 0px 16px;
}
input[type='checkbox'],
Expand Down
57 changes: 52 additions & 5 deletions src/components/plan/PlanForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@
<script lang="ts">
import { SearchParameters } from '../../enums/searchParameters';
import { planSnapshotId, planSnapshotsWithSimulations } from '../../stores/planSnapshots';
import { simulationDataset, simulationDatasetId } from '../../stores/simulation';
import { viewTogglePanel } from '../../stores/views';
import type { User } from '../../types/app';
import type { Plan } from '../../types/plan';
import type { PlanSnapshot as PlanSnapshotType } from '../../types/plan-snapshot';
import type { PlanTagsInsertInput, Tag, TagsChangeEvent } from '../../types/tags';
import effects from '../../utilities/effects';
import { setQueryParam } from '../../utilities/generic';
import { removeQueryParam, setQueryParam } from '../../utilities/generic';
import { permissionHandler } from '../../utilities/permissionHandler';
import { featurePermissions } from '../../utilities/permissions';
import { getShortISOForDate } from '../../utilities/time';
import { tooltip } from '../../utilities/tooltip';
import Collapse from '../Collapse.svelte';
import Input from '../form/Input.svelte';
import CardList from '../ui/CardList.svelte';
import FilterToggleButton from '../ui/FilterToggleButton.svelte';
import TagsInput from '../ui/Tags/TagsInput.svelte';
import PlanSnapshot from './PlanSnapshot.svelte';
Expand All @@ -24,6 +28,8 @@
export let user: User | null;
let hasPermission: boolean = false;
let filteredPlanSnapshots: PlanSnapshotType[] = [];
let isFilteredBySimulation: boolean = false;
let permissionError = 'You do not have permission to edit this plan.';
$: {
Expand All @@ -34,6 +40,14 @@
}
}
$: if (isFilteredBySimulation && $simulationDataset != null) {
filteredPlanSnapshots = $planSnapshotsWithSimulations.filter(
planSnapshot => planSnapshot.revision === $simulationDataset?.plan_revision,
);
} else {
filteredPlanSnapshots = $planSnapshotsWithSimulations;
}
async function onTagsInputChange(event: TagsChangeEvent) {
const {
detail: { tag, type },
Expand All @@ -59,6 +73,10 @@
effects.createPlanSnapshot(plan, user);
}
}
function onToggleFilter() {
isFilteredBySimulation = !isFilteredBySimulation;
}
</script>

<div class="plan-form">
Expand Down Expand Up @@ -153,19 +171,43 @@
</fieldset>
<fieldset>
<Collapse title="Snapshots" padContent={false}>
<button class="st-button secondary" slot="right" on:click={onCreatePlanSnapshot}>Take Snapshot</button>
<div class="buttons" slot="right">
{#if $simulationDatasetId >= 0}
<FilterToggleButton
label="Snapshot"
offTooltipContent="Filter snapshots by selected simulation"
onTooltipContent="Remove filter"
isOn={isFilteredBySimulation}
on:toggle={onToggleFilter}
/>
{/if}
<button class="st-button secondary" on:click={onCreatePlanSnapshot}>Take Snapshot</button>
</div>
<div style="margin-top: 8px">
<CardList>
{#each $planSnapshotsWithSimulations as planSnapshot (planSnapshot.snapshot_id)}
{#each filteredPlanSnapshots as planSnapshot (planSnapshot.snapshot_id)}
<PlanSnapshot
activePlanSnapshotId={$planSnapshotId}
{planSnapshot}
on:click={() => setQueryParam(SearchParameters.SNAPSHOT_ID, `${planSnapshot.snapshot_id}`, 'PUSH')}
on:click={() => {
setQueryParam(SearchParameters.SNAPSHOT_ID, `${planSnapshot.snapshot_id}`, 'PUSH');
$planSnapshotId = planSnapshot.snapshot_id;

if (planSnapshot.simulation?.id != null) {
setQueryParam(SearchParameters.SIMULATION_DATASET_ID, `${planSnapshot.simulation?.id}`, 'PUSH');
$simulationDatasetId = planSnapshot.simulation?.id;

viewTogglePanel({ state: true, type: 'left', update: { leftComponentTop: 'SimulationPanel' } });
} else {
removeQueryParam(SearchParameters.SIMULATION_DATASET_ID);
$simulationDatasetId = -1;
}
}}
on:restore={() => effects.restorePlanSnapshot(planSnapshot, user)}
on:delete={() => effects.deletePlanSnapshot(planSnapshot, user)}
/>
{/each}
{#if $planSnapshotsWithSimulations.length < 1}
{#if filteredPlanSnapshots.length < 1}
<div class="st-typography-label">No Plan Snapshots Found</div>
{/if}
</CardList>
Expand All @@ -179,4 +221,9 @@
.plan-form fieldset:last-child {
padding-bottom: 16px;
}
.buttons {
column-gap: 4px;
display: flex;
}
</style>
2 changes: 1 addition & 1 deletion src/components/plan/PlanMergeReview.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const mockInitialPlan: Plan = {
parent_plan: null,
revision: 3,
scheduling_specifications: [{ id: 1 }],
simulations: [{ simulation_datasets: [{ id: 1 }] }],
simulations: [{ simulation_datasets: [{ id: 1, plan_revision: 3 }] }],
start_time: '2023-02-16T00:00:00',
start_time_doy: '2023-047T00:00:00',
tags: [],
Expand Down
51 changes: 51 additions & 0 deletions src/components/plan/PlanSnapshotBar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<svelte:options immutable={true} />

<script lang="ts">
import { createEventDispatcher } from 'svelte';
import type { PlanSnapshot } from '../../types/plan-snapshot';
export let snapshot: PlanSnapshot;
export let numOfDirectives: number;
const dispatch = createEventDispatcher();
</script>

<div class="snapshot-bar">
<div class="info">
<div>Preview of plan snapshot</div>
<div class="snapshot-name">{snapshot.snapshot_name}</div>
<div>{numOfDirectives} directive{numOfDirectives !== 1 ? 's' : ''}</div>
</div>

<div class="buttons">
<button class="st-button" on:click|stopPropagation={() => dispatch('restore', snapshot)}>Restore Snapshot</button>
<button class="st-button secondary" on:click={() => dispatch('close')}>Close Preview</button>
</div>
</div>

<style>
.snapshot-bar {
align-items: center;
background-color: var(--st-primary-10, #e6e6ff);
border-bottom: 1px solid var(--st-primary-30, #a1a4fc);
display: flex;
justify-content: space-between;
padding: 10px 16px;
}
.snapshot-bar .info {
align-items: center;
color: var(--st-primary-90, #1a237e);
column-gap: 10px;
display: flex;
display: flex;
font-weight: 500;
}
.snapshot-bar .info .snapshot-name {
background-color: #fff;
border: 1px solid var(--st-primary-30, #a1a4fc);
border-radius: 16px;
padding: 4px 12px;
}
</style>
45 changes: 42 additions & 3 deletions src/components/simulation/SimulationPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
<script lang="ts">
import PlanLeftArrow from '@nasa-jpl/stellar/icons/plan_with_left_arrow.svg?component';
import PlanRightArrow from '@nasa-jpl/stellar/icons/plan_with_right_arrow.svg?component';
import { SearchParameters } from '../../enums/searchParameters';
import { field } from '../../stores/form';
import { plan, planEndTimeMs, planStartTimeMs } from '../../stores/plan';
import { planSnapshot } from '../../stores/planSnapshots';
import {
enableSimulation,
simulation,
Expand All @@ -16,9 +18,15 @@
import type { User } from '../../types/app';
import type { FieldStore } from '../../types/form';
import type { FormParameter, ParametersMap } from '../../types/parameter';
import type { Simulation, SimulationTemplate, SimulationTemplateInsertInput } from '../../types/simulation';
import type {
Simulation,
SimulationDataset,
SimulationTemplate,
SimulationTemplateInsertInput,
} from '../../types/simulation';
import type { ViewGridSection } from '../../types/view';
import effects from '../../utilities/effects';
import { setQueryParam } from '../../utilities/generic';
import { getArguments, getFormParameters } from '../../utilities/parameters';
import { permissionHandler } from '../../utilities/permissionHandler';
import { featurePermissions } from '../../utilities/permissions';
Expand All @@ -31,11 +39,13 @@
import GridMenu from '../menus/GridMenu.svelte';
import Parameters from '../parameters/Parameters.svelte';
import DatePickerActionButton from '../ui/DatePicker/DatePickerActionButton.svelte';
import FilterToggleButton from '../ui/FilterToggleButton.svelte';
import Panel from '../ui/Panel.svelte';
import PanelHeaderActionButton from '../ui/PanelHeaderActionButton.svelte';
import PanelHeaderActions from '../ui/PanelHeaderActions.svelte';
import SimulationHistoryDataset from './SimulationHistoryDataset.svelte';
import SimulationTemplateInput from './SimulationTemplateInput.svelte';
import { viewTogglePanel } from '../../stores/views';
export let gridSection: ViewGridSection;
export let user: User | null;
Expand All @@ -47,10 +57,12 @@
let formParameters: FormParameter[] = [];
let hasRunPermission: boolean = false;
let hasUpdatePermission: boolean = false;
let isFilteredBySnapshot: boolean = false;
let numOfUserChanges: number = 0;
let startTimeDoy: string;
let startTimeDoyField: FieldStore<string>;
let modelParametersMap: ParametersMap = {};
let filteredSimulationDatasets: SimulationDataset[] = [];
$: if (user !== null && $plan !== null) {
hasRunPermission = featurePermissions.simulation.canRun(user, $plan);
Expand Down Expand Up @@ -98,6 +110,16 @@
});
}
$: isFilteredBySnapshot = $planSnapshot !== null;
$: if (isFilteredBySnapshot) {
filteredSimulationDatasets = $simulationDatasetsPlan.filter(
simulationDataset => $planSnapshot === null || simulationDataset.plan_revision === $planSnapshot?.revision,
);
} else {
filteredSimulationDatasets = $simulationDatasetsPlan;
}
async function onChangeFormParameters(event: CustomEvent<FormParameter>) {
if ($simulation !== null) {
const { detail: formParameter } = event;
Expand Down Expand Up @@ -192,6 +214,10 @@
}
}
function onToggleFilter() {
isFilteredBySnapshot = !isFilteredBySnapshot;
}
function updateStartTime(doyString: string) {
if ($simulation !== null) {
const newSimulation: Simulation = { ...$simulation, simulation_start_time: doyString };
Expand Down Expand Up @@ -348,11 +374,22 @@

<fieldset>
<Collapse title="Simulation History" padContent={false}>
<svelte:fragment slot="right">
{#if $planSnapshot}
<FilterToggleButton
label="Simulation"
offTooltipContent="Filter simulations by selected snapshot"
onTooltipContent="Remove filter"
isOn={isFilteredBySnapshot}
on:toggle={onToggleFilter}
/>
{/if}
</svelte:fragment>
<div class="simulation-history">
{#if !$simulationDatasetsPlan || !$simulationDatasetsPlan.length}
{#if !filteredSimulationDatasets || !filteredSimulationDatasets.length}
<div>No Simulation Datasets</div>
{:else}
{#each $simulationDatasetsPlan as simDataset (simDataset.id)}
{#each filteredSimulationDatasets as simDataset (simDataset.id)}
<SimulationHistoryDataset
queuePosition={getSimulationQueuePosition(simDataset, $simulationDatasetsAll)}
simulationDataset={simDataset}
Expand All @@ -361,6 +398,8 @@
selected={simDataset.id === $simulationDatasetId}
on:click={() => {
simulationDatasetId.set(simDataset.id);
setQueryParam(SearchParameters.SIMULATION_DATASET_ID, `${$simulationDatasetId}`);
viewTogglePanel({ state: true, type: 'right', update: { rightComponentTop: 'PlanMetadataPanel' } });
}}
on:cancel={onCancelSimulation}
/>
Expand Down
Loading

0 comments on commit c8aa142

Please sign in to comment.