@morscherlab/mint-sdk 1.2.0-beta.1 → 1.2.0-beta.10
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 +35 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-Dphh3RrI.js} +5 -8
- package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
- package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
- package/dist/__tests__/components/ExperimentTimeline.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__/composables/useListReorder.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/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/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -0
- 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/FitPanel.vue.d.ts +1 -1
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- 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/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/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/TimePicker.vue.d.ts +1 -0
- 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 +29 -0
- package/dist/components/index.d.ts +9 -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/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-CgAUzF8F.js} +2497 -2235
- package/dist/components-CgAUzF8F.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +9 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- 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/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/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-B_pia3hO.js} +209 -82
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-_W0-LbA6.js} +103 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-Cwl9AYxw.js} +3 -8
- package/dist/experiment-Cwl9AYxw.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
- package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
- package/dist/index.d.ts +1 -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 +11247 -29501
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-aMZlb4Sc.js} +462 -1130
- package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
- package/dist/useDropdownState-DitCtrTT.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BmX_iVBR.js} +766 -212
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
- 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/package.json +1 -1
- 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/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -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 +88 -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__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +140 -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/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 +2 -5
- 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/FileUploader.vue +0 -4
- 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 +3 -3
- 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 -4
- 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/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 +48 -5
- 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/index.ts +9 -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/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/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +43 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- 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/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +22 -10
- 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/usePluginClient.ts +47 -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 +16 -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/form-builder.css +5 -5
- 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 +9 -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/form-builder.ts +1 -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 → components/DataStates.test.d.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'
|
|
2
|
+
import { readErrorMessage } from '../utils/errors'
|
|
2
3
|
|
|
3
4
|
export type ResourceKey = string | number
|
|
4
5
|
|
|
@@ -38,7 +39,11 @@ export interface UseResourceCrudReturn<TItem, TCreate, TUpdate, TKey extends Res
|
|
|
38
39
|
clearError: () => void
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Common list/create/update/delete state wrapper for generated plugin clients.
|
|
44
|
+
*
|
|
45
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useGeneratedPluginClient()` instead.
|
|
46
|
+
*/
|
|
42
47
|
export function useResourceCrud<
|
|
43
48
|
TItem,
|
|
44
49
|
TCreate = Partial<TItem>,
|
|
@@ -228,18 +233,3 @@ function resolveKey<TItem, TKey extends ResourceKey>(
|
|
|
228
233
|
}
|
|
229
234
|
return getKey(keyOrItem as TItem)
|
|
230
235
|
}
|
|
231
|
-
|
|
232
|
-
function readErrorMessage(value: unknown): string {
|
|
233
|
-
if (value instanceof Error && value.message) return value.message
|
|
234
|
-
if (typeof value === 'string' && value.trim()) return value
|
|
235
|
-
if (
|
|
236
|
-
typeof value === 'object'
|
|
237
|
-
&& value !== null
|
|
238
|
-
&& 'message' in value
|
|
239
|
-
&& typeof (value as { message?: unknown }).message === 'string'
|
|
240
|
-
&& (value as { message: string }).message.trim()
|
|
241
|
-
) {
|
|
242
|
-
return (value as { message: string }).message
|
|
243
|
-
}
|
|
244
|
-
return 'Request failed.'
|
|
245
|
-
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { nextTick } from 'vue'
|
|
2
|
+
|
|
3
|
+
export interface UseRovingFocusOptions {
|
|
4
|
+
/** Selectable item ids, in DOM order. Already excludes items skipped entirely (e.g. disabled tabs). */
|
|
5
|
+
ids: () => string[]
|
|
6
|
+
/** The id that is currently active/selected. */
|
|
7
|
+
activeId: () => string | undefined
|
|
8
|
+
/** Activates an id (e.g. emit `update:modelValue`). The composable focuses the matching element afterward. */
|
|
9
|
+
activate: (id: string) => void
|
|
10
|
+
/** Returns the focusable element for an id, queried lazily so it reflects the post-activation DOM. */
|
|
11
|
+
getElement: (id: string) => HTMLElement | null | undefined
|
|
12
|
+
/** Arrow-key axis: `'horizontal'` (Left/Right, default) or `'vertical'` (Up/Down). */
|
|
13
|
+
orientation?: 'horizontal' | 'vertical'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface UseRovingFocusReturn {
|
|
17
|
+
/** Bind to each item's `@keydown`. */
|
|
18
|
+
handleKeydown: (event: KeyboardEvent) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* WAI-ARIA roving-tabindex navigation with automatic activation (the tabs pattern):
|
|
23
|
+
* Left/Right (or Up/Down when `orientation` is `'vertical'`) move to the adjacent item
|
|
24
|
+
* and activate it immediately, wrapping past the ends; Home/End jump to the first/last
|
|
25
|
+
* item. Only the active item should carry `tabindex="0"`; give every other item
|
|
26
|
+
* `tabindex="-1"`. Used by BaseTabs.
|
|
27
|
+
*/
|
|
28
|
+
export function useRovingFocus(options: UseRovingFocusOptions): UseRovingFocusReturn {
|
|
29
|
+
const orientation = options.orientation ?? 'horizontal'
|
|
30
|
+
const prevKey = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft'
|
|
31
|
+
const nextKey = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight'
|
|
32
|
+
|
|
33
|
+
function moveTo(id: string | undefined) {
|
|
34
|
+
if (id === undefined) return
|
|
35
|
+
options.activate(id)
|
|
36
|
+
void nextTick(() => options.getElement(id)?.focus())
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
40
|
+
const ids = options.ids()
|
|
41
|
+
if (ids.length === 0) return
|
|
42
|
+
const currentIndex = ids.indexOf(options.activeId() ?? '')
|
|
43
|
+
|
|
44
|
+
if (event.key === 'Home') {
|
|
45
|
+
event.preventDefault()
|
|
46
|
+
moveTo(ids[0])
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
if (event.key === 'End') {
|
|
50
|
+
event.preventDefault()
|
|
51
|
+
moveTo(ids[ids.length - 1])
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if (event.key === prevKey) {
|
|
55
|
+
event.preventDefault()
|
|
56
|
+
moveTo(ids[currentIndex <= 0 ? ids.length - 1 : currentIndex - 1])
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if (event.key === nextKey) {
|
|
60
|
+
event.preventDefault()
|
|
61
|
+
moveTo(ids[currentIndex === -1 || currentIndex >= ids.length - 1 ? 0 : currentIndex + 1])
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return { handleKeydown }
|
|
66
|
+
}
|
|
@@ -200,6 +200,42 @@ export function useScheduleDrag(options: UseScheduleDragOptions) {
|
|
|
200
200
|
cleanup()
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Keyboard alternative to the pointer drag: shifts an event by one slot
|
|
205
|
+
* (`mode: 'move'`) or grows/shrinks its end by one slot (`mode: 'resize'`),
|
|
206
|
+
* staying inside the visible day. Returns whether the nudge was applied.
|
|
207
|
+
*/
|
|
208
|
+
function nudgeEvent(
|
|
209
|
+
event: ScheduleEvent,
|
|
210
|
+
direction: -1 | 1,
|
|
211
|
+
mode: 'move' | 'resize' = 'move',
|
|
212
|
+
): boolean {
|
|
213
|
+
if (options.readonly.value) return false
|
|
214
|
+
if (mode === 'move' && event.draggable === false) return false
|
|
215
|
+
if (mode === 'resize' && event.resizable === false) return false
|
|
216
|
+
|
|
217
|
+
const slotMin = options.slotDuration.value
|
|
218
|
+
const dayStart = options.dayStartHour.value * 60
|
|
219
|
+
const dayEnd = options.dayEndHour.value * 60
|
|
220
|
+
const start = dateToMinutes(new Date(event.start))
|
|
221
|
+
const end = dateToMinutes(new Date(event.end))
|
|
222
|
+
|
|
223
|
+
const nextStart = mode === 'move' ? start + direction * slotMin : start
|
|
224
|
+
const nextEnd = mode === 'move'
|
|
225
|
+
? end + direction * slotMin
|
|
226
|
+
: Math.max(start + slotMin, end + direction * slotMin)
|
|
227
|
+
|
|
228
|
+
if (nextStart < dayStart || nextEnd > dayEnd || nextEnd <= nextStart) return false
|
|
229
|
+
|
|
230
|
+
const base = new Date(event.start)
|
|
231
|
+
const newStart = minutesToDate(base, nextStart)
|
|
232
|
+
const newEnd = minutesToDate(base, nextEnd)
|
|
233
|
+
|
|
234
|
+
if (mode === 'move') options.onMoveComplete?.(event, newStart, newEnd)
|
|
235
|
+
else options.onResizeComplete?.(event, newStart, newEnd)
|
|
236
|
+
return true
|
|
237
|
+
}
|
|
238
|
+
|
|
203
239
|
function addListeners() {
|
|
204
240
|
document.addEventListener('pointermove', onPointerMove)
|
|
205
241
|
document.addEventListener('pointerup', onPointerUp)
|
|
@@ -221,6 +257,7 @@ export function useScheduleDrag(options: UseScheduleDragOptions) {
|
|
|
221
257
|
startCreate,
|
|
222
258
|
startMove,
|
|
223
259
|
startResize,
|
|
260
|
+
nudgeEvent,
|
|
224
261
|
}
|
|
225
262
|
}
|
|
226
263
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { computed, ref, toValue, type ComputedRef, type Ref } from 'vue'
|
|
2
2
|
import type { WellPlateFormat } from '../types'
|
|
3
|
+
import {
|
|
4
|
+
PLATE_CONFIGS as PLATE_DIMENSIONS,
|
|
5
|
+
rowIndex as rowLabelToIndex,
|
|
6
|
+
rowLabel as indexToRowLabel,
|
|
7
|
+
} from '../components/WellPlate.geometry'
|
|
3
8
|
|
|
4
9
|
export type WellPlateSource<T> = T | Ref<T> | ComputedRef<T> | (() => T)
|
|
5
10
|
|
|
@@ -34,19 +39,12 @@ export interface UseWellPaintingReturn<TMode extends string = string, TPayload =
|
|
|
34
39
|
cancel: () => void
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
const ROW_LABELS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
54: { rows: 6, cols: 9 },
|
|
45
|
-
96: { rows: 8, cols: 12 },
|
|
46
|
-
384: { rows: 16, cols: 24 },
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Pointer painting/rectangle selection state for WellPlate-based editors. */
|
|
43
|
+
/**
|
|
44
|
+
* Pointer painting/rectangle selection state for WellPlate-based editors.
|
|
45
|
+
*
|
|
46
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
47
|
+
*/
|
|
50
48
|
export function useWellPainting<TMode extends string = string, TPayload = unknown>(
|
|
51
49
|
options: UseWellPaintingOptions<TMode, TPayload>,
|
|
52
50
|
): UseWellPaintingReturn<TMode, TPayload> {
|
|
@@ -166,22 +164,4 @@ export function wellIdsInRectangle(
|
|
|
166
164
|
return ids
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
function rowLabelToIndex(label: string): number {
|
|
170
|
-
let result = 0
|
|
171
|
-
for (const char of label) {
|
|
172
|
-
result = result * 26 + (char.charCodeAt(0) - 64)
|
|
173
|
-
}
|
|
174
|
-
return result - 1
|
|
175
|
-
}
|
|
176
167
|
|
|
177
|
-
function indexToRowLabel(index: number): string {
|
|
178
|
-
if (index < ROW_LABELS.length) return ROW_LABELS[index]
|
|
179
|
-
let value = index + 1
|
|
180
|
-
let label = ''
|
|
181
|
-
while (value > 0) {
|
|
182
|
-
value--
|
|
183
|
-
label = ROW_LABELS[value % 26] + label
|
|
184
|
-
value = Math.floor(value / 26)
|
|
185
|
-
}
|
|
186
|
-
return label
|
|
187
|
-
}
|
|
@@ -28,7 +28,11 @@ export interface UseWellPlateAdapterReturn {
|
|
|
28
28
|
wells: ComputedRef<Record<string, Partial<Well>>>
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Convert domain rows into WellPlate's wells prop without hand-written adapters.
|
|
33
|
+
*
|
|
34
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
35
|
+
*/
|
|
32
36
|
export function useWellPlateAdapter<TEntry>(
|
|
33
37
|
options: WellPlateAdapterOptions<TEntry>,
|
|
34
38
|
): UseWellPlateAdapterReturn {
|
|
@@ -5,18 +5,8 @@ import type {
|
|
|
5
5
|
SampleType,
|
|
6
6
|
WellPlateFormat,
|
|
7
7
|
} from '../types'
|
|
8
|
+
import { SAMPLE_COLOR_SCALE as DEFAULT_PALETTE } from '../utils/color'
|
|
8
9
|
|
|
9
|
-
const DEFAULT_PALETTE = [
|
|
10
|
-
'#3B82F6', // blue
|
|
11
|
-
'#10B981', // green
|
|
12
|
-
'#EF4444', // red
|
|
13
|
-
'#F59E0B', // amber
|
|
14
|
-
'#8B5CF6', // purple
|
|
15
|
-
'#F97316', // orange
|
|
16
|
-
'#06B6D4', // cyan
|
|
17
|
-
'#14B8A6', // teal
|
|
18
|
-
'#6B7280', // gray
|
|
19
|
-
]
|
|
20
10
|
|
|
21
11
|
const MAX_HISTORY = 50
|
|
22
12
|
|
|
@@ -33,7 +33,11 @@ export interface UseWellPlateValidationReturn<TType extends string = string> {
|
|
|
33
33
|
errorCount: ComputedRef<number>
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Rule-driven validation state for WellPlate layout/design screens.
|
|
38
|
+
*
|
|
39
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
|
|
40
|
+
*/
|
|
37
41
|
export function useWellPlateValidation<TContext, TType extends string = string>(
|
|
38
42
|
options: UseWellPlateValidationOptions<TContext, TType>,
|
|
39
43
|
): UseWellPlateValidationReturn<TType> {
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import type { TopBarVariant } from '../types'
|
|
2
|
+
import type { FormEnhancements } from '../types/form-builder'
|
|
3
|
+
import type {
|
|
4
|
+
ControlModel,
|
|
5
|
+
ControlModelBinding,
|
|
6
|
+
ControlSchema,
|
|
7
|
+
ControlWorkspaceOptions,
|
|
8
|
+
UseControlWorkspaceReturn,
|
|
9
|
+
} from './useControlSchema'
|
|
10
|
+
import { mergeControlWorkspaceOptions, resolveControlModel } from './useControlSchema'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Merges `initialValues`/external `modelValue`/`values` on top of a base
|
|
14
|
+
* `ControlWorkspaceOptions.initialValues`, matching the layering FormBuilder expects: base
|
|
15
|
+
* defaults, then caller-supplied initial values, then live external values win last. Shared by
|
|
16
|
+
* {@link controlWorkspaceProps} and {@link bioTemplatePresetWorkspaceProps} so both "generate a
|
|
17
|
+
* workspace from options, initialValues, and v-model" views merge options identically.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveControlOptionsWithExternalValues<TOptions extends ControlWorkspaceOptions>(
|
|
20
|
+
base: TOptions,
|
|
21
|
+
initialValues: Record<string, unknown> | undefined,
|
|
22
|
+
externalValues: Record<string, unknown> | undefined,
|
|
23
|
+
): TOptions {
|
|
24
|
+
if (initialValues === undefined && externalValues === undefined) return base
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
...base,
|
|
28
|
+
initialValues: {
|
|
29
|
+
...(base.initialValues ?? {}),
|
|
30
|
+
...(initialValues ?? {}),
|
|
31
|
+
...(externalValues ?? {}),
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ControlWorkspaceModelProps {
|
|
37
|
+
model?: ControlModel | ControlModelBinding
|
|
38
|
+
controls?: ControlSchema
|
|
39
|
+
controlOptions?: ControlWorkspaceOptions
|
|
40
|
+
initialValues?: Record<string, unknown>
|
|
41
|
+
modelValue?: Record<string, unknown>
|
|
42
|
+
values?: Record<string, unknown>
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ResolvedControlWorkspaceModel {
|
|
46
|
+
/** `modelValue` if provided, else `values` — the single external v-model source of truth. */
|
|
47
|
+
externalValues: Record<string, unknown> | undefined
|
|
48
|
+
/** `model` resolved through `resolveControlModel()`, or undefined for a raw `controls` schema. */
|
|
49
|
+
resolvedModel: ControlModelBinding | undefined
|
|
50
|
+
/** `controls` if provided, else the resolved model's controls, else `{}`. */
|
|
51
|
+
resolvedControls: ControlSchema
|
|
52
|
+
/** `controlOptions` merged over the resolved model's own options, with initialValues/external values layered on top. */
|
|
53
|
+
resolvedControlOptions: ControlWorkspaceOptions
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolves ControlWorkspaceView's `model`/`controls`/`controlOptions`/`initialValues`/
|
|
58
|
+
* `modelValue`/`values` props into the schema + options pair `useControlWorkspace()` needs.
|
|
59
|
+
* Pure and framework-free so callers wrap each field in their own `computed()`.
|
|
60
|
+
*
|
|
61
|
+
* @example Recommended
|
|
62
|
+
* ```ts
|
|
63
|
+
* const resolved = computed(() => controlWorkspaceProps(props))
|
|
64
|
+
* const resolvedControls = computed(() => resolved.value.resolvedControls)
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function controlWorkspaceProps(props: ControlWorkspaceModelProps): ResolvedControlWorkspaceModel {
|
|
68
|
+
const externalValues = props.modelValue ?? props.values
|
|
69
|
+
const resolvedModel = resolveControlModel(props.model)
|
|
70
|
+
const resolvedControls: ControlSchema = props.controls ?? resolvedModel?.controls ?? {}
|
|
71
|
+
const baseControlOptions = mergeControlWorkspaceOptions(resolvedModel?.controlOptions, props.controlOptions)
|
|
72
|
+
const resolvedControlOptions = resolveControlOptionsWithExternalValues(
|
|
73
|
+
baseControlOptions,
|
|
74
|
+
props.initialValues,
|
|
75
|
+
externalValues,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return { externalValues, resolvedModel, resolvedControls, resolvedControlOptions }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface DoseDesignWorkspacePassthroughProps {
|
|
82
|
+
workspace?: UseControlWorkspaceReturn<ControlSchema>
|
|
83
|
+
controlOptions?: ControlWorkspaceOptions
|
|
84
|
+
initialValues?: Record<string, unknown>
|
|
85
|
+
modelValue?: Record<string, unknown>
|
|
86
|
+
values?: Record<string, unknown>
|
|
87
|
+
title?: string
|
|
88
|
+
subtitle?: string
|
|
89
|
+
topBarVariant?: TopBarVariant
|
|
90
|
+
sidebarWidth?: string
|
|
91
|
+
sidebarVariant?: 'default' | 'analysis'
|
|
92
|
+
responsiveSidebar?: boolean
|
|
93
|
+
sidebarPosition?: 'left' | 'right'
|
|
94
|
+
sidebarTitle?: string
|
|
95
|
+
sidebarSubtitle?: string
|
|
96
|
+
sidebarBadge?: string | number
|
|
97
|
+
floating?: boolean
|
|
98
|
+
dense?: boolean
|
|
99
|
+
showSettings?: boolean
|
|
100
|
+
showFormActions?: boolean
|
|
101
|
+
formEnhancements?: FormEnhancements<Record<string, unknown>>
|
|
102
|
+
formLoading?: boolean
|
|
103
|
+
formDisabled?: boolean
|
|
104
|
+
formReadonly?: boolean
|
|
105
|
+
formSize?: 'sm' | 'md' | 'lg'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Maps DoseDesignWorkspaceView's props straight through to the identically-named
|
|
110
|
+
* ControlWorkspaceView props it wraps — the ~25-key pass-through list that used to be spelled
|
|
111
|
+
* out attribute-by-attribute in the template. `model` is the caller's already-resolved dose
|
|
112
|
+
* design model, not the raw (possibly absent) `props.model`.
|
|
113
|
+
*
|
|
114
|
+
* @example Recommended
|
|
115
|
+
* ```vue
|
|
116
|
+
* <ControlWorkspaceView v-bind="doseDesignWorkspaceProps(props, resolvedModel)" />
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export function doseDesignWorkspaceProps(
|
|
120
|
+
props: DoseDesignWorkspacePassthroughProps,
|
|
121
|
+
model: ControlModel | ControlModelBinding,
|
|
122
|
+
) {
|
|
123
|
+
return {
|
|
124
|
+
model,
|
|
125
|
+
workspace: props.workspace,
|
|
126
|
+
controlOptions: props.controlOptions,
|
|
127
|
+
initialValues: props.initialValues,
|
|
128
|
+
modelValue: props.modelValue,
|
|
129
|
+
values: props.values,
|
|
130
|
+
title: props.title,
|
|
131
|
+
subtitle: props.subtitle,
|
|
132
|
+
topBarVariant: props.topBarVariant,
|
|
133
|
+
sidebarWidth: props.sidebarWidth,
|
|
134
|
+
sidebarVariant: props.sidebarVariant,
|
|
135
|
+
responsiveSidebar: props.responsiveSidebar,
|
|
136
|
+
sidebarPosition: props.sidebarPosition,
|
|
137
|
+
sidebarTitle: props.sidebarTitle,
|
|
138
|
+
sidebarSubtitle: props.sidebarSubtitle,
|
|
139
|
+
sidebarBadge: props.sidebarBadge,
|
|
140
|
+
floating: props.floating,
|
|
141
|
+
dense: props.dense,
|
|
142
|
+
showSettings: props.showSettings,
|
|
143
|
+
showFormActions: props.showFormActions,
|
|
144
|
+
formEnhancements: props.formEnhancements,
|
|
145
|
+
formLoading: props.formLoading,
|
|
146
|
+
formDisabled: props.formDisabled,
|
|
147
|
+
formReadonly: props.formReadonly,
|
|
148
|
+
formSize: props.formSize,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface BioTemplateExperimentWorkspaceStatusProps {
|
|
153
|
+
status?: {
|
|
154
|
+
loading?: boolean
|
|
155
|
+
saving?: boolean
|
|
156
|
+
error?: string | null
|
|
157
|
+
hasExperiment?: boolean
|
|
158
|
+
currentExperimentId?: number
|
|
159
|
+
lastLoadedAt?: Date | null
|
|
160
|
+
lastSavedAt?: Date | null
|
|
161
|
+
}
|
|
162
|
+
loading?: boolean
|
|
163
|
+
error?: string | null
|
|
164
|
+
hasExperiment?: boolean
|
|
165
|
+
currentExperimentId?: number
|
|
166
|
+
lastLoadedAt?: Date | null
|
|
167
|
+
lastSavedAt?: Date | null
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ResolvedBioTemplateExperimentStatus {
|
|
171
|
+
loading: boolean
|
|
172
|
+
error: string | null | undefined
|
|
173
|
+
hasExperiment: boolean
|
|
174
|
+
currentExperimentId: number | undefined
|
|
175
|
+
lastLoadedAt: Date | null | undefined
|
|
176
|
+
lastSavedAt: Date | null | undefined
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Merges BioTemplateExperimentWorkspaceView's grouped `status` prop over its individual
|
|
181
|
+
* `loading`/`error`/`hasExperiment`/... props: `status` wins whenever the corresponding field
|
|
182
|
+
* on it is set, otherwise the flat prop (or its default) is used. Centralizes the six
|
|
183
|
+
* independent fallback rules generated plugin pages rely on when they pass a request/experiment
|
|
184
|
+
* `status` object instead of wiring each field by hand.
|
|
185
|
+
*/
|
|
186
|
+
export function bioTemplateExperimentWorkspaceProps(
|
|
187
|
+
props: BioTemplateExperimentWorkspaceStatusProps,
|
|
188
|
+
): ResolvedBioTemplateExperimentStatus {
|
|
189
|
+
const status = props.status
|
|
190
|
+
return {
|
|
191
|
+
loading: status?.loading !== undefined || status?.saving !== undefined
|
|
192
|
+
? Boolean(status?.loading) || Boolean(status?.saving)
|
|
193
|
+
: Boolean(props.loading),
|
|
194
|
+
error: status?.error !== undefined ? status.error : props.error,
|
|
195
|
+
hasExperiment: status?.hasExperiment ?? props.hasExperiment ?? false,
|
|
196
|
+
currentExperimentId: status?.currentExperimentId ?? props.currentExperimentId,
|
|
197
|
+
lastLoadedAt: status?.lastLoadedAt !== undefined ? status.lastLoadedAt : props.lastLoadedAt,
|
|
198
|
+
lastSavedAt: status?.lastSavedAt !== undefined ? status.lastSavedAt : props.lastSavedAt,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface BioTemplatePackWorkspacePassthroughProps {
|
|
203
|
+
message?: string
|
|
204
|
+
dense?: boolean
|
|
205
|
+
readonly?: boolean
|
|
206
|
+
showStatus?: boolean
|
|
207
|
+
showTemplateSummary?: boolean
|
|
208
|
+
loadLabel?: string
|
|
209
|
+
resetLabel?: string
|
|
210
|
+
saveLabel?: string
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Assembles the prop object BioTemplatePackWorkspaceView binds onto the
|
|
215
|
+
* BioTemplateExperimentWorkspaceView it wraps: its own display props passed straight through,
|
|
216
|
+
* plus the pack-derived `target`/`label`/`status`/`actions` computed by the caller.
|
|
217
|
+
*/
|
|
218
|
+
export function bioTemplatePackWorkspaceProps<TTarget, TStatus, TActions>(
|
|
219
|
+
props: BioTemplatePackWorkspacePassthroughProps,
|
|
220
|
+
derived: {
|
|
221
|
+
target: TTarget
|
|
222
|
+
label: string
|
|
223
|
+
status: TStatus
|
|
224
|
+
actions: TActions
|
|
225
|
+
},
|
|
226
|
+
) {
|
|
227
|
+
return {
|
|
228
|
+
target: derived.target,
|
|
229
|
+
kind: 'collection' as const,
|
|
230
|
+
label: derived.label,
|
|
231
|
+
message: props.message,
|
|
232
|
+
status: derived.status,
|
|
233
|
+
actions: derived.actions,
|
|
234
|
+
dense: props.dense,
|
|
235
|
+
readonly: props.readonly,
|
|
236
|
+
showStatus: props.showStatus,
|
|
237
|
+
showTemplateSummary: props.showTemplateSummary,
|
|
238
|
+
loadLabel: props.loadLabel,
|
|
239
|
+
resetLabel: props.resetLabel,
|
|
240
|
+
saveLabel: props.saveLabel,
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface BioTemplatePresetWorkspaceOptionsProps<TOptions extends ControlWorkspaceOptions> {
|
|
245
|
+
workspaceOptions?: TOptions
|
|
246
|
+
initialValues?: Record<string, unknown>
|
|
247
|
+
modelValue?: Record<string, unknown>
|
|
248
|
+
values?: Record<string, unknown>
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Resolves BioTemplatePresetWorkspaceView's `workspaceOptions`/`initialValues`/`modelValue`/
|
|
253
|
+
* `values` props into the single options object `useBioTemplatePresetWorkspace()` needs,
|
|
254
|
+
* reusing the same base/initialValues/external-values layering as {@link controlWorkspaceProps}.
|
|
255
|
+
*/
|
|
256
|
+
export function bioTemplatePresetWorkspaceProps<TOptions extends ControlWorkspaceOptions>(
|
|
257
|
+
props: BioTemplatePresetWorkspaceOptionsProps<TOptions>,
|
|
258
|
+
): { externalValues: Record<string, unknown> | undefined; resolvedWorkspaceOptions: TOptions } {
|
|
259
|
+
const externalValues = props.modelValue ?? props.values
|
|
260
|
+
const resolvedWorkspaceOptions = resolveControlOptionsWithExternalValues(
|
|
261
|
+
(props.workspaceOptions ?? {}) as TOptions,
|
|
262
|
+
props.initialValues,
|
|
263
|
+
externalValues,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
return { externalValues, resolvedWorkspaceOptions }
|
|
267
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -41,6 +41,22 @@ export {
|
|
|
41
41
|
deriveShade,
|
|
42
42
|
type Hsl,
|
|
43
43
|
} from './utils/color'
|
|
44
|
+
export {
|
|
45
|
+
PLUGIN_SECRET_FORMAT_KEY,
|
|
46
|
+
PLUGIN_SECRET_FORMAT_REF,
|
|
47
|
+
PLUGIN_SECRET_REF_KEY,
|
|
48
|
+
clearPluginSecret,
|
|
49
|
+
isPluginSecretLocked,
|
|
50
|
+
isPluginSecretRef,
|
|
51
|
+
keepPluginSecret,
|
|
52
|
+
pluginSecretId,
|
|
53
|
+
pluginSecretLabel,
|
|
54
|
+
pluginSecretState,
|
|
55
|
+
setPluginSecret,
|
|
56
|
+
usesPluginSecretReferences,
|
|
57
|
+
type PluginSecretRef,
|
|
58
|
+
type PluginSecretState,
|
|
59
|
+
} from './utils/pluginSecrets'
|
|
44
60
|
export {
|
|
45
61
|
LCMS_DEFAULT_CONTROL_POSITIONS,
|
|
46
62
|
createLcmsControlWellEditData,
|
package/src/permissions.ts
CHANGED
|
@@ -2,7 +2,6 @@ export const ADMIN_ROLE = 'admin'
|
|
|
2
2
|
|
|
3
3
|
export const ADMIN_PANEL_PERMISSIONS = [
|
|
4
4
|
'users.view',
|
|
5
|
-
'users.invite',
|
|
6
5
|
'users.manage',
|
|
7
6
|
'platform.configure',
|
|
8
7
|
'platform.view_logs',
|
|
@@ -41,11 +40,36 @@ export interface AccessPolicy {
|
|
|
41
40
|
plugin?: string
|
|
42
41
|
}
|
|
43
42
|
|
|
43
|
+
/**
|
|
44
|
+
* An object that carries an access rule.
|
|
45
|
+
*
|
|
46
|
+
* The nested `access` policy is the supported shape. The four flat fields are
|
|
47
|
+
* the pre-1.2 spelling of the same four `AccessPolicy` fields; they still work
|
|
48
|
+
* but are deprecated, and `normalizeAccessPolicy()` lets the nested policy win
|
|
49
|
+
* wherever both are given.
|
|
50
|
+
*/
|
|
44
51
|
export interface AccessControlled {
|
|
52
|
+
/** The access policy. Preferred over the flat fields below. */
|
|
45
53
|
access?: AccessPolicy
|
|
54
|
+
/**
|
|
55
|
+
* @deprecated Since MINT 1.2; use `access.visibleFor` instead. The flat
|
|
56
|
+
* duplicate is removed in 1.3.
|
|
57
|
+
*/
|
|
46
58
|
visibleFor?: AccessAudienceInput
|
|
59
|
+
/**
|
|
60
|
+
* @deprecated Since MINT 1.2; use `access.requiresAdmin` instead. The flat
|
|
61
|
+
* duplicate is removed in 1.3.
|
|
62
|
+
*/
|
|
47
63
|
requiresAdmin?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* @deprecated Since MINT 1.2; use `access.permissions` instead. The flat
|
|
66
|
+
* duplicate is removed in 1.3.
|
|
67
|
+
*/
|
|
48
68
|
permissions?: readonly string[]
|
|
69
|
+
/**
|
|
70
|
+
* @deprecated Since MINT 1.2; use `access.anyPermissions` instead. The flat
|
|
71
|
+
* duplicate is removed in 1.3.
|
|
72
|
+
*/
|
|
49
73
|
anyPermissions?: readonly string[]
|
|
50
74
|
}
|
|
51
75
|
|
|
@@ -105,17 +129,32 @@ export function canAccessPlugin(
|
|
|
105
129
|
return Array.isArray(access) && access.includes(pluginName)
|
|
106
130
|
}
|
|
107
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Flatten an access rule — either shape, or a mix of both — into one policy.
|
|
134
|
+
*
|
|
135
|
+
* ## Precedence
|
|
136
|
+
*
|
|
137
|
+
* 1. A defined field on the nested `access` policy wins. It is the supported
|
|
138
|
+
* spelling, so an object that carries both shapes is read as "the nested
|
|
139
|
+
* policy, with the deprecated flat fields as leftovers".
|
|
140
|
+
* 2. Otherwise the flat field on the rule itself is used.
|
|
141
|
+
* 3. A field set to `undefined` on either side counts as unset and never
|
|
142
|
+
* masks the other side.
|
|
143
|
+
*
|
|
144
|
+
* Only `AccessPolicy` fields the flat shape never had (`audience`,
|
|
145
|
+
* `requiresAuth`, `plugin`) can come from the nested policy alone; the four
|
|
146
|
+
* duplicated fields are the ones this ordering exists for.
|
|
147
|
+
*/
|
|
108
148
|
export function normalizeAccessPolicy(rule: AccessControlled | AccessPolicy | undefined): AccessPolicy {
|
|
109
149
|
if (!rule) return {}
|
|
110
|
-
const { access: nested, ...
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
...('requiresAdmin' in rule && rule.requiresAdmin !== undefined ? { requiresAdmin: rule.requiresAdmin } : {}),
|
|
116
|
-
...('permissions' in rule && rule.permissions !== undefined ? { permissions: rule.permissions } : {}),
|
|
117
|
-
...('anyPermissions' in rule && rule.anyPermissions !== undefined ? { anyPermissions: rule.anyPermissions } : {}),
|
|
150
|
+
const { access: nested, ...flat } = rule as AccessPolicy & { access?: AccessPolicy }
|
|
151
|
+
const policy = { ...flat } as Record<string, unknown>
|
|
152
|
+
|
|
153
|
+
for (const [field, value] of Object.entries(nested ?? {})) {
|
|
154
|
+
if (value !== undefined) policy[field] = value
|
|
118
155
|
}
|
|
156
|
+
|
|
157
|
+
return policy as AccessPolicy
|
|
119
158
|
}
|
|
120
159
|
|
|
121
160
|
export function canAccessByPolicy(
|
package/src/stores/auth.ts
CHANGED
package/src/stores/experiment.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
2
|
import { ref } from 'vue'
|
|
3
3
|
import { useApi } from '../composables/useApi'
|
|
4
|
+
import { readErrorMessage } from '../utils/errors'
|
|
4
5
|
import type { ExperimentSummary, PlatformContext } from '../types'
|
|
5
6
|
|
|
6
7
|
function getPlatformApiUrl(): string | undefined {
|
|
@@ -9,12 +10,6 @@ function getPlatformApiUrl(): string | undefined {
|
|
|
9
10
|
?.platformApiUrl
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
function readErrorMessage(value: unknown): string {
|
|
13
|
-
if (value instanceof Error && value.message) return value.message
|
|
14
|
-
if (typeof value === 'string' && value.trim()) return value
|
|
15
|
-
return 'Failed to load experiment'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
13
|
/**
|
|
19
14
|
* The single source of truth for the experiment a plugin is currently working on.
|
|
20
15
|
*
|
|
@@ -89,7 +84,7 @@ export const useExperimentStore = defineStore('mint-experiment', () => {
|
|
|
89
84
|
} catch (err) {
|
|
90
85
|
if (token !== selectionToken) return null
|
|
91
86
|
current.value = null
|
|
92
|
-
error.value = readErrorMessage(err)
|
|
87
|
+
error.value = readErrorMessage(err, 'Failed to load experiment')
|
|
93
88
|
return null
|
|
94
89
|
} finally {
|
|
95
90
|
// Only the newest request owns the loading flag; otherwise a superseded
|