@morscherlab/mint-sdk 1.2.0-beta.2 → 1.2.0-beta.20
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 +65 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-CJdNlCZb.js} +24 -15
- package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
- package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-BYR20I4c.js} +5 -8
- package/dist/SettingsModal-BYR20I4c.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-BAF3CKY7.js} +111 -93
- package/dist/Skeleton-BAF3CKY7.js.map +1 -0
- package/dist/__tests__/components/DataStates.test.d.ts +1 -0
- package/dist/__tests__/components/ExperimentTimeline.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/PlotlyChart.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
- package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
- package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
- package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
- package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/apiErrors.d.ts +26 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BaseInput.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +4 -4
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +1 -1
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +2 -2
- package/dist/components/DateTimePicker.vue.d.ts +3 -1
- package/dist/components/DropdownButton.vue.d.ts +2 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
- package/dist/components/ExperimentPopover.vue.d.ts +1 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +29 -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 +5 -2
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- 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 +29 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
- package/dist/components/ReagentList.vue.d.ts +29 -1
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
- package/dist/components/SampleLegend.vue.d.ts +1 -1
- package/dist/components/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +35 -2
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +28 -0
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -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 +2 -1
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.geometry.d.ts +15 -0
- package/dist/components/WellPlate.interaction.d.ts +13 -0
- package/dist/components/WellPlate.vue.d.ts +30 -1
- package/dist/components/fileBrowserPresentation.d.ts +10 -0
- package/dist/components/index.d.ts +13 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
- package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
- 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/internal/WellEditPopupInternal.vue.d.ts +3 -1
- package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
- package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
- package/dist/{components-DkHddRMl.js → components-DIum5hkx.js} +5882 -3200
- package/dist/components-DIum5hkx.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -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/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +11 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useApi.d.ts +14 -7
- package/dist/composables/useAsync.d.ts +5 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
- package/dist/composables/useCommandHistory.d.ts +5 -1
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +9 -0
- package/dist/composables/useFileBrowser.d.ts +55 -0
- package/dist/composables/useFilePicker.d.ts +189 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
- package/dist/composables/useJobsStatusTray.d.ts +25 -1
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +29 -0
- package/dist/composables/useOptimisticMutation.d.ts +5 -1
- package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
- package/dist/composables/usePluginClient.d.ts +2 -0
- package/dist/composables/usePluginConfig.d.ts +27 -0
- package/dist/composables/usePluginWorkspace.d.ts +51 -0
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useResourceCrud.d.ts +5 -1
- package/dist/composables/useRovingFocus.d.ts +24 -0
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/composables/useWellPainting.d.ts +5 -1
- package/dist/composables/useWellPlateAdapter.d.ts +5 -1
- package/dist/composables/useWellPlateValidation.d.ts +5 -1
- package/dist/composables/workspaceRecipes.d.ts +188 -0
- package/dist/{composables-C_i90sGS.js → composables-mFXsTA4g.js} +502 -86
- package/dist/composables-mFXsTA4g.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-BLuqMee5.js} +179 -16
- package/dist/errors-BLuqMee5.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-CVDRAnqp.js} +3 -8
- package/dist/experiment-CVDRAnqp.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-CV2Wza3z.js} +70 -51
- package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -7
- package/dist/install.js.map +1 -1
- package/dist/permissions.d.ts +42 -1
- package/dist/permissions.js +20 -10
- package/dist/permissions.js.map +1 -1
- package/dist/stores/auth.d.ts +6 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -3
- package/dist/stores/settings.d.ts +31 -1
- package/dist/styles.css +15135 -32397
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-CmGfmBRA.js} +303 -106
- package/dist/templates-CmGfmBRA.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/fileBrowserTypes.d.ts +77 -0
- package/dist/types/filePicker.d.ts +77 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-DldpxNOP.js} +499 -1162
- package/dist/useControlSchema-DldpxNOP.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-C7hRiVQf.js} +22 -6
- package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-CEcIaueJ.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-z5L_dUIy.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/pluginSecrets.d.ts +53 -0
- package/dist/utils/records.d.ts +4 -0
- package/dist/{useProtocolTemplates-CS_SQl6U.js → validation-uwoJGEb6.js} +811 -212
- package/dist/validation-uwoJGEb6.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/apiErrors.test.ts +81 -0
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
- package/src/__tests__/components/BaseTabs.test.ts +67 -0
- package/src/__tests__/components/DataFrame.test.ts +183 -11
- package/src/__tests__/components/DataStates.test.ts +176 -0
- package/src/__tests__/components/DatePicker.test.ts +76 -0
- package/src/__tests__/components/DateTimePicker.test.ts +36 -0
- package/src/__tests__/components/DropdownButton.test.ts +134 -0
- package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -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/GeneratedPlotlyResult.test.ts +52 -5
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PlotlyChart.test.ts +305 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
- package/src/__tests__/components/RackEditor.test.ts +35 -0
- package/src/__tests__/components/ReagentList.test.ts +64 -2
- package/src/__tests__/components/RetiredStyles.test.ts +31 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
- package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
- package/src/__tests__/components/SecretInput.test.ts +87 -0
- package/src/__tests__/components/SegmentedControl.test.ts +107 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
- package/src/__tests__/composables/useApi.test.ts +92 -9
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
- package/src/__tests__/composables/usePluginClient.test.ts +143 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
- package/src/__tests__/stores/settings.test.ts +71 -1
- package/src/__tests__/styles/cssTokens.test.ts +131 -0
- package/src/__tests__/utils/permissions.test.ts +68 -0
- package/src/apiErrors.ts +85 -0
- package/src/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +26 -7
- package/src/components/AppLayout.vue +0 -4
- package/src/components/AppPluginSwitcher.story.vue +87 -0
- package/src/components/AppPluginSwitcher.vue +2 -5
- package/src/components/AppSidebar.vue +0 -4
- package/src/components/AppToastContainer.vue +6 -8
- package/src/components/AppTopBar.vue +0 -4
- package/src/components/ArtifactSaveDialog.vue +0 -4
- package/src/components/ArtifactSelectorModal.vue +0 -4
- package/src/components/AuditTrail.story.vue +18 -0
- package/src/components/AuditTrail.vue +27 -7
- package/src/components/AutoGroupModal.vue +0 -4
- package/src/components/Avatar.vue +0 -4
- package/src/components/BaseButton.vue +0 -4
- package/src/components/BaseCheckbox.vue +0 -4
- package/src/components/BaseInput.vue +0 -4
- package/src/components/BaseModal.vue +8 -60
- package/src/components/BasePill.vue +0 -4
- package/src/components/BaseRadioGroup.vue +0 -4
- package/src/components/BaseSelect.vue +0 -4
- package/src/components/BaseSlider.vue +0 -4
- package/src/components/BaseTabs.vue +26 -5
- package/src/components/BaseTextarea.vue +0 -4
- package/src/components/BaseToggle.vue +0 -4
- package/src/components/BatchProgressList.story.vue +18 -0
- package/src/components/BatchProgressList.vue +32 -4
- package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
- package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
- package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
- package/src/components/Breadcrumb.vue +0 -4
- package/src/components/Calendar.vue +0 -4
- package/src/components/ChartContainer.story.vue +1 -1
- package/src/components/ChartContainer.vue +0 -4
- package/src/components/ChemicalFormula.vue +0 -4
- package/src/components/CollapsibleCard.vue +0 -4
- package/src/components/ColorSlider.vue +0 -4
- package/src/components/ComponentBindingRenderer.vue +1 -3
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/ControlWorkspaceView.vue +11 -22
- package/src/components/DataFrame.story.vue +14 -0
- package/src/components/DataFrame.vue +97 -23
- package/src/components/DatePicker.vue +73 -27
- package/src/components/DateTimePicker.vue +45 -17
- package/src/components/Divider.vue +0 -4
- package/src/components/DoseCalculator.vue +0 -4
- package/src/components/DoseDesignWorkspaceView.vue +6 -25
- package/src/components/DropdownButton.vue +24 -6
- package/src/components/EmptyState.vue +0 -4
- package/src/components/ExperimentCodeBadge.vue +0 -4
- package/src/components/ExperimentDataViewer.story.vue +3 -0
- package/src/components/ExperimentDataViewer.vue +33 -13
- package/src/components/ExperimentPopover.vue +12 -7
- package/src/components/ExperimentSelectorModal.vue +0 -4
- package/src/components/ExperimentTimeline.story.vue +18 -0
- package/src/components/ExperimentTimeline.vue +81 -75
- 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 +32 -18
- package/src/components/FitPanel.vue +0 -4
- package/src/components/FormActions.story.vue +96 -0
- package/src/components/FormActions.vue +0 -4
- package/src/components/FormBuilder.vue +0 -4
- package/src/components/FormField.vue +0 -4
- package/src/components/FormulaInput.vue +0 -4
- package/src/components/GeneratedPathInput.story.vue +68 -0
- package/src/components/GeneratedPlotlyResult.story.vue +96 -0
- package/src/components/GeneratedPlotlyResult.vue +34 -69
- package/src/components/GeneratedPluginView.story.vue +145 -0
- package/src/components/GeneratedPluginView.vue +10 -10
- package/src/components/GeneratedResultRenderer.story.vue +117 -0
- package/src/components/GeneratedResultRenderer.vue +4 -9
- package/src/components/GroupAssigner.vue +67 -5
- package/src/components/IconButton.vue +0 -4
- package/src/components/InstrumentAlertLog.vue +0 -4
- package/src/components/InstrumentStateBadge.vue +0 -4
- package/src/components/InstrumentStatusCard.vue +0 -4
- package/src/components/JobsStatusTray.vue +16 -5
- package/src/components/LcmsSequenceTable.vue +81 -50
- package/src/components/LoadingSpinner.vue +0 -4
- package/src/components/MobileSupportGate.vue +0 -4
- package/src/components/MoleculeInput.vue +0 -4
- package/src/components/MultiSelect.vue +0 -4
- package/src/components/NumberInput.vue +0 -4
- package/src/components/PlateMapEditor.vue +3 -14
- package/src/components/PlotlyChart.story.vue +61 -0
- package/src/components/PlotlyChart.vue +233 -0
- package/src/components/PluginIcon.vue +0 -4
- package/src/components/PluginWorkspaceView.props.ts +38 -0
- package/src/components/PluginWorkspaceView.vue +53 -224
- package/src/components/ProgressBar.vue +0 -4
- package/src/components/ProtocolStepEditor.vue +2 -4
- package/src/components/RackEditor.vue +51 -70
- package/src/components/ReagentEditor.vue +0 -4
- package/src/components/ReagentList.story.vue +18 -0
- package/src/components/ReagentList.vue +127 -82
- package/src/components/ResourceCard.vue +0 -4
- package/src/components/RuntimeUpdateNotice.story.vue +49 -0
- package/src/components/RuntimeUpdateNotice.vue +4 -4
- package/src/components/SampleHierarchyTree.story.vue +18 -0
- package/src/components/SampleHierarchyTree.vue +32 -9
- package/src/components/SampleLegend.vue +2 -8
- package/src/components/SampleSelector.drag.ts +51 -0
- package/src/components/SampleSelector.story.vue +6 -0
- package/src/components/SampleSelector.tree.ts +2 -0
- package/src/components/SampleSelector.vue +49 -10
- package/src/components/SampleSelectorGroupNode.vue +19 -0
- package/src/components/ScheduleCalendar.story.vue +6 -0
- package/src/components/ScheduleCalendar.vue +82 -7
- package/src/components/ScientificNumber.vue +0 -4
- package/src/components/SecretInput.story.vue +79 -0
- package/src/components/SecretInput.vue +150 -0
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +50 -7
- package/src/components/SequenceInput.vue +0 -4
- package/src/components/SequenceProgressBar.story.vue +110 -0
- package/src/components/SequenceProgressBar.vue +0 -4
- package/src/components/SettingsModal.vue +0 -4
- package/src/components/Skeleton.vue +0 -4
- package/src/components/SmartGroupFieldRecipe.vue +8 -6
- package/src/components/SmartGroupManual.vue +0 -4
- package/src/components/StatusIndicator.vue +0 -4
- package/src/components/StepWizard.vue +0 -4
- package/src/components/TagsInput.vue +4 -6
- package/src/components/ThemeToggle.vue +0 -4
- package/src/components/TimePicker.vue +36 -7
- package/src/components/TimeRangeInput.vue +0 -4
- package/src/components/Tooltip.story.vue +3 -3
- package/src/components/Tooltip.vue +0 -4
- package/src/components/UnitInput.vue +0 -4
- package/src/components/WellPlate.geometry.ts +60 -1
- package/src/components/WellPlate.interaction.ts +44 -0
- package/src/components/WellPlate.story.vue +8 -0
- package/src/components/WellPlate.vue +53 -7
- package/src/components/fileBrowserPresentation.ts +39 -0
- package/src/components/index.ts +14 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
- package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
- package/src/components/internal/DataStateInternal.vue +74 -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/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +20 -5
- package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
- package/src/components/internal/WorkspaceShellInternal.vue +125 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/experimentDesignData.ts +1 -3
- package/src/composables/filePicker/localFiles.ts +58 -0
- package/src/composables/filePicker/usePickerNavigation.ts +220 -0
- package/src/composables/filePicker/usePickerSelection.ts +259 -0
- package/src/composables/filePicker/validation.ts +41 -0
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +50 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useApi.ts +57 -13
- package/src/composables/useAsync.ts +5 -1
- package/src/composables/useAuth.ts +3 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
- package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
- package/src/composables/useBioTemplateWorkspace.ts +18 -43
- package/src/composables/useCommandHistory.ts +5 -1
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +14 -2
- package/src/composables/useFileBrowser.ts +314 -0
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFilePicker.ts +366 -0
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +32 -27
- package/src/composables/useJobsStatusTray.ts +184 -17
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +90 -0
- package/src/composables/useOptimisticMutation.ts +6 -16
- package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
- package/src/composables/usePluginClient.ts +50 -4
- package/src/composables/usePluginConfig.ts +252 -0
- package/src/composables/usePluginWorkspace.ts +208 -0
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +6 -16
- package/src/composables/useRovingFocus.ts +66 -0
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +10 -30
- package/src/composables/useWellPlateAdapter.ts +5 -1
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/composables/useWellPlateValidation.ts +5 -1
- package/src/composables/workspaceRecipes.ts +267 -0
- package/src/index.ts +19 -0
- package/src/permissions.ts +48 -9
- package/src/stores/auth.ts +1 -0
- package/src/stores/experiment.ts +2 -7
- package/src/stores/index.ts +9 -1
- package/src/stores/settings.ts +93 -1
- package/src/styles/components/audit-trail.css +5 -5
- package/src/styles/components/batch-progress-list.css +7 -0
- package/src/styles/components/color-slider.css +2 -2
- package/src/styles/components/data-state.css +30 -0
- package/src/styles/components/dataframe.css +29 -35
- package/src/styles/components/experiment-data-viewer.css +4 -4
- package/src/styles/components/experiment-timeline.css +3 -30
- 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 +5 -5
- package/src/styles/components/icon-button.css +9 -0
- package/src/styles/components/lcms-sequence-table.css +16 -1
- package/src/styles/components/multi-select.css +1 -1
- package/src/styles/components/reagent-list.css +38 -31
- package/src/styles/components/sample-hierarchy-tree.css +5 -19
- package/src/styles/components/sample-selector.css +9 -2
- package/src/styles/components/schedule-calendar.css +8 -0
- package/src/styles/components/scientific-number.css +1 -1
- package/src/styles/components/secret-input.css +60 -0
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +12 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/builderReadUtils.ts +1 -3
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/componentTargetResolvers.ts +1 -3
- package/src/templates/controlSchemaTargets.ts +1 -3
- package/src/templates/doseResponseAdapters.ts +2 -13
- package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
- package/src/templates/plateMapBuilder.ts +2 -2
- package/src/templates/qpcrPlateBuilder.ts +1 -1
- package/src/templates/templateValidators.ts +1 -1
- package/src/templates/timeCourseBuilder.ts +2 -2
- package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
- package/src/types/auth.ts +1 -0
- package/src/types/fileBrowserTypes.ts +85 -0
- package/src/types/filePicker.ts +72 -0
- package/src/types/form-builder.ts +1 -0
- package/src/types/index.ts +14 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/src/utils/formModelSync.ts +1 -3
- package/src/utils/pluginIcon.ts +1 -3
- package/src/utils/pluginSecrets.ts +102 -0
- package/src/utils/records.ts +9 -0
- package/dist/EmptyState-p90quq8Z.js.map +0 -1
- package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
- package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
- package/dist/SettingsModal-BgKY93zh.js.map +0 -1
- package/dist/components-DkHddRMl.js.map +0 -1
- package/dist/composables/autoGroupConstants.d.ts +0 -1
- package/dist/composables/autoGroupGrouping.d.ts +0 -3
- package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
- package/dist/composables-C_i90sGS.js.map +0 -1
- package/dist/experiment-Cq145oEW.js.map +0 -1
- package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-DsP51i-S.js.map +0 -1
- package/dist/useApi-J6zFkHmn.js.map +0 -1
- package/dist/useControlSchema-BDx2Olha.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
- package/src/composables/autoGroupConstants.ts +0 -4
- package/src/composables/autoGroupGrouping.ts +0 -148
- package/src/composables/useAutoGroupInputSources.ts +0 -147
- package/src/templates/builderDefaults.ts +0 -11
- package/src/templates/plateGeometry.ts +0 -62
- /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { r as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
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-BAF3CKY7.js";
|
|
3
|
+
import { B as currentExperimentFromContext, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, et as useEventStream, lt as PLUGIN_SECRET_FORMAT_KEY } from "./useControlSchema-DldpxNOP.js";
|
|
4
|
+
import { n as pickerFormat } from "./validation-uwoJGEb6.js";
|
|
5
|
+
import { i as usePlatformContext } from "./useFormBuilder-z5L_dUIy.js";
|
|
6
|
+
import { bn as rowLabel, pn as PLATE_CONFIGS, yn as rowIndex } from "./templates-CmGfmBRA.js";
|
|
7
|
+
import { computed, getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, onUnmounted, ref, shallowRef, toValue, watch } from "vue";
|
|
6
8
|
import axios from "axios";
|
|
7
9
|
//#region src/composables/useAuth.ts
|
|
8
10
|
var TOKEN_REFRESH_MARGIN_MS = 300 * 1e3;
|
|
@@ -26,6 +28,7 @@ function useAuth() {
|
|
|
26
28
|
passkeyEnabled: response.data.passkey_enabled,
|
|
27
29
|
passkeyRegistered: response.data.passkey_registered ?? false,
|
|
28
30
|
registrationEnabled: response.data.registration_enabled ?? false,
|
|
31
|
+
databaseMode: response.data.database_mode ?? "none",
|
|
29
32
|
experimentVisibilityMode: response.data.access?.experiment_visibility_mode ?? response.data.access?.experimentVisibilityMode ?? "open"
|
|
30
33
|
};
|
|
31
34
|
authStore.setAuthConfig(config);
|
|
@@ -37,6 +40,7 @@ function useAuth() {
|
|
|
37
40
|
passkeyEnabled: false,
|
|
38
41
|
passkeyRegistered: false,
|
|
39
42
|
registrationEnabled: false,
|
|
43
|
+
databaseMode: "none",
|
|
40
44
|
experimentVisibilityMode: "open"
|
|
41
45
|
};
|
|
42
46
|
}
|
|
@@ -504,7 +508,11 @@ function defaultTransformError(error) {
|
|
|
504
508
|
* const handleSubmit = () => submit(new FormData(formRef.value))
|
|
505
509
|
* ```
|
|
506
510
|
*/
|
|
507
|
-
/**
|
|
511
|
+
/**
|
|
512
|
+
* Wraps an async function with reactive loading, error, and success state plus optional auto-execute.
|
|
513
|
+
*
|
|
514
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.
|
|
515
|
+
*/
|
|
508
516
|
function useAsync(asyncFn, options = {}) {
|
|
509
517
|
const { initialData = null, immediate = false, immediateArgs = [], transformError = defaultTransformError, onSuccess, onError, resetOnExecute = false } = options;
|
|
510
518
|
const data = ref(initialData);
|
|
@@ -611,6 +619,343 @@ function useAsyncBatch(asyncFns) {
|
|
|
611
619
|
};
|
|
612
620
|
}
|
|
613
621
|
//#endregion
|
|
622
|
+
//#region src/composables/usePluginConfig.ts
|
|
623
|
+
var PLATFORM_OWNED_SETTINGS_KEY$1 = "allowed_experiment_types";
|
|
624
|
+
function cloneConfig(config) {
|
|
625
|
+
return JSON.parse(JSON.stringify(config));
|
|
626
|
+
}
|
|
627
|
+
function hasOwnConfig(config, key) {
|
|
628
|
+
return Object.prototype.hasOwnProperty.call(config, key);
|
|
629
|
+
}
|
|
630
|
+
function changedTopLevelKeys(current, saved) {
|
|
631
|
+
return new Set([...new Set([...Object.keys(current), ...Object.keys(saved)])].filter((key) => JSON.stringify(current[key]) !== JSON.stringify(saved[key])));
|
|
632
|
+
}
|
|
633
|
+
function topLevelConfigPatch(current, keys) {
|
|
634
|
+
return Object.fromEntries([...keys].map((key) => [key, hasOwnConfig(current, key) ? current[key] : null]));
|
|
635
|
+
}
|
|
636
|
+
function platformOwnedConfigPatch(config) {
|
|
637
|
+
return { [PLATFORM_OWNED_SETTINGS_KEY$1]: hasOwnConfig(config, PLATFORM_OWNED_SETTINGS_KEY$1) ? config[PLATFORM_OWNED_SETTINGS_KEY$1] : null };
|
|
638
|
+
}
|
|
639
|
+
function responseConfigPayload(response) {
|
|
640
|
+
return response.config ?? response.settings ?? {};
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.
|
|
644
|
+
*/
|
|
645
|
+
function usePluginConfig(pluginName) {
|
|
646
|
+
const injectedContext = getInjectedPlatformContext();
|
|
647
|
+
const { plugin } = usePlatformContext();
|
|
648
|
+
const platformApi = useApi();
|
|
649
|
+
const pluginApi = useApi({ baseUrl: injectedContext?.plugin?.api_prefix ?? plugin.value?.api_prefix });
|
|
650
|
+
const resolvedName = computed(() => pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? "");
|
|
651
|
+
const usesPluginSettingsApi = computed(() => {
|
|
652
|
+
const currentPlugin = injectedContext?.plugin ?? plugin.value;
|
|
653
|
+
return currentPlugin?.settings_api === "plugin" && resolvedName.value === currentPlugin.name;
|
|
654
|
+
});
|
|
655
|
+
const config = ref({});
|
|
656
|
+
const savedConfig = ref({});
|
|
657
|
+
const revision = ref(null);
|
|
658
|
+
const request = useRequestSyncState("Plugin config request failed.");
|
|
659
|
+
const isLoading = ref(false);
|
|
660
|
+
const isSaving = ref(false);
|
|
661
|
+
const error = request.error;
|
|
662
|
+
const lastLoadedAt = request.lastLoadedAt;
|
|
663
|
+
const lastSavedAt = request.lastSavedAt;
|
|
664
|
+
const isDirty = computed(() => {
|
|
665
|
+
return JSON.stringify(config.value) !== JSON.stringify(savedConfig.value);
|
|
666
|
+
});
|
|
667
|
+
async function load() {
|
|
668
|
+
const name = resolvedName.value;
|
|
669
|
+
if (!name) return;
|
|
670
|
+
isLoading.value = true;
|
|
671
|
+
try {
|
|
672
|
+
const response = usesPluginSettingsApi.value ? await request.run(() => pluginApi.get("/settings"), {
|
|
673
|
+
success: "load",
|
|
674
|
+
errorMessage: "Failed to load plugin config"
|
|
675
|
+
}) : await request.run(() => platformApi.get(`/plugins/${encodeURIComponent(name)}/config`), {
|
|
676
|
+
success: "load",
|
|
677
|
+
errorMessage: "Failed to load plugin config"
|
|
678
|
+
});
|
|
679
|
+
const responseConfig = responseConfigPayload(response);
|
|
680
|
+
config.value = cloneConfig(responseConfig);
|
|
681
|
+
savedConfig.value = cloneConfig(responseConfig);
|
|
682
|
+
revision.value = response.revision ?? null;
|
|
683
|
+
} catch {} finally {
|
|
684
|
+
isLoading.value = false;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
async function save() {
|
|
688
|
+
const name = resolvedName.value;
|
|
689
|
+
if (!name) return false;
|
|
690
|
+
isSaving.value = true;
|
|
691
|
+
try {
|
|
692
|
+
const payload = cloneConfig(config.value);
|
|
693
|
+
let response;
|
|
694
|
+
let nextRevision = revision.value;
|
|
695
|
+
if (usesPluginSettingsApi.value) {
|
|
696
|
+
response = await request.run(() => pluginApi.put("/settings", payload, revision.value ? { headers: { "If-Match": `"${revision.value}"` } } : void 0), {
|
|
697
|
+
success: "save",
|
|
698
|
+
errorMessage: "Failed to save plugin config"
|
|
699
|
+
});
|
|
700
|
+
nextRevision = response.revision ?? nextRevision;
|
|
701
|
+
} else {
|
|
702
|
+
const dirtyKeys = changedTopLevelKeys(payload, savedConfig.value);
|
|
703
|
+
const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY$1);
|
|
704
|
+
const typedKeys = [...dirtyKeys].filter((key) => key !== PLATFORM_OWNED_SETTINGS_KEY$1);
|
|
705
|
+
if (typedKeys.length) {
|
|
706
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(name)}/config`, { config: topLevelConfigPatch(payload, typedKeys) }), {
|
|
707
|
+
success: "save",
|
|
708
|
+
errorMessage: "Failed to save plugin config"
|
|
709
|
+
});
|
|
710
|
+
nextRevision = response.revision ?? nextRevision;
|
|
711
|
+
}
|
|
712
|
+
if (platformOwnedChanged) {
|
|
713
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(name)}/config`, { config: platformOwnedConfigPatch(payload) }), {
|
|
714
|
+
success: "save",
|
|
715
|
+
errorMessage: "Failed to save plugin config"
|
|
716
|
+
});
|
|
717
|
+
nextRevision = response.revision ?? nextRevision;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if (!response) return true;
|
|
721
|
+
const responseConfig = responseConfigPayload(response);
|
|
722
|
+
config.value = cloneConfig(responseConfig);
|
|
723
|
+
savedConfig.value = cloneConfig(responseConfig);
|
|
724
|
+
revision.value = response.revision ?? nextRevision;
|
|
725
|
+
return true;
|
|
726
|
+
} catch {
|
|
727
|
+
return false;
|
|
728
|
+
} finally {
|
|
729
|
+
isSaving.value = false;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function reset() {
|
|
733
|
+
config.value = cloneConfig(savedConfig.value);
|
|
734
|
+
request.clearError();
|
|
735
|
+
}
|
|
736
|
+
onMounted(() => {
|
|
737
|
+
load();
|
|
738
|
+
});
|
|
739
|
+
return {
|
|
740
|
+
config,
|
|
741
|
+
isLoading,
|
|
742
|
+
isSaving,
|
|
743
|
+
error,
|
|
744
|
+
lastLoadedAt,
|
|
745
|
+
lastSavedAt,
|
|
746
|
+
isDirty,
|
|
747
|
+
load,
|
|
748
|
+
save,
|
|
749
|
+
reset
|
|
750
|
+
};
|
|
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
|
|
614
959
|
//#region src/composables/analysisArtifactTarget.ts
|
|
615
960
|
var EXPERIMENT_ID = "experiment_id";
|
|
616
961
|
var ARTIFACT_PLUGIN_ID = "artifact_plugin_id";
|
|
@@ -647,7 +992,11 @@ function parseAnalysisArtifactTarget(query) {
|
|
|
647
992
|
}
|
|
648
993
|
//#endregion
|
|
649
994
|
//#region src/composables/useCommandHistory.ts
|
|
650
|
-
/**
|
|
995
|
+
/**
|
|
996
|
+
* Generic command-stack state for plugin editors with undo/redo controls.
|
|
997
|
+
*
|
|
998
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; keep command stacks plugin-local.
|
|
999
|
+
*/
|
|
651
1000
|
function useCommandHistory(options = {}) {
|
|
652
1001
|
const maxDepth = Math.max(1, options.maxDepth ?? 50);
|
|
653
1002
|
const undoStack = ref([]);
|
|
@@ -710,7 +1059,11 @@ function isPromiseLike(value) {
|
|
|
710
1059
|
}
|
|
711
1060
|
//#endregion
|
|
712
1061
|
//#region src/composables/useOptimisticMutation.ts
|
|
713
|
-
/**
|
|
1062
|
+
/**
|
|
1063
|
+
* Run async mutations with optional optimistic local updates and rollback.
|
|
1064
|
+
*
|
|
1065
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.
|
|
1066
|
+
*/
|
|
714
1067
|
function useOptimisticMutation(options) {
|
|
715
1068
|
const loading = shallowRef(false);
|
|
716
1069
|
const error = ref(null);
|
|
@@ -744,7 +1097,7 @@ function useOptimisticMutation(options) {
|
|
|
744
1097
|
return result;
|
|
745
1098
|
} catch (err) {
|
|
746
1099
|
options.rollback?.(snapshot, variables, err);
|
|
747
|
-
error.value = options.readErrorMessage?.(err) ?? readErrorMessage
|
|
1100
|
+
error.value = options.readErrorMessage?.(err) ?? readErrorMessage(err);
|
|
748
1101
|
options.onError?.(err, context);
|
|
749
1102
|
throw err;
|
|
750
1103
|
} finally {
|
|
@@ -763,15 +1116,13 @@ function useOptimisticMutation(options) {
|
|
|
763
1116
|
reset
|
|
764
1117
|
};
|
|
765
1118
|
}
|
|
766
|
-
function readErrorMessage$1(value) {
|
|
767
|
-
if (value instanceof Error && value.message) return value.message;
|
|
768
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
769
|
-
if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" && value.message.trim()) return value.message;
|
|
770
|
-
return "Request failed.";
|
|
771
|
-
}
|
|
772
1119
|
//#endregion
|
|
773
1120
|
//#region src/composables/useResourceCrud.ts
|
|
774
|
-
/**
|
|
1121
|
+
/**
|
|
1122
|
+
* Common list/create/update/delete state wrapper for generated plugin clients.
|
|
1123
|
+
*
|
|
1124
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useGeneratedPluginClient()` instead.
|
|
1125
|
+
*/
|
|
775
1126
|
function useResourceCrud(options) {
|
|
776
1127
|
const items = ref([...options.initialItems ?? []]);
|
|
777
1128
|
const loading = shallowRef(false);
|
|
@@ -899,46 +1250,13 @@ function resolveKey(keyOrItem, getKey) {
|
|
|
899
1250
|
if (typeof keyOrItem === "string" || typeof keyOrItem === "number") return keyOrItem;
|
|
900
1251
|
return getKey(keyOrItem);
|
|
901
1252
|
}
|
|
902
|
-
function readErrorMessage(value) {
|
|
903
|
-
if (value instanceof Error && value.message) return value.message;
|
|
904
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
905
|
-
if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" && value.message.trim()) return value.message;
|
|
906
|
-
return "Request failed.";
|
|
907
|
-
}
|
|
908
1253
|
//#endregion
|
|
909
1254
|
//#region src/composables/useWellPainting.ts
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
},
|
|
916
|
-
12: {
|
|
917
|
-
rows: 3,
|
|
918
|
-
cols: 4
|
|
919
|
-
},
|
|
920
|
-
24: {
|
|
921
|
-
rows: 4,
|
|
922
|
-
cols: 6
|
|
923
|
-
},
|
|
924
|
-
48: {
|
|
925
|
-
rows: 6,
|
|
926
|
-
cols: 8
|
|
927
|
-
},
|
|
928
|
-
54: {
|
|
929
|
-
rows: 6,
|
|
930
|
-
cols: 9
|
|
931
|
-
},
|
|
932
|
-
96: {
|
|
933
|
-
rows: 8,
|
|
934
|
-
cols: 12
|
|
935
|
-
},
|
|
936
|
-
384: {
|
|
937
|
-
rows: 16,
|
|
938
|
-
cols: 24
|
|
939
|
-
}
|
|
940
|
-
};
|
|
941
|
-
/** Pointer painting/rectangle selection state for WellPlate-based editors. */
|
|
1255
|
+
/**
|
|
1256
|
+
* Pointer painting/rectangle selection state for WellPlate-based editors.
|
|
1257
|
+
*
|
|
1258
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
1259
|
+
*/
|
|
942
1260
|
function useWellPainting(options) {
|
|
943
1261
|
const activeMode = ref(options.initialMode ?? "select");
|
|
944
1262
|
const activePayload = ref(options.initialPayload);
|
|
@@ -1013,15 +1331,15 @@ function wellIdToCoordinate(wellId) {
|
|
|
1013
1331
|
const match = /^([A-Z]+)(\d+)$/i.exec(wellId.trim());
|
|
1014
1332
|
if (!match) return null;
|
|
1015
1333
|
return {
|
|
1016
|
-
row:
|
|
1334
|
+
row: rowIndex(match[1].toUpperCase()),
|
|
1017
1335
|
col: Number(match[2]) - 1
|
|
1018
1336
|
};
|
|
1019
1337
|
}
|
|
1020
1338
|
function coordinateToWellId(coord) {
|
|
1021
|
-
return `${
|
|
1339
|
+
return `${rowLabel(coord.row)}${coord.col + 1}`;
|
|
1022
1340
|
}
|
|
1023
1341
|
function wellIdsInRectangle(start, end, format) {
|
|
1024
|
-
const dimensions =
|
|
1342
|
+
const dimensions = PLATE_CONFIGS[format];
|
|
1025
1343
|
const minRow = Math.max(0, Math.min(start.row, end.row));
|
|
1026
1344
|
const maxRow = Math.min(dimensions.rows - 1, Math.max(start.row, end.row));
|
|
1027
1345
|
const minCol = Math.max(0, Math.min(start.col, end.col));
|
|
@@ -1033,25 +1351,13 @@ function wellIdsInRectangle(start, end, format) {
|
|
|
1033
1351
|
}));
|
|
1034
1352
|
return ids;
|
|
1035
1353
|
}
|
|
1036
|
-
function rowLabelToIndex$1(label) {
|
|
1037
|
-
let result = 0;
|
|
1038
|
-
for (const char of label) result = result * 26 + (char.charCodeAt(0) - 64);
|
|
1039
|
-
return result - 1;
|
|
1040
|
-
}
|
|
1041
|
-
function indexToRowLabel$1(index) {
|
|
1042
|
-
if (index < 26) return ROW_LABELS[index];
|
|
1043
|
-
let value = index + 1;
|
|
1044
|
-
let label = "";
|
|
1045
|
-
while (value > 0) {
|
|
1046
|
-
value--;
|
|
1047
|
-
label = ROW_LABELS[value % 26] + label;
|
|
1048
|
-
value = Math.floor(value / 26);
|
|
1049
|
-
}
|
|
1050
|
-
return label;
|
|
1051
|
-
}
|
|
1052
1354
|
//#endregion
|
|
1053
1355
|
//#region src/composables/useWellPlateAdapter.ts
|
|
1054
|
-
/**
|
|
1356
|
+
/**
|
|
1357
|
+
* Convert domain rows into WellPlate's wells prop without hand-written adapters.
|
|
1358
|
+
*
|
|
1359
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
1360
|
+
*/
|
|
1055
1361
|
function useWellPlateAdapter(options) {
|
|
1056
1362
|
return { wells: computed(() => createWellPlateWells(toValue(options.entries), options)) };
|
|
1057
1363
|
}
|
|
@@ -1137,7 +1443,11 @@ function indexToRowLabel(index) {
|
|
|
1137
1443
|
}
|
|
1138
1444
|
//#endregion
|
|
1139
1445
|
//#region src/composables/useWellPlateValidation.ts
|
|
1140
|
-
/**
|
|
1446
|
+
/**
|
|
1447
|
+
* Rule-driven validation state for WellPlate layout/design screens.
|
|
1448
|
+
*
|
|
1449
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
1450
|
+
*/
|
|
1141
1451
|
function useWellPlateValidation(options) {
|
|
1142
1452
|
const warnings = computed(() => runWellPlateValidation(toValue(options.context), toValue(options.rules)));
|
|
1143
1453
|
return {
|
|
@@ -1419,7 +1729,8 @@ function createPluginClient(contract, options) {
|
|
|
1419
1729
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1420
1730
|
const api = useApi({
|
|
1421
1731
|
baseUrl: parts.baseUrl,
|
|
1422
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1732
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1733
|
+
typedErrors: true
|
|
1423
1734
|
});
|
|
1424
1735
|
const config = endpointRequestConfig(endpoint, parts.query, callOptions);
|
|
1425
1736
|
if (endpoint.method === "get") return api.get(parts.path, config);
|
|
@@ -1450,7 +1761,8 @@ async function uploadPluginEndpoint(contract, endpoint, payload, options = {}) {
|
|
|
1450
1761
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1451
1762
|
const api = useApi({
|
|
1452
1763
|
baseUrl: parts.baseUrl,
|
|
1453
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1764
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1765
|
+
typedErrors: true
|
|
1454
1766
|
});
|
|
1455
1767
|
const body = endpoint.hasBody ? requestBodyFromPayload(payload, parts.requestPayload, endpoint) : payload;
|
|
1456
1768
|
if (endpoint.requestContentType === OCTET_STREAM) {
|
|
@@ -1475,7 +1787,8 @@ async function downloadPluginEndpoint(contract, endpoint, payload, options = {})
|
|
|
1475
1787
|
const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
|
|
1476
1788
|
const api = useApi({
|
|
1477
1789
|
baseUrl: parts.baseUrl,
|
|
1478
|
-
withAuth: endpoint.requiresAuth !== false
|
|
1790
|
+
withAuth: endpoint.requiresAuth !== false,
|
|
1791
|
+
typedErrors: true
|
|
1479
1792
|
});
|
|
1480
1793
|
const config = {
|
|
1481
1794
|
...endpointRequestConfig(endpoint, parts.query, { signal: options.signal }) ?? {},
|
|
@@ -1499,7 +1812,29 @@ async function downloadPluginEndpoint(contract, endpoint, payload, options = {})
|
|
|
1499
1812
|
function normalizePluginSettingsOptions(options = {}) {
|
|
1500
1813
|
return typeof options === "string" ? { pluginName: options } : options;
|
|
1501
1814
|
}
|
|
1815
|
+
/** @deprecated Use `useGeneratedPluginClient()` for generated clients. */
|
|
1816
|
+
function usePluginClient(client) {
|
|
1817
|
+
return client;
|
|
1818
|
+
}
|
|
1502
1819
|
var PLATFORM_OWNED_SETTINGS_KEY = "allowed_experiment_types";
|
|
1820
|
+
/**
|
|
1821
|
+
* Secret settings travel as `{ "$secret": "<id>" }` references, so an untouched
|
|
1822
|
+
* secret round-trips without ever exposing its value. Declaring the format on
|
|
1823
|
+
* every write keeps a `null` unambiguous: it clears the stored secret instead of
|
|
1824
|
+
* meaning "unchanged", which is what the deprecated placeholder form meant.
|
|
1825
|
+
*/
|
|
1826
|
+
function withSecretFormat(payload, secretFormat) {
|
|
1827
|
+
if (!secretFormat) return payload;
|
|
1828
|
+
return {
|
|
1829
|
+
...payload,
|
|
1830
|
+
[PLUGIN_SECRET_FORMAT_KEY]: secretFormat
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
function responseSecretFormat(response) {
|
|
1834
|
+
if (!response || typeof response !== "object") return null;
|
|
1835
|
+
const format = response[PLUGIN_SECRET_FORMAT_KEY];
|
|
1836
|
+
return typeof format === "string" && format ? format : null;
|
|
1837
|
+
}
|
|
1503
1838
|
function cloneRecord(value) {
|
|
1504
1839
|
return JSON.parse(JSON.stringify(value));
|
|
1505
1840
|
}
|
|
@@ -1537,6 +1872,7 @@ function usePluginSettings(options = {}) {
|
|
|
1537
1872
|
const values = ref({});
|
|
1538
1873
|
const savedValues = shallowRef({});
|
|
1539
1874
|
const revision = ref(null);
|
|
1875
|
+
const secretFormat = ref(null);
|
|
1540
1876
|
const request = useRequestSyncState("Plugin settings request failed.");
|
|
1541
1877
|
const isLoading = ref(false);
|
|
1542
1878
|
const isSaving = ref(false);
|
|
@@ -1557,11 +1893,12 @@ function usePluginSettings(options = {}) {
|
|
|
1557
1893
|
function setValues(nextValues) {
|
|
1558
1894
|
values.value = cloneRecord(nextValues);
|
|
1559
1895
|
}
|
|
1560
|
-
function applyLoaded(nextValues, nextRevision) {
|
|
1896
|
+
function applyLoaded(nextValues, nextRevision, nextSecretFormat = secretFormat.value) {
|
|
1561
1897
|
const cloned = cloneRecord(nextValues);
|
|
1562
1898
|
values.value = cloned;
|
|
1563
1899
|
savedValues.value = cloneRecord(cloned);
|
|
1564
1900
|
revision.value = nextRevision;
|
|
1901
|
+
secretFormat.value = nextSecretFormat;
|
|
1565
1902
|
}
|
|
1566
1903
|
async function load() {
|
|
1567
1904
|
isLoading.value = true;
|
|
@@ -1573,7 +1910,7 @@ function usePluginSettings(options = {}) {
|
|
|
1573
1910
|
success: "load",
|
|
1574
1911
|
errorMessage: "Failed to load plugin settings"
|
|
1575
1912
|
});
|
|
1576
|
-
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response));
|
|
1913
|
+
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response), responseSecretFormat(response));
|
|
1577
1914
|
} catch {} finally {
|
|
1578
1915
|
isLoading.value = false;
|
|
1579
1916
|
}
|
|
@@ -1590,7 +1927,7 @@ function usePluginSettings(options = {}) {
|
|
|
1590
1927
|
const typedKeys = [...dirtyKeys].filter((key) => key !== PLATFORM_OWNED_SETTINGS_KEY);
|
|
1591
1928
|
let nextRevision = revision.value;
|
|
1592
1929
|
if (typedKeys.length) {
|
|
1593
|
-
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`, { config: topLevelSettingsPatch(payload, typedKeys) }), {
|
|
1930
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`, { config: withSecretFormat(topLevelSettingsPatch(payload, typedKeys), secretFormat.value) }), {
|
|
1594
1931
|
success: "save",
|
|
1595
1932
|
errorMessage: "Failed to save plugin settings"
|
|
1596
1933
|
});
|
|
@@ -1604,16 +1941,16 @@ function usePluginSettings(options = {}) {
|
|
|
1604
1941
|
nextRevision = responseSettingsRevision(response) ?? nextRevision;
|
|
1605
1942
|
}
|
|
1606
1943
|
if (!response) return true;
|
|
1607
|
-
applyLoaded(responseSettingsPayload(response), nextRevision);
|
|
1944
|
+
applyLoaded(responseSettingsPayload(response), nextRevision, responseSecretFormat(response) ?? secretFormat.value);
|
|
1608
1945
|
return true;
|
|
1609
1946
|
} else {
|
|
1610
1947
|
const ifMatch = revision.value ? { headers: { "If-Match": `"${revision.value}"` } } : void 0;
|
|
1611
|
-
response = await request.run(() => pluginApi.put("/settings", payload, ifMatch), {
|
|
1948
|
+
response = await request.run(() => pluginApi.put("/settings", withSecretFormat(payload, secretFormat.value), ifMatch), {
|
|
1612
1949
|
success: "save",
|
|
1613
1950
|
errorMessage: "Failed to save plugin settings"
|
|
1614
1951
|
});
|
|
1615
1952
|
}
|
|
1616
|
-
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response) ?? revision.value);
|
|
1953
|
+
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response) ?? revision.value, responseSecretFormat(response) ?? secretFormat.value);
|
|
1617
1954
|
return true;
|
|
1618
1955
|
} catch {
|
|
1619
1956
|
return false;
|
|
@@ -1763,6 +2100,85 @@ function useCurrentExperiment(options = {}) {
|
|
|
1763
2100
|
};
|
|
1764
2101
|
}
|
|
1765
2102
|
//#endregion
|
|
1766
|
-
|
|
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 };
|
|
1767
2183
|
|
|
1768
|
-
//# sourceMappingURL=composables-
|
|
2184
|
+
//# sourceMappingURL=composables-mFXsTA4g.js.map
|