Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions e2e-tests/tests/workspace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ test.describe.serial('Workspace', () => {

test('Edit and save user metadata', async () => {
// Create a file
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seq`);
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seqN.txt`);
await workspace.searchForFileAndWait(sequenceName);
await workspace.clickFile(sequenceName);

Expand Down Expand Up @@ -631,7 +631,7 @@ test.describe.serial('Workspace', () => {

test('Cancel discards user metadata changes', async () => {
// Create a file
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seq`);
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seqN.txt`);
await workspace.searchForFileAndWait(sequenceName);
await workspace.clickFile(sequenceName);

Expand All @@ -657,7 +657,7 @@ test.describe.serial('Workspace', () => {

test('Invalid JSON disables user metadata save button', async () => {
// Create a file
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seq`);
const { sequenceName } = await workspace.createSequence(undefined, `${generateRandomName()}.seqN.txt`);
await workspace.searchForFileAndWait(sequenceName);
await workspace.clickFile(sequenceName);

Expand Down Expand Up @@ -688,8 +688,8 @@ test.describe.serial('Workspace', () => {

test('Switching files discards unsaved user metadata edits', async () => {
// Create two files
const { sequenceName: file1 } = await workspace.createSequence(undefined, `${generateRandomName()}.seq`);
const { sequenceName: file2 } = await workspace.createSequence(undefined, `${generateRandomName()}.seq`);
const { sequenceName: file1 } = await workspace.createSequence(undefined, `${generateRandomName()}.seqN.txt`);
const { sequenceName: file2 } = await workspace.createSequence(undefined, `${generateRandomName()}.seqN.txt`);

// Open first file and start editing metadata
await workspace.searchForFileAndWait(file1);
Expand Down
51 changes: 2 additions & 49 deletions src/components/sequencing/EditorToolbar.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<svelte:options immutable={true} />

<script lang="ts" generics="OutputFormat extends { name: string }">
import { Button, cn, DropdownMenu } from '@nasa-jpl/stellar-svelte';
import { Braces, Bug, Clipboard, Download, FileOutput } from 'lucide-svelte';
import { Button, cn } from '@nasa-jpl/stellar-svelte';
import { Braces, Bug, Clipboard, Download } from 'lucide-svelte';
import { createEventDispatcher } from 'svelte';
import type { ActionDefinition } from '../../types/actions';
import { isMacOs } from '../../utilities/browser';
Expand Down Expand Up @@ -34,12 +34,6 @@
export let downloadTooltip: string = 'Download';
export let onDownload: (() => void) | undefined = undefined;

// Output formats dropdown
export let outputFormats: OutputFormat[] = [];
export let outputDisabled: boolean = false;
export let onCopyOutput: ((format: OutputFormat) => void) | undefined = undefined;
export let onDownloadOutput: ((format: OutputFormat) => void) | undefined = undefined;

// Save button
export let showSaveButton: boolean = false;
export let saveDisabled: boolean = false;
Expand Down Expand Up @@ -94,47 +88,6 @@
</Tooltip>
{/if}

{#if outputFormats.length > 0}
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button builders={[builder]} variant="outline" class="gap-1">
<FileOutput size={14} />
Output
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content align="start" class="flex flex-col">
{#each outputFormats as outputFormat}
<Tooltip side="left" content={`Copy as ${outputFormat.name} to clipboard`}>
<DropdownMenu.Item
size="sm"
on:click={() => onCopyOutput?.(outputFormat)}
disabled={outputDisabled}
class="w-full"
>
<div class="flex gap-2">
<Clipboard size={16} />
{outputFormat.name}
</div>
</DropdownMenu.Item>
</Tooltip>
<Tooltip side="left" class="flex" content={`Download as ${outputFormat.name}`}>
<DropdownMenu.Item
size="sm"
on:click={() => onDownloadOutput?.(outputFormat)}
disabled={outputDisabled}
class="w-full"
>
<div class="flex gap-2">
<Download size={16} />
{outputFormat.name}
</div>
</DropdownMenu.Item>
</Tooltip>
{/each}
</DropdownMenu.Content>
</DropdownMenu.Root>
{/if}

<slot name="end" />

{#if showSaveButton && onSave}
Expand Down
74 changes: 74 additions & 0 deletions src/components/sequencing/OutputToolbar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<svelte:options immutable={true} />

<script lang="ts">
import type { OutputLanguage } from '@nasa-jpl/aerie-sequence-languages';

import { Button, Label } from '@nasa-jpl/stellar-svelte';
import { Clipboard, Download, PanelBottomClose, PanelBottomOpen } from 'lucide-svelte';
import { createEventDispatcher } from 'svelte';
import Tooltip from '../ui/Tooltip.svelte';

export let isPreviewOpen: boolean = false;
export let outputLanguages: OutputLanguage[] = [];
export let outputDisabled: boolean = false;
export let selectedOutputFormat: OutputLanguage | undefined;

const dispatch = createEventDispatcher<{
copyOutput: void;
downloadOutput: void;
togglePreview: void;
}>();

let copyTooltip: string = 'Copy to clipboard';
let downloadTooltip: string = `Download`;

$: copyTooltip = `Copy as ${selectedOutputFormat?.name} to clipboard`;
$: downloadTooltip = `Download as ${selectedOutputFormat?.name}`;

function onCopy() {
dispatch('copyOutput');
}

function onDownload() {
dispatch('downloadOutput');
}

function onTogglePreview() {
dispatch('togglePreview');
}
</script>

<div class="flex items-center justify-end gap-1.5">
{#if outputLanguages.length > 0}
<Label size="sm" class="mr-1 whitespace-nowrap text-muted-foreground" for="outputFormat">Output Format</Label>
<select bind:value={selectedOutputFormat} class="st-select w-full" name="outputFormat">
{#each outputLanguages as outputFormatItem}
<option value={outputFormatItem}>
{outputFormatItem.name}
</option>
{/each}
</select>
{/if}
<div class="flex items-center gap-1.5">
<Tooltip content={copyTooltip}>
<Button variant="outline" size="icon" on:click={onCopy} disabled={outputDisabled}>
<Clipboard size={16} />
</Button>
</Tooltip>
<Tooltip content={downloadTooltip}>
<Button variant="outline" size="icon" on:click={onDownload} disabled={outputDisabled}>
<Download size={16} />
</Button>
</Tooltip>

<Tooltip content={isPreviewOpen ? `Collapse Editor` : `Expand Editor`}>
<Button size="icon" variant="ghost" on:click={onTogglePreview}>
{#if isPreviewOpen}
<PanelBottomClose size={16} />
{:else}
<PanelBottomOpen size={16} />
{/if}
</Button>
</Tooltip>
</div>
</div>
Loading
Loading