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

Import SATF Library Sequence #1592

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
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
67 changes: 67 additions & 0 deletions src/components/modals/LibrarySequenceModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<svelte:options immutable={true} />

<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { parcels } from '../../stores/sequencing';
import Modal from './Modal.svelte';
import ModalContent from './ModalContent.svelte';
import ModalFooter from './ModalFooter.svelte';
import ModalHeader from './ModalHeader.svelte';

export let height: number = 200;
export let width: number = 380;

const dispatch = createEventDispatcher<{
close: void;
save: { library: FileList; parcel: number };
}>();

let saveButtonDisabled: boolean = true;
let modalTitle: string;
let libraryName: FileList;
let parcelId: number;

$: saveButtonDisabled = parcelId === null || libraryName === undefined;
$: modalTitle = 'Import Library';

function save() {
if (!saveButtonDisabled) {
dispatch('save', { library: libraryName, parcel: parcelId });
}
}

function onKeydown(event: KeyboardEvent) {
const { key } = event;
if (key === 'Enter') {
event.preventDefault();
save();
}
}
</script>

<svelte:window on:keydown={onKeydown} />

<Modal {height} {width}>
<ModalHeader on:close>{modalTitle}</ModalHeader>

<ModalContent>
<div class="st-typography-body">Parcel (required)</div>
<select bind:value={parcelId} class="st-select w-100" name="parcel">
<option value={null} />
{#each $parcels as parcel}
<option value={parcel.id}>
{parcel.name}
</option>
{/each}
</select>
<fieldset>
<label for="name">Imported Library</label>
<input bind:files={libraryName} class="w-100" name="libraryFile" type="file" accept=".satf" />
</fieldset>
</ModalContent>

<ModalFooter>
<button class="st-button secondary" on:click={() => dispatch('close')}> Cancel </button>
<button class="st-button" disabled={saveButtonDisabled} on:click={save}> Import </button>
</ModalFooter>
</Modal>
44 changes: 44 additions & 0 deletions src/components/sequencing/Sequences.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import { parcels, userSequences, userSequencesColumns, workspaces } from '../../stores/sequencing';
import type { User } from '../../types/app';
import type { Parcel, UserSequence, Workspace } from '../../types/sequencing';
import { satfToSequence } from '../../utilities/codemirror/satf/satf-sasf-utils';
import effects from '../../utilities/effects';
import { getSearchParameterNumber, setQueryParam } from '../../utilities/generic';
import { permissionHandler } from '../../utilities/permissionHandler';
import { featurePermissions } from '../../utilities/permissions';
Expand Down Expand Up @@ -59,6 +61,28 @@
const workspaceId = getSearchParameterNumber(SearchParameters.WORKSPACE_ID);
goto(`${base}/sequencing/new${workspaceId ? `?${SearchParameters.WORKSPACE_ID}=${workspaceId}` : ''}`);
}

async function importLibrary(): Promise<void> {
const library = await effects.importLibrarySequences(workspaceId);
if (!library) {
return;
}

const parcel = library.parcel;
const sequences = (await satfToSequence(library.fileContents)).sequences;
sequences.forEach(async seqN => {
await effects.createUserSequence(
{
definition: seqN.sequence,
name: seqN.name,
parcel_id: parcel,
seq_json: '',
workspace_id: workspaceId !== null ? workspaceId : -1,
},
user,
);
});
}
</script>

<CssGrid bind:columns={$userSequencesColumns}>
Expand Down Expand Up @@ -86,6 +110,18 @@
>
New Sequence
</button>

<button
duranb marked this conversation as resolved.
Show resolved Hide resolved
class="st-button secondary ellipsis"
use:permissionHandler={{
hasPermission: featurePermissions.sequences.canCreate(user),
permissionError: 'You do not have permission to upload library sequences',
}}
disabled={workspace === undefined}
on:click|stopPropagation={importLibrary}
>
Import Library
</button>
</div>
</svelte:fragment>

Expand All @@ -108,3 +144,11 @@
{user}
/>
</CssGrid>

<style>
.right {
column-gap: 5px;
display: flex;
flex-wrap: nowrap;
}
</style>
4 changes: 3 additions & 1 deletion src/utilities/codemirror/codemirror-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,12 @@ describe('getDefaultVariableArgs', () => {
{ allowable_ranges: [{ min: 5 }], type: 'INT' },
{ allowable_ranges: [{ min: 7 }], type: 'UINT' },
{ allowable_values: ['VALUE1'], enum_name: 'ExampleEnum', type: 'ENUM' },
{ enum_name: 'ExampleEnum2', type: 'ENUM' },
{ type: 'INT' },
{ name: 'hexValue', type: 'HEX' },
] as VariableDeclaration[];
it('should return default values for different types', () => {
const result = getDefaultVariableArgs(mockParameters);
expect(result).toEqual(['"exampleString"', 1.2, 5, 7, '"VALUE1"', 0]);
expect(result).toEqual(['"exampleString"', 1.2, 5, 7, '"VALUE1"', '"ExampleEnum2"', 0, 'ERROR:"hexValue"']);
});
});
4 changes: 2 additions & 2 deletions src/utilities/codemirror/codemirror-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ export function getDefaultVariableArgs(parameters: VariableDeclaration[]): strin
return parameter.allowable_values && parameter.allowable_values.length > 0
? `"${parameter.allowable_values[0]}"`
: parameter.enum_name
? `${parameter.enum_name}`
? `"${parameter.enum_name}"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we update the test for this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure added a unit test to test this path

: 'UNKNOWN';
default:
throw Error(`unknown argument type ${parameter.type}`);
return `ERROR:"${parameter.name}"`;
goetzrrGit marked this conversation as resolved.
Show resolved Hide resolved
}
}) as string[];
}
Expand Down
12 changes: 6 additions & 6 deletions src/utilities/codemirror/satf/satf-sasf-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ describe('satfToSequence', () => {
expect(result.sequences[0].name).toStrictEqual('test');
expect(result.sequences[0].sequence).toStrictEqual(`## test
R00:01:00 01VV param6 10 false "abc" # This command turns, to correct position.
@MODEL(x,1,"00:00:00")
@MODEL(z,1.1,"00:00:00")
@MODEL(y,"abc","00:00:00")`);
@MODEL "x" 1 "00:00:00"
@MODEL "z" 1.1 "00:00:00"
@MODEL "y" "abc" "00:00:00"`);
});

it('should return multiple sequence with models', async () => {
Expand Down Expand Up @@ -127,9 +127,9 @@ R00:01:00 01VV param6 10 false "abc" # This command turns, to correct position.
expect(result.sequences[0].name).toStrictEqual('test');
expect(result.sequences[0].sequence).toStrictEqual(`## test
R00:01:00 01VV param6 10 false "abc" # This command turns, to correct position.
@MODEL(x,1,"00:00:00")
@MODEL(z,1.1,"00:00:00")
@MODEL(y,"abc","00:00:00")`);
@MODEL "x" 1 "00:00:00"
@MODEL "z" 1.1 "00:00:00"
@MODEL "y" "abc" "00:00:00"`);
});
});

Expand Down
12 changes: 10 additions & 2 deletions src/utilities/codemirror/satf/satf-sasf-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,15 @@ export function generateSatfVariables(
return (
`\t${variable.name}` +
`(\n\t\tTYPE,${variable.type}${variable.enum_name ? `\n\tENUM,${variable.enum_name}` : ''}` +
`${variable.allowable_ranges ? `\n\t\tRANGES,${variable.allowable_ranges}` : ''}` +
`${
variable.allowable_ranges
? variable.allowable_ranges
.map(range => {
return `\n\t\tRANGES,\\${range.min}...${range.max}\\`;
})
.join(',')
: ''
}` +
`${variable.allowable_values ? `\n\t\tVALUES,${variable.allowable_values}` : ''}` +
`${variable.sc_name ? `\n\t\tSC_NAME,${variable.sc_name}` : ''}\n\t)`
);
Expand Down Expand Up @@ -881,7 +889,7 @@ function parseModel(modelNode: SyntaxNode | null, text: string): string {
if (!keyNode || !valueNode) {
return null;
}
return `@MODEL(${text.slice(keyNode.from, keyNode.to)},${text.slice(valueNode.from, valueNode.to)},"00:00:00")`;
return `@MODEL "${text.slice(keyNode.from, keyNode.to)}" ${text.slice(valueNode.from, valueNode.to)} "00:00:00"`;
})
.filter(model => model !== null)
.join('\n');
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/codemirror/satf/satf-sasf.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
HeaderPairs { HeaderPair* }
HeaderPair {Key"="Value ";" newLine}
Key { (identifier | ":")* }
Value { headerValue+ }
Value { (headerValue | "/")+ }
SfduHeader { headerMarker newLine HeaderPairs headerMarker}

Start { "$$"identifier identifier* newLine}
Expand Down
23 changes: 23 additions & 0 deletions src/utilities/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ import {
showDeleteActivitiesModal,
showDeleteExternalSourceModal,
showEditViewModal,
showLibrarySequenceModel,
showManageGroupsAndTypes,
showManagePlanConstraintsModal,
showManagePlanDerivationGroups,
Expand Down Expand Up @@ -4791,6 +4792,28 @@ const effects = {
}
},

async importLibrarySequences(
workspaceId: number | null,
): Promise<{ fileContents: string; parcel: number } | undefined> {
if (workspaceId === null) {
showFailureToast("Library Import: Workspace doesn't exist");
return undefined;
}
const { confirm, value } = await showLibrarySequenceModel();

if (!confirm || !value) {
return undefined;
}

try {
const contents = await value.libraryFile.text();
return { fileContents: contents, parcel: value.parcel };
} catch (e) {
showFailureToast('Library Import: Unable to open file');
return undefined;
}
},

async importPlan(
name: string,
modelId: number,
Expand Down
34 changes: 34 additions & 0 deletions src/utilities/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import DeleteExternalEventSourceTypeModal from '../components/modals/DeleteExter
import DeleteExternalSourceModal from '../components/modals/DeleteExternalSourceModal.svelte';
import EditViewModal from '../components/modals/EditViewModal.svelte';
import ExpansionSequenceModal from '../components/modals/ExpansionSequenceModal.svelte';
import LibrarySequenceModal from '../components/modals/LibrarySequenceModal.svelte';
import ManageGroupsAndTypesModal from '../components/modals/ManageGroupsAndTypesModal.svelte';
import ManagePlanConstraintsModal from '../components/modals/ManagePlanConstraintsModal.svelte';
import ManagePlanDerivationGroupsModal from '../components/modals/ManagePlanDerivationGroupsModal.svelte';
Expand Down Expand Up @@ -556,6 +557,39 @@ export async function showWorkspaceModal(
});
}

export async function showLibrarySequenceModel(): Promise<ModalElementValue<{ libraryFile: File; parcel: number }>> {
return new Promise(resolve => {
if (browser) {
const target: ModalElement | null = document.querySelector('#svelte-modal');

if (target) {
const workspaceModal = new LibrarySequenceModal({
target,
});
target.resolve = resolve;

workspaceModal.$on('close', () => {
target.replaceChildren();
target.resolve = null;
resolve({ confirm: false });
workspaceModal.$destroy();
});

workspaceModal.$on('save', (e: CustomEvent<{ library: FileList; parcel: number }>) => {
const library = e.detail.library[0];
const parcel = e.detail.parcel;
target.replaceChildren();
target.resolve = null;
resolve({ confirm: true, value: { libraryFile: library, parcel } });
workspaceModal.$destroy();
});
}
} else {
resolve({ confirm: false });
}
});
}

/**
* Shows a CreatePlanBranchModal with the supplied arguments.
*/
Expand Down
16 changes: 12 additions & 4 deletions src/utilities/sequence-editor/sequence-linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,16 +567,24 @@ function validateActivateLoad(
} else {
value = parseInt(num);
}
parameter.allowable_ranges?.forEach(range => {
if (value < range.min || value > range.max) {

if (parameter.allowable_ranges) {
const invalidRanges = parameter.allowable_ranges.filter(range => {
return value < range.min || value > range.max;
});
if (invalidRanges.length === parameter.allowable_ranges.length) {
diagnostics.push({
from: arg.from,
message: `Value must be between ${range.min} and ${range.max}`,
message: `Value must be between ${parameter.allowable_ranges
.map(range => {
return `[${range.min} and ${range.max}]`;
})
.join(' or ')}`,
severity: 'error',
to: arg.to,
});
}
});
}

if (parameter.type === 'UINT') {
if (value < 0) {
Expand Down
Loading