@morscherlab/mint-sdk 1.0.0-rc.1 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/__tests__/components/LcmsSequenceTable.test.d.ts +1 -0
- package/dist/__tests__/components/ProgressBar.test.d.ts +1 -0
- package/dist/__tests__/components/RackEditor.test.d.ts +1 -0
- package/dist/__tests__/components/SequenceProgressBar.test.d.ts +1 -0
- package/dist/__tests__/composables/useExperimentSamples.test.d.ts +1 -0
- package/dist/__tests__/utils/instrument.test.d.ts +1 -0
- package/dist/__tests__/utils/lcms.test.d.ts +1 -0
- package/dist/__tests__/utils/permissions.test.d.ts +1 -0
- package/dist/__tests__/utils/rack.test.d.ts +1 -0
- package/dist/{auth-CBG3bWEc.js → auth-B7g4J4ZF.js} +99 -5
- package/dist/auth-B7g4J4ZF.js.map +1 -0
- package/dist/components/AppSidebar.vue.d.ts +3 -3
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +1 -1
- package/dist/components/BaseToggle.vue.d.ts +2 -2
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
- package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +1 -1
- package/dist/components/ControlWorkspaceView.vue.d.ts +3 -3
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +2 -2
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/InstrumentAlertLog.vue.d.ts +22 -0
- package/dist/components/InstrumentStateBadge.vue.d.ts +11 -0
- package/dist/components/InstrumentStatusCard.vue.d.ts +13 -0
- package/dist/components/LcmsSequenceTable.vue.d.ts +26 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +3 -3
- package/dist/components/ProgressBar.vue.d.ts +1 -0
- package/dist/components/RackEditor.vue.d.ts +41 -3
- package/dist/components/ReagentList.vue.d.ts +1 -1
- package/dist/components/SampleSelector.vue.d.ts +5 -2
- package/dist/components/SegmentedControl.vue.d.ts +2 -0
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/SequenceProgressBar.vue.d.ts +15 -0
- package/dist/components/SettingsModal.vue.d.ts +3 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.vue.d.ts +42 -3
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +3 -3
- package/dist/{components-5KSfsVqf.js → components-DafPc4rM.js} +2091 -1051
- package/dist/components-DafPc4rM.js.map +1 -0
- package/dist/composables/controlComponentBindings.d.ts +7 -0
- package/dist/composables/controlSchemaAdapters.d.ts +20 -0
- package/dist/composables/controlSchemaFormFields.d.ts +3 -0
- package/dist/composables/controlSchemaLayout.d.ts +7 -0
- package/dist/composables/controlSchemaNormalize.d.ts +15 -0
- package/dist/composables/controlSchemaUtils.d.ts +9 -0
- package/dist/composables/controlWorkspaceOptions.d.ts +2 -0
- package/dist/composables/experimentDesignData.d.ts +17 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +4 -4
- package/dist/composables/useControlSchema.d.ts +15 -30
- package/dist/composables/useControlWorkspace.d.ts +5 -0
- package/dist/composables/useExperimentData.d.ts +11 -3
- package/dist/composables/useExperimentSamples.d.ts +42 -0
- package/dist/composables/usePlatformContext.d.ts +54 -0
- package/dist/{composables-D4Myb30a.js → composables-BMkPQhVK.js} +5 -3
- package/dist/composables-BMkPQhVK.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +168 -6
- package/dist/index.js.map +1 -0
- package/dist/install.js +2 -2
- package/dist/instrument.d.ts +7 -0
- package/dist/lcms.d.ts +27 -0
- package/dist/permissions.d.ts +46 -0
- package/dist/stores/auth.d.ts +74 -2
- package/dist/stores/index.js +1 -1
- package/dist/styles.css +3316 -1216
- package/dist/templates/adapters.d.ts +14 -47
- package/dist/templates/assayLookups.d.ts +3 -0
- package/dist/templates/assayMatrixAdapters.d.ts +6 -0
- package/dist/templates/assayMatrixBuilder.d.ts +2 -0
- package/dist/templates/assayNormalizers.d.ts +4 -0
- package/dist/templates/builderDefaults.d.ts +1 -0
- package/dist/templates/builderIdUtils.d.ts +4 -0
- package/dist/templates/builderPresetControls.d.ts +10 -0
- package/dist/templates/builderReadUtils.d.ts +8 -0
- package/dist/templates/builders.d.ts +26 -63
- package/dist/templates/calibrationCurveAdapters.d.ts +4 -0
- package/dist/templates/calibrationCurveBuilder.d.ts +2 -0
- package/dist/templates/calibrationNormalizers.d.ts +5 -0
- package/dist/templates/componentBindingCatalog.d.ts +25 -0
- package/dist/templates/componentBindingHelpers.d.ts +17 -0
- package/dist/templates/componentDoseResponseProps.d.ts +3 -0
- package/dist/templates/componentGenericProps.d.ts +8 -0
- package/dist/templates/componentPlateHelpers.d.ts +5 -0
- package/dist/templates/componentPlateMapProps.d.ts +3 -0
- package/dist/templates/componentPropsFactory.d.ts +3 -0
- package/dist/templates/componentQpcrPlateProps.d.ts +3 -0
- package/dist/templates/componentTargetResolvers.d.ts +5 -0
- package/dist/templates/componentTemplateProps.d.ts +3 -0
- package/dist/templates/controlSchemaClone.d.ts +4 -0
- package/dist/templates/controlSchemaConstants.d.ts +10 -0
- package/dist/templates/controlSchemaMerge.d.ts +3 -0
- package/dist/templates/controlSchemaTargets.d.ts +17 -0
- package/dist/templates/controlSchemaTypes.d.ts +4 -0
- package/dist/templates/controlSchemas.d.ts +4 -4
- package/dist/templates/defaultBioTemplateBuilder.d.ts +2 -0
- package/dist/templates/doseResponseAdapters.d.ts +4 -0
- package/dist/templates/doseResponseBuilder.d.ts +2 -0
- package/dist/templates/elisaAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryPanelBuilder.d.ts +2 -0
- package/dist/templates/flowNormalizers.d.ts +8 -0
- package/dist/templates/flowPanelAdapters.d.ts +4 -0
- package/dist/templates/index.d.ts +2 -2
- package/dist/templates/index.js +2 -2
- package/dist/templates/instrumentRunAdapterHelpers.d.ts +8 -0
- package/dist/templates/instrumentRunAdapters.d.ts +8 -0
- package/dist/templates/instrumentRunBuilder.d.ts +2 -0
- package/dist/templates/lcmsBatchCollectionBuilder.d.ts +2 -0
- package/dist/templates/plateGeometry.d.ts +4 -0
- package/dist/templates/plateMapAdapters.d.ts +3 -0
- package/dist/templates/plateMapBuilder.d.ts +2 -0
- package/dist/templates/presetControlSchemas.d.ts +534 -0
- package/dist/templates/presets.d.ts +12 -0
- package/dist/templates/protocolAdapters.d.ts +5 -0
- package/dist/templates/protocolNormalizers.d.ts +6 -0
- package/dist/templates/protocolStepsBuilder.d.ts +2 -0
- package/dist/templates/qpcrAdapters.d.ts +5 -0
- package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +2 -0
- package/dist/templates/qpcrPlateBuilder.d.ts +2 -0
- package/dist/templates/reagentAdapters.d.ts +5 -0
- package/dist/templates/reagentListBuilder.d.ts +2 -0
- package/dist/templates/runNormalizers.d.ts +10 -0
- package/dist/templates/sampleNormalizers.d.ts +4 -0
- package/dist/templates/samplePrepAdapters.d.ts +4 -0
- package/dist/templates/samplePrepBuilder.d.ts +2 -0
- package/dist/templates/sampleSheetAdapters.d.ts +5 -0
- package/dist/templates/sampleSheetBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsHelpers.d.ts +5 -0
- package/dist/templates/templateControlSchemas.d.ts +400 -0
- package/dist/templates/templateEnvelopes.d.ts +9 -0
- package/dist/templates/templatePackCollectionBuilder.d.ts +2 -0
- package/dist/templates/templatePresetCollectionBuilder.d.ts +18 -0
- package/dist/templates/templateValidators.d.ts +13 -0
- package/dist/templates/timeCourseAdapters.d.ts +5 -0
- package/dist/templates/timeCourseBuilder.d.ts +2 -0
- package/dist/templates/types.d.ts +16 -1
- package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +2 -0
- package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +2 -0
- package/dist/{templates-BSlxwV2c.js → templates-bUAWMn5L.js} +3610 -3154
- package/dist/templates-bUAWMn5L.js.map +1 -0
- package/dist/types/auth.d.ts +2 -0
- package/dist/types/components.d.ts +32 -3
- package/dist/types/form-builder.d.ts +2 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/instrument.d.ts +56 -0
- package/dist/types/platform.d.ts +3 -0
- package/dist/{useExperimentData-BbbdI5xT.js → useProtocolTemplates-QZtHFFH2.js} +534 -359
- package/dist/useProtocolTemplates-QZtHFFH2.js.map +1 -0
- package/dist/utils/rack.d.ts +47 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.test.ts +15 -0
- package/src/__tests__/components/BaseTabs.test.ts +15 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +57 -0
- package/src/__tests__/components/ProgressBar.test.ts +18 -0
- package/src/__tests__/components/RackEditor.test.ts +125 -0
- package/src/__tests__/components/SampleSelector.test.ts +25 -0
- package/src/__tests__/components/SegmentedControl.test.ts +45 -0
- package/src/__tests__/components/SequenceProgressBar.test.ts +39 -0
- package/src/__tests__/components/SettingsModal.test.ts +83 -2
- package/src/__tests__/composables/useControlSchema.test.ts +4 -0
- package/src/__tests__/composables/useExperimentData.test.ts +23 -0
- package/src/__tests__/composables/useExperimentSamples.test.ts +91 -0
- package/src/__tests__/templates/templates.test.ts +86 -0
- package/src/__tests__/utils/instrument.test.ts +47 -0
- package/src/__tests__/utils/lcms.test.ts +73 -0
- package/src/__tests__/utils/permissions.test.ts +50 -0
- package/src/__tests__/utils/rack.test.ts +120 -0
- package/src/components/AppTopBar.vue +1 -0
- package/src/components/BaseTabs.vue +22 -1
- package/src/components/InstrumentAlertLog.vue +191 -0
- package/src/components/InstrumentStateBadge.vue +50 -0
- package/src/components/InstrumentStatusCard.vue +188 -0
- package/src/components/LcmsSequenceTable.vue +191 -0
- package/src/components/ProgressBar.vue +3 -0
- package/src/components/RackEditor.vue +73 -2
- package/src/components/SampleSelector.vue +28 -9
- package/src/components/SegmentedControl.story.vue +17 -0
- package/src/components/SegmentedControl.vue +14 -3
- package/src/components/SequenceProgressBar.vue +71 -0
- package/src/components/SettingsModal.vue +42 -2
- package/src/components/WellPlate.vue +142 -21
- package/src/components/index.ts +5 -0
- package/src/components/internal/WellEditPopupInternal.vue +1 -0
- package/src/composables/controlComponentBindings.ts +80 -0
- package/src/composables/controlSchemaAdapters.ts +196 -0
- package/src/composables/controlSchemaFormFields.ts +61 -0
- package/src/composables/controlSchemaLayout.ts +59 -0
- package/src/composables/controlSchemaNormalize.ts +101 -0
- package/src/composables/controlSchemaUtils.ts +36 -0
- package/src/composables/controlWorkspaceOptions.ts +21 -0
- package/src/composables/experimentDesignData.ts +182 -0
- package/src/composables/index.ts +14 -0
- package/src/composables/useAuth.ts +4 -0
- package/src/composables/useAutoGroup.ts +5 -1
- package/src/composables/useControlSchema.ts +62 -618
- package/src/composables/useControlWorkspace.ts +207 -0
- package/src/composables/useExperimentData.ts +57 -16
- package/src/composables/useExperimentSamples.ts +142 -0
- package/src/index.ts +27 -0
- package/src/instrument.ts +90 -0
- package/src/lcms.ts +108 -0
- package/src/permissions.ts +143 -0
- package/src/stores/auth.ts +31 -3
- package/src/styles/components/instrument-monitor.css +478 -0
- package/src/styles/components/lcms-sequence-table.css +189 -0
- package/src/styles/components/sequence-progress-bar.css +63 -0
- package/src/styles/components/tabs.css +9 -0
- package/src/styles/components/well-edit-popup.css +7 -1
- package/src/styles/components/well-plate.css +5 -0
- package/src/styles/index.css +3 -0
- package/src/templates/adapters.ts +89 -930
- package/src/templates/assayLookups.ts +33 -0
- package/src/templates/assayMatrixAdapters.ts +78 -0
- package/src/templates/assayMatrixBuilder.ts +59 -0
- package/src/templates/assayNormalizers.ts +34 -0
- package/src/templates/builderDefaults.ts +11 -0
- package/src/templates/builderIdUtils.ts +20 -0
- package/src/templates/builderPresetControls.ts +165 -0
- package/src/templates/builderReadUtils.ts +57 -0
- package/src/templates/builders.ts +122 -2149
- package/src/templates/calibrationCurveAdapters.ts +59 -0
- package/src/templates/calibrationCurveBuilder.ts +99 -0
- package/src/templates/calibrationNormalizers.ts +60 -0
- package/src/templates/componentBindingCatalog.ts +90 -0
- package/src/templates/componentBindingHelpers.ts +93 -0
- package/src/templates/componentBindings.ts +12 -461
- package/src/templates/componentDoseResponseProps.ts +42 -0
- package/src/templates/componentGenericProps.ts +77 -0
- package/src/templates/componentPlateHelpers.ts +29 -0
- package/src/templates/componentPlateMapProps.ts +32 -0
- package/src/templates/componentPropsFactory.ts +21 -0
- package/src/templates/componentQpcrPlateProps.ts +28 -0
- package/src/templates/componentTargetResolvers.ts +69 -0
- package/src/templates/componentTemplateProps.ts +78 -0
- package/src/templates/controlSchemaClone.ts +32 -0
- package/src/templates/controlSchemaConstants.ts +11 -0
- package/src/templates/controlSchemaMerge.ts +40 -0
- package/src/templates/controlSchemaTargets.ts +87 -0
- package/src/templates/controlSchemaTypes.ts +20 -0
- package/src/templates/controlSchemas.ts +22 -636
- package/src/templates/defaultBioTemplateBuilder.ts +124 -0
- package/src/templates/doseResponseAdapters.ts +45 -0
- package/src/templates/doseResponseBuilder.ts +44 -0
- package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
- package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
- package/src/templates/flowCytometryPanelBuilder.ts +53 -0
- package/src/templates/flowNormalizers.ts +58 -0
- package/src/templates/flowPanelAdapters.ts +58 -0
- package/src/templates/index.ts +2 -0
- package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
- package/src/templates/instrumentRunAdapters.ts +163 -0
- package/src/templates/instrumentRunBuilder.ts +97 -0
- package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
- package/src/templates/plateGeometry.ts +62 -0
- package/src/templates/plateMapAdapters.ts +36 -0
- package/src/templates/plateMapBuilder.ts +43 -0
- package/src/templates/presetControlSchemas.ts +258 -0
- package/src/templates/presets.ts +23 -0
- package/src/templates/protocolAdapters.ts +69 -0
- package/src/templates/protocolNormalizers.ts +37 -0
- package/src/templates/protocolStepsBuilder.ts +36 -0
- package/src/templates/qpcrAdapters.ts +104 -0
- package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
- package/src/templates/qpcrPlateBuilder.ts +96 -0
- package/src/templates/reagentAdapters.ts +77 -0
- package/src/templates/reagentListBuilder.ts +30 -0
- package/src/templates/runNormalizers.ts +63 -0
- package/src/templates/sampleNormalizers.ts +58 -0
- package/src/templates/samplePrepAdapters.ts +63 -0
- package/src/templates/samplePrepBuilder.ts +51 -0
- package/src/templates/sampleSheetAdapters.ts +75 -0
- package/src/templates/sampleSheetBuilder.ts +23 -0
- package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
- package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
- package/src/templates/templateControlSchemas.ts +320 -0
- package/src/templates/templateEnvelopes.ts +137 -0
- package/src/templates/templatePackCollectionBuilder.ts +23 -0
- package/src/templates/templatePresetCollectionBuilder.ts +139 -0
- package/src/templates/templateValidators.ts +414 -0
- package/src/templates/timeCourseAdapters.ts +73 -0
- package/src/templates/timeCourseBuilder.ts +64 -0
- package/src/templates/types.ts +17 -0
- package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
- package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
- package/src/types/auth.ts +3 -0
- package/src/types/components.ts +45 -3
- package/src/types/form-builder.ts +2 -1
- package/src/types/index.ts +35 -0
- package/src/types/instrument.ts +61 -0
- package/src/types/platform.ts +4 -0
- package/src/utils/rack.ts +209 -0
- package/dist/auth-CBG3bWEc.js.map +0 -1
- package/dist/components-5KSfsVqf.js.map +0 -1
- package/dist/composables-D4Myb30a.js.map +0 -1
- package/dist/templates-BSlxwV2c.js.map +0 -1
- package/dist/useExperimentData-BbbdI5xT.js.map +0 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SelectOption,
|
|
3
|
+
} from '../types'
|
|
4
|
+
import type {
|
|
5
|
+
FormFieldType,
|
|
6
|
+
} from '../types/form-builder'
|
|
7
|
+
import {
|
|
8
|
+
getTypeDefault,
|
|
9
|
+
} from './formBuilderRegistry'
|
|
10
|
+
import {
|
|
11
|
+
humanize,
|
|
12
|
+
} from './controlSchemaUtils'
|
|
13
|
+
import type {
|
|
14
|
+
ControlDefinition,
|
|
15
|
+
ControlInput,
|
|
16
|
+
ControlOption,
|
|
17
|
+
ControlOptionValue,
|
|
18
|
+
ControlSchema,
|
|
19
|
+
ControlSchemaOptions,
|
|
20
|
+
} from './useControlSchema'
|
|
21
|
+
|
|
22
|
+
export interface NormalizedControl {
|
|
23
|
+
name: string
|
|
24
|
+
definition: ControlDefinition
|
|
25
|
+
type: FormFieldType
|
|
26
|
+
sectionId: string
|
|
27
|
+
viewId: string
|
|
28
|
+
order: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function normalizeControls(
|
|
32
|
+
controls: ControlSchema,
|
|
33
|
+
options: ControlSchemaOptions = {},
|
|
34
|
+
): NormalizedControl[] {
|
|
35
|
+
return Object.entries(controls)
|
|
36
|
+
.map(([name, input], index): NormalizedControl => {
|
|
37
|
+
const definition = normalizeControlDefinition(input)
|
|
38
|
+
const type = definition.type ?? inferControlType(definition)
|
|
39
|
+
return {
|
|
40
|
+
name,
|
|
41
|
+
definition,
|
|
42
|
+
type,
|
|
43
|
+
sectionId: definition.section ?? options.section ?? 'controls',
|
|
44
|
+
viewId: definition.view ?? options.view ?? 'default',
|
|
45
|
+
order: definition.order ?? index,
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.sort((a, b) => a.order - b.order)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function normalizeControlDefinition(input: ControlInput): ControlDefinition {
|
|
52
|
+
if (isControlOptionArray(input)) {
|
|
53
|
+
if (input.length === 0) return { type: 'tags', default: [] }
|
|
54
|
+
return {
|
|
55
|
+
default: optionValue(input[0]),
|
|
56
|
+
options: input,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (typeof input === 'string' || typeof input === 'number' || typeof input === 'boolean') {
|
|
61
|
+
return { default: input }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return input
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function defaultValueForControl(definition: ControlDefinition, type: FormFieldType): unknown {
|
|
68
|
+
if (definition.default !== undefined) return definition.default
|
|
69
|
+
if (definition.defaultValue !== undefined) return definition.defaultValue
|
|
70
|
+
return getTypeDefault(type)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function normalizeOption(option: ControlOption): SelectOption<unknown> {
|
|
74
|
+
if (typeof option === 'object' && option !== null && 'label' in option) {
|
|
75
|
+
return option
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
value: option,
|
|
79
|
+
label: humanize(String(option)),
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isControlOptionArray(input: ControlInput): input is readonly ControlOption[] {
|
|
84
|
+
return Array.isArray(input)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function inferControlType(definition: ControlDefinition): FormFieldType {
|
|
88
|
+
const value = definition.default ?? definition.defaultValue
|
|
89
|
+
if (definition.options?.length) return Array.isArray(value) ? 'multiselect' : 'select'
|
|
90
|
+
if (typeof value === 'boolean') return 'toggle'
|
|
91
|
+
if (typeof value === 'number') return 'number'
|
|
92
|
+
if (Array.isArray(value)) return 'tags'
|
|
93
|
+
return 'text'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function optionValue(option: ControlOption): ControlOptionValue | unknown {
|
|
97
|
+
if (typeof option === 'object' && option !== null && 'value' in option) {
|
|
98
|
+
return option.value
|
|
99
|
+
}
|
|
100
|
+
return option
|
|
101
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function recordValue(value: unknown): Record<string, unknown> {
|
|
2
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
3
|
+
? value as Record<string, unknown>
|
|
4
|
+
: {}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function numericValue(value: number | { value: number; message: string }): number {
|
|
8
|
+
return typeof value === 'number' ? value : value.value
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function orderedUnique(values: string[]): string[] {
|
|
12
|
+
return [...new Set(values)]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function replaceRecord(target: Record<string, unknown>, values: Record<string, unknown>) {
|
|
16
|
+
for (const key of Object.keys(target)) {
|
|
17
|
+
delete target[key]
|
|
18
|
+
}
|
|
19
|
+
Object.assign(target, values)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function omitUndefined<T extends object>(record: T): T {
|
|
23
|
+
const next: Record<string, unknown> = {}
|
|
24
|
+
for (const [key, value] of Object.entries(record as Record<string, unknown>)) {
|
|
25
|
+
if (value !== undefined) next[key] = value
|
|
26
|
+
}
|
|
27
|
+
return next as T
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function humanize(value: string): string {
|
|
31
|
+
return value
|
|
32
|
+
.replace(/[_-]+/g, ' ')
|
|
33
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
34
|
+
.trim()
|
|
35
|
+
.replace(/\w\S*/g, word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ControlWorkspaceOptions,
|
|
3
|
+
} from './useControlSchema'
|
|
4
|
+
|
|
5
|
+
export function mergeControlWorkspaceOptions(
|
|
6
|
+
base?: ControlWorkspaceOptions,
|
|
7
|
+
override?: ControlWorkspaceOptions,
|
|
8
|
+
): ControlWorkspaceOptions {
|
|
9
|
+
return {
|
|
10
|
+
...(base ?? {}),
|
|
11
|
+
...(override ?? {}),
|
|
12
|
+
initialValues: {
|
|
13
|
+
...(base?.initialValues ?? {}),
|
|
14
|
+
...(override?.initialValues ?? {}),
|
|
15
|
+
},
|
|
16
|
+
topBarSettings: {
|
|
17
|
+
...(base?.topBarSettings ?? {}),
|
|
18
|
+
...(override?.topBarSettings ?? {}),
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import type { SelectOption } from '../types'
|
|
2
|
+
|
|
3
|
+
export interface ExperimentDesignDataResponse {
|
|
4
|
+
experiment_id?: number
|
|
5
|
+
plugin_id?: string
|
|
6
|
+
data?: Record<string, unknown>
|
|
7
|
+
schema_version?: string
|
|
8
|
+
updated_at?: string | null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ExtractExperimentSamplesOptions {
|
|
12
|
+
includeControls?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
16
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isPlatformDesignDataResponse(value: Record<string, unknown>): boolean {
|
|
20
|
+
return (
|
|
21
|
+
'data' in value
|
|
22
|
+
&& (
|
|
23
|
+
'experiment_id' in value
|
|
24
|
+
|| 'plugin_id' in value
|
|
25
|
+
|| 'schema_version' in value
|
|
26
|
+
|| 'updated_at' in value
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Return the plugin-defined design_data payload from common platform and plugin response shapes. */
|
|
32
|
+
export function unwrapExperimentDesignData(
|
|
33
|
+
rawData: Record<string, unknown> | null | undefined,
|
|
34
|
+
): Record<string, unknown> | null {
|
|
35
|
+
if (!rawData) return null
|
|
36
|
+
|
|
37
|
+
if (isRecord(rawData.data) && isPlatformDesignDataResponse(rawData)) {
|
|
38
|
+
return rawData.data
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isRecord(rawData.design_data)) {
|
|
42
|
+
return rawData.design_data
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isRecord(rawData.designData)) {
|
|
46
|
+
return rawData.designData
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return rawData
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function shouldIncludeSample(record: Record<string, unknown>, options: ExtractExperimentSamplesOptions): boolean {
|
|
53
|
+
if (options.includeControls) return true
|
|
54
|
+
const rawType = record.sample_type ?? record.sampleType ?? record.type ?? record.well_type ?? record.wellType
|
|
55
|
+
const type = typeof rawType === 'string' ? rawType.toLowerCase() : ''
|
|
56
|
+
return !['blank', 'qc'].includes(type)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function readSampleValue(record: Record<string, unknown>): string | null {
|
|
60
|
+
const candidates = [
|
|
61
|
+
record.sample_name,
|
|
62
|
+
record.sampleName,
|
|
63
|
+
record.sample_id,
|
|
64
|
+
record.sampleId,
|
|
65
|
+
record.name,
|
|
66
|
+
record.id,
|
|
67
|
+
record.label,
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
for (const candidate of candidates) {
|
|
71
|
+
if (typeof candidate === 'string' && candidate.trim()) {
|
|
72
|
+
return candidate
|
|
73
|
+
}
|
|
74
|
+
if (typeof candidate === 'number' && Number.isFinite(candidate)) {
|
|
75
|
+
return String(candidate)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function readSampleLabel(record: Record<string, unknown>, fallback: string): string {
|
|
83
|
+
const label = record.name ?? record.label ?? record.sample_name ?? record.sampleName
|
|
84
|
+
return typeof label === 'string' && label.trim() ? label : fallback
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readSampleDescription(record: Record<string, unknown>): string | undefined {
|
|
88
|
+
const parts = [
|
|
89
|
+
record.group,
|
|
90
|
+
record.batch,
|
|
91
|
+
record.batch_id,
|
|
92
|
+
record.batchId,
|
|
93
|
+
record.plate_id,
|
|
94
|
+
record.plateId,
|
|
95
|
+
record.well_id,
|
|
96
|
+
record.wellId,
|
|
97
|
+
].filter((value): value is string | number =>
|
|
98
|
+
(typeof value === 'string' && value.trim().length > 0)
|
|
99
|
+
|| typeof value === 'number',
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return parts.length > 0 ? parts.map(String).join(' / ') : undefined
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function addSampleRecord(
|
|
106
|
+
options: SelectOption<string>[],
|
|
107
|
+
seen: Set<string>,
|
|
108
|
+
value: unknown,
|
|
109
|
+
extractOptions: ExtractExperimentSamplesOptions,
|
|
110
|
+
): void {
|
|
111
|
+
if (typeof value === 'string') {
|
|
112
|
+
const trimmed = value.trim()
|
|
113
|
+
if (trimmed && !seen.has(trimmed)) {
|
|
114
|
+
seen.add(trimmed)
|
|
115
|
+
options.push({ value: trimmed, label: trimmed })
|
|
116
|
+
}
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!isRecord(value) || !shouldIncludeSample(value, extractOptions)) return
|
|
121
|
+
|
|
122
|
+
const sampleValue = readSampleValue(value)
|
|
123
|
+
if (!sampleValue || seen.has(sampleValue)) return
|
|
124
|
+
|
|
125
|
+
seen.add(sampleValue)
|
|
126
|
+
options.push({
|
|
127
|
+
value: sampleValue,
|
|
128
|
+
label: readSampleLabel(value, sampleValue),
|
|
129
|
+
description: readSampleDescription(value),
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function addSampleArray(
|
|
134
|
+
options: SelectOption<string>[],
|
|
135
|
+
seen: Set<string>,
|
|
136
|
+
value: unknown,
|
|
137
|
+
extractOptions: ExtractExperimentSamplesOptions,
|
|
138
|
+
): void {
|
|
139
|
+
if (!Array.isArray(value)) return
|
|
140
|
+
for (const sample of value) {
|
|
141
|
+
addSampleRecord(options, seen, sample, extractOptions)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Extract selectable sample options from raw or wrapped experiment design_data. */
|
|
146
|
+
export function extractSampleOptionsFromDesignData(
|
|
147
|
+
rawData: Record<string, unknown> | null | undefined,
|
|
148
|
+
options: ExtractExperimentSamplesOptions = {},
|
|
149
|
+
): SelectOption<string>[] {
|
|
150
|
+
const designData = unwrapExperimentDesignData(rawData)
|
|
151
|
+
if (!designData) return []
|
|
152
|
+
|
|
153
|
+
const sampleOptions: SelectOption<string>[] = []
|
|
154
|
+
const seen = new Set<string>()
|
|
155
|
+
|
|
156
|
+
addSampleArray(sampleOptions, seen, designData.samples, options)
|
|
157
|
+
|
|
158
|
+
if (isRecord(designData.templates)) {
|
|
159
|
+
for (const template of Object.values(designData.templates)) {
|
|
160
|
+
if (!isRecord(template)) continue
|
|
161
|
+
const templateData = isRecord(template.data) ? template.data : template
|
|
162
|
+
addSampleArray(sampleOptions, seen, templateData.samples, options)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (Array.isArray(designData.plates)) {
|
|
167
|
+
for (const plate of designData.plates) {
|
|
168
|
+
if (!isRecord(plate)) continue
|
|
169
|
+
addSampleArray(sampleOptions, seen, plate.samples, options)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return sampleOptions
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Extract SampleSelector-compatible string values from raw or wrapped experiment design_data. */
|
|
177
|
+
export function extractSampleNamesFromDesignData(
|
|
178
|
+
rawData: Record<string, unknown> | null | undefined,
|
|
179
|
+
options: ExtractExperimentSamplesOptions = {},
|
|
180
|
+
): string[] {
|
|
181
|
+
return extractSampleOptionsFromDesignData(rawData, options).map(sample => sample.value)
|
|
182
|
+
}
|
package/src/composables/index.ts
CHANGED
|
@@ -144,6 +144,20 @@ export {
|
|
|
144
144
|
type UseExperimentDataOptions,
|
|
145
145
|
type UseExperimentDataReturn,
|
|
146
146
|
} from './useExperimentData'
|
|
147
|
+
export {
|
|
148
|
+
extractSampleNamesFromDesignData,
|
|
149
|
+
extractSampleOptionsFromDesignData,
|
|
150
|
+
unwrapExperimentDesignData,
|
|
151
|
+
type ExperimentDesignDataResponse,
|
|
152
|
+
type ExtractExperimentSamplesOptions,
|
|
153
|
+
} from './experimentDesignData'
|
|
154
|
+
export {
|
|
155
|
+
useExperimentSamples,
|
|
156
|
+
type ExperimentDesignDataSource,
|
|
157
|
+
type ExperimentIdSource,
|
|
158
|
+
type UseExperimentSamplesOptions,
|
|
159
|
+
type UseExperimentSamplesReturn,
|
|
160
|
+
} from './useExperimentSamples'
|
|
147
161
|
export {
|
|
148
162
|
getFieldRegistryEntry,
|
|
149
163
|
getTypeDefault,
|
|
@@ -3,6 +3,7 @@ import { ref, onMounted, onUnmounted, watch, getCurrentInstance, type Ref } from
|
|
|
3
3
|
import { useAuthStore } from '../stores/auth'
|
|
4
4
|
import { useSettingsStore } from '../stores/settings'
|
|
5
5
|
import type { AuthConfig, UserInfo, LoginResponse, TokenVerifyResponse, UpdateProfileRequest } from '../types'
|
|
6
|
+
import type { RoleInfo } from '../permissions'
|
|
6
7
|
|
|
7
8
|
interface UserResponse {
|
|
8
9
|
id: string
|
|
@@ -10,6 +11,7 @@ interface UserResponse {
|
|
|
10
11
|
shortname: string | null
|
|
11
12
|
email: string | null
|
|
12
13
|
role: string
|
|
14
|
+
role_obj?: RoleInfo | null
|
|
13
15
|
is_active: boolean
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -187,6 +189,7 @@ export function useAuth(): UseAuthReturn {
|
|
|
187
189
|
shortname: response.data.shortname,
|
|
188
190
|
email: response.data.email,
|
|
189
191
|
role: response.data.role,
|
|
192
|
+
roleObj: response.data.role_obj ?? null,
|
|
190
193
|
isActive: response.data.is_active,
|
|
191
194
|
}
|
|
192
195
|
|
|
@@ -379,6 +382,7 @@ export function useAuth(): UseAuthReturn {
|
|
|
379
382
|
shortname: response.data.shortname,
|
|
380
383
|
email: response.data.email,
|
|
381
384
|
role: response.data.role,
|
|
385
|
+
roleObj: response.data.role_obj ?? null,
|
|
382
386
|
isActive: response.data.is_active,
|
|
383
387
|
}
|
|
384
388
|
authStore.setUserInfo(userInfo)
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
ParsedCsvData,
|
|
10
10
|
} from '../types/auto-group'
|
|
11
11
|
import type { SampleGroup } from '../types/components'
|
|
12
|
+
import { unwrapExperimentDesignData } from './experimentDesignData'
|
|
12
13
|
|
|
13
14
|
export const DEFAULT_COLORS = [
|
|
14
15
|
'#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6',
|
|
@@ -311,7 +312,10 @@ export function computeGroups(
|
|
|
311
312
|
export function extractSamplesFromDesignData(
|
|
312
313
|
rawData: Record<string, unknown>,
|
|
313
314
|
): ParsedCsvData | null {
|
|
314
|
-
const
|
|
315
|
+
const designData = unwrapExperimentDesignData(rawData)
|
|
316
|
+
if (!designData) return null
|
|
317
|
+
|
|
318
|
+
const samples = designData.samples
|
|
315
319
|
if (!Array.isArray(samples) || samples.length === 0) return null
|
|
316
320
|
|
|
317
321
|
// Single pass: filter QC/blank and collect all condition keys
|