Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simulation snapshot panel interactions #913

Merged
merged 11 commits into from
Oct 9, 2023
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;
AaronPlave marked this conversation as resolved.
Show resolved Hide resolved
}
}}
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
AaronPlave marked this conversation as resolved.
Show resolved Hide resolved
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}
AaronPlave marked this conversation as resolved.
Show resolved Hide resolved
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
Loading