This is an automated email from the ASF dual-hosted git repository. yasithdev pushed a commit to branch feat/generic-experiment-launcher in repository https://gitbox.apache.org/repos/asf/airavata-portals.git
commit 5a3db3915a4e380fd9a8f8543b52c3db2555b179 Author: yasithdev <[email protected]> AuthorDate: Fri Apr 24 22:16:40 2026 -0400 fix(launcher): add setStorages/setProfile + honor optional outputs + reset previewLoading --- .../tests/unit/stores/launch.spec.ts | 38 ++++++++++++++++++++++ .../static/common/js/stores/launch.ts | 17 +++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/tests/unit/stores/launch.spec.ts b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/tests/unit/stores/launch.spec.ts index 9046aacea..b064e646f 100644 --- a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/tests/unit/stores/launch.spec.ts +++ b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/tests/unit/stores/launch.spec.ts @@ -64,3 +64,41 @@ describe("useLaunchStore", () => { expect(s.draftHash).toBe(h2); }); }); + +describe("setters and reset", () => { + beforeEach(() => setActivePinia(createPinia())); + + it("setStorages and setProfile populate state", () => { + const s = useLaunchStore(); + s.setStorages([{ storage_id: "x", name: "X", is_primary: true }]); + s.setProfile({ project_id: "p1", allocation_id: "A1", compute_resources: [] }); + expect(s.storages).toHaveLength(1); + expect(s.profile?.allocation_id).toBe("A1"); + }); + + it("reset clears all state including previewLoading", () => { + const s = useLaunchStore(); + s.setMeta({ name: "x", project_id: "p1", description: "" }); + s.previewLoading = true; + s.reset(); + expect(s.draft.name).toBe(""); + expect(s.draft.project_id).toBeNull(); + expect(s.previewLoading).toBe(false); + }); + + it("optional outputs do not block tab1 validity", () => { + const s = useLaunchStore(); + const iface = { + name: "run", + inputs: [{ name: "x", type: "int" as const, required: true }], + outputs: [{ name: "log", type: "file" as const, required: false }], + }; + s.setMeta({ name: "x", project_id: "p1", description: "" }); + s.pickApp({ app_id: "a", name: "A", category: "C", + content: { kind: "github", url: "g" }, interfaces: [iface] }); + s.pickInterface("run"); + s.setInput("x", 1); + // No output set, but it's not required + expect(s.tab1Valid).toBe(true); + }); +}); diff --git a/airavata-django-portal/django_airavata/static/common/js/stores/launch.ts b/airavata-django-portal/django_airavata/static/common/js/stores/launch.ts index e249d41ab..5e34c91b8 100644 --- a/airavata-django-portal/django_airavata/static/common/js/stores/launch.ts +++ b/airavata-django-portal/django_airavata/static/common/js/stores/launch.ts @@ -109,7 +109,11 @@ export const useLaunchStore = defineStore("launch", () => { for (const io of iface.outputs) { if (io.type !== "file" && io.type !== "dir") continue; const v = draft.outputs[io.name]; - if (!v || !v.path || !v.storage_id) return false; + if (!v) { + if (io.required) return false; + continue; + } + if (!v.path || !v.storage_id) return false; } return true; }); @@ -130,12 +134,21 @@ export const useLaunchStore = defineStore("launch", () => { return (h >>> 0).toString(16); }); + function setStorages(s: UserStorage[]) { + storages.value = s; + } + + function setProfile(p: ResourceProfile | null) { + profile.value = p; + } + function reset() { Object.assign(draft, makeDraft()); pickedApp.value = null; profile.value = null; preview.value = null; previewError.value = null; + previewLoading.value = false; lastPreviewedHash.value = null; } @@ -158,6 +171,8 @@ export const useLaunchStore = defineStore("launch", () => { setInput, setOutput, setRuntime, + setStorages, + setProfile, reset, }; });
