@morscherlab/mint-sdk 1.2.0-beta.9 → 1.2.1
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 +30 -0
- package/dist/{ExperimentPopover-oL0fg_A0.js → ExperimentPopover-CJdNlCZb.js} +21 -14
- package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
- package/dist/{ExperimentSelectorModal-BeEOomw_.js → ExperimentSelectorModal-DHE9k8TP.js} +5 -5
- package/dist/{ExperimentSelectorModal-BeEOomw_.js.map → ExperimentSelectorModal-DHE9k8TP.js.map} +1 -1
- package/dist/{SettingsModal-Dphh3RrI.js → SettingsModal-DOcCf0Vo.js} +41 -18
- package/dist/SettingsModal-DOcCf0Vo.js.map +1 -0
- package/dist/{Skeleton-DxtwJ5gt.js → Skeleton-jhF9wUkU.js} +19 -9
- package/dist/Skeleton-jhF9wUkU.js.map +1 -0
- package/dist/__tests__/apiErrors.test.d.ts +1 -0
- package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
- package/dist/__tests__/components/FormField.test.d.ts +1 -0
- package/dist/__tests__/components/NumberInput.test.d.ts +1 -0
- package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
- package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
- package/dist/__tests__/composables/localFiles.test.d.ts +1 -0
- package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
- package/dist/__tests__/composables/usePickerSelection.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
- package/dist/__tests__/styles/tokenOnlyColors.test.d.ts +1 -0
- package/dist/apiErrors.d.ts +26 -0
- package/dist/components/AppSidebar.vue.d.ts +7 -7
- package/dist/components/BaseInput.vue.d.ts +1 -1
- package/dist/components/BasePill.vue.d.ts +3 -0
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseTabs.vue.d.ts +1 -4
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +1 -1
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +1 -1
- package/dist/components/FileBrowserModal.vue.d.ts +99 -0
- package/dist/components/FilePicker.vue.d.ts +32 -0
- package/dist/components/FileUploader.vue.d.ts +8 -2
- package/dist/components/FormField.vue.d.ts +8 -1
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
- package/dist/components/MobileSupportGate.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlotlyChart.vue.d.ts +59 -0
- package/dist/components/PluginWorkspaceView.props.d.ts +3 -3
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SecretInput.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/TimePicker.vue.d.ts +1 -1
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.vue.d.ts +1 -1
- package/dist/components/fileBrowserPresentation.d.ts +10 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
- package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
- package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
- package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
- package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
- package/dist/{components-CgAUzF8F.js → components-Cp8DcNrU.js} +4363 -1730
- package/dist/components-Cp8DcNrU.js.map +1 -0
- package/dist/composables/filePicker/localFiles.d.ts +3 -0
- package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
- package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
- package/dist/composables/filePicker/validation.d.ts +5 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +0 -3
- package/dist/composables/useApi.d.ts +14 -7
- package/dist/composables/useFileBrowser.d.ts +55 -0
- package/dist/composables/useFilePicker.d.ts +189 -0
- package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
- package/dist/composables/useToast.d.ts +22 -1
- package/dist/{composables-B_pia3hO.js → composables-D_4qqOlp.js} +300 -11
- package/dist/composables-D_4qqOlp.js.map +1 -0
- package/dist/{errors-_W0-LbA6.js → errors-BLuqMee5.js} +78 -15
- package/dist/errors-BLuqMee5.js.map +1 -0
- package/dist/{experiment-Cwl9AYxw.js → experiment-CVDRAnqp.js} +2 -2
- package/dist/{experiment-Cwl9AYxw.js.map → experiment-CVDRAnqp.js.map} +1 -1
- package/dist/{experiment-utils-DV3DrvE_.js → experiment-utils-CV2Wza3z.js} +1 -1
- package/dist/{experiment-utils-DV3DrvE_.js.map → experiment-utils-CV2Wza3z.js.map} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -2
- package/dist/stores/index.js +2 -2
- package/dist/styles.css +2957 -1708
- package/dist/templates/index.js +2 -2
- package/dist/{templates-Qq113pyZ.js → templates-Dd9bBSs6.js} +2 -2
- package/dist/{templates-Qq113pyZ.js.map → templates-Dd9bBSs6.js.map} +1 -1
- package/dist/types/components.d.ts +21 -0
- package/dist/types/fileBrowserTypes.d.ts +77 -0
- package/dist/types/filePicker.d.ts +77 -0
- package/dist/types/form-builder.d.ts +2 -0
- package/dist/types/generated-ui.d.ts +2 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/{useControlSchema-aMZlb4Sc.js → useControlSchema-BB2GRPhW.js} +190 -105
- package/dist/useControlSchema-BB2GRPhW.js.map +1 -0
- package/dist/{useDropdownState-DitCtrTT.js → useDropdownState-C7hRiVQf.js} +2 -2
- package/dist/{useDropdownState-DitCtrTT.js.map → useDropdownState-C7hRiVQf.js.map} +1 -1
- package/dist/{useExperimentSelector-I8HC8hUu.js → useExperimentSelector-G_CAOFTX.js} +4 -4
- package/dist/{useExperimentSelector-I8HC8hUu.js.map → useExperimentSelector-G_CAOFTX.js.map} +1 -1
- package/dist/{useFormBuilder-TCxNnqeb.js → useFormBuilder-BnGSdSRG.js} +2 -2
- package/dist/{useFormBuilder-TCxNnqeb.js.map → useFormBuilder-BnGSdSRG.js.map} +1 -1
- package/dist/{useProtocolTemplates-BmX_iVBR.js → validation-CTxuzLIX.js} +70 -13
- package/dist/validation-CTxuzLIX.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/apiErrors.test.ts +81 -0
- package/src/__tests__/components/AppSidebar.test.ts +84 -94
- package/src/__tests__/components/AppToastContainer.test.ts +55 -1
- package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +0 -21
- package/src/__tests__/components/ControlWorkspaceView.test.ts +0 -2
- package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +0 -2
- package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
- package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
- package/src/__tests__/components/FilePicker.state.test.ts +287 -0
- package/src/__tests__/components/FilePicker.test.ts +487 -0
- package/src/__tests__/components/FormBuilder.test.ts +26 -0
- package/src/__tests__/components/FormField.test.ts +26 -0
- package/src/__tests__/components/GeneratedPathInput.test.ts +18 -0
- package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
- package/src/__tests__/components/NumberInput.test.ts +105 -0
- package/src/__tests__/components/PlotlyChart.test.ts +305 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +1 -2
- package/src/__tests__/components/PluginWorkspaceView.test.ts +1 -2
- package/src/__tests__/components/SegmentedControl.test.ts +19 -0
- package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
- package/src/__tests__/composables/localFiles.test.ts +57 -0
- package/src/__tests__/composables/useApi.test.ts +92 -9
- package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
- package/src/__tests__/composables/usePickerSelection.test.ts +98 -0
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
- package/src/__tests__/composables/usePluginClient.test.ts +3 -0
- package/src/__tests__/generatedUi.test.ts +111 -0
- package/src/__tests__/styles/tokenOnlyColors.test.ts +16 -0
- package/src/apiErrors.ts +85 -0
- package/src/components/AppLayout.story.vue +1 -1
- package/src/components/AppSidebar.story.vue +7 -10
- package/src/components/AppSidebar.vue +178 -58
- package/src/components/AppToastContainer.vue +65 -23
- package/src/components/BasePill.story.vue +2 -0
- package/src/components/BasePill.vue +4 -0
- package/src/components/BaseTabs.story.vue +0 -42
- package/src/components/BaseTabs.vue +3 -6
- package/src/components/ExperimentPopover.vue +10 -2
- package/src/components/FileBrowserModal.story.vue +203 -0
- package/src/components/FileBrowserModal.vue +384 -0
- package/src/components/FilePicker.story.vue +44 -0
- package/src/components/FilePicker.vue +284 -0
- package/src/components/FileUploader.vue +42 -15
- package/src/components/FormField.vue +10 -3
- package/src/components/GeneratedPathInput.vue +11 -7
- package/src/components/GeneratedPlotlyResult.vue +34 -69
- package/src/components/GeneratedResultRenderer.vue +0 -5
- package/src/components/NumberInput.story.vue +32 -13
- package/src/components/NumberInput.vue +116 -55
- package/src/components/PlotlyChart.story.vue +61 -0
- package/src/components/PlotlyChart.vue +233 -0
- package/src/components/PluginWorkspaceView.props.ts +3 -3
- package/src/components/SegmentedControl.vue +2 -2
- package/src/components/fileBrowserPresentation.ts +39 -0
- package/src/components/index.ts +5 -0
- package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
- package/src/components/internal/FileBrowserListingInternal.vue +197 -0
- package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
- package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
- package/src/components/internal/FilePickerTreeInternal.vue +238 -0
- package/src/components/internal/FormFieldRendererInternal.vue +17 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +1 -2
- package/src/composables/filePicker/localFiles.ts +65 -0
- package/src/composables/filePicker/usePickerNavigation.ts +220 -0
- package/src/composables/filePicker/usePickerSelection.ts +270 -0
- package/src/composables/filePicker/validation.ts +41 -0
- package/src/composables/index.ts +7 -0
- package/src/composables/pluginWorkspaceModel.ts +0 -3
- package/src/composables/useApi.ts +57 -13
- package/src/composables/useFileBrowser.ts +314 -0
- package/src/composables/useFilePicker.ts +366 -0
- package/src/composables/useGeneratedAnalysis.ts +10 -17
- package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
- package/src/composables/usePluginClient.ts +3 -0
- package/src/composables/usePluginWorkspace.ts +1 -2
- package/src/composables/useToast.ts +21 -5
- package/src/generated/schema.ts +58 -18
- package/src/index.ts +3 -0
- package/src/styles/components/app-sidebar.css +282 -121
- package/src/styles/components/file-browser-modal.css +489 -0
- package/src/styles/components/file-picker.css +502 -0
- package/src/styles/components/form-builder.css +1 -1
- package/src/styles/components/form-field.css +28 -0
- package/src/styles/components/icon-button.css +9 -0
- package/src/styles/components/number-input.css +73 -91
- package/src/styles/components/pill.css +49 -51
- package/src/styles/components/segmented-control.css +16 -11
- package/src/styles/components/tabs.css +18 -34
- package/src/styles/components/toast.css +136 -27
- package/src/styles/index.css +3 -0
- package/src/styles/variables.css +25 -5
- package/src/types/components.ts +23 -0
- package/src/types/fileBrowserTypes.ts +85 -0
- package/src/types/filePicker.ts +72 -0
- package/src/types/form-builder.ts +2 -0
- package/src/types/generated-ui.ts +2 -0
- package/src/types/index.ts +16 -0
- package/dist/ExperimentPopover-oL0fg_A0.js.map +0 -1
- package/dist/SettingsModal-Dphh3RrI.js.map +0 -1
- package/dist/Skeleton-DxtwJ5gt.js.map +0 -1
- package/dist/components-CgAUzF8F.js.map +0 -1
- package/dist/composables-B_pia3hO.js.map +0 -1
- package/dist/errors-_W0-LbA6.js.map +0 -1
- package/dist/useControlSchema-aMZlb4Sc.js.map +0 -1
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { a as useAuthStore, d as useSettingsStore, i as useApi, n as AuthenticationRequiredError, r as authenticationRequiredError, t as readErrorMessage } from "./errors-BLuqMee5.js";
|
|
2
|
+
import { n as useRequestSyncState } from "./Skeleton-jhF9wUkU.js";
|
|
3
|
+
import { B as currentExperimentFromContext, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, et as useEventStream, lt as PLUGIN_SECRET_FORMAT_KEY } from "./useControlSchema-BB2GRPhW.js";
|
|
4
|
+
import { n as pickerFormat } from "./validation-CTxuzLIX.js";
|
|
5
|
+
import { i as usePlatformContext } from "./useFormBuilder-BnGSdSRG.js";
|
|
6
|
+
import { bn as rowLabel, pn as PLATE_CONFIGS, yn as rowIndex } from "./templates-Dd9bBSs6.js";
|
|
7
|
+
import { computed, getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, onUnmounted, ref, shallowRef, toValue, watch } from "vue";
|
|
7
8
|
import axios from "axios";
|
|
8
9
|
//#region src/composables/useAuth.ts
|
|
9
10
|
var TOKEN_REFRESH_MARGIN_MS = 300 * 1e3;
|
|
@@ -749,6 +750,212 @@ function usePluginConfig(pluginName) {
|
|
|
749
750
|
};
|
|
750
751
|
}
|
|
751
752
|
//#endregion
|
|
753
|
+
//#region src/composables/useFileBrowser.ts
|
|
754
|
+
/**
|
|
755
|
+
* Drives FileBrowserModal against the platform's `/api/filesystem` routes.
|
|
756
|
+
*
|
|
757
|
+
* Requires the `filesystem.browse` permission and a deployment that declares
|
|
758
|
+
* mounts; with none configured the routes are absent and `mounts` stays empty.
|
|
759
|
+
*/
|
|
760
|
+
function useFileBrowser(options = {}) {
|
|
761
|
+
const injectedContext = getInjectedPlatformContext();
|
|
762
|
+
const api = useApi({ baseUrl: options.apiBaseUrl ?? injectedContext?.platformApiUrl });
|
|
763
|
+
const sync = useRequestSyncState("Could not read the server mounts.");
|
|
764
|
+
const mounts = ref([]);
|
|
765
|
+
const mountId = shallowRef("");
|
|
766
|
+
const path = shallowRef("");
|
|
767
|
+
const parent = ref(null);
|
|
768
|
+
const entries = ref([]);
|
|
769
|
+
const breadcrumbs = ref([]);
|
|
770
|
+
const totalCount = ref(null);
|
|
771
|
+
const matchCount = ref(null);
|
|
772
|
+
const shownCount = ref(null);
|
|
773
|
+
const truncated = ref(false);
|
|
774
|
+
const search = shallowRef("");
|
|
775
|
+
const sort = shallowRef("name");
|
|
776
|
+
const selected = ref([]);
|
|
777
|
+
const mountsLoading = shallowRef(false);
|
|
778
|
+
const listingLoading = shallowRef(false);
|
|
779
|
+
const listingReady = shallowRef(false);
|
|
780
|
+
const isLoading = computed(() => mountsLoading.value || listingLoading.value);
|
|
781
|
+
let listToken = 0;
|
|
782
|
+
let mountsToken = 0;
|
|
783
|
+
let disposed = false;
|
|
784
|
+
let listingController;
|
|
785
|
+
let mountsController;
|
|
786
|
+
let searchTimer;
|
|
787
|
+
function resetListing() {
|
|
788
|
+
listingReady.value = false;
|
|
789
|
+
entries.value = [];
|
|
790
|
+
breadcrumbs.value = [];
|
|
791
|
+
parent.value = null;
|
|
792
|
+
totalCount.value = null;
|
|
793
|
+
matchCount.value = null;
|
|
794
|
+
shownCount.value = null;
|
|
795
|
+
truncated.value = false;
|
|
796
|
+
}
|
|
797
|
+
function typeRuleParams() {
|
|
798
|
+
return (toValue(options.typeRules) ?? []).map((rule) => `&type_rules=${encodeURIComponent(rule)}`).join("");
|
|
799
|
+
}
|
|
800
|
+
/** Prefer the API's own `detail` over axios's "Request failed with status N". */
|
|
801
|
+
function describe(cause, fallback) {
|
|
802
|
+
const detail = cause?.response?.data?.detail;
|
|
803
|
+
return typeof detail === "string" && detail ? detail : sync.readErrorMessage(cause, fallback);
|
|
804
|
+
}
|
|
805
|
+
function fail(cause, fallback) {
|
|
806
|
+
sync.setError(new Error(describe(cause, fallback)), fallback);
|
|
807
|
+
}
|
|
808
|
+
function statusOf(cause) {
|
|
809
|
+
return cause?.response?.status;
|
|
810
|
+
}
|
|
811
|
+
async function loadMounts() {
|
|
812
|
+
const token = ++mountsToken;
|
|
813
|
+
mountsController?.abort();
|
|
814
|
+
mountsController = new AbortController();
|
|
815
|
+
mountsLoading.value = true;
|
|
816
|
+
try {
|
|
817
|
+
const data = await api.get("/filesystem/mounts", { signal: mountsController.signal });
|
|
818
|
+
if (disposed || token !== mountsToken) return false;
|
|
819
|
+
mounts.value = data.mounts ?? [];
|
|
820
|
+
sync.clearError();
|
|
821
|
+
sync.markLoaded();
|
|
822
|
+
return true;
|
|
823
|
+
} catch (cause) {
|
|
824
|
+
if (disposed || token !== mountsToken) return false;
|
|
825
|
+
if (statusOf(cause) === 404) {
|
|
826
|
+
mounts.value = [];
|
|
827
|
+
sync.clearError();
|
|
828
|
+
sync.markLoaded();
|
|
829
|
+
return true;
|
|
830
|
+
}
|
|
831
|
+
mounts.value = [];
|
|
832
|
+
fail(cause, "Could not read the server mounts.");
|
|
833
|
+
return false;
|
|
834
|
+
} finally {
|
|
835
|
+
if (token === mountsToken) mountsLoading.value = false;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
async function navigate(location) {
|
|
839
|
+
if (disposed || !location.mount_id) return;
|
|
840
|
+
clearTimeout(searchTimer);
|
|
841
|
+
const token = ++listToken;
|
|
842
|
+
listingController?.abort();
|
|
843
|
+
listingController = new AbortController();
|
|
844
|
+
listingLoading.value = true;
|
|
845
|
+
mountId.value = location.mount_id;
|
|
846
|
+
path.value = location.path;
|
|
847
|
+
resetListing();
|
|
848
|
+
sync.clearError();
|
|
849
|
+
try {
|
|
850
|
+
const query = `mount_id=${encodeURIComponent(location.mount_id)}&path=${encodeURIComponent(location.path)}&sort=${sort.value}` + (search.value ? `&search=${encodeURIComponent(search.value)}` : "") + typeRuleParams();
|
|
851
|
+
const listing = await api.get(`/filesystem/browse?${query}`, { signal: listingController.signal });
|
|
852
|
+
if (disposed || token !== listToken) return;
|
|
853
|
+
mountId.value = listing.mount_id;
|
|
854
|
+
path.value = listing.path;
|
|
855
|
+
parent.value = listing.parent ?? null;
|
|
856
|
+
entries.value = listing.entries ?? [];
|
|
857
|
+
breadcrumbs.value = listing.breadcrumbs ?? [];
|
|
858
|
+
totalCount.value = listing.total_count ?? null;
|
|
859
|
+
matchCount.value = listing.match_count ?? null;
|
|
860
|
+
shownCount.value = listing.shown_count ?? listing.entries?.length ?? null;
|
|
861
|
+
truncated.value = listing.truncated ?? false;
|
|
862
|
+
listingReady.value = true;
|
|
863
|
+
sync.clearError();
|
|
864
|
+
sync.markLoaded();
|
|
865
|
+
} catch (cause) {
|
|
866
|
+
if (disposed || token !== listToken) return;
|
|
867
|
+
entries.value = [];
|
|
868
|
+
fail(cause, "Could not read that folder.");
|
|
869
|
+
} finally {
|
|
870
|
+
if (token === listToken) listingLoading.value = false;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
async function init() {
|
|
874
|
+
if (disposed) return;
|
|
875
|
+
const navigationToken = listToken;
|
|
876
|
+
if (!await loadMounts() || disposed || navigationToken !== listToken) return;
|
|
877
|
+
const preferred = toValue(options.initialMountId);
|
|
878
|
+
const reachable = (mount) => mount.available !== false;
|
|
879
|
+
const target = mounts.value.find((mount) => mount.id === preferred && reachable(mount)) ?? mounts.value.find(reachable);
|
|
880
|
+
if (target) await navigate({
|
|
881
|
+
mount_id: target.id,
|
|
882
|
+
path: ""
|
|
883
|
+
});
|
|
884
|
+
else {
|
|
885
|
+
mountId.value = "";
|
|
886
|
+
path.value = "";
|
|
887
|
+
resetListing();
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
async function refresh() {
|
|
891
|
+
if (disposed) return;
|
|
892
|
+
if (mountId.value) await navigate({
|
|
893
|
+
mount_id: mountId.value,
|
|
894
|
+
path: path.value
|
|
895
|
+
});
|
|
896
|
+
else await init();
|
|
897
|
+
}
|
|
898
|
+
function selectCurrentFolder() {
|
|
899
|
+
if (!mountId.value || !listingReady.value || isLoading.value || sync.error.value) return;
|
|
900
|
+
const crumb = breadcrumbs.value[breadcrumbs.value.length - 1];
|
|
901
|
+
const key = JSON.stringify([mountId.value, path.value]);
|
|
902
|
+
if (selected.value.some((item) => JSON.stringify([item.mount_id, item.path]) === key)) return;
|
|
903
|
+
selected.value = [...selected.value, {
|
|
904
|
+
mount_id: mountId.value,
|
|
905
|
+
path: path.value,
|
|
906
|
+
name: crumb?.label ?? path.value,
|
|
907
|
+
kind: "directory",
|
|
908
|
+
child_count: totalCount.value
|
|
909
|
+
}];
|
|
910
|
+
}
|
|
911
|
+
function clear() {
|
|
912
|
+
selected.value = [];
|
|
913
|
+
}
|
|
914
|
+
watch(search, () => {
|
|
915
|
+
if (!mountId.value) return;
|
|
916
|
+
clearTimeout(searchTimer);
|
|
917
|
+
searchTimer = setTimeout(() => {
|
|
918
|
+
refresh();
|
|
919
|
+
}, 250);
|
|
920
|
+
});
|
|
921
|
+
watch(sort, () => {
|
|
922
|
+
if (mountId.value) refresh();
|
|
923
|
+
});
|
|
924
|
+
watch(() => toValue(options.typeRules), () => {
|
|
925
|
+
if (mountId.value) refresh();
|
|
926
|
+
}, { deep: true });
|
|
927
|
+
if (getCurrentScope()) onScopeDispose(() => {
|
|
928
|
+
disposed = true;
|
|
929
|
+
++listToken;
|
|
930
|
+
++mountsToken;
|
|
931
|
+
clearTimeout(searchTimer);
|
|
932
|
+
listingController?.abort();
|
|
933
|
+
mountsController?.abort();
|
|
934
|
+
});
|
|
935
|
+
return {
|
|
936
|
+
mounts,
|
|
937
|
+
mountId,
|
|
938
|
+
path,
|
|
939
|
+
parent,
|
|
940
|
+
entries,
|
|
941
|
+
breadcrumbs,
|
|
942
|
+
totalCount,
|
|
943
|
+
matchCount,
|
|
944
|
+
shownCount,
|
|
945
|
+
truncated,
|
|
946
|
+
search,
|
|
947
|
+
sort,
|
|
948
|
+
selected,
|
|
949
|
+
isLoading,
|
|
950
|
+
error: sync.error,
|
|
951
|
+
init,
|
|
952
|
+
navigate,
|
|
953
|
+
refresh,
|
|
954
|
+
selectCurrentFolder,
|
|
955
|
+
clear
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
//#endregion
|
|
752
959
|
//#region src/composables/analysisArtifactTarget.ts
|
|
753
960
|
var EXPERIMENT_ID = "experiment_id";
|
|
754
961
|
var ARTIFACT_PLUGIN_ID = "artifact_plugin_id";
|
|
@@ -1522,7 +1729,8 @@ function createPluginClient(contract, options) {
|
|
|
1522
1729
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1523
1730
|
const api = useApi({
|
|
1524
1731
|
baseUrl: parts.baseUrl,
|
|
1525
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1732
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1733
|
+
typedErrors: true
|
|
1526
1734
|
});
|
|
1527
1735
|
const config = endpointRequestConfig(endpoint, parts.query, callOptions);
|
|
1528
1736
|
if (endpoint.method === "get") return api.get(parts.path, config);
|
|
@@ -1553,7 +1761,8 @@ async function uploadPluginEndpoint(contract, endpoint, payload, options = {}) {
|
|
|
1553
1761
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1554
1762
|
const api = useApi({
|
|
1555
1763
|
baseUrl: parts.baseUrl,
|
|
1556
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1764
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1765
|
+
typedErrors: true
|
|
1557
1766
|
});
|
|
1558
1767
|
const body = endpoint.hasBody ? requestBodyFromPayload(payload, parts.requestPayload, endpoint) : payload;
|
|
1559
1768
|
if (endpoint.requestContentType === OCTET_STREAM) {
|
|
@@ -1578,7 +1787,8 @@ async function downloadPluginEndpoint(contract, endpoint, payload, options = {})
|
|
|
1578
1787
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1579
1788
|
const api = useApi({
|
|
1580
1789
|
baseUrl: parts.baseUrl,
|
|
1581
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1790
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1791
|
+
typedErrors: true
|
|
1582
1792
|
});
|
|
1583
1793
|
const config = {
|
|
1584
1794
|
...endpointRequestConfig(endpoint, parts.query, { signal: options.signal }) ?? {},
|
|
@@ -1890,6 +2100,85 @@ function useCurrentExperiment(options = {}) {
|
|
|
1890
2100
|
};
|
|
1891
2101
|
}
|
|
1892
2102
|
//#endregion
|
|
1893
|
-
|
|
2103
|
+
//#region src/composables/usePlatformFilePickerAdapter.ts
|
|
2104
|
+
/** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
|
|
2105
|
+
function encodePlatformPickerPath(mountId, path = "") {
|
|
2106
|
+
return JSON.stringify([mountId, path]);
|
|
2107
|
+
}
|
|
2108
|
+
function decodePlatformPickerPath(path) {
|
|
2109
|
+
const decoded = JSON.parse(path);
|
|
2110
|
+
if (!Array.isArray(decoded) || decoded.length !== 2 || !decoded.every((item) => typeof item === "string") || !decoded[0]) throw new Error("Invalid platform picker path.");
|
|
2111
|
+
return {
|
|
2112
|
+
mountId: decoded[0],
|
|
2113
|
+
path: decoded[1]
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
/** Adapt the authenticated MINT mount API without exposing absolute host paths. */
|
|
2117
|
+
function usePlatformFilePickerAdapter(options = {}) {
|
|
2118
|
+
const api = useApi({ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl });
|
|
2119
|
+
const mountLabels = /* @__PURE__ */ new Map();
|
|
2120
|
+
async function listRoot(request) {
|
|
2121
|
+
try {
|
|
2122
|
+
const { mounts } = await api.get("/filesystem/mounts", { signal: request?.signal });
|
|
2123
|
+
return mounts.map((mount) => {
|
|
2124
|
+
mountLabels.set(mount.id, mount.label);
|
|
2125
|
+
return {
|
|
2126
|
+
kind: "folder",
|
|
2127
|
+
path: encodePlatformPickerPath(mount.id),
|
|
2128
|
+
name: mount.label,
|
|
2129
|
+
parentPath: null,
|
|
2130
|
+
parentName: "Server mounts",
|
|
2131
|
+
unavailableReason: mount.available === false ? "This mount is offline." : void 0
|
|
2132
|
+
};
|
|
2133
|
+
});
|
|
2134
|
+
} catch (cause) {
|
|
2135
|
+
if (cause.response?.status === 404) return [];
|
|
2136
|
+
throw cause;
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
async function listChildren(path, request) {
|
|
2140
|
+
const location = decodePlatformPickerPath(path);
|
|
2141
|
+
const query = new URLSearchParams({
|
|
2142
|
+
mount_id: location.mountId,
|
|
2143
|
+
path: location.path
|
|
2144
|
+
});
|
|
2145
|
+
const listing = await api.get(`/filesystem/browse?${query}`, { signal: request?.signal });
|
|
2146
|
+
if (listing.truncated) throw new Error("This directory exceeds the server listing limit. Choose a smaller data directory.");
|
|
2147
|
+
return (listing.entries ?? []).map((entry) => ({
|
|
2148
|
+
kind: entry.kind === "directory" ? "folder" : "file",
|
|
2149
|
+
path: encodePlatformPickerPath(location.mountId, entry.path),
|
|
2150
|
+
parentPath: path,
|
|
2151
|
+
parentName: `${mountLabels.get(location.mountId) ?? location.mountId}${location.path ? ` / ${location.path}` : ""}`,
|
|
2152
|
+
name: entry.name,
|
|
2153
|
+
bytes: entry.size_bytes,
|
|
2154
|
+
...entry.kind === "directory" ? { hasChildren: entry.child_count !== 0 } : { format: pickerFormat(entry.name) }
|
|
2155
|
+
}));
|
|
2156
|
+
}
|
|
2157
|
+
return {
|
|
2158
|
+
listRoot,
|
|
2159
|
+
listChildren,
|
|
2160
|
+
async search(query, scope, request) {
|
|
2161
|
+
const matches = [];
|
|
2162
|
+
const queue = [scope.path];
|
|
2163
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2164
|
+
while (queue.length) {
|
|
2165
|
+
request?.signal?.throwIfAborted();
|
|
2166
|
+
const path = queue.shift();
|
|
2167
|
+
if (visited.has(path)) continue;
|
|
2168
|
+
visited.add(path);
|
|
2169
|
+
if (visited.size > 500) throw new Error("Search reached its folder limit. Search a smaller location or turn off Subfolders.");
|
|
2170
|
+
const nodes = path ? await listChildren(path, request) : await listRoot(request);
|
|
2171
|
+
for (const node of nodes) {
|
|
2172
|
+
if (node.name.toLowerCase().includes(query.toLowerCase())) matches.push(node);
|
|
2173
|
+
if (scope.recursive && node.kind === "folder" && !node.unavailableReason) queue.push(node.path);
|
|
2174
|
+
}
|
|
2175
|
+
if (matches.length > 1e4) throw new Error("Too many search results. Use a more specific search.");
|
|
2176
|
+
}
|
|
2177
|
+
return matches;
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
//#endregion
|
|
2182
|
+
export { buildAnalysisArtifactTargetQuery as A, useWellPainting as C, useResourceCrud as D, createPluginResourceClient as E, useAsyncBatch as F, resolvePluginFrontendBase as I, usePasskey as L, useFileBrowser as M, usePluginConfig as N, useOptimisticMutation as O, useAsync as P, useAuth as R, coordinateToWellId as S, wellIdsInRectangle as T, useWellPlateValidation as _, downloadBlob as a, createWellPlateWells as b, pluginFormDataFromPayload as c, usePluginClient as d, usePluginEventStream as f, runWellPlateValidation as g, resolvePluginBaseUrl as h, createPluginClient as i, parseAnalysisArtifactTarget as j, useCommandHistory as k, uploadPluginEndpoint as l, buildPluginEndpointUrl as m, encodePlatformPickerPath as n, downloadPluginEndpoint as o, usePluginSettings as p, usePlatformFilePickerAdapter as r, getPluginPageSelectorItems as s, decodePlatformPickerPath as t, useCurrentExperiment as u, createColumnConditions as v, wellIdToCoordinate as w, useWellPlateAdapter as x, createRowConditions as y };
|
|
1894
2183
|
|
|
1895
|
-
//# sourceMappingURL=composables-
|
|
2184
|
+
//# sourceMappingURL=composables-D_4qqOlp.js.map
|