Skip to content

Commit 3a5a1fe

Browse files
committed
More updates
1 parent 4969668 commit 3a5a1fe

10 files changed

Lines changed: 178 additions & 77 deletions

File tree

src/components/modals/RunActionModal.svelte

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<svelte:options immutable={true} />
22

33
<script lang="ts">
4+
import { Alert } from '@nasa-jpl/stellar-svelte';
5+
import { TriangleAlert } from 'lucide-svelte';
46
import { createEventDispatcher } from 'svelte';
57
import type { ActionDefinition, ActionParametersMap } from '../../types/actions';
68
import type { User } from '../../types/app';
@@ -36,8 +38,13 @@
3638
let running: boolean = false;
3739
let parametersMap: ActionParametersMap = {};
3840
const latestRunnable = getLatestRunnableVersion(actionDefinition.versions);
41+
const initialVersionArchived =
42+
initialRevision !== undefined &&
43+
actionDefinition.versions.find(v => v.revision === initialRevision)?.archived === true;
3944
let selectedRevision: string =
40-
initialRevision !== undefined && initialRevision !== latestRunnable?.revision ? String(initialRevision) : 'latest';
45+
initialRevision !== undefined && !initialVersionArchived && initialRevision !== latestRunnable?.revision
46+
? String(initialRevision)
47+
: 'latest';
4148
let settingsArgumentsMap: ArgumentsMap = {};
4249
let settingsParametersMap: ActionParametersMap = {};
4350
@@ -47,12 +54,14 @@
4754
}>();
4855
4956
$: latestVersion = getLatestRunnableVersion(actionDefinition.versions);
50-
$: runnableVersions = getRunnableVersions(actionDefinition.versions, initialRevision);
57+
$: runnableVersions = getRunnableVersions(actionDefinition.versions);
5158
$: selectedVersion =
5259
selectedRevision === 'latest'
5360
? latestVersion
5461
: (runnableVersions.find(v => v.revision === Number(selectedRevision)) ?? latestVersion);
5562
$: isLatestSelected = selectedRevision === 'latest';
63+
$: effectiveSelectedRevision = selectedRevision === 'latest' ? latestVersion?.revision : Number(selectedRevision);
64+
$: versionMismatch = isRerun && initialRevision !== undefined && effectiveSelectedRevision !== initialRevision;
5665
5766
$: if (parameters !== undefined) {
5867
argumentsMap = parameters;
@@ -173,6 +182,18 @@
173182
<Modal height="max-content" width={500} on:close closeOnEscape={false} closeOnOutsideClick={false}>
174183
<ModalHeader on:close>{isRerun ? `Re-run: ${actionDefinition.name}` : actionDefinition.name}</ModalHeader>
175184
<ModalContent style="max-height: 50vh;overflow: auto">
185+
{#if versionMismatch}
186+
<Alert.Root variant="destructive" class="mb-3">
187+
<TriangleAlert class="h-4 w-4" />
188+
<Alert.Description>
189+
{#if initialVersionArchived}
190+
Version {initialRevision} from the original run has been archived. This re-run will use version {effectiveSelectedRevision}.
191+
{:else}
192+
The selected version (v{effectiveSelectedRevision}) differs from the original run's version (v{initialRevision}).
193+
{/if}
194+
</Alert.Description>
195+
</Alert.Root>
196+
{/if}
176197
{#if showSettings && Object.keys(settingsParametersMap).length > 0}
177198
<div class="pb-4">
178199
<div class="pb-2 font-medium text-muted-foreground">

src/components/sequencing/actions/ActionDetailView.svelte

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<script lang="ts">
44
import { Badge, Button, Tabs } from '@nasa-jpl/stellar-svelte';
55
import type { ColDef, ICellRendererParams, ValueFormatterParams } from 'ag-grid-community';
6-
import { Archive } from 'lucide-svelte';
76
import { createEventDispatcher, onDestroy } from 'svelte';
87
import { actionDefinitionsByWorkspace, actionRunsByWorkspace } from '../../../stores/actions';
98
import { workspaceId } from '../../../stores/workspaces';
@@ -17,10 +16,12 @@
1716
getLatestRunnableVersion,
1817
getStatusForActionRun,
1918
getUserSequenceValueSchemaOptions,
19+
openActionRun,
2020
truncateRunParameters,
2121
valueSchemaRecordToParametersMap,
2222
} from '../../../utilities/actions';
2323
import effects from '../../../utilities/effects';
24+
import { isMetaOrCtrlPressed } from '../../../utilities/keyboardEvents';
2425
import { showConfirmModal } from '../../../utilities/modal';
2526
import { getArguments, getFormParameters } from '../../../utilities/parameters';
2627
import { permissionHandler } from '../../../utilities/permissionHandler';
@@ -162,7 +163,7 @@
162163
const { confirm } = await showConfirmModal(
163164
actionDefinition.archived ? 'Unarchive' : 'Archive',
164165
`Are you sure you want to ${action} "${actionDefinition.name}"?${action === 'archive' ? ' This operation can only be undone by an admin.' : ''}`,
165-
`${actionDefinition.archived ? 'Unarchive' : 'Archive'} Action`,
166+
`${actionDefinition.archived ? 'Unarchive' : 'Archive'} action`,
166167
true,
167168
);
168169
if (!confirm) {
@@ -243,10 +244,14 @@
243244
}
244245
}
245246
246-
function onRowClicked(event: CustomEvent<{ data: ActionRunSlim }>) {
247-
const { data } = event.detail;
247+
function onRowClicked(event: CustomEvent<{ data: ActionRunSlim; event?: Event | null }>) {
248+
const { data, event: originalEvent } = event.detail;
248249
if (data) {
249-
dispatch('viewRun', { runId: data.id });
250+
if (originalEvent && isMetaOrCtrlPressed(originalEvent as MouseEvent)) {
251+
openActionRun($workspaceId, data.id, true);
252+
} else {
253+
dispatch('viewRun', { runId: data.id });
254+
}
250255
}
251256
}
252257
@@ -409,7 +414,7 @@
409414
permissionError: 'You do not have permission to run an action',
410415
}}
411416
>
412-
<Button on:click={onRunClick}>Run Action</Button>
417+
<Button on:click={onRunClick} disabled={actionDefinition.archived}>Run Action</Button>
413418
</div>
414419
<input bind:this={uploadFileInput} accept=".js" class="hidden" on:change={uploadNewVersion} type="file" />
415420
<div
@@ -418,7 +423,9 @@
418423
permissionError: 'You do not have permission to upload a new version',
419424
}}
420425
>
421-
<Button variant="outline" on:click={() => uploadFileInput?.click()}>Upload New Version</Button>
426+
<Button variant="outline" on:click={() => uploadFileInput?.click()} disabled={actionDefinition.archived}>
427+
Upload New Version
428+
</Button>
422429
</div>
423430
<Button on:click={() => dispatch('close')} variant="outline">Close</Button>
424431
</div>
@@ -454,6 +461,10 @@
454461
</div>
455462
{#if activeTab === 'code'}
456463
<div class="flex items-center gap-2 pr-2">
464+
<label class="flex shrink-0 cursor-pointer items-center gap-1 text-xs text-muted-foreground">
465+
<input type="checkbox" bind:checked={showArchivedVersions} class="h-3.5 w-3.5" />
466+
<span>Archived</span>
467+
</label>
457468
<select
458469
class="st-input h-6 bg-white !px-1 text-xs"
459470
value={selectedVersion?.revision ?? 0}
@@ -471,26 +482,21 @@
471482
</select>
472483
{#if selectedVersion}
473484
<span class="text-xs text-muted-foreground">
474-
{selectedVersion.author ?? 'Unknown'} • {new Date(selectedVersion.created_at).toLocaleDateString()}
485+
Author:
486+
{selectedVersion.author ?? 'Unknown'} • Created: {new Date(
487+
selectedVersion.created_at,
488+
).toLocaleDateString()}
475489
</span>
476490
{/if}
477-
<button
478-
class="flex shrink-0 items-center rounded p-0.5 {showArchivedVersions
479-
? 'bg-accent'
480-
: 'text-muted-foreground hover:text-foreground'}"
481-
title={showArchivedVersions ? 'Hide archived versions' : 'Show archived versions'}
482-
on:click={() => (showArchivedVersions = !showArchivedVersions)}
483-
>
484-
<Archive size={14} />
485-
</button>
491+
486492
{#if selectedVersion && (selectedVersion !== actionDefinition.versions[0] || actionDefinition.versions.filter(v => !v.archived && v !== selectedVersion).length > 0)}
487493
<Button
488494
variant="outline"
489495
class="h-6 text-xs"
490496
disabled={!hasUpdatePermission}
491497
on:click={() => toggleVersionArchive(actionDefinition, selectedVersion, user)}
492498
>
493-
{selectedVersion.archived ? 'Unarchive' : 'Archive'}
499+
{selectedVersion.archived ? 'Unarchive Version' : 'Archive Version'}
494500
</Button>
495501
{/if}
496502
</div>
@@ -626,6 +632,65 @@
626632
{/if}
627633
</div>
628634

635+
<!-- Versions section -->
636+
<div class="flex flex-col gap-3 rounded border border-border p-4">
637+
<div class="flex items-center justify-between">
638+
<h3 class="text-sm font-medium">Versions</h3>
639+
<label class="flex items-center gap-1.5 text-xs text-muted-foreground">
640+
<input type="checkbox" bind:checked={showArchivedVersions} class="h-3.5 w-3.5" />
641+
Show archived
642+
</label>
643+
</div>
644+
{#if displayedVersions.length === 0}
645+
<p class="text-xs italic text-muted-foreground">No versions</p>
646+
{:else}
647+
<div class="divide-y divide-border rounded border border-border">
648+
{#each displayedVersions as version, i (version.revision)}
649+
<div
650+
class="flex items-center justify-between px-3 py-2 text-xs {version.archived ? 'opacity-50' : ''}"
651+
>
652+
<div class="flex flex-wrap items-center gap-x-4 gap-y-1">
653+
<span class="font-medium">
654+
v{version.revision}
655+
{#if i === 0 && !version.archived}
656+
<span class="text-muted-foreground">(latest)</span>
657+
{/if}
658+
</span>
659+
<span class="text-muted-foreground">
660+
Author: <span class="text-foreground">{version.author ?? 'Unknown'}</span>
661+
</span>
662+
<span class="text-muted-foreground">
663+
Created: <span class="text-foreground"
664+
>{new Date(version.created_at).toLocaleDateString()}</span
665+
>
666+
</span>
667+
{#if version.archived}
668+
<Badge variant="destructive">Archived</Badge>
669+
{/if}
670+
</div>
671+
{#if version !== actionDefinition.versions[0] || actionDefinition.versions.filter(v => !v.archived && v !== version).length > 0}
672+
<div
673+
use:permissionHandler={{
674+
hasPermission: hasUpdatePermission,
675+
permissionError: 'You do not have permission to archive a version',
676+
}}
677+
>
678+
<Button
679+
variant="outline"
680+
class="h-6 shrink-0 text-xs"
681+
disabled={!hasUpdatePermission}
682+
on:click={() => toggleVersionArchive(actionDefinition, version, user)}
683+
>
684+
{version.archived ? 'Unarchive Version' : 'Archive Version'}
685+
</Button>
686+
</div>
687+
{/if}
688+
</div>
689+
{/each}
690+
</div>
691+
{/if}
692+
</div>
693+
629694
<div class="flex items-center gap-2">
630695
<div
631696
use:permissionHandler={{
@@ -644,7 +709,7 @@
644709
}}
645710
>
646711
<Button variant="outline" on:click={toggleArchive}>
647-
{actionDefinition.archived ? 'Unarchive' : 'Archive'}
712+
{actionDefinition.archived ? 'Unarchive Action' : 'Archive Action'}
648713
</Button>
649714
</div>
650715
</div>

src/components/sequencing/actions/ActionRunDetailView.svelte

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<script lang="ts">
44
import { Button, Tabs } from '@nasa-jpl/stellar-svelte';
55
import { capitalize } from 'lodash-es';
6-
import { ArrowLeft, Ban, ExternalLink, RefreshCw } from 'lucide-svelte';
6+
import { ArrowLeft, Ban, RefreshCw } from 'lucide-svelte';
77
import { createEventDispatcher } from 'svelte';
88
import { writable } from 'svelte/store';
99
import { Status } from '../../../enums/status';
@@ -17,7 +17,6 @@
1717
import {
1818
getActionDefinitionForRun,
1919
getStatusForActionRun,
20-
openActionRun,
2120
valueSchemaRecordToParametersMap,
2221
} from '../../../utilities/actions';
2322
import effects from '../../../utilities/effects';
@@ -158,10 +157,6 @@
158157
}
159158
}
160159
161-
function onOpenInNewTab() {
162-
openActionRun($workspaceId, actionRunId, true);
163-
}
164-
165160
function onBack() {
166161
dispatch('back');
167162
}
@@ -194,7 +189,7 @@
194189
</div>
195190
</div>
196191
<div class="flex items-center gap-2">
197-
{#if actionDefinition}
192+
{#if actionDefinition && !actionDefinition.archived}
198193
<div
199194
use:permissionHandler={{ hasPermission, permissionError: 'You do not have permission to run an action' }}
200195
>
@@ -214,13 +209,6 @@
214209
Cancel
215210
</button>
216211
{/if}
217-
<button
218-
class="rounded p-1 hover:bg-accent"
219-
on:click={onOpenInNewTab}
220-
use:tooltip={{ content: 'Open in new tab', placement: 'bottom' }}
221-
>
222-
<ExternalLink size={14} />
223-
</button>
224212
</div>
225213
</div>
226214

src/components/sequencing/actions/ActionRunsListView.svelte

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88
import { workspaceId } from '../../../stores/workspaces';
99
import type { ActionRunSlim } from '../../../types/actions';
1010
import type { User } from '../../../types/app';
11-
import { getActionDefinitionForRun, getStatusForActionRun, truncateRunParameters } from '../../../utilities/actions';
11+
import {
12+
getActionDefinitionForRun,
13+
getStatusForActionRun,
14+
openActionRun,
15+
truncateRunParameters,
16+
} from '../../../utilities/actions';
1217
import effects from '../../../utilities/effects';
18+
import { isMetaOrCtrlPressed } from '../../../utilities/keyboardEvents';
1319
import { formatMS } from '../../../utilities/time';
1420
import SingleActionDataGrid from '../../ui/DataGrid/SingleActionDataGrid.svelte';
1521
import SectionTitle from '../../ui/SectionTitle.svelte';
@@ -81,10 +87,14 @@
8187
return div;
8288
}
8389
84-
function onRowClicked(event: CustomEvent<{ data: ActionRunSlim }>) {
85-
const { data } = event.detail;
90+
function onRowClicked(event: CustomEvent<{ data: ActionRunSlim; event?: Event | null }>) {
91+
const { data, event: originalEvent } = event.detail;
8692
if (data) {
87-
dispatch('viewRun', { runId: data.id });
93+
if (originalEvent && isMetaOrCtrlPressed(originalEvent as MouseEvent)) {
94+
openActionRun($workspaceId, data.id, true);
95+
} else {
96+
dispatch('viewRun', { runId: data.id });
97+
}
8898
}
8999
}
90100

0 commit comments

Comments
 (0)