@morscherlab/mint-sdk 1.4.0-beta.8 → 1.4.0
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 +14 -3
- package/dist/{ActionMenu-CScINahU.js → AlertBox-DwgNTEqf.js} +40 -209
- package/dist/AlertBox-DwgNTEqf.js.map +1 -0
- package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-CZZaxni0.js} +1249 -239
- package/dist/AppSidebar-CZZaxni0.js.map +1 -0
- package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-CjWoxAD1.js} +2 -2
- package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-CjWoxAD1.js.map} +1 -1
- package/dist/ExperimentPopover-DujiuQIO.js +337 -0
- package/dist/ExperimentPopover-DujiuQIO.js.map +1 -0
- package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-B4j4eUOJ.js} +244 -211
- package/dist/ExperimentSelectorModal-B4j4eUOJ.js.map +1 -0
- package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-DyUPH3I5.js} +2 -2
- package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-DyUPH3I5.js.map} +1 -1
- package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-D2MOOtuO.js} +28 -27
- package/dist/SettingsModal-D2MOOtuO.js.map +1 -0
- package/dist/__stories__/experiment-helpers.d.ts +10 -0
- package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
- package/dist/__tests__/components/FloatingPanelsInModal.test.d.ts +1 -0
- package/dist/__tests__/composables/useFloatingPanel.test.d.ts +1 -0
- package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
- package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
- package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AppTopBar.vue.d.ts +20 -5
- package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
- package/dist/components/AuditTrail.vue.d.ts +1 -1
- package/dist/components/BaseButton.vue.d.ts +4 -2
- package/dist/components/BaseSelect.vue.d.ts +2 -2
- package/dist/components/ChartContainer.vue.d.ts +2 -0
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/ExperimentPopover.vue.d.ts +18 -0
- package/dist/components/ExperimentSelectorModal.vue.d.ts +15 -5
- package/dist/components/FilePicker.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/JobsStatusTray.vue.d.ts +15 -4
- package/dist/components/PluginIcon.vue.d.ts +2 -2
- package/dist/components/PluginWorkspaceView.props.d.ts +3 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +3 -0
- package/dist/components/SampleSelector.vue.d.ts +6 -6
- package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +3 -3
- package/dist/components/StepWizard.vue.d.ts +3 -0
- package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
- package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +3 -3
- package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
- package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
- package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
- package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +8 -0
- package/dist/composables/createClient.d.ts +2 -0
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/pluginIdentity.d.ts +24 -0
- package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
- package/dist/composables/useAppExperiment.d.ts +8 -0
- package/dist/composables/useCalendarGrid.d.ts +1 -1
- package/dist/composables/useExperimentSelector.d.ts +6 -2
- package/dist/composables/useFileImport.d.ts +7 -0
- package/dist/composables/useFloatingPanel.d.ts +29 -0
- package/dist/composables/useJobCenter.d.ts +41 -3
- package/dist/composables/useOnboarding.d.ts +119 -0
- package/dist/composables/usePlatform.d.ts +1 -0
- package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-Bsg0t5Ab.js} +2 -2
- package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-Bsg0t5Ab.js.map} +1 -1
- package/dist/{data-C2PwI_dn.js → data-Boeh4uPI.js} +180 -125
- package/dist/data-Boeh4uPI.js.map +1 -0
- package/dist/data.d.ts +1 -1
- package/dist/data.js +9 -9
- package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
- package/dist/experiment-DyO54FQB.js.map +1 -0
- package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-DCn2QKG7.js} +3 -3
- package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-DCn2QKG7.js.map} +1 -1
- package/dist/index.js +20 -20
- package/dist/{install-DAID6c2-.js → install-BEHp7Mo-.js} +15 -14
- package/dist/{install-DAID6c2-.js.map → install-BEHp7Mo-.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-DLwRl_Ql.js → lab-D61eaX6f.js} +136 -148
- package/dist/lab-D61eaX6f.js.map +1 -0
- package/dist/lab.js +4 -3
- package/dist/{records-BzTcxekG.js → records-D4aQXyZu.js} +647 -389
- package/dist/records-D4aQXyZu.js.map +1 -0
- package/dist/{runtime-D6gVat6r.js → runtime-q-R0CNLh.js} +417 -54
- package/dist/runtime-q-R0CNLh.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +7 -7
- package/dist/{shell-5ju97nOS.js → shell-6CGFvUUw.js} +10 -5
- package/dist/{shell-5ju97nOS.js.map → shell-6CGFvUUw.js.map} +1 -1
- package/dist/shell.d.ts +1 -0
- package/dist/shell.js +6 -6
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +2 -2
- package/dist/stores/settings.d.ts +4 -12
- package/dist/styles.css +2753 -2101
- package/dist/types/componentWorkflowTypes.d.ts +2 -0
- package/dist/types/components.d.ts +2 -0
- package/dist/types/generated/platformContext.d.ts +1 -0
- package/dist/types/generated-ui.d.ts +4 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/jobs.d.ts +9 -0
- package/dist/types/platform.d.ts +1 -1
- package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-uFIz6Yv8.js} +75 -5
- package/dist/useDropdownState-uFIz6Yv8.js.map +1 -0
- package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-QEFoq4tf.js} +48 -6
- package/dist/useExperimentSamples-QEFoq4tf.js.map +1 -0
- package/dist/{useListReorder-CcbEYxX-.js → useListReorder-DsuzwWGS.js} +219 -437
- package/dist/useListReorder-DsuzwWGS.js.map +1 -0
- package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-KpZ4iJ6o.js} +85 -81
- package/dist/useRackEditor-KpZ4iJ6o.js.map +1 -0
- package/dist/useRealtime-B58Lo-Tm.js +508 -0
- package/dist/useRealtime-B58Lo-Tm.js.map +1 -0
- package/dist/useRequest-BuDmW8Jc.js +215 -0
- package/dist/useRequest-BuDmW8Jc.js.map +1 -0
- package/dist/utils/time.d.ts +7 -0
- package/package.json +3 -2
- package/src/__stories__/experiment-helpers.ts +3 -3
- package/src/__tests__/components/ActionMenu.test.ts +2 -2
- package/src/__tests__/components/AppTopBar.test.ts +257 -3
- package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
- package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
- package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
- package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
- package/src/__tests__/components/BaseButton.test.ts +19 -0
- package/src/__tests__/components/BaseModal.test.ts +13 -0
- package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
- package/src/__tests__/components/BaseSelect.test.ts +2 -1
- package/src/__tests__/components/BatchProgressList.test.ts +16 -0
- package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
- package/src/__tests__/components/ChartContainer.test.ts +11 -0
- package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
- package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
- package/src/__tests__/components/DatePicker.test.ts +21 -0
- package/src/__tests__/components/DatePicker.time.test.ts +2 -2
- package/src/__tests__/components/EmptyState.test.ts +1 -1
- package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
- package/src/__tests__/components/ExperimentSelectorModal.test.ts +153 -14
- package/src/__tests__/components/FloatingPanelsInModal.test.ts +94 -0
- package/src/__tests__/components/GeneratedPluginView.test.ts +23 -2
- package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
- package/src/__tests__/components/JobsStatusTray.test.ts +373 -71
- package/src/__tests__/components/PluginWorkspaceView.test.ts +63 -1
- package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
- package/src/__tests__/components/SampleSelector.test.ts +33 -8
- package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
- package/src/__tests__/components/SettingsModal.test.ts +9 -2
- package/src/__tests__/components/StepWizard.test.ts +11 -0
- package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
- package/src/__tests__/components/deprecationTags.test.ts +1 -1
- package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
- package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
- package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
- package/src/__tests__/composables/useFileImport.test.ts +36 -0
- package/src/__tests__/composables/useFloatingPanel.test.ts +68 -0
- package/src/__tests__/composables/useJobCenter.test.ts +262 -3
- package/src/__tests__/composables/useOnboarding.test.ts +317 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +4 -3
- package/src/__tests__/fixtures/table-import/cells.xlsx +0 -0
- package/src/__tests__/fixtures/table-import/samples.xlsx +0 -0
- package/src/__tests__/stores/settings.test.ts +21 -21
- package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
- package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
- package/src/__tests__/styles/cssTokens.test.ts +6 -3
- package/src/__tests__/styles/menusShellRefresh.test.ts +22 -12
- package/src/__tests__/styles/paletteTokens.test.ts +44 -0
- package/src/__tests__/styles/v2AuditRules.test.ts +104 -0
- package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
- package/src/__tests__/utils/time.test.ts +18 -1
- package/src/components/ActionMenu.vue +6 -37
- package/src/components/AdductText.story.vue +7 -0
- package/src/components/AdductText.vue +1 -1
- package/src/components/AlertBox.story.vue +2 -2
- package/src/components/AlertBox.vue +18 -16
- package/src/components/AppSidebar.story.vue +0 -28
- package/src/components/AppTopBar.onboarding.story.vue +69 -0
- package/src/components/AppTopBar.story.vue +105 -15
- package/src/components/AppTopBar.vue +248 -122
- package/src/components/ArtifactSaveDialog.story.vue +23 -0
- package/src/components/ArtifactSaveDialog.vue +102 -12
- package/src/components/AuditTrail.story.vue +2 -1
- package/src/components/AuditTrail.vue +2 -21
- package/src/components/Avatar.vue +10 -14
- package/src/components/BaseButton.vue +16 -2
- package/src/components/BaseModal.vue +2 -1
- package/src/components/BaseSelect.multiple.story.vue +13 -2
- package/src/components/BaseSelect.vue +4 -3
- package/src/components/BatchProgressList.vue +35 -25
- package/src/components/ChartContainer.story.vue +2 -1
- package/src/components/ChartContainer.vue +8 -6
- package/src/components/ConfirmDialog.story.vue +1 -1
- package/src/components/EmptyState.vue +1 -1
- package/src/components/ExperimentPopover.story.vue +165 -53
- package/src/components/ExperimentPopover.vue +169 -187
- package/src/components/ExperimentSelectorModal.story.vue +73 -31
- package/src/components/ExperimentSelectorModal.vue +144 -111
- package/src/components/FormField.story.vue +8 -48
- package/src/components/GeneratedPluginView.vue +11 -10
- package/src/components/GeneratedResultRenderer.vue +3 -4
- package/src/components/InstrumentStateBadge.vue +1 -1
- package/src/components/JobsStatusTray.story.vue +97 -43
- package/src/components/JobsStatusTray.vue +287 -290
- package/src/components/LayoutResizeHandle.story.vue +65 -4
- package/src/components/LoadingSpinner.vue +1 -1
- package/src/components/NumberInput.vue +3 -6
- package/src/components/PluginIcon.story.vue +2 -10
- package/src/components/PluginIcon.vue +2 -2
- package/src/components/PluginWorkspaceView.props.ts +3 -0
- package/src/components/PluginWorkspaceView.story.vue +1 -1
- package/src/components/PluginWorkspaceView.vue +17 -0
- package/src/components/RuntimeUpdateNotice.vue +1 -1
- package/src/components/SampleSelector.story.vue +22 -7
- package/src/components/SampleSelector.vue +34 -37
- package/src/components/SampleSelectorGroupNode.vue +1 -1
- package/src/components/SectionCard.story.vue +35 -2
- package/src/components/SequenceProgressBar.story.vue +9 -0
- package/src/components/SequenceProgressBar.vue +6 -1
- package/src/components/SettingsModal.schema.ts +1 -1
- package/src/components/SettingsModal.vue +9 -14
- package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
- package/src/components/SmartGroupManual.story.vue +1 -1
- package/src/components/StepWizard.story.vue +33 -0
- package/src/components/StepWizard.vue +8 -1
- package/src/components/Tooltip.vue +9 -32
- package/src/components/WellPlate.story.vue +3 -1
- package/src/components/WellPlate.vue +7 -0
- package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
- package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
- package/src/components/internal/DatePickerDateInternal.vue +23 -85
- package/src/components/internal/DatePickerDateTimeInternal.vue +10 -14
- package/src/components/internal/DatePickerTimeInternal.vue +13 -9
- package/src/components/internal/NumberUnitInputInternal.vue +4 -18
- package/src/components/internal/OnboardingLayerInternal.vue +173 -0
- package/src/components/internal/ResourcePickerListInternal.vue +45 -85
- package/src/components/internal/SelectMultipleInternal.vue +187 -65
- package/src/components/internal/SelectSearchableInternal.vue +8 -4
- package/src/components/internal/WellEditPopupInternal.vue +11 -22
- package/src/components/internal/WorkspaceShellInternal.vue +12 -0
- package/src/composables/createClient.ts +2 -0
- package/src/composables/index.ts +1 -0
- package/src/composables/pluginIdentity.ts +31 -0
- package/src/composables/pluginWorkspaceModel.ts +2 -2
- package/src/composables/useAppExperiment.ts +20 -0
- package/src/composables/useCalendarGrid.ts +4 -3
- package/src/composables/useExperimentSelector.ts +77 -31
- package/src/composables/useFileImport.ts +51 -1
- package/src/composables/useFloatingPanel.ts +107 -0
- package/src/composables/useJobCenter.ts +188 -6
- package/src/composables/useOnboarding.ts +465 -0
- package/src/composables/usePluginWorkspace.ts +1 -1
- package/src/data.ts +1 -0
- package/src/runtime.ts +2 -1
- package/src/shell.ts +17 -0
- package/src/stores/index.ts +0 -2
- package/src/stores/settings.ts +20 -50
- package/src/styles/components/action-menu.css +1 -1
- package/src/styles/components/adduct-text.css +13 -5
- package/src/styles/components/alert-box.css +39 -58
- package/src/styles/components/app-layout.css +10 -6
- package/src/styles/components/app-page-selector.css +121 -44
- package/src/styles/components/app-pill-nav.css +11 -12
- package/src/styles/components/app-sidebar.css +9 -18
- package/src/styles/components/app-top-bar.css +219 -55
- package/src/styles/components/artifact-save-dialog.css +153 -2
- package/src/styles/components/audit-trail.css +16 -19
- package/src/styles/components/avatar.css +6 -4
- package/src/styles/components/batch-progress-list.css +38 -36
- package/src/styles/components/button.css +36 -59
- package/src/styles/components/calendar.css +12 -12
- package/src/styles/components/chart-container.css +34 -23
- package/src/styles/components/checkbox.css +2 -12
- package/src/styles/components/collapsible-card.css +27 -29
- package/src/styles/components/confirm-dialog.css +13 -14
- package/src/styles/components/dataframe.css +13 -5
- package/src/styles/components/date-picker.css +84 -94
- package/src/styles/components/datetime-picker.css +35 -47
- package/src/styles/components/divider.css +20 -20
- package/src/styles/components/dose-calculator.css +3 -3
- package/src/styles/components/empty-state.css +20 -17
- package/src/styles/components/experiment-code-badge.css +2 -0
- package/src/styles/components/experiment-popover.css +174 -329
- package/src/styles/components/experiment-selector-modal.css +88 -56
- package/src/styles/components/file-picker.css +3 -3
- package/src/styles/components/file-uploader.css +38 -49
- package/src/styles/components/form-builder.css +3 -3
- package/src/styles/components/formula-input.css +1 -1
- package/src/styles/components/icon-button.css +18 -24
- package/src/styles/components/input.css +5 -4
- package/src/styles/components/instrument-monitor.css +13 -15
- package/src/styles/components/jobs-status-tray.css +140 -296
- package/src/styles/components/layout-resize-handle.css +59 -16
- package/src/styles/components/modal.css +5 -7
- package/src/styles/components/molecule-input.css +2 -2
- package/src/styles/components/multi-select.css +65 -117
- package/src/styles/components/number-input.css +26 -19
- package/src/styles/components/onboarding.css +368 -0
- package/src/styles/components/pill.css +3 -2
- package/src/styles/components/plate-editor.css +0 -1
- package/src/styles/components/plugin-icon.css +26 -23
- package/src/styles/components/popover.css +2 -2
- package/src/styles/components/presence-avatars.css +1 -1
- package/src/styles/components/progress-bar.css +3 -3
- package/src/styles/components/protocol-step-editor.css +1 -3
- package/src/styles/components/resource-card.css +2 -2
- package/src/styles/components/resource-picker-list.css +6 -57
- package/src/styles/components/sample-hierarchy-tree.css +4 -4
- package/src/styles/components/sample-selector.css +138 -79
- package/src/styles/components/schedule-calendar.css +8 -8
- package/src/styles/components/searchable-select.css +15 -19
- package/src/styles/components/section-card.css +54 -49
- package/src/styles/components/segmented-control.css +18 -15
- package/src/styles/components/select.css +3 -3
- package/src/styles/components/sequence-input.css +2 -2
- package/src/styles/components/sequence-progress-bar.css +17 -8
- package/src/styles/components/settings-modal.css +7 -2
- package/src/styles/components/smart-group.css +18 -18
- package/src/styles/components/step-wizard.css +52 -16
- package/src/styles/components/tabs.css +2 -2
- package/src/styles/components/textarea.css +3 -3
- package/src/styles/components/time-picker.css +37 -25
- package/src/styles/components/toast.css +13 -11
- package/src/styles/components/toggle.css +1 -11
- package/src/styles/components/tooltip.css +12 -11
- package/src/styles/components/unit-input.css +9 -8
- package/src/styles/components/well-edit-popup.css +2 -2
- package/src/styles/components/well-plate.css +9 -2
- package/src/styles/index.css +1 -0
- package/src/styles/variables.css +247 -78
- package/src/types/componentWorkflowTypes.ts +2 -0
- package/src/types/components.ts +2 -0
- package/src/types/generated/platformContext.ts +1 -0
- package/src/types/generated-ui.ts +4 -0
- package/src/types/index.ts +1 -0
- package/src/types/jobs.ts +10 -0
- package/src/types/platform.ts +1 -1
- package/src/utils/time.ts +21 -0
- package/dist/ActionMenu-CScINahU.js.map +0 -1
- package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
- package/dist/BaseModal-DfRIuVoj.js.map +0 -1
- package/dist/ExperimentPopover-C4sGw-is.js +0 -359
- package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
- package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
- package/dist/SettingsModal-CSLE31yg.js.map +0 -1
- package/dist/data-C2PwI_dn.js.map +0 -1
- package/dist/experiment-43OJtH7R.js.map +0 -1
- package/dist/lab-DLwRl_Ql.js.map +0 -1
- package/dist/records-BzTcxekG.js.map +0 -1
- package/dist/runtime-D6gVat6r.js.map +0 -1
- package/dist/useExperimentSamples-CxcnxZ8h.js.map +0 -1
- package/dist/useListReorder-CcbEYxX-.js.map +0 -1
- package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
- package/dist/useRealtime-PalKue84.js +0 -696
- package/dist/useRealtime-PalKue84.js.map +0 -1
- package/dist/useRequest-D5JDfsgZ.js +0 -76
- package/dist/useRequest-D5JDfsgZ.js.map +0 -1
|
@@ -10,6 +10,7 @@ const mockExperiments: ExperimentSummary[] = [
|
|
|
10
10
|
{
|
|
11
11
|
id: 1,
|
|
12
12
|
experiment_code: 'DR-HeLa-DOX-001',
|
|
13
|
+
created_by: 1,
|
|
13
14
|
name: 'Doxorubicin dose-response in HeLa cells',
|
|
14
15
|
status: 'completed',
|
|
15
16
|
experiment_type: 'dose_response',
|
|
@@ -34,6 +35,7 @@ const mockExperiments: ExperimentSummary[] = [
|
|
|
34
35
|
{
|
|
35
36
|
id: 3,
|
|
36
37
|
experiment_code: 'DR-PANC1-GEM-003',
|
|
38
|
+
created_by: 1,
|
|
37
39
|
name: 'Gemcitabine IC50 in PANC-1',
|
|
38
40
|
status: 'ongoing',
|
|
39
41
|
experiment_type: 'dose_response',
|
|
@@ -70,6 +72,7 @@ const mockExperiments: ExperimentSummary[] = [
|
|
|
70
72
|
{
|
|
71
73
|
id: 6,
|
|
72
74
|
experiment_code: 'SYN-HeLa-COMBO-006',
|
|
75
|
+
created_by: 1,
|
|
73
76
|
name: 'DOX + 5-FU synergy screen in HeLa',
|
|
74
77
|
status: 'planned',
|
|
75
78
|
experiment_type: 'synergy',
|
|
@@ -106,6 +109,7 @@ const mockExperiments: ExperimentSummary[] = [
|
|
|
106
109
|
{
|
|
107
110
|
id: 9,
|
|
108
111
|
experiment_code: 'CV-JURKAT-VIN-009',
|
|
112
|
+
created_by: 1,
|
|
109
113
|
name: 'Vincristine titration Jurkat T-cells',
|
|
110
114
|
status: 'ongoing',
|
|
111
115
|
experiment_type: 'cell_viability',
|
|
@@ -128,9 +132,9 @@ const mockExperiments: ExperimentSummary[] = [
|
|
|
128
132
|
]
|
|
129
133
|
|
|
130
134
|
const mockExperimentTypes = [
|
|
131
|
-
{
|
|
132
|
-
{
|
|
133
|
-
{
|
|
135
|
+
{ value: 'dose_response', label: 'Dose response' },
|
|
136
|
+
{ value: 'cell_viability', label: 'Cell viability' },
|
|
137
|
+
{ value: 'synergy', label: 'Synergy' },
|
|
134
138
|
]
|
|
135
139
|
|
|
136
140
|
const mockProjects = [
|
|
@@ -152,6 +156,7 @@ function applyMockFilters(
|
|
|
152
156
|
const expType = params.get('experiment_type')
|
|
153
157
|
const project = params.get('project')
|
|
154
158
|
const search = params.get('search')?.toLowerCase()
|
|
159
|
+
const mine = params.get('mine') === 'true'
|
|
155
160
|
const createdAfter = params.get('created_after')
|
|
156
161
|
const sortBy = (params.get('sort_by') ?? 'created_at') as ExperimentSortField
|
|
157
162
|
const sortOrder = params.get('sort_order') ?? 'desc'
|
|
@@ -159,6 +164,7 @@ function applyMockFilters(
|
|
|
159
164
|
if (status) filtered = filtered.filter((e) => e.status === status)
|
|
160
165
|
if (expType) filtered = filtered.filter((e) => e.experiment_type === expType)
|
|
161
166
|
if (project) filtered = filtered.filter((e) => e.project === project)
|
|
167
|
+
if (mine) filtered = filtered.filter((e) => e.created_by === 1)
|
|
162
168
|
if (search) {
|
|
163
169
|
filtered = filtered.filter(
|
|
164
170
|
(e) =>
|
|
@@ -208,7 +214,24 @@ onMounted(async () => {
|
|
|
208
214
|
if (url.includes('/projects')) {
|
|
209
215
|
config.adapter = () =>
|
|
210
216
|
Promise.resolve({
|
|
211
|
-
data: mockProjects,
|
|
217
|
+
data: { projects: mockProjects, total: mockProjects.length },
|
|
218
|
+
status: 200,
|
|
219
|
+
statusText: 'OK',
|
|
220
|
+
headers: {},
|
|
221
|
+
config,
|
|
222
|
+
})
|
|
223
|
+
return config
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Status counts: the list filters without status (the route never receives one).
|
|
227
|
+
if (/^(\/api)?\/experiments\/stats(\?|$)/.test(url)) {
|
|
228
|
+
const params = new URLSearchParams(url.split('?')[1] ?? '')
|
|
229
|
+
const filtered = applyMockFilters(mockExperiments, params)
|
|
230
|
+
const by_status: Record<string, number> = { planned: 0, ongoing: 0, completed: 0, cancelled: 0 }
|
|
231
|
+
for (const e of filtered) by_status[e.status] = (by_status[e.status] ?? 0) + 1
|
|
232
|
+
config.adapter = () =>
|
|
233
|
+
Promise.resolve({
|
|
234
|
+
data: { total: filtered.length, by_status },
|
|
212
235
|
status: 200,
|
|
213
236
|
statusText: 'OK',
|
|
214
237
|
headers: {},
|
|
@@ -245,10 +268,10 @@ onMounted(async () => {
|
|
|
245
268
|
|
|
246
269
|
// -- Story state --
|
|
247
270
|
const isOpen = ref(false)
|
|
271
|
+
const isOpenRun = ref(false)
|
|
248
272
|
const isOpenEmpty = ref(false)
|
|
249
|
-
const isOpenGrouped = ref(false)
|
|
250
273
|
const isOpenWithSelection = ref(false)
|
|
251
|
-
const
|
|
274
|
+
const isOpenFilters = ref(false)
|
|
252
275
|
|
|
253
276
|
// The modal commits to the shared store rather than emitting; stories read the
|
|
254
277
|
// selection back from the same place a plugin would.
|
|
@@ -262,7 +285,7 @@ const selectedExperiment = computed(() => experimentStore.current)
|
|
|
262
285
|
<template #default="{ state }">
|
|
263
286
|
<div style="padding: 2rem;">
|
|
264
287
|
<button
|
|
265
|
-
style="padding: 0.5rem 1rem; background: var(--color-primary
|
|
288
|
+
style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
|
|
266
289
|
@click="isOpen = true"
|
|
267
290
|
>
|
|
268
291
|
Open Experiment Selector
|
|
@@ -287,6 +310,7 @@ const selectedExperiment = computed(() => experimentStore.current)
|
|
|
287
310
|
v-model:open="isOpen"
|
|
288
311
|
:experiment-type="state.experimentType || undefined"
|
|
289
312
|
:title="state.title"
|
|
313
|
+
:size="state.size || undefined"
|
|
290
314
|
:current-experiment-id="selectedExperiment?.id ?? null"
|
|
291
315
|
/>
|
|
292
316
|
</div>
|
|
@@ -294,68 +318,86 @@ const selectedExperiment = computed(() => experimentStore.current)
|
|
|
294
318
|
|
|
295
319
|
<template #controls="{ state }">
|
|
296
320
|
<HstCheckbox v-model="isOpen" title="Open" />
|
|
321
|
+
<HstSelect v-model="state.size" title="Size (default lg)" :options="['', 'md', 'lg', 'xl', 'full']" />
|
|
297
322
|
<HstText v-model="state.title" title="Title" />
|
|
298
323
|
<HstText v-model="state.experimentType" title="Experiment Type" />
|
|
299
324
|
</template>
|
|
300
325
|
</Variant>
|
|
301
326
|
|
|
302
|
-
<Variant title="
|
|
327
|
+
<Variant title="Active Filters">
|
|
303
328
|
<div style="padding: 2rem;">
|
|
304
|
-
<p style="font-size: 0.8125rem; color: var(--text-muted
|
|
305
|
-
|
|
329
|
+
<p style="font-size: 0.8125rem; color: var(--text-muted); margin: 0 0 1rem;">
|
|
330
|
+
Pick a status (each option shows its count), pick a project or press Mine: the trigger
|
|
331
|
+
fills with the accent tint and "Clear N" appears. Mine keeps the experiments of user 1.
|
|
306
332
|
</p>
|
|
307
333
|
<button
|
|
308
|
-
style="padding: 0.5rem 1rem; background: var(--color-primary
|
|
309
|
-
@click="
|
|
334
|
+
style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
|
|
335
|
+
@click="isOpenFilters = true"
|
|
310
336
|
>
|
|
311
337
|
Open With Filters
|
|
312
338
|
</button>
|
|
313
339
|
|
|
314
340
|
<ExperimentSelectorModal
|
|
315
|
-
v-model:open="
|
|
341
|
+
v-model:open="isOpenFilters"
|
|
316
342
|
title="Select Experiment"
|
|
317
|
-
:show-filters="true"
|
|
318
343
|
/>
|
|
319
344
|
</div>
|
|
320
345
|
</Variant>
|
|
321
346
|
|
|
322
|
-
<Variant title="
|
|
347
|
+
<Variant title="With Clear Selection">
|
|
323
348
|
<div style="padding: 2rem;">
|
|
324
349
|
<p style="font-size: 0.8125rem; color: var(--text-muted, #94a3b8); margin: 0 0 1rem;">
|
|
325
|
-
|
|
350
|
+
Shows the "Clear selection" footer when an experiment is selected.
|
|
326
351
|
</p>
|
|
327
352
|
<button
|
|
328
|
-
style="padding: 0.5rem 1rem; background: var(--color-primary
|
|
329
|
-
@click="
|
|
353
|
+
style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
|
|
354
|
+
@click="isOpenWithSelection = true"
|
|
330
355
|
>
|
|
331
|
-
Open
|
|
356
|
+
Open Selector (with selection)
|
|
332
357
|
</button>
|
|
333
358
|
|
|
334
359
|
<ExperimentSelectorModal
|
|
335
|
-
v-model:open="
|
|
360
|
+
v-model:open="isOpenWithSelection"
|
|
336
361
|
title="Select Experiment"
|
|
337
|
-
:
|
|
362
|
+
:current-experiment-id="1"
|
|
338
363
|
/>
|
|
339
364
|
</div>
|
|
340
365
|
</Variant>
|
|
341
366
|
|
|
342
|
-
<Variant title="
|
|
367
|
+
<Variant title="Run Destination (slots)">
|
|
343
368
|
<div style="padding: 2rem;">
|
|
344
369
|
<p style="font-size: 0.8125rem; color: var(--text-muted, #94a3b8); margin: 0 0 1rem;">
|
|
345
|
-
|
|
370
|
+
A plugin asks where to save a run: the description slot explains why, and the footer slot adds Skip with close().
|
|
346
371
|
</p>
|
|
347
372
|
<button
|
|
348
|
-
style="padding: 0.5rem 1rem; background: var(--color-primary
|
|
349
|
-
@click="
|
|
373
|
+
style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
|
|
374
|
+
@click="isOpenRun = true"
|
|
350
375
|
>
|
|
351
|
-
|
|
376
|
+
Run extraction
|
|
352
377
|
</button>
|
|
353
378
|
|
|
354
379
|
<ExperimentSelectorModal
|
|
355
|
-
v-model:open="
|
|
356
|
-
title="
|
|
357
|
-
|
|
358
|
-
|
|
380
|
+
v-model:open="isOpenRun"
|
|
381
|
+
title="Save the result to an experiment?"
|
|
382
|
+
>
|
|
383
|
+
<template #description>
|
|
384
|
+
Pick an experiment to save this run as a new artifact in it, next to the samples it belongs to.
|
|
385
|
+
</template>
|
|
386
|
+
<template #footer="{ close }">
|
|
387
|
+
<div style="display: flex; align-items: center; gap: 0.75rem;">
|
|
388
|
+
<span style="flex: 1; font-size: 0.75rem; color: var(--text-secondary);">
|
|
389
|
+
Skip: the result stays in the plugin. You can save it to an experiment later.
|
|
390
|
+
</span>
|
|
391
|
+
<button
|
|
392
|
+
type="button"
|
|
393
|
+
style="height: 2rem; padding: 0 0.75rem; border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-card); color: var(--text-primary); cursor: pointer;"
|
|
394
|
+
@click="close"
|
|
395
|
+
>
|
|
396
|
+
Skip
|
|
397
|
+
</button>
|
|
398
|
+
</div>
|
|
399
|
+
</template>
|
|
400
|
+
</ExperimentSelectorModal>
|
|
359
401
|
</div>
|
|
360
402
|
</Variant>
|
|
361
403
|
|
|
@@ -365,7 +407,7 @@ const selectedExperiment = computed(() => experimentStore.current)
|
|
|
365
407
|
Filters to a non-existent experiment type, showing the empty state.
|
|
366
408
|
</p>
|
|
367
409
|
<button
|
|
368
|
-
style="padding: 0.5rem 1rem; background: var(--color-primary
|
|
410
|
+
style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
|
|
369
411
|
@click="isOpenEmpty = true"
|
|
370
412
|
>
|
|
371
413
|
Open Experiment Selector (Empty)
|
|
@@ -7,18 +7,15 @@
|
|
|
7
7
|
* <ExperimentSelectorModal v-model:open="open" :allowed-experiment-types="['mass-spectrometry']" />
|
|
8
8
|
* ```
|
|
9
9
|
*/
|
|
10
|
-
import { ref, computed, watch } from 'vue'
|
|
11
|
-
import
|
|
10
|
+
import { ref, computed, watch, type Component } from 'vue'
|
|
11
|
+
import { ChevronDown, CircleDot, Folder, Shapes, User } from 'lucide-vue-next'
|
|
12
|
+
import type { ModalSize, ExperimentSummary, ExperimentFilters, ActionMenuItem, Tone } from '../types'
|
|
12
13
|
import { useExperimentSelector } from '../composables/useExperimentSelector'
|
|
13
14
|
import { useExperimentStore } from '../stores/experiment'
|
|
14
|
-
import {
|
|
15
|
-
formatExperimentDate,
|
|
16
|
-
DATE_PRESET_OPTIONS,
|
|
17
|
-
SORT_OPTIONS,
|
|
18
|
-
} from '../composables/experiment-utils'
|
|
15
|
+
import { formatExperimentDate } from '../composables/experiment-utils'
|
|
19
16
|
import * as experimentStatus from '../utils/experimentStatus'
|
|
20
17
|
import BaseModal from './BaseModal.vue'
|
|
21
|
-
import
|
|
18
|
+
import ActionMenu from './ActionMenu.vue'
|
|
22
19
|
import ResourcePickerListInternal from './internal/ResourcePickerListInternal.vue'
|
|
23
20
|
|
|
24
21
|
interface Props {
|
|
@@ -28,16 +25,12 @@ interface Props {
|
|
|
28
25
|
currentExperimentId?: number | null
|
|
29
26
|
title?: string
|
|
30
27
|
size?: ModalSize
|
|
31
|
-
groupByProject?: boolean
|
|
32
|
-
showFilters?: boolean
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
const props = withDefaults(defineProps<Props>(), {
|
|
36
31
|
currentExperimentId: null,
|
|
37
32
|
title: 'Select Experiment',
|
|
38
|
-
size: '
|
|
39
|
-
groupByProject: false,
|
|
40
|
-
showFilters: false,
|
|
33
|
+
size: 'lg',
|
|
41
34
|
})
|
|
42
35
|
|
|
43
36
|
// Selection is committed to the shared experiment store rather than emitted.
|
|
@@ -47,6 +40,17 @@ const emit = defineEmits<{
|
|
|
47
40
|
'update:open': [value: boolean]
|
|
48
41
|
}>()
|
|
49
42
|
|
|
43
|
+
defineSlots<{
|
|
44
|
+
/** Text above the experiment list: why the caller asks for an experiment. */
|
|
45
|
+
description?: () => unknown
|
|
46
|
+
/** Extra footer content, before Clear selection. `close()` closes the modal without a selection. */
|
|
47
|
+
footer?: (props: { close: () => void }) => unknown
|
|
48
|
+
}>()
|
|
49
|
+
|
|
50
|
+
function close() {
|
|
51
|
+
emit('update:open', false)
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
const experimentStore = useExperimentStore()
|
|
51
55
|
|
|
52
56
|
const {
|
|
@@ -54,55 +58,102 @@ const {
|
|
|
54
58
|
filters,
|
|
55
59
|
isLoading,
|
|
56
60
|
error,
|
|
57
|
-
sortKey,
|
|
58
61
|
experimentTypes,
|
|
59
62
|
projects,
|
|
60
|
-
|
|
63
|
+
statusCounts,
|
|
61
64
|
fetch: fetchExperiments,
|
|
62
65
|
fetchFilterOptions,
|
|
66
|
+
fetchStatusCounts,
|
|
63
67
|
} = useExperimentSelector({
|
|
64
68
|
experimentType: props.experimentType,
|
|
65
69
|
allowedExperimentTypes: props.allowedExperimentTypes,
|
|
70
|
+
withStatusCounts: true,
|
|
66
71
|
})
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
const groupToggle = ref(props.groupByProject)
|
|
70
|
-
// Re-mounting the list on open clears its collapsed groups and keyboard highlight.
|
|
73
|
+
// Re-mounting the list on open clears its keyboard highlight.
|
|
71
74
|
const openCount = ref(0)
|
|
72
75
|
|
|
73
|
-
|
|
74
|
-
const hasActiveAdvancedFilters = computed(() =>
|
|
75
|
-
!!(filters.project || filters.experimentType || filters.datePreset || sortKey.value !== 'created_at:desc'),
|
|
76
|
-
)
|
|
76
|
+
const STATUS_ORDER = ['ongoing', 'planned', 'completed', 'cancelled'] as const
|
|
77
77
|
|
|
78
|
-
// Build type filter options from fetched experiment types
|
|
79
|
-
const typeFilterOptions = computed(() => [
|
|
80
|
-
{ value: '', label: 'All types' },
|
|
81
|
-
...experimentTypes.value.map(t => ({ value: t.value, label: t.label })),
|
|
82
|
-
])
|
|
83
78
|
const canChooseExperimentType = computed(() =>
|
|
84
|
-
!props.experimentType &&
|
|
79
|
+
!props.experimentType && experimentTypes.value.length > 1,
|
|
85
80
|
)
|
|
86
81
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
type FilterKey = 'status' | 'project' | 'experimentType'
|
|
83
|
+
|
|
84
|
+
interface FilterMenu {
|
|
85
|
+
key: FilterKey
|
|
86
|
+
label: string
|
|
87
|
+
icon: Component
|
|
88
|
+
items: ActionMenuItem[]
|
|
89
|
+
/** Trigger text while the filter is set. */
|
|
90
|
+
activeLabel?: string
|
|
91
|
+
dotTone?: Tone
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Every item carries `checked`, so ActionMenu renders a single-choice menu. */
|
|
95
|
+
function choiceItems(key: FilterKey, anyLabel: string, options: { value: string; label: string }[]): ActionMenuItem[] {
|
|
96
|
+
const current = filters[key] ?? ''
|
|
97
|
+
return [{ value: '', label: anyLabel }, ...options].map(option => ({
|
|
98
|
+
id: option.value,
|
|
99
|
+
label: option.label,
|
|
100
|
+
checked: option.value === current,
|
|
101
|
+
}))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const filterMenus = computed<FilterMenu[]>(() => {
|
|
105
|
+
const menus: FilterMenu[] = [{
|
|
106
|
+
key: 'status',
|
|
107
|
+
label: 'Status',
|
|
108
|
+
icon: CircleDot,
|
|
109
|
+
items: choiceItems('status', 'Any status', STATUS_ORDER.map(status => {
|
|
110
|
+
const count = statusCounts.value[status]
|
|
111
|
+
const label = experimentStatus.format(status)
|
|
112
|
+
return { value: status, label: count === undefined ? label : `${label} · ${count}` }
|
|
113
|
+
})),
|
|
114
|
+
activeLabel: filters.status ? experimentStatus.format(filters.status) : undefined,
|
|
115
|
+
dotTone: filters.status ? experimentStatus.tone(filters.status) : undefined,
|
|
116
|
+
}]
|
|
117
|
+
if (projects.value.length) {
|
|
118
|
+
menus.push({
|
|
119
|
+
key: 'project',
|
|
120
|
+
label: 'Project',
|
|
121
|
+
icon: Folder,
|
|
122
|
+
items: choiceItems('project', 'Any project', projects.value),
|
|
123
|
+
activeLabel: filters.project ?? undefined,
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
if (canChooseExperimentType.value) {
|
|
127
|
+
menus.push({
|
|
128
|
+
key: 'experimentType',
|
|
129
|
+
label: 'Type',
|
|
130
|
+
icon: Shapes,
|
|
131
|
+
items: choiceItems('experimentType', 'Any type', experimentTypes.value),
|
|
132
|
+
activeLabel: experimentTypes.value.find(t => t.value === filters.experimentType)?.label
|
|
133
|
+
?? filters.experimentType ?? undefined,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
return menus
|
|
137
|
+
})
|
|
92
138
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
? groupedByProject.value.map(([label, items]) => ({ label, items }))
|
|
96
|
-
: null,
|
|
139
|
+
const activeFilterCount = computed(() =>
|
|
140
|
+
[filters.status, filters.project, filters.experimentType, filters.mine].filter(Boolean).length,
|
|
97
141
|
)
|
|
98
142
|
|
|
143
|
+
function clearFilters() {
|
|
144
|
+
filters.status = undefined
|
|
145
|
+
filters.project = undefined
|
|
146
|
+
filters.experimentType = undefined
|
|
147
|
+
filters.mine = undefined
|
|
148
|
+
}
|
|
149
|
+
|
|
99
150
|
function describe(experiment: ExperimentSummary) {
|
|
100
151
|
const owner = experiment.created_by_user
|
|
101
152
|
return {
|
|
102
153
|
code: experiment.experiment_code,
|
|
103
154
|
title: experiment.name,
|
|
104
155
|
meta: [
|
|
105
|
-
|
|
156
|
+
experiment.project_name || experiment.project || '',
|
|
106
157
|
owner ? [owner.first_name, owner.last_name].filter(Boolean).join(' ') || owner.username : '',
|
|
107
158
|
].filter(Boolean),
|
|
108
159
|
status: experiment.status
|
|
@@ -116,10 +167,6 @@ function setFilter<K extends keyof ExperimentFilters>(key: K, value: string | nu
|
|
|
116
167
|
;(filters as Record<string, unknown>)[key] = String(value) || undefined
|
|
117
168
|
}
|
|
118
169
|
|
|
119
|
-
function handleSortChange(value: string | number) {
|
|
120
|
-
sortKey.value = String(value) || 'created_at:desc'
|
|
121
|
-
}
|
|
122
|
-
|
|
123
170
|
function handleSelect(experiment: ExperimentSummary) {
|
|
124
171
|
experimentStore.select(experiment)
|
|
125
172
|
emit('update:open', false)
|
|
@@ -138,6 +185,7 @@ watch(
|
|
|
138
185
|
openCount.value++
|
|
139
186
|
fetchFilterOptions()
|
|
140
187
|
fetchExperiments()
|
|
188
|
+
fetchStatusCounts()
|
|
141
189
|
}
|
|
142
190
|
},
|
|
143
191
|
{ immediate: true },
|
|
@@ -151,14 +199,18 @@ watch(
|
|
|
151
199
|
:size="size"
|
|
152
200
|
@update:open="emit('update:open', $event)"
|
|
153
201
|
>
|
|
202
|
+
<div v-if="$slots.description" class="mint-experiment-selector__description">
|
|
203
|
+
<slot name="description" />
|
|
204
|
+
</div>
|
|
205
|
+
|
|
154
206
|
<ResourcePickerListInternal
|
|
155
207
|
:key="openCount"
|
|
156
208
|
:search="filters.search ?? ''"
|
|
157
209
|
class="mint-experiment-selector"
|
|
210
|
+
autofocus-search
|
|
158
211
|
label="Experiments"
|
|
159
212
|
placeholder="Search experiments…"
|
|
160
213
|
:items="experiments"
|
|
161
|
-
:groups="groups"
|
|
162
214
|
:item-key="(experiment) => experiment.id"
|
|
163
215
|
:describe="describe"
|
|
164
216
|
:selected-key="currentExperimentId"
|
|
@@ -169,82 +221,63 @@ watch(
|
|
|
169
221
|
@select="handleSelect"
|
|
170
222
|
>
|
|
171
223
|
<template #filters>
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
224
|
+
<ActionMenu
|
|
225
|
+
v-for="menu in filterMenus"
|
|
226
|
+
:key="menu.key"
|
|
227
|
+
:label="menu.label"
|
|
228
|
+
:items="menu.items"
|
|
229
|
+
@select="item => setFilter(menu.key, item.id)"
|
|
230
|
+
>
|
|
231
|
+
<template #trigger="{ open: menuOpen, toggle, keydown }">
|
|
232
|
+
<button
|
|
233
|
+
type="button"
|
|
234
|
+
class="mint-experiment-selector__toggle"
|
|
235
|
+
:class="{ 'mint-experiment-selector__toggle--active': menu.activeLabel }"
|
|
236
|
+
:aria-label="`${menu.label}: ${menu.activeLabel ?? menu.items[0].label}`"
|
|
237
|
+
aria-haspopup="menu"
|
|
238
|
+
:aria-expanded="menuOpen"
|
|
239
|
+
@click="toggle"
|
|
240
|
+
@keydown="keydown"
|
|
241
|
+
>
|
|
242
|
+
<span
|
|
243
|
+
v-if="menu.dotTone"
|
|
244
|
+
class="mint-experiment-selector__dot"
|
|
245
|
+
:class="`mint-experiment-selector__dot--${menu.dotTone}`"
|
|
246
|
+
aria-hidden="true"
|
|
247
|
+
/>
|
|
248
|
+
<component :is="menu.icon" v-else :size="13" aria-hidden="true" />
|
|
249
|
+
<span class="mint-experiment-selector__toggle-label">{{ menu.activeLabel ?? menu.label }}</span>
|
|
250
|
+
<ChevronDown :size="12" aria-hidden="true" />
|
|
251
|
+
</button>
|
|
252
|
+
</template>
|
|
253
|
+
</ActionMenu>
|
|
190
254
|
<button
|
|
191
|
-
class="mint-experiment-selector__filters-toggle"
|
|
192
|
-
:class="{ 'mint-experiment-selector__filters-toggle--active': hasActiveAdvancedFilters }"
|
|
193
255
|
type="button"
|
|
194
|
-
|
|
195
|
-
|
|
256
|
+
class="mint-experiment-selector__toggle"
|
|
257
|
+
:class="{ 'mint-experiment-selector__toggle--active': filters.mine }"
|
|
258
|
+
:aria-pressed="!!filters.mine"
|
|
259
|
+
@click="filters.mine = filters.mine ? undefined : true"
|
|
196
260
|
>
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
261
|
+
<User :size="13" aria-hidden="true" />
|
|
262
|
+
Mine
|
|
263
|
+
</button>
|
|
264
|
+
<button
|
|
265
|
+
v-if="activeFilterCount"
|
|
266
|
+
type="button"
|
|
267
|
+
class="mint-experiment-selector__clear-filters"
|
|
268
|
+
@click="clearFilters"
|
|
269
|
+
>
|
|
270
|
+
Clear {{ activeFilterCount }}
|
|
203
271
|
</button>
|
|
204
|
-
</template>
|
|
205
|
-
<template #advanced>
|
|
206
|
-
<div v-if="showAdvanced" class="mint-experiment-selector__filters-advanced">
|
|
207
|
-
<div v-if="projectFilterOptions.length > 1" class="mint-experiment-selector__filter-select">
|
|
208
|
-
<BaseSelect
|
|
209
|
-
:model-value="filters.project ?? ''"
|
|
210
|
-
:options="projectFilterOptions"
|
|
211
|
-
size="sm"
|
|
212
|
-
aria-label="Filter by project"
|
|
213
|
-
@update:model-value="v => setFilter('project', v)"
|
|
214
|
-
/>
|
|
215
|
-
</div>
|
|
216
|
-
<div class="mint-experiment-selector__filter-select">
|
|
217
|
-
<BaseSelect
|
|
218
|
-
:model-value="filters.datePreset ?? ''"
|
|
219
|
-
:options="DATE_PRESET_OPTIONS"
|
|
220
|
-
size="sm"
|
|
221
|
-
aria-label="Filter by date"
|
|
222
|
-
@update:model-value="v => setFilter('datePreset', v)"
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
<div class="mint-experiment-selector__filter-select">
|
|
226
|
-
<BaseSelect
|
|
227
|
-
:model-value="sortKey"
|
|
228
|
-
:options="SORT_OPTIONS"
|
|
229
|
-
size="sm"
|
|
230
|
-
aria-label="Sort"
|
|
231
|
-
@update:model-value="handleSortChange"
|
|
232
|
-
/>
|
|
233
|
-
</div>
|
|
234
|
-
<label class="mint-experiment-selector__group-toggle">
|
|
235
|
-
<input
|
|
236
|
-
v-model="groupToggle"
|
|
237
|
-
type="checkbox"
|
|
238
|
-
class="mint-experiment-selector__group-checkbox"
|
|
239
|
-
/>
|
|
240
|
-
Group by project
|
|
241
|
-
</label>
|
|
242
|
-
</div>
|
|
243
272
|
</template>
|
|
244
273
|
</ResourcePickerListInternal>
|
|
245
274
|
|
|
246
|
-
<div v-if="currentExperimentId != null" class="mint-experiment-selector__footer">
|
|
275
|
+
<div v-if="$slots.footer || currentExperimentId != null" class="mint-experiment-selector__footer">
|
|
276
|
+
<div v-if="$slots.footer" class="mint-experiment-selector__footer-slot">
|
|
277
|
+
<slot name="footer" :close="close" />
|
|
278
|
+
</div>
|
|
247
279
|
<button
|
|
280
|
+
v-if="currentExperimentId != null"
|
|
248
281
|
type="button"
|
|
249
282
|
class="mint-experiment-selector__clear-btn"
|
|
250
283
|
@click="handleDeselect"
|