@morscherlab/mint-sdk 1.2.0-beta.2 → 1.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-B6P2msT4.js} +3 -3
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js.map → ExperimentSelectorModal-B6P2msT4.js.map} +1 -1
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-CkNM8qAI.js} +4 -4
- package/dist/{SettingsModal-BgKY93zh.js.map → SettingsModal-CkNM8qAI.js.map} +1 -1
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/SampleLegend.vue.d.ts +1 -1
- package/dist/components/SampleSelector.vue.d.ts +1 -1
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -1
- package/dist/components/index.js +4 -4
- package/dist/{components-DkHddRMl.js → components-MGNL6tRn.js} +16 -10
- package/dist/components-MGNL6tRn.js.map +1 -0
- package/dist/composables/index.d.ts +3 -2
- package/dist/composables/index.js +8 -8
- package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
- package/dist/composables/useJobsStatusTray.d.ts +25 -1
- package/dist/composables/usePluginClient.d.ts +2 -0
- package/dist/composables/usePluginConfig.d.ts +25 -0
- package/dist/{composables-C_i90sGS.js → composables-CKxOcvgh.js} +140 -5
- package/dist/composables-CKxOcvgh.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-Y9Iz7KYi.js} +2 -2
- package/dist/{experiment-Cq145oEW.js.map → experiment-Y9Iz7KYi.js.map} +1 -1
- package/dist/index.js +12 -12
- package/dist/install.js +4 -4
- package/dist/stores/auth.d.ts +6 -0
- package/dist/stores/index.js +2 -2
- package/dist/templates/index.js +2 -2
- package/dist/{templates-DsP51i-S.js → templates-BTJ9C9Kb.js} +2 -2
- package/dist/{templates-DsP51i-S.js.map → templates-BTJ9C9Kb.js.map} +1 -1
- package/dist/types/auth.d.ts +1 -0
- package/dist/{useApi-J6zFkHmn.js → useApi-CDBq6z23.js} +2 -1
- package/dist/useApi-CDBq6z23.js.map +1 -0
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-CXhxTul7.js} +10 -3
- package/dist/useControlSchema-CXhxTul7.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-D0pjj9WH.js} +2 -2
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-D0pjj9WH.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-CuOFB3aP.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-CuOFB3aP.js.map} +1 -1
- package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BWhQIWV5.js} +113 -22
- package/dist/useProtocolTemplates-BWhQIWV5.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +17 -6
- package/src/components/JobsStatusTray.vue +16 -1
- package/src/composables/index.ts +7 -0
- package/src/composables/useAuth.ts +3 -0
- package/src/composables/useGeneratedAnalysis.ts +14 -1
- package/src/composables/useJobsStatusTray.ts +184 -17
- package/src/composables/usePluginClient.ts +5 -0
- package/src/composables/usePluginConfig.ts +250 -0
- package/src/stores/auth.ts +1 -0
- package/src/types/auth.ts +1 -0
- package/dist/components-DkHddRMl.js.map +0 -1
- package/dist/composables-C_i90sGS.js.map +0 -1
- package/dist/useApi-J6zFkHmn.js.map +0 -1
- package/dist/useControlSchema-BDx2Olha.js.map +0 -1
- package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { d as resolveExperimentCode } from "./experiment-utils-CLnzPPq5.js";
|
|
2
2
|
import { r as useRequestSyncState } from "./EmptyState-p90quq8Z.js";
|
|
3
|
-
import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-
|
|
4
|
-
import { o as useSettingsStore, r as useApi } from "./useApi-
|
|
5
|
-
import { t as useExperimentStore } from "./experiment-
|
|
6
|
-
import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-
|
|
3
|
+
import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-CXhxTul7.js";
|
|
4
|
+
import { o as useSettingsStore, r as useApi } from "./useApi-CDBq6z23.js";
|
|
5
|
+
import { t as useExperimentStore } from "./experiment-Y9Iz7KYi.js";
|
|
6
|
+
import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-BTJ9C9Kb.js";
|
|
7
7
|
import { computed, effectScope, getCurrentScope, inject, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
|
|
8
8
|
//#region src/composables/useSortedItems.ts
|
|
9
9
|
/** Shared sorting for SDK tables and lists with stable empty-value handling. */
|
|
@@ -601,6 +601,12 @@ var PluginJobSourceDisposeError = class extends Error {
|
|
|
601
601
|
function duplicatePluginJobId(jobId) {
|
|
602
602
|
return /* @__PURE__ */ new Error(`Duplicate plugin job id across combined sources: ${jobId}`);
|
|
603
603
|
}
|
|
604
|
+
function responseJobs(response) {
|
|
605
|
+
return "jobs" in response ? response.jobs : response;
|
|
606
|
+
}
|
|
607
|
+
function isSnapshotPayload(data) {
|
|
608
|
+
return "jobs" in data && Array.isArray(data.jobs);
|
|
609
|
+
}
|
|
604
610
|
function errorMessage(error, fallback) {
|
|
605
611
|
return error instanceof Error ? error.message : fallback;
|
|
606
612
|
}
|
|
@@ -611,38 +617,94 @@ function errorMessage(error, fallback) {
|
|
|
611
617
|
* source. The controller never mirrors source jobs into another ref.
|
|
612
618
|
*/
|
|
613
619
|
function usePluginJobCenter(options = {}) {
|
|
620
|
+
const legacyOverride = shallowRef(null);
|
|
614
621
|
const isOpen = ref(false);
|
|
615
622
|
const activeTab = ref("active");
|
|
616
623
|
const isLoading = ref(false);
|
|
617
624
|
const error = shallowRef(null);
|
|
618
625
|
const pendingJobIds = ref(/* @__PURE__ */ new Set());
|
|
626
|
+
const jobRevisions = /* @__PURE__ */ new Map();
|
|
627
|
+
let stateRevision = 0;
|
|
619
628
|
let requestGeneration = 0;
|
|
620
629
|
let active = true;
|
|
621
630
|
const source = computed(() => toValue(options.source));
|
|
622
|
-
const
|
|
631
|
+
const adapter = computed(() => toValue(options.adapter));
|
|
632
|
+
const jobs = computed(() => {
|
|
633
|
+
const currentSource = source.value;
|
|
634
|
+
if (currentSource) return [...toValue(currentSource.jobs)].map(normalizeJobState);
|
|
635
|
+
const input = toValue(options.jobs);
|
|
636
|
+
const override = legacyOverride.value;
|
|
637
|
+
if (override && override.input === input) return override.jobs;
|
|
638
|
+
return input ? [...input].map(normalizeJobState) : [];
|
|
639
|
+
});
|
|
623
640
|
const activeJobs = computed(() => jobs.value.filter((job) => isActiveJobStatus(job.status)));
|
|
624
641
|
const historyJobs = computed(() => jobs.value.filter((job) => !isActiveJobStatus(job.status)));
|
|
625
642
|
const deletableJobs = computed(() => historyJobs.value.filter((job) => job.can_delete));
|
|
626
643
|
const featuredJob = computed(() => activeJobs.value[0] ?? historyJobs.value[0] ?? null);
|
|
627
|
-
const canRefresh = computed(() => Boolean(source.value?.refreshJobs));
|
|
628
|
-
const canCancel = computed(() => Boolean(source.value?.cancelJob));
|
|
629
|
-
const canDelete = computed(() => Boolean(source.value?.deleteJob));
|
|
630
|
-
const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob));
|
|
644
|
+
const canRefresh = computed(() => Boolean(source.value?.refreshJobs || adapter.value?.listJobs));
|
|
645
|
+
const canCancel = computed(() => Boolean(source.value?.cancelJob || adapter.value?.cancelJob));
|
|
646
|
+
const canDelete = computed(() => Boolean(source.value?.deleteJob || adapter.value?.deleteJob));
|
|
647
|
+
const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob || adapter.value?.clearFinishedJobs || adapter.value?.deleteJob));
|
|
648
|
+
function bumpJobRevision(jobId) {
|
|
649
|
+
jobRevisions.set(jobId, (jobRevisions.get(jobId) ?? 0) + 1);
|
|
650
|
+
}
|
|
651
|
+
function replaceLegacyJobs(nextJobs) {
|
|
652
|
+
const normalized = nextJobs.map(normalizeJobState);
|
|
653
|
+
new Set([...jobs.value.map((job) => job.job_id), ...normalized.map((job) => job.job_id)]).forEach(bumpJobRevision);
|
|
654
|
+
legacyOverride.value = {
|
|
655
|
+
input: toValue(options.jobs),
|
|
656
|
+
jobs: normalized
|
|
657
|
+
};
|
|
658
|
+
stateRevision += 1;
|
|
659
|
+
}
|
|
660
|
+
function upsertLegacyJob(nextJob) {
|
|
661
|
+
const normalized = normalizeJobState(nextJob);
|
|
662
|
+
const existingIndex = jobs.value.findIndex((job) => job.job_id === normalized.job_id);
|
|
663
|
+
const nextJobs = [...jobs.value];
|
|
664
|
+
if (existingIndex === -1) nextJobs.unshift(normalized);
|
|
665
|
+
else nextJobs[existingIndex] = normalized;
|
|
666
|
+
legacyOverride.value = {
|
|
667
|
+
input: toValue(options.jobs),
|
|
668
|
+
jobs: nextJobs
|
|
669
|
+
};
|
|
670
|
+
bumpJobRevision(normalized.job_id);
|
|
671
|
+
stateRevision += 1;
|
|
672
|
+
}
|
|
673
|
+
function removeLegacyJobs(jobIds) {
|
|
674
|
+
legacyOverride.value = {
|
|
675
|
+
input: toValue(options.jobs),
|
|
676
|
+
jobs: jobs.value.filter((job) => !jobIds.has(job.job_id))
|
|
677
|
+
};
|
|
678
|
+
jobIds.forEach(bumpJobRevision);
|
|
679
|
+
stateRevision += 1;
|
|
680
|
+
}
|
|
631
681
|
function setPending(jobId, pending) {
|
|
632
682
|
const next = new Set(pendingJobIds.value);
|
|
633
683
|
if (pending) next.add(jobId);
|
|
634
684
|
else next.delete(jobId);
|
|
635
685
|
pendingJobIds.value = next;
|
|
636
686
|
}
|
|
687
|
+
function applyStreamMessage(message) {
|
|
688
|
+
if (!active || source.value) return;
|
|
689
|
+
if (message.event === "snapshot" && isSnapshotPayload(message.data)) {
|
|
690
|
+
replaceLegacyJobs(message.data.jobs);
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
if ((message.event === "job" || message.event === "terminal") && !isSnapshotPayload(message.data)) upsertLegacyJob(message.data);
|
|
694
|
+
}
|
|
637
695
|
async function refresh() {
|
|
638
|
-
const
|
|
639
|
-
|
|
696
|
+
const currentSource = source.value;
|
|
697
|
+
const listJobs = currentSource?.refreshJobs ?? adapter.value?.listJobs;
|
|
698
|
+
if (!listJobs) return false;
|
|
640
699
|
const generation = ++requestGeneration;
|
|
700
|
+
const revision = stateRevision;
|
|
641
701
|
isLoading.value = true;
|
|
642
702
|
error.value = null;
|
|
643
703
|
try {
|
|
644
|
-
await
|
|
645
|
-
|
|
704
|
+
const response = await listJobs();
|
|
705
|
+
if (!active || generation !== requestGeneration || revision !== stateRevision) return false;
|
|
706
|
+
if (!currentSource && response) replaceLegacyJobs(responseJobs(response));
|
|
707
|
+
return true;
|
|
646
708
|
} catch (cause) {
|
|
647
709
|
if (active && generation === requestGeneration) error.value = errorMessage(cause, "Failed to load jobs");
|
|
648
710
|
return false;
|
|
@@ -652,12 +714,17 @@ function usePluginJobCenter(options = {}) {
|
|
|
652
714
|
}
|
|
653
715
|
async function cancelJob(job) {
|
|
654
716
|
const sourceCancel = source.value?.cancelJob;
|
|
655
|
-
|
|
717
|
+
const adapterCancel = adapter.value?.cancelJob;
|
|
718
|
+
if (!job.can_cancel || !sourceCancel && !adapterCancel || pendingJobIds.value.has(job.job_id)) return false;
|
|
719
|
+
const revision = jobRevisions.get(job.job_id) ?? 0;
|
|
656
720
|
setPending(job.job_id, true);
|
|
657
721
|
error.value = null;
|
|
658
722
|
try {
|
|
659
|
-
await sourceCancel(job.job_id);
|
|
660
|
-
return
|
|
723
|
+
const updated = sourceCancel ? await sourceCancel(job.job_id) : await adapterCancel(job);
|
|
724
|
+
if (!active) return false;
|
|
725
|
+
if (!sourceCancel && revision === (jobRevisions.get(job.job_id) ?? 0)) if (updated) upsertLegacyJob(updated);
|
|
726
|
+
else await refresh();
|
|
727
|
+
return true;
|
|
661
728
|
} catch (cause) {
|
|
662
729
|
if (active) error.value = errorMessage(cause, "Failed to cancel job");
|
|
663
730
|
return false;
|
|
@@ -667,12 +734,16 @@ function usePluginJobCenter(options = {}) {
|
|
|
667
734
|
}
|
|
668
735
|
async function deleteJob(job) {
|
|
669
736
|
const sourceDelete = source.value?.deleteJob;
|
|
670
|
-
|
|
737
|
+
const adapterDelete = adapter.value?.deleteJob;
|
|
738
|
+
if (!job.can_delete || !sourceDelete && !adapterDelete || pendingJobIds.value.has(job.job_id)) return false;
|
|
671
739
|
setPending(job.job_id, true);
|
|
672
740
|
error.value = null;
|
|
673
741
|
try {
|
|
674
|
-
const deleted = await sourceDelete(job.job_id);
|
|
675
|
-
|
|
742
|
+
const deleted = sourceDelete ? await sourceDelete(job.job_id) : await adapterDelete(job);
|
|
743
|
+
if (!active) return false;
|
|
744
|
+
if (!sourceDelete) if (deleted === false) await refresh();
|
|
745
|
+
else removeLegacyJobs(new Set([job.job_id]));
|
|
746
|
+
return deleted !== false;
|
|
676
747
|
} catch (cause) {
|
|
677
748
|
if (active) error.value = errorMessage(cause, "Failed to delete job");
|
|
678
749
|
return false;
|
|
@@ -692,12 +763,27 @@ function usePluginJobCenter(options = {}) {
|
|
|
692
763
|
return typeof deleted !== "number" || deleted === targets.length;
|
|
693
764
|
}
|
|
694
765
|
if (currentSource?.deleteJob) return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
|
|
695
|
-
|
|
766
|
+
const currentAdapter = adapter.value;
|
|
767
|
+
if (currentAdapter?.clearFinishedJobs) {
|
|
768
|
+
const deleted = await currentAdapter.clearFinishedJobs(targets);
|
|
769
|
+
if (!active) return false;
|
|
770
|
+
if (typeof deleted === "number" && deleted !== targets.length) {
|
|
771
|
+
await refresh();
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
removeLegacyJobs(new Set(targets.map((job) => job.job_id)));
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
if (!currentAdapter?.deleteJob) return false;
|
|
778
|
+
return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
|
|
696
779
|
} catch (cause) {
|
|
697
780
|
if (active) error.value = errorMessage(cause, "Failed to clear jobs");
|
|
698
781
|
return false;
|
|
699
782
|
}
|
|
700
783
|
}
|
|
784
|
+
if (options.eventStream !== void 0) watch(() => toValue(options.eventStream)?.lastMessage.value ?? null, (message) => {
|
|
785
|
+
if (message) applyStreamMessage(message);
|
|
786
|
+
}, { immediate: true });
|
|
701
787
|
onMounted(() => {
|
|
702
788
|
if (options.loadOnMount !== false) refresh();
|
|
703
789
|
});
|
|
@@ -730,12 +816,17 @@ function usePluginJobCenter(options = {}) {
|
|
|
730
816
|
isOpen.value = !isOpen.value;
|
|
731
817
|
},
|
|
732
818
|
refresh,
|
|
819
|
+
applyStreamMessage,
|
|
733
820
|
cancelJob,
|
|
734
821
|
deleteJob,
|
|
735
822
|
clearFinished,
|
|
736
823
|
isPending: (job) => pendingJobIds.value.has(job.job_id)
|
|
737
824
|
};
|
|
738
825
|
}
|
|
826
|
+
/** @deprecated Use `usePluginJobCenter()` for the plugin job-center controller. */
|
|
827
|
+
function useJobsStatusTray(options = {}) {
|
|
828
|
+
return usePluginJobCenter(options);
|
|
829
|
+
}
|
|
739
830
|
//#endregion
|
|
740
831
|
//#region src/composables/useDoseCalculator.ts
|
|
741
832
|
var VOLUME_UNITS = [
|
|
@@ -5053,6 +5144,6 @@ function useProtocolTemplates() {
|
|
|
5053
5144
|
};
|
|
5054
5145
|
}
|
|
5055
5146
|
//#endregion
|
|
5056
|
-
export {
|
|
5147
|
+
export { useToast as $, useFileImport as A, useDoseCalculator as B, getSampleGroupParentPath as C, detectDelimiter as D, hslToHex as E, extractSampleNamesFromDesignData as F, useMobileSupportGate as G, useJobsStatusTray as H, extractSampleOptionsFromDesignData as I, getInjectedFrontendRevision as J, APP_EXPERIMENT_KEY as K, unwrapExperimentDesignData as L, extractSamplesFromDesignData as M, useAutoGroup as N, parseDelimitedText as O, parseCSV as P, useTheme as Q, DEFAULT_COLORS as R, getSampleGroupMajorPrefix as S, hexToHsl as T, usePluginJobCenter as U, combinePluginJobSources as V, DEFAULT_MOBILE_VIEWPORT_QUERY as W, getPresenceClientId as X, useRuntimeAlignment as Y, usePresenceHeartbeat as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, candidateMatchesSearch as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useSortedItems as it, validateImportFile as j, readFileAsText as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, useTextSearch as nt, useGroupAssignment as o, useBioTemplateComponents as p, useAppExperiment as q, DEFAULT_UNITS as r, compareSortValues as rt, useRackEditor as s, useProtocolTemplates as t, normalizeSearchQuery as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, deriveShade as w, useSampleGroups as x, useExperimentData as y, useWellPlateEditor as z };
|
|
5057
5148
|
|
|
5058
|
-
//# sourceMappingURL=useProtocolTemplates-
|
|
5149
|
+
//# sourceMappingURL=useProtocolTemplates-BWhQIWV5.js.map
|