@morscherlab/mint-sdk 1.1.0-beta.1 → 1.1.0-beta.11
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 +18 -4
- package/dist/{EmptyState-D1c4RdC7.js → EmptyState-DgBRoYAy.js} +22 -13
- package/dist/EmptyState-DgBRoYAy.js.map +1 -0
- package/dist/{ExperimentSelectorModal-B7w6k3Y8.js → ExperimentSelectorModal-BBWXC7KW.js} +3 -3
- package/dist/{ExperimentSelectorModal-B7w6k3Y8.js.map → ExperimentSelectorModal-BBWXC7KW.js.map} +1 -1
- package/dist/{SettingsModal-DPDwCbXK.js → SettingsModal-Dpg-X1OM.js} +3 -3
- package/dist/{SettingsModal-DPDwCbXK.js.map → SettingsModal-Dpg-X1OM.js.map} +1 -1
- package/dist/__tests__/components/BaseToggle.test.d.ts +1 -0
- package/dist/__tests__/components/SectionCard.test.d.ts +1 -0
- package/dist/__tests__/composables/analysisArtifactTarget.test.d.ts +1 -0
- package/dist/__tests__/types/GeneratedJsonSchema.test.d.ts +1 -0
- package/dist/analysisArtifactTypes-ejqR8MX3.js.map +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseToggle.vue.d.ts +2 -0
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/PluginWorkspaceView.props.d.ts +1 -1
- package/dist/components/SectionCard.vue.d.ts +47 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +6 -6
- package/dist/{components-UfkPN1bK.js → components-Ci_BTx00.js} +711 -633
- package/dist/components-Ci_BTx00.js.map +1 -0
- package/dist/composables/analysisArtifactTarget.d.ts +5 -0
- package/dist/composables/index.d.ts +3 -1
- package/dist/composables/index.js +8 -8
- package/dist/composables/platformContextHelpers.d.ts +2 -0
- package/dist/composables/useAnalysisArtifacts.d.ts +3 -1
- package/dist/composables/useGeneratedAnalysis.d.ts +1 -1
- package/dist/composables/usePlatformContext.d.ts +3 -0
- package/dist/composables/usePluginClient.d.ts +11 -5
- package/dist/{composables-F4JFK9K1.js → composables-C0VEJ73O.js} +172 -30
- package/dist/composables-C0VEJ73O.js.map +1 -0
- package/dist/index.js +11 -11
- package/dist/install.js +5 -5
- package/dist/styles.css +312 -11
- package/dist/tailwind.preset.d.ts +5 -0
- package/dist/tailwind.preset.js +7 -2
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/templates/index.js +3 -3
- package/dist/{templates-Cttbjbyc.js → templates-Cdj93S9C.js} +2 -2
- package/dist/{templates-Cttbjbyc.js.map → templates-Cdj93S9C.js.map} +1 -1
- package/dist/types/analysisArtifactTypes.d.ts +8 -0
- package/dist/types/components.d.ts +2 -0
- package/dist/types/generated-ui.d.ts +13 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/platform.d.ts +2 -0
- package/dist/{useControlSchema-Dallso-L.js → useControlSchema-B_qgU4rW.js} +48 -19
- package/dist/useControlSchema-B_qgU4rW.js.map +1 -0
- package/dist/{useExperimentSelector-BMjzNcf2.js → useExperimentSelector-BuQZRgMt.js} +2 -2
- package/dist/{useExperimentSelector-BMjzNcf2.js.map → useExperimentSelector-BuQZRgMt.js.map} +1 -1
- package/dist/{useFormBuilder-BXaaDI41.js → useFormBuilder-D1G5J5Z5.js} +2 -2
- package/dist/{useFormBuilder-BXaaDI41.js.map → useFormBuilder-D1G5J5Z5.js.map} +1 -1
- package/dist/{useProtocolTemplates-BP7_4RGQ.js → useProtocolTemplates-DeaOmMaw.js} +4 -4
- package/dist/{useProtocolTemplates-BP7_4RGQ.js.map → useProtocolTemplates-DeaOmMaw.js.map} +1 -1
- package/package.json +1 -1
- package/src/__tests__/components/BaseSelect.test.ts +52 -0
- package/src/__tests__/components/BaseToggle.test.ts +40 -0
- package/src/__tests__/components/GeneratedPluginView.test.ts +10 -0
- package/src/__tests__/components/PluginWorkspaceView.test.ts +68 -14
- package/src/__tests__/components/SectionCard.test.ts +181 -0
- package/src/__tests__/composables/analysisArtifactTarget.test.ts +77 -0
- package/src/__tests__/composables/useAnalysisArtifacts.test.ts +74 -1
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +2 -0
- package/src/__tests__/composables/usePlatformContext.test.ts +28 -0
- package/src/__tests__/composables/usePluginClient.test.ts +365 -21
- package/src/__tests__/composables/usePluginConfig.test.ts +323 -7
- package/src/__tests__/types/GeneratedJsonSchema.test.ts +62 -0
- package/src/components/BaseSelect.vue +16 -2
- package/src/components/BaseToggle.vue +3 -1
- package/src/components/GeneratedPluginView.vue +1 -1
- package/src/components/PluginWorkspaceView.props.ts +1 -1
- package/src/components/PluginWorkspaceView.vue +1 -5
- package/src/components/SectionCard.story.vue +163 -0
- package/src/components/SectionCard.vue +98 -0
- package/src/components/index.ts +1 -0
- package/src/composables/analysisArtifactTarget.ts +53 -0
- package/src/composables/index.ts +6 -0
- package/src/composables/platformContextHelpers.ts +10 -3
- package/src/composables/useAnalysisArtifacts.ts +48 -0
- package/src/composables/useGeneratedAnalysis.ts +30 -12
- package/src/composables/usePluginClient.ts +130 -20
- package/src/composables/usePluginConfig.ts +156 -20
- package/src/styles/components/section-card.css +161 -0
- package/src/styles/index.css +1 -0
- package/src/styles/variables.css +25 -0
- package/src/tailwind.preset.ts +5 -0
- package/src/types/analysisArtifactTypes.ts +9 -0
- package/src/types/components.ts +12 -0
- package/src/types/generated-ui.ts +13 -0
- package/src/types/index.ts +3 -0
- package/src/types/platform.ts +2 -0
- package/dist/EmptyState-D1c4RdC7.js.map +0 -1
- package/dist/components-UfkPN1bK.js.map +0 -1
- package/dist/composables-F4JFK9K1.js.map +0 -1
- package/dist/useControlSchema-Dallso-L.js.map +0 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AnalysisArtifactTarget } from '../types/analysisArtifactTypes';
|
|
2
|
+
/** Build the canonical query used to open one analysis artifact in a plugin. */
|
|
3
|
+
export declare function buildAnalysisArtifactTargetQuery(target: AnalysisArtifactTarget): URLSearchParams;
|
|
4
|
+
/** Parse a complete canonical target. Incomplete or invalid input is not guessed. */
|
|
5
|
+
export declare function parseAnalysisArtifactTarget(query: URLSearchParams): AnalysisArtifactTarget | null;
|
|
@@ -26,6 +26,8 @@ export { useReagentSeries, generateDilutionSeries, DEFAULT_PRESETS, DEFAULT_UNIT
|
|
|
26
26
|
export { usePluginConfig, type UsePluginConfigReturn } from './usePluginConfig';
|
|
27
27
|
export { useExperimentSelector, type UseExperimentSelectorOptions, type UseExperimentSelectorReturn, } from './useExperimentSelector';
|
|
28
28
|
export { useAnalysisArtifacts, ANALYSIS_FILE_ARTIFACT_SCHEMA, type UseAnalysisArtifactsOptions, type UseAnalysisArtifactsReturn, } from './useAnalysisArtifacts';
|
|
29
|
+
export { buildAnalysisArtifactTargetQuery, parseAnalysisArtifactTarget, } from './analysisArtifactTarget';
|
|
30
|
+
export { resolveCurrentPluginId } from './platformContextHelpers';
|
|
29
31
|
export { formatExperimentDate, formatExperimentStatus, getExperimentStatusVariant, resolveExperimentCode, datePresetToISO, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, EXPERIMENT_STATUS_LABELS, DATE_PRESET_OPTIONS, SORT_OPTIONS, } from './experiment-utils';
|
|
30
32
|
export { useExperimentData, type UseExperimentDataOptions, type UseExperimentDataReturn, } from './useExperimentData';
|
|
31
33
|
export { extractSampleNamesFromDesignData, extractSampleOptionsFromDesignData, unwrapExperimentDesignData, type ExperimentDesignDataResponse, type ExtractExperimentSamplesOptions, } from './experimentDesignData';
|
|
@@ -55,5 +57,5 @@ export { getBioTemplateComponentProps, getBioTemplateComponentBindings, toBioTem
|
|
|
55
57
|
export { useBioTemplateWorkspace, type BioTemplateRendererBinding, type BioTemplateWorkspaceBindings, type BioTemplateWorkspaceTarget, type UseBioTemplateWorkspaceReturn, } from './useBioTemplateWorkspace';
|
|
56
58
|
export { useBioTemplatePresetWorkspace, type BioTemplatePresetWorkspaceBindings, type UseBioTemplatePresetWorkspaceOptions, type UseBioTemplatePresetWorkspaceReturn, } from './useBioTemplatePresetWorkspace';
|
|
57
59
|
export { useBioTemplatePackWorkspace, type UseBioTemplatePackWorkspaceOptions, type UseBioTemplatePackWorkspaceReturn, } from './useBioTemplatePackWorkspace';
|
|
58
|
-
export { buildPluginEndpointUrl, createPluginClient, downloadBlob, downloadPluginEndpoint, getPluginPageSelectorItems, pluginFormDataFromPayload, resolvePluginBaseUrl, uploadPluginEndpoint, usePluginClient, usePluginEventStream, usePluginSettings, useCurrentExperiment, type BuildPluginEndpointUrlOptions, type DownloadBlobOptions, type DownloadPluginEndpointOptions, type PluginContract, type PluginClientRequestOptions, type PluginEndpointContract, type PluginEndpointDefinition, type PluginHttpMethod, type PluginNavItemContract, type PluginEndpointRequestOptions, type PluginEventStreamMessage, type PluginEventStreamOptions, type PluginFormDataPayload, type PluginFormDataValue, type CreatePluginClientOptions, type UseCurrentExperimentOptions, type UseCurrentExperimentReturn, type UsePluginEventStreamReturn, type UsePluginSettingsOptions, type UsePluginSettingsReturn, } from './usePluginClient';
|
|
60
|
+
export { buildPluginEndpointUrl, createPluginClient, downloadBlob, downloadPluginEndpoint, getPluginPageSelectorItems, pluginFormDataFromPayload, resolvePluginBaseUrl, uploadPluginEndpoint, usePluginClient, usePluginEventStream, usePluginSettings, useCurrentExperiment, type BuildPluginEndpointUrlOptions, type DownloadBlobOptions, type DownloadPluginEndpointOptions, type PluginContract, type PluginContractSettings, type PluginClientRequestOptions, type PluginEndpointContract, type PluginEndpointDefinition, type PluginHttpMethod, type PluginNavItemContract, type PluginEndpointRequestOptions, type PluginEventStreamMessage, type PluginEventStreamOptions, type PluginFormDataPayload, type PluginFormDataValue, type CreatePluginClientOptions, type UseCurrentExperimentOptions, type UseCurrentExperimentReturn, type UsePluginEventStreamReturn, type UsePluginSettingsOptions, type UsePluginSettingsReturn, } from './usePluginClient';
|
|
59
61
|
export { combinePluginJobSources, usePluginJobCenter, useJobsStatusTray, type CombinedPluginJobCenterSource, type PluginJobCenterSource, type JobsStatusTrayAdapter, type JobsStatusTrayTab, type JobStreamMessage, type UsePluginJobCenterOptions, type UsePluginJobCenterReturn, type UseJobsStatusTrayOptions, type UseJobsStatusTrayReturn, } from './useJobsStatusTray';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { a as SORT_OPTIONS, c as formatExperimentStatus, f as useEventListener, i as EXPERIMENT_STATUS_VARIANT_MAP, l as getExperimentStatusVariant, n as EXPERIMENT_STATUS_LABELS, o as datePresetToISO, r as EXPERIMENT_STATUS_OPTIONS, s as formatExperimentDate, t as DATE_PRESET_OPTIONS, u as resolveExperimentCode } from "../experiment-utils-CxkruZ3G.js";
|
|
2
|
-
import { i as AuthenticationRequiredError, o as useApi, r as useRequestSyncState } from "../EmptyState-
|
|
3
|
-
import { A as useConcentrationUnits, B as useAnalysisArtifacts, C as controlsToViewIds, D as getTypeDefault, E as getFieldRegistryEntry, F as ATOMIC_WEIGHTS, G as
|
|
4
|
-
import { A as extractSamplesFromDesignData, B as useJobsStatusTray, D as readFileAsText, E as parseDelimitedText, F as unwrapExperimentDesignData, G as useAppExperiment, H as DEFAULT_MOBILE_VIEWPORT_QUERY, I as DEFAULT_COLORS, J as candidateMatchesSearch, K as useTheme, L as useWellPlateEditor, N as extractSampleNamesFromDesignData, O as useFileImport, P as extractSampleOptionsFromDesignData, Q as useSortedItems, R as useDoseCalculator, T as detectDelimiter, U as useMobileSupportGate, V as usePluginJobCenter, W as APP_EXPERIMENT_KEY, X as useTextSearch, Y as normalizeSearchQuery, Z as compareSortValues, _ as useScheduleDrag, a as useReagentSeries, b as useExpansionSet, c as useBioTemplatePresetWorkspace, d as getBioTemplateComponentProps, f as toBioTemplateComponentPropsByComponent, g as useExperimentSave, h as useTemplateCollection, i as generateDilutionSeries, j as useAutoGroup, k as validateImportFile, l as useBioTemplatePackWorkspace, m as useBioTemplateControls, n as DEFAULT_PRESETS, o as useGroupAssignment, p as useBioTemplateComponents, q as useToast, r as DEFAULT_UNITS, s as useRackEditor, t as useProtocolTemplates, u as useBioTemplateWorkspace, v as useExperimentSamples, x as useSampleGroups, y as useExperimentData, z as combinePluginJobSources } from "../useProtocolTemplates-
|
|
5
|
-
import { i as usePlatformContext, n as evaluateCondition, r as useForm, t as useFormBuilder } from "../useFormBuilder-
|
|
2
|
+
import { i as AuthenticationRequiredError, o as useApi, r as useRequestSyncState } from "../EmptyState-DgBRoYAy.js";
|
|
3
|
+
import { A as useConcentrationUnits, B as useAnalysisArtifacts, C as controlsToViewIds, D as getTypeDefault, E as getFieldRegistryEntry, Et as useSelectionLimit, F as ATOMIC_WEIGHTS, G as resolveCurrentPluginId, I as useChemicalFormula, J as usePluginJobs, K as createGeneratedAnalysisTransport, N as useSequenceUtils, S as controlsToTopBarSettingsConfig, St as useTimeUtils, T as getDefaultControlView, Tt as useListSelection, _ as controlsToFormSchema, _t as isTimeInRange, a as defineDoseCalculatorControlProps, b as controlsToSettingsSchema, bt as snapToSlot, c as defineWellPlateDoseComponentBindings, ct as compareTime, d as defineControlModel, dt as findNearestTimeSlotIndex, ft as formatDuration, gt as generateTimeSlots, h as controlValuesToComponentProps, ht as fromMinutes, i as useControlSchema, l as defineWellPlateDoseControlProps, lt as durationMinutes, m as controlValuesToComponentBindingsById, mt as formatTimeSlot, n as defineControls, o as defineDoseDesignControlModel, p as controlValuesToComponentBindings, pt as formatTime, q as useGeneratedAnalysis, r as getControlDefaults, s as defineWellPlateControlProps, st as addMinutes, t as defineControlComponentBindings, u as useControlWorkspace, ut as findAvailableSlots, v as controlsToSectionFormSchema, vt as parseTime, w as controlsToViewItems, x as controlsToSidebarPanels, xt as toMinutes, y as controlsToSectionFormSchemas, yt as rangesOverlap } from "../useControlSchema-B_qgU4rW.js";
|
|
4
|
+
import { A as extractSamplesFromDesignData, B as useJobsStatusTray, D as readFileAsText, E as parseDelimitedText, F as unwrapExperimentDesignData, G as useAppExperiment, H as DEFAULT_MOBILE_VIEWPORT_QUERY, I as DEFAULT_COLORS, J as candidateMatchesSearch, K as useTheme, L as useWellPlateEditor, N as extractSampleNamesFromDesignData, O as useFileImport, P as extractSampleOptionsFromDesignData, Q as useSortedItems, R as useDoseCalculator, T as detectDelimiter, U as useMobileSupportGate, V as usePluginJobCenter, W as APP_EXPERIMENT_KEY, X as useTextSearch, Y as normalizeSearchQuery, Z as compareSortValues, _ as useScheduleDrag, a as useReagentSeries, b as useExpansionSet, c as useBioTemplatePresetWorkspace, d as getBioTemplateComponentProps, f as toBioTemplateComponentPropsByComponent, g as useExperimentSave, h as useTemplateCollection, i as generateDilutionSeries, j as useAutoGroup, k as validateImportFile, l as useBioTemplatePackWorkspace, m as useBioTemplateControls, n as DEFAULT_PRESETS, o as useGroupAssignment, p as useBioTemplateComponents, q as useToast, r as DEFAULT_UNITS, s as useRackEditor, t as useProtocolTemplates, u as useBioTemplateWorkspace, v as useExperimentSamples, x as useSampleGroups, y as useExperimentData, z as combinePluginJobSources } from "../useProtocolTemplates-DeaOmMaw.js";
|
|
5
|
+
import { i as usePlatformContext, n as evaluateCondition, r as useForm, t as useFormBuilder } from "../useFormBuilder-D1G5J5Z5.js";
|
|
6
6
|
import { t as ANALYSIS_FILE_ARTIFACT_SCHEMA } from "../analysisArtifactTypes-ejqR8MX3.js";
|
|
7
|
-
import { B as toBioTemplateComponentProps, H as toBioTemplateComponentPropsById, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, R as toBioTemplateComponentBindingsById, l as requireBioTemplateControlSchema, o as getBioTemplateControlSchema } from "../templates-
|
|
8
|
-
import { n as useDebouncedWatch, t as useExperimentSelector } from "../useExperimentSelector-
|
|
9
|
-
import { A as
|
|
10
|
-
export { ANALYSIS_FILE_ARTIFACT_SCHEMA, APP_EXPERIMENT_KEY, ATOMIC_WEIGHTS, AuthenticationRequiredError, DATE_PRESET_OPTIONS, DEFAULT_COLORS, DEFAULT_MOBILE_VIEWPORT_QUERY, DEFAULT_PRESETS, DEFAULT_UNITS, EXPERIMENT_STATUS_LABELS, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, SORT_OPTIONS, addMinutes, buildPluginEndpointUrl, candidateMatchesSearch, combinePluginJobSources, compareSortValues, compareTime, controlValuesToComponentBindings, controlValuesToComponentBindingsById, controlValuesToComponentProps, controlsToFormSchema, controlsToSectionFormSchema, controlsToSectionFormSchemas, controlsToSettingsSchema, controlsToSidebarPanels, controlsToTopBarSettingsConfig, controlsToViewIds, controlsToViewItems, coordinateToWellId, createColumnConditions, createGeneratedAnalysisTransport, createPluginClient, createPluginResourceClient, createRowConditions, createWellPlateWells, datePresetToISO, defineControlComponentBindings, defineControlModel, defineControls, defineDoseCalculatorControlProps, defineDoseDesignControlModel, defineWellPlateControlProps, defineWellPlateDoseComponentBindings, defineWellPlateDoseControlProps, detectDelimiter, downloadBlob, downloadPluginEndpoint, durationMinutes, evaluateCondition, extractSampleNamesFromDesignData, extractSampleOptionsFromDesignData, extractSamplesFromDesignData, findAvailableSlots, findNearestTimeSlotIndex, formatDuration, formatExperimentDate, formatExperimentStatus, formatTime, formatTimeSlot, fromMinutes, generateDilutionSeries, generateTimeSlots, getBioTemplateComponentBindings, getBioTemplateComponentProps, getBioTemplateControlSchema, getControlDefaults, getDefaultControlView, getExperimentStatusVariant, getFieldRegistryEntry, getPluginPageSelectorItems, getTypeDefault, isTimeInRange, normalizeSearchQuery, parseDelimitedText, parseTime, pluginFormDataFromPayload, rangesOverlap, readFileAsText, requireBioTemplateControlSchema, resolveExperimentCode, resolvePluginBaseUrl, resolvePluginFrontendBase, runWellPlateValidation, snapToSlot, toBioTemplateComponentBindings, toBioTemplateComponentBindingsById, toBioTemplateComponentProps, toBioTemplateComponentPropsByComponent, toBioTemplateComponentPropsById, toMinutes, unwrapExperimentDesignData, uploadPluginEndpoint, useAnalysisArtifacts, useApi, useAppExperiment, useAsync, useAsyncBatch, useAuth, useAutoGroup, useBioTemplateComponents, useBioTemplateControls, useBioTemplatePackWorkspace, useBioTemplatePresetWorkspace, useBioTemplateWorkspace, useChemicalFormula, useCommandHistory, useConcentrationUnits, useControlSchema, useControlWorkspace, useCurrentExperiment, useDebouncedWatch, useDoseCalculator, useEventListener, useExpansionSet, useExperimentData, useExperimentSamples, useExperimentSave, useExperimentSelector, useFileImport, useForm, useFormBuilder, useGeneratedAnalysis, useGroupAssignment, useJobsStatusTray, useListSelection, useMobileSupportGate, useOptimisticMutation, usePasskey, usePlatformContext, usePluginClient, usePluginConfig, usePluginEventStream, usePluginJobCenter, usePluginJobs, usePluginSettings, useProtocolTemplates, useRackEditor, useReagentSeries, useRequestSyncState, useResourceCrud, useSampleGroups, useScheduleDrag, useSelectionLimit, useSequenceUtils, useSortedItems, useTemplateCollection, useTextSearch, useTheme, useTimeUtils, useToast, useWellPainting, useWellPlateAdapter, useWellPlateEditor, useWellPlateValidation, validateImportFile, wellIdToCoordinate, wellIdsInRectangle };
|
|
7
|
+
import { B as toBioTemplateComponentProps, H as toBioTemplateComponentPropsById, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, R as toBioTemplateComponentBindingsById, l as requireBioTemplateControlSchema, o as getBioTemplateControlSchema } from "../templates-Cdj93S9C.js";
|
|
8
|
+
import { n as useDebouncedWatch, t as useExperimentSelector } from "../useExperimentSelector-BuQZRgMt.js";
|
|
9
|
+
import { A as useAsync, C as createPluginResourceClient, D as buildAnalysisArtifactTargetQuery, E as useCommandHistory, M as resolvePluginFrontendBase, N as usePasskey, O as parseAnalysisArtifactTarget, P as useAuth, S as wellIdsInRectangle, T as useOptimisticMutation, _ as createWellPlateWells, a as pluginFormDataFromPayload, b as useWellPainting, c as usePluginClient, d as buildPluginEndpointUrl, f as resolvePluginBaseUrl, g as createRowConditions, h as createColumnConditions, i as getPluginPageSelectorItems, j as useAsyncBatch, k as usePluginConfig, l as usePluginEventStream, m as useWellPlateValidation, n as downloadBlob, o as uploadPluginEndpoint, p as runWellPlateValidation, r as downloadPluginEndpoint, s as useCurrentExperiment, t as createPluginClient, u as usePluginSettings, v as useWellPlateAdapter, w as useResourceCrud, x as wellIdToCoordinate, y as coordinateToWellId } from "../composables-C0VEJ73O.js";
|
|
10
|
+
export { ANALYSIS_FILE_ARTIFACT_SCHEMA, APP_EXPERIMENT_KEY, ATOMIC_WEIGHTS, AuthenticationRequiredError, DATE_PRESET_OPTIONS, DEFAULT_COLORS, DEFAULT_MOBILE_VIEWPORT_QUERY, DEFAULT_PRESETS, DEFAULT_UNITS, EXPERIMENT_STATUS_LABELS, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, SORT_OPTIONS, addMinutes, buildAnalysisArtifactTargetQuery, buildPluginEndpointUrl, candidateMatchesSearch, combinePluginJobSources, compareSortValues, compareTime, controlValuesToComponentBindings, controlValuesToComponentBindingsById, controlValuesToComponentProps, controlsToFormSchema, controlsToSectionFormSchema, controlsToSectionFormSchemas, controlsToSettingsSchema, controlsToSidebarPanels, controlsToTopBarSettingsConfig, controlsToViewIds, controlsToViewItems, coordinateToWellId, createColumnConditions, createGeneratedAnalysisTransport, createPluginClient, createPluginResourceClient, createRowConditions, createWellPlateWells, datePresetToISO, defineControlComponentBindings, defineControlModel, defineControls, defineDoseCalculatorControlProps, defineDoseDesignControlModel, defineWellPlateControlProps, defineWellPlateDoseComponentBindings, defineWellPlateDoseControlProps, detectDelimiter, downloadBlob, downloadPluginEndpoint, durationMinutes, evaluateCondition, extractSampleNamesFromDesignData, extractSampleOptionsFromDesignData, extractSamplesFromDesignData, findAvailableSlots, findNearestTimeSlotIndex, formatDuration, formatExperimentDate, formatExperimentStatus, formatTime, formatTimeSlot, fromMinutes, generateDilutionSeries, generateTimeSlots, getBioTemplateComponentBindings, getBioTemplateComponentProps, getBioTemplateControlSchema, getControlDefaults, getDefaultControlView, getExperimentStatusVariant, getFieldRegistryEntry, getPluginPageSelectorItems, getTypeDefault, isTimeInRange, normalizeSearchQuery, parseAnalysisArtifactTarget, parseDelimitedText, parseTime, pluginFormDataFromPayload, rangesOverlap, readFileAsText, requireBioTemplateControlSchema, resolveCurrentPluginId, resolveExperimentCode, resolvePluginBaseUrl, resolvePluginFrontendBase, runWellPlateValidation, snapToSlot, toBioTemplateComponentBindings, toBioTemplateComponentBindingsById, toBioTemplateComponentProps, toBioTemplateComponentPropsByComponent, toBioTemplateComponentPropsById, toMinutes, unwrapExperimentDesignData, uploadPluginEndpoint, useAnalysisArtifacts, useApi, useAppExperiment, useAsync, useAsyncBatch, useAuth, useAutoGroup, useBioTemplateComponents, useBioTemplateControls, useBioTemplatePackWorkspace, useBioTemplatePresetWorkspace, useBioTemplateWorkspace, useChemicalFormula, useCommandHistory, useConcentrationUnits, useControlSchema, useControlWorkspace, useCurrentExperiment, useDebouncedWatch, useDoseCalculator, useEventListener, useExpansionSet, useExperimentData, useExperimentSamples, useExperimentSave, useExperimentSelector, useFileImport, useForm, useFormBuilder, useGeneratedAnalysis, useGroupAssignment, useJobsStatusTray, useListSelection, useMobileSupportGate, useOptimisticMutation, usePasskey, usePlatformContext, usePluginClient, usePluginConfig, usePluginEventStream, usePluginJobCenter, usePluginJobs, usePluginSettings, useProtocolTemplates, useRackEditor, useReagentSeries, useRequestSyncState, useResourceCrud, useSampleGroups, useScheduleDrag, useSelectionLimit, useSequenceUtils, useSortedItems, useTemplateCollection, useTextSearch, useTheme, useTimeUtils, useToast, useWellPainting, useWellPlateAdapter, useWellPlateEditor, useWellPlateValidation, validateImportFile, wellIdToCoordinate, wellIdsInRectangle };
|
|
@@ -6,6 +6,8 @@ export type ExperimentAwarePlatformContext = PlatformContext & {
|
|
|
6
6
|
experimentId?: unknown;
|
|
7
7
|
};
|
|
8
8
|
export declare function getInjectedPlatformContext(): PlatformContext | undefined;
|
|
9
|
+
/** Return the platform's canonical plugin identity for the mounted frontend. */
|
|
10
|
+
export declare function resolveCurrentPluginId(): string | undefined;
|
|
9
11
|
export declare function getInjectedExperimentContext(): ExperimentAwarePlatformContext | undefined;
|
|
10
12
|
export declare function currentExperimentFromContext<TExperiment>(context?: ExperimentAwarePlatformContext | undefined): TExperiment | undefined;
|
|
11
13
|
export declare function currentExperimentIdFromContext(context?: ExperimentAwarePlatformContext | undefined): number | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
|
|
2
|
-
import { AnalysisArtifactDetail, AnalysisArtifactMetadataUpdate, AnalysisArtifactStatusFilter, AnalysisArtifactSummary } from '../types/analysisArtifactTypes';
|
|
2
|
+
import { AnalysisArtifactDetail, AnalysisArtifactMetadataUpdate, AnalysisArtifactStatusFilter, AnalysisArtifactSummary, AnalysisArtifactTarget } from '../types/analysisArtifactTypes';
|
|
3
3
|
export { ANALYSIS_FILE_ARTIFACT_SCHEMA } from '../types/analysisArtifactTypes';
|
|
4
4
|
export interface UseAnalysisArtifactsOptions {
|
|
5
5
|
/** Experiment id; defaults to platform injection or URL. Refetches when it changes. */
|
|
@@ -44,6 +44,8 @@ export interface UseAnalysisArtifactsReturn {
|
|
|
44
44
|
refresh: () => Promise<AnalysisArtifactSummary[]>;
|
|
45
45
|
/** Fetch one artifact with its result payload; null when it fails or is superseded. */
|
|
46
46
|
getDetail: (artifactId: number) => Promise<AnalysisArtifactDetail | null>;
|
|
47
|
+
/** Resolve and fetch the exact stable artifact identity. */
|
|
48
|
+
resolveTarget: (target: AnalysisArtifactTarget) => Promise<AnalysisArtifactDetail | null>;
|
|
47
49
|
/** Update display_name and/or note; resolves to the updated summary or null. */
|
|
48
50
|
updateMetadata: (artifactId: number, updates: AnalysisArtifactMetadataUpdate) => Promise<AnalysisArtifactSummary | null>;
|
|
49
51
|
/** Archive an artifact; resolves to the updated summary or null. */
|
|
@@ -35,7 +35,7 @@ export interface UsePluginJobsReturn extends PluginJobCenterSource {
|
|
|
35
35
|
status: ShallowRef<'idle' | 'initializing' | 'ready' | 'paused' | 'error' | 'disposed'>;
|
|
36
36
|
initialize: () => Promise<void>;
|
|
37
37
|
ready: () => Promise<void>;
|
|
38
|
-
uploadPath: (input: PluginJobPathInput) => Promise<PluginJobPathUpload>;
|
|
38
|
+
uploadPath: (input: PluginJobPathInput, definitionId?: string) => Promise<PluginJobPathUpload>;
|
|
39
39
|
uploadStagedPart: <Metadata>(input: PluginJobStagedPartInput<Metadata>) => Promise<PluginJobStagedPartUploadResult<Metadata>>;
|
|
40
40
|
getJobStaging: <Metadata = unknown>(job: GeneratedAnalysisJob | string, pagination?: PluginJobStagingPagination) => Promise<PluginJobStaging<Metadata>>;
|
|
41
41
|
sealJob: (job: GeneratedAnalysisJob | string) => Promise<GeneratedAnalysisJob>;
|
|
@@ -37,6 +37,7 @@ export declare function usePlatformContext(options?: PlatformContextOptions): {
|
|
|
37
37
|
color?: string | undefined;
|
|
38
38
|
route_prefix: string;
|
|
39
39
|
api_prefix: string;
|
|
40
|
+
settings_api?: "plugin" | "platform" | undefined;
|
|
40
41
|
nav_items?: {
|
|
41
42
|
id?: string | undefined;
|
|
42
43
|
label: string;
|
|
@@ -96,6 +97,7 @@ export declare function usePlatformContext(options?: PlatformContextOptions): {
|
|
|
96
97
|
color?: string | undefined;
|
|
97
98
|
route_prefix: string;
|
|
98
99
|
api_prefix: string;
|
|
100
|
+
settings_api?: "plugin" | "platform" | undefined;
|
|
99
101
|
nav_items?: {
|
|
100
102
|
id?: string | undefined;
|
|
101
103
|
label: string;
|
|
@@ -155,6 +157,7 @@ export declare function usePlatformContext(options?: PlatformContextOptions): {
|
|
|
155
157
|
color?: string | undefined;
|
|
156
158
|
route_prefix: string;
|
|
157
159
|
api_prefix: string;
|
|
160
|
+
settings_api?: "plugin" | "platform" | undefined;
|
|
158
161
|
nav_items?: {
|
|
159
162
|
id?: string | undefined;
|
|
160
163
|
label: string;
|
|
@@ -4,6 +4,7 @@ export { buildPluginEndpointUrl, resolvePluginBaseUrl, } from './pluginEndpointB
|
|
|
4
4
|
export type PluginHttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
5
5
|
export interface PluginEndpointContract {
|
|
6
6
|
name: string;
|
|
7
|
+
operationId?: string;
|
|
7
8
|
method: PluginHttpMethod;
|
|
8
9
|
path: string;
|
|
9
10
|
requiresAuth?: boolean;
|
|
@@ -31,8 +32,15 @@ export interface PluginNavItemContract {
|
|
|
31
32
|
requiresAdmin?: boolean;
|
|
32
33
|
requiresFeature?: string;
|
|
33
34
|
}
|
|
35
|
+
export interface PluginContractSettings {
|
|
36
|
+
modelName: string | null;
|
|
37
|
+
/** Pydantic JSON Schema used to generate typed settings values. */
|
|
38
|
+
valueSchema: Record<string, unknown> | null;
|
|
39
|
+
/** SDK SettingsModal schema used to render the settings form. */
|
|
40
|
+
formSchema: SettingsModalSchema | null;
|
|
41
|
+
}
|
|
34
42
|
export interface PluginContract {
|
|
35
|
-
schemaVersion:
|
|
43
|
+
schemaVersion: 2;
|
|
36
44
|
plugin: {
|
|
37
45
|
name?: string;
|
|
38
46
|
packageName?: string;
|
|
@@ -48,11 +56,9 @@ export interface PluginContract {
|
|
|
48
56
|
analysisResultReaders?: string[];
|
|
49
57
|
capabilities?: Record<string, unknown>;
|
|
50
58
|
};
|
|
51
|
-
settings
|
|
52
|
-
modelName?: string | null;
|
|
53
|
-
schema?: SettingsModalSchema | null;
|
|
54
|
-
};
|
|
59
|
+
settings: PluginContractSettings;
|
|
55
60
|
endpoints: PluginEndpointContract[];
|
|
61
|
+
schemas?: Record<string, Record<string, unknown>>;
|
|
56
62
|
jobs?: GeneratedJobDefinition[];
|
|
57
63
|
hash: string;
|
|
58
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as authenticationRequiredError, i as AuthenticationRequiredError, o as useApi, r as useRequestSyncState } from "./EmptyState-
|
|
2
|
-
import { H as getInjectedPlatformContext, V as currentExperimentFromContext, W as resolveCurrentExperimentId } from "./useControlSchema-
|
|
1
|
+
import { a as authenticationRequiredError, i as AuthenticationRequiredError, o as useApi, r as useRequestSyncState } from "./EmptyState-DgBRoYAy.js";
|
|
2
|
+
import { H as getInjectedPlatformContext, V as currentExperimentFromContext, W as resolveCurrentExperimentId } from "./useControlSchema-B_qgU4rW.js";
|
|
3
3
|
import { r as useSettingsStore, t as useAuthStore } from "./auth-B87xM--s.js";
|
|
4
|
-
import { i as usePlatformContext } from "./useFormBuilder-
|
|
4
|
+
import { i as usePlatformContext } from "./useFormBuilder-D1G5J5Z5.js";
|
|
5
5
|
import { computed, getCurrentInstance, onMounted, onUnmounted, ref, shallowRef, toValue, watch } from "vue";
|
|
6
6
|
import axios from "axios";
|
|
7
7
|
//#region src/composables/useAuth.ts
|
|
@@ -614,13 +614,39 @@ function useAsyncBatch(asyncFns) {
|
|
|
614
614
|
}
|
|
615
615
|
//#endregion
|
|
616
616
|
//#region src/composables/usePluginConfig.ts
|
|
617
|
+
var PLATFORM_OWNED_SETTINGS_KEY$1 = "allowed_experiment_types";
|
|
618
|
+
function cloneConfig(config) {
|
|
619
|
+
return JSON.parse(JSON.stringify(config));
|
|
620
|
+
}
|
|
621
|
+
function hasOwnConfig(config, key) {
|
|
622
|
+
return Object.prototype.hasOwnProperty.call(config, key);
|
|
623
|
+
}
|
|
624
|
+
function changedTopLevelKeys(current, saved) {
|
|
625
|
+
return new Set([...new Set([...Object.keys(current), ...Object.keys(saved)])].filter((key) => JSON.stringify(current[key]) !== JSON.stringify(saved[key])));
|
|
626
|
+
}
|
|
627
|
+
function topLevelConfigPatch(current, keys) {
|
|
628
|
+
return Object.fromEntries([...keys].map((key) => [key, hasOwnConfig(current, key) ? current[key] : null]));
|
|
629
|
+
}
|
|
630
|
+
function platformOwnedConfigPatch(config) {
|
|
631
|
+
return { [PLATFORM_OWNED_SETTINGS_KEY$1]: hasOwnConfig(config, PLATFORM_OWNED_SETTINGS_KEY$1) ? config[PLATFORM_OWNED_SETTINGS_KEY$1] : null };
|
|
632
|
+
}
|
|
633
|
+
function responseConfigPayload(response) {
|
|
634
|
+
return response.config ?? response.settings ?? {};
|
|
635
|
+
}
|
|
617
636
|
/** Loads, saves, and tracks dirty state for a plugin's persistent configuration via the platform API. */
|
|
618
637
|
function usePluginConfig(pluginName) {
|
|
619
|
-
const
|
|
638
|
+
const injectedContext = getInjectedPlatformContext();
|
|
620
639
|
const { plugin } = usePlatformContext();
|
|
621
|
-
const
|
|
640
|
+
const platformApi = useApi();
|
|
641
|
+
const pluginApi = useApi({ baseUrl: injectedContext?.plugin?.api_prefix ?? plugin.value?.api_prefix });
|
|
642
|
+
const resolvedName = computed(() => pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? "");
|
|
643
|
+
const usesPluginSettingsApi = computed(() => {
|
|
644
|
+
const currentPlugin = injectedContext?.plugin ?? plugin.value;
|
|
645
|
+
return currentPlugin?.settings_api === "plugin" && resolvedName.value === currentPlugin.name;
|
|
646
|
+
});
|
|
622
647
|
const config = ref({});
|
|
623
648
|
const savedConfig = ref({});
|
|
649
|
+
const revision = ref(null);
|
|
624
650
|
const request = useRequestSyncState("Plugin config request failed.");
|
|
625
651
|
const isLoading = ref(false);
|
|
626
652
|
const isSaving = ref(false);
|
|
@@ -635,12 +661,17 @@ function usePluginConfig(pluginName) {
|
|
|
635
661
|
if (!name) return;
|
|
636
662
|
isLoading.value = true;
|
|
637
663
|
try {
|
|
638
|
-
const response = await request.run(() =>
|
|
664
|
+
const response = usesPluginSettingsApi.value ? await request.run(() => pluginApi.get("/settings"), {
|
|
665
|
+
success: "load",
|
|
666
|
+
errorMessage: "Failed to load plugin config"
|
|
667
|
+
}) : await request.run(() => platformApi.get(`/plugins/${encodeURIComponent(name)}/config`), {
|
|
639
668
|
success: "load",
|
|
640
669
|
errorMessage: "Failed to load plugin config"
|
|
641
670
|
});
|
|
642
|
-
|
|
643
|
-
|
|
671
|
+
const responseConfig = responseConfigPayload(response);
|
|
672
|
+
config.value = cloneConfig(responseConfig);
|
|
673
|
+
savedConfig.value = cloneConfig(responseConfig);
|
|
674
|
+
revision.value = response.revision ?? null;
|
|
644
675
|
} catch {} finally {
|
|
645
676
|
isLoading.value = false;
|
|
646
677
|
}
|
|
@@ -650,12 +681,39 @@ function usePluginConfig(pluginName) {
|
|
|
650
681
|
if (!name) return false;
|
|
651
682
|
isSaving.value = true;
|
|
652
683
|
try {
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
684
|
+
const payload = cloneConfig(config.value);
|
|
685
|
+
let response;
|
|
686
|
+
let nextRevision = revision.value;
|
|
687
|
+
if (usesPluginSettingsApi.value) {
|
|
688
|
+
response = await request.run(() => pluginApi.put("/settings", payload, revision.value ? { headers: { "If-Match": `"${revision.value}"` } } : void 0), {
|
|
689
|
+
success: "save",
|
|
690
|
+
errorMessage: "Failed to save plugin config"
|
|
691
|
+
});
|
|
692
|
+
nextRevision = response.revision ?? nextRevision;
|
|
693
|
+
} else {
|
|
694
|
+
const dirtyKeys = changedTopLevelKeys(payload, savedConfig.value);
|
|
695
|
+
const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY$1);
|
|
696
|
+
const typedKeys = [...dirtyKeys].filter((key) => key !== PLATFORM_OWNED_SETTINGS_KEY$1);
|
|
697
|
+
if (typedKeys.length) {
|
|
698
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(name)}/config`, { config: topLevelConfigPatch(payload, typedKeys) }), {
|
|
699
|
+
success: "save",
|
|
700
|
+
errorMessage: "Failed to save plugin config"
|
|
701
|
+
});
|
|
702
|
+
nextRevision = response.revision ?? nextRevision;
|
|
703
|
+
}
|
|
704
|
+
if (platformOwnedChanged) {
|
|
705
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(name)}/config`, { config: platformOwnedConfigPatch(payload) }), {
|
|
706
|
+
success: "save",
|
|
707
|
+
errorMessage: "Failed to save plugin config"
|
|
708
|
+
});
|
|
709
|
+
nextRevision = response.revision ?? nextRevision;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (!response) return true;
|
|
713
|
+
const responseConfig = responseConfigPayload(response);
|
|
714
|
+
config.value = cloneConfig(responseConfig);
|
|
715
|
+
savedConfig.value = cloneConfig(responseConfig);
|
|
716
|
+
revision.value = response.revision ?? nextRevision;
|
|
659
717
|
return true;
|
|
660
718
|
} catch {
|
|
661
719
|
return false;
|
|
@@ -664,7 +722,7 @@ function usePluginConfig(pluginName) {
|
|
|
664
722
|
}
|
|
665
723
|
}
|
|
666
724
|
function reset() {
|
|
667
|
-
config.value =
|
|
725
|
+
config.value = cloneConfig(savedConfig.value);
|
|
668
726
|
request.clearError();
|
|
669
727
|
}
|
|
670
728
|
onMounted(() => {
|
|
@@ -684,6 +742,41 @@ function usePluginConfig(pluginName) {
|
|
|
684
742
|
};
|
|
685
743
|
}
|
|
686
744
|
//#endregion
|
|
745
|
+
//#region src/composables/analysisArtifactTarget.ts
|
|
746
|
+
var EXPERIMENT_ID = "experiment_id";
|
|
747
|
+
var ARTIFACT_PLUGIN_ID = "artifact_plugin_id";
|
|
748
|
+
var ARTIFACT_KEY = "artifact_key";
|
|
749
|
+
var ARTIFACT_ID = "artifact_id";
|
|
750
|
+
function parsePositiveInteger(value) {
|
|
751
|
+
if (value === null || !/^\d+$/.test(value)) return void 0;
|
|
752
|
+
const parsed = Number(value);
|
|
753
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
754
|
+
}
|
|
755
|
+
/** Build the canonical query used to open one analysis artifact in a plugin. */
|
|
756
|
+
function buildAnalysisArtifactTargetQuery(target) {
|
|
757
|
+
const query = new URLSearchParams();
|
|
758
|
+
query.set(EXPERIMENT_ID, String(target.experimentId));
|
|
759
|
+
query.set(ARTIFACT_PLUGIN_ID, target.artifactPluginId);
|
|
760
|
+
query.set(ARTIFACT_KEY, target.artifactKey);
|
|
761
|
+
if (target.artifactId !== void 0) query.set(ARTIFACT_ID, String(target.artifactId));
|
|
762
|
+
return query;
|
|
763
|
+
}
|
|
764
|
+
/** Parse a complete canonical target. Incomplete or invalid input is not guessed. */
|
|
765
|
+
function parseAnalysisArtifactTarget(query) {
|
|
766
|
+
const experimentId = parsePositiveInteger(query.get(EXPERIMENT_ID));
|
|
767
|
+
const artifactPluginId = query.get(ARTIFACT_PLUGIN_ID)?.trim();
|
|
768
|
+
const artifactKey = query.get(ARTIFACT_KEY)?.trim();
|
|
769
|
+
const rawArtifactId = query.get(ARTIFACT_ID);
|
|
770
|
+
const artifactId = parsePositiveInteger(rawArtifactId);
|
|
771
|
+
if (experimentId === void 0 || !artifactPluginId || !artifactKey || rawArtifactId !== null && artifactId === void 0) return null;
|
|
772
|
+
return {
|
|
773
|
+
experimentId,
|
|
774
|
+
artifactPluginId,
|
|
775
|
+
artifactKey,
|
|
776
|
+
...artifactId === void 0 ? {} : { artifactId }
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
//#endregion
|
|
687
780
|
//#region src/composables/useCommandHistory.ts
|
|
688
781
|
/** Generic command-stack state for plugin editors with undo/redo controls. */
|
|
689
782
|
function useCommandHistory(options = {}) {
|
|
@@ -1541,8 +1634,12 @@ function usePluginClient(client) {
|
|
|
1541
1634
|
function normalizePluginSettingsOptions(options = {}) {
|
|
1542
1635
|
return typeof options === "string" ? { pluginName: options } : options;
|
|
1543
1636
|
}
|
|
1637
|
+
var PLATFORM_OWNED_SETTINGS_KEY = "allowed_experiment_types";
|
|
1544
1638
|
function cloneRecord(value) {
|
|
1545
|
-
return
|
|
1639
|
+
return JSON.parse(JSON.stringify(value));
|
|
1640
|
+
}
|
|
1641
|
+
function hasOwnSetting(settings, key) {
|
|
1642
|
+
return Object.prototype.hasOwnProperty.call(settings, key);
|
|
1546
1643
|
}
|
|
1547
1644
|
function responseSettingsPayload(response) {
|
|
1548
1645
|
if (!response || typeof response !== "object") return {};
|
|
@@ -1551,6 +1648,20 @@ function responseSettingsPayload(response) {
|
|
|
1551
1648
|
if (data.settings && typeof data.settings === "object") return cloneRecord(data.settings);
|
|
1552
1649
|
return {};
|
|
1553
1650
|
}
|
|
1651
|
+
function responseSettingsRevision(response) {
|
|
1652
|
+
if (!response || typeof response !== "object") return null;
|
|
1653
|
+
const revision = response.revision;
|
|
1654
|
+
return typeof revision === "string" && revision ? revision : null;
|
|
1655
|
+
}
|
|
1656
|
+
function topLevelSettingsPatch(current, keys) {
|
|
1657
|
+
return Object.fromEntries([...keys].map((key) => [key, hasOwnSetting(current, key) ? current[key] : null]));
|
|
1658
|
+
}
|
|
1659
|
+
function changedTopLevelSettingKeys(current, saved) {
|
|
1660
|
+
return new Set([...new Set([...Object.keys(current), ...Object.keys(saved)])].filter((key) => JSON.stringify(current[key]) !== JSON.stringify(saved[key])));
|
|
1661
|
+
}
|
|
1662
|
+
function platformOwnedSettingsPatch(settings) {
|
|
1663
|
+
return { [PLATFORM_OWNED_SETTINGS_KEY]: hasOwnSetting(settings, PLATFORM_OWNED_SETTINGS_KEY) ? settings[PLATFORM_OWNED_SETTINGS_KEY] : null };
|
|
1664
|
+
}
|
|
1554
1665
|
/** Load, edit, and persist plugin settings from platform config or the plugin-local settings router. */
|
|
1555
1666
|
function usePluginSettings(options = {}) {
|
|
1556
1667
|
const resolvedOptions = normalizePluginSettingsOptions(options);
|
|
@@ -1558,13 +1669,18 @@ function usePluginSettings(options = {}) {
|
|
|
1558
1669
|
const { plugin, isIntegrated } = usePlatformContext();
|
|
1559
1670
|
const platformApi = useApi({ baseUrl: resolvedOptions.platformApiBaseUrl ?? injectedContext?.platformApiUrl });
|
|
1560
1671
|
const pluginApi = useApi({ baseUrl: resolvedOptions.apiBaseUrl ?? injectedContext?.plugin?.api_prefix });
|
|
1561
|
-
const values =
|
|
1672
|
+
const values = ref({});
|
|
1562
1673
|
const savedValues = shallowRef({});
|
|
1674
|
+
const revision = ref(null);
|
|
1563
1675
|
const request = useRequestSyncState("Plugin settings request failed.");
|
|
1564
1676
|
const isLoading = ref(false);
|
|
1565
1677
|
const isSaving = ref(false);
|
|
1566
1678
|
const resolvedPluginName = computed(() => resolvedOptions.pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? "");
|
|
1567
|
-
const
|
|
1679
|
+
const usesPluginSettingsApi = computed(() => {
|
|
1680
|
+
const currentPlugin = injectedContext?.plugin ?? plugin.value;
|
|
1681
|
+
return currentPlugin?.settings_api === "plugin" && resolvedPluginName.value === currentPlugin.name;
|
|
1682
|
+
});
|
|
1683
|
+
const usesPlatformConfig = computed(() => Boolean((isIntegrated.value || injectedContext?.isIntegrated) && resolvedPluginName.value && !usesPluginSettingsApi.value));
|
|
1568
1684
|
const settings = computed(() => values.value);
|
|
1569
1685
|
const isDirty = computed(() => JSON.stringify(values.value) !== JSON.stringify(savedValues.value));
|
|
1570
1686
|
const settingsConfig = computed(() => ({
|
|
@@ -1576,21 +1692,23 @@ function usePluginSettings(options = {}) {
|
|
|
1576
1692
|
function setValues(nextValues) {
|
|
1577
1693
|
values.value = cloneRecord(nextValues);
|
|
1578
1694
|
}
|
|
1579
|
-
function applyLoaded(nextValues) {
|
|
1695
|
+
function applyLoaded(nextValues, nextRevision) {
|
|
1580
1696
|
const cloned = cloneRecord(nextValues);
|
|
1581
1697
|
values.value = cloned;
|
|
1582
1698
|
savedValues.value = cloneRecord(cloned);
|
|
1699
|
+
revision.value = nextRevision;
|
|
1583
1700
|
}
|
|
1584
1701
|
async function load() {
|
|
1585
1702
|
isLoading.value = true;
|
|
1586
1703
|
try {
|
|
1587
|
-
|
|
1704
|
+
const response = usesPlatformConfig.value ? await request.run(() => platformApi.get(`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`), {
|
|
1588
1705
|
success: "load",
|
|
1589
1706
|
errorMessage: "Failed to load plugin settings"
|
|
1590
1707
|
}) : await request.run(() => pluginApi.get("/settings"), {
|
|
1591
1708
|
success: "load",
|
|
1592
1709
|
errorMessage: "Failed to load plugin settings"
|
|
1593
|
-
})
|
|
1710
|
+
});
|
|
1711
|
+
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response));
|
|
1594
1712
|
} catch {} finally {
|
|
1595
1713
|
isLoading.value = false;
|
|
1596
1714
|
}
|
|
@@ -1600,13 +1718,37 @@ function usePluginSettings(options = {}) {
|
|
|
1600
1718
|
isSaving.value = true;
|
|
1601
1719
|
try {
|
|
1602
1720
|
const payload = cloneRecord(values.value);
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1721
|
+
let response;
|
|
1722
|
+
if (usesPlatformConfig.value) {
|
|
1723
|
+
const dirtyKeys = changedTopLevelSettingKeys(payload, savedValues.value);
|
|
1724
|
+
const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY);
|
|
1725
|
+
const typedKeys = [...dirtyKeys].filter((key) => key !== PLATFORM_OWNED_SETTINGS_KEY);
|
|
1726
|
+
let nextRevision = revision.value;
|
|
1727
|
+
if (typedKeys.length) {
|
|
1728
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`, { config: topLevelSettingsPatch(payload, typedKeys) }), {
|
|
1729
|
+
success: "save",
|
|
1730
|
+
errorMessage: "Failed to save plugin settings"
|
|
1731
|
+
});
|
|
1732
|
+
nextRevision = responseSettingsRevision(response) ?? nextRevision;
|
|
1733
|
+
}
|
|
1734
|
+
if (platformOwnedChanged) {
|
|
1735
|
+
response = await request.run(() => platformApi.patch(`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`, { config: platformOwnedSettingsPatch(payload) }), {
|
|
1736
|
+
success: "save",
|
|
1737
|
+
errorMessage: "Failed to save plugin settings"
|
|
1738
|
+
});
|
|
1739
|
+
nextRevision = responseSettingsRevision(response) ?? nextRevision;
|
|
1740
|
+
}
|
|
1741
|
+
if (!response) return true;
|
|
1742
|
+
applyLoaded(responseSettingsPayload(response), nextRevision);
|
|
1743
|
+
return true;
|
|
1744
|
+
} else {
|
|
1745
|
+
const ifMatch = revision.value ? { headers: { "If-Match": `"${revision.value}"` } } : void 0;
|
|
1746
|
+
response = await request.run(() => pluginApi.put("/settings", payload, ifMatch), {
|
|
1747
|
+
success: "save",
|
|
1748
|
+
errorMessage: "Failed to save plugin settings"
|
|
1749
|
+
});
|
|
1750
|
+
}
|
|
1751
|
+
applyLoaded(responseSettingsPayload(response), responseSettingsRevision(response) ?? revision.value);
|
|
1610
1752
|
return true;
|
|
1611
1753
|
} catch {
|
|
1612
1754
|
return false;
|
|
@@ -1897,6 +2039,6 @@ function useCurrentExperiment(options = {}) {
|
|
|
1897
2039
|
};
|
|
1898
2040
|
}
|
|
1899
2041
|
//#endregion
|
|
1900
|
-
export {
|
|
2042
|
+
export { useAsync as A, createPluginResourceClient as C, buildAnalysisArtifactTargetQuery as D, useCommandHistory as E, resolvePluginFrontendBase as M, usePasskey as N, parseAnalysisArtifactTarget as O, useAuth as P, wellIdsInRectangle as S, useOptimisticMutation as T, createWellPlateWells as _, pluginFormDataFromPayload as a, useWellPainting as b, usePluginClient as c, buildPluginEndpointUrl as d, resolvePluginBaseUrl as f, createRowConditions as g, createColumnConditions as h, getPluginPageSelectorItems as i, useAsyncBatch as j, usePluginConfig as k, usePluginEventStream as l, useWellPlateValidation as m, downloadBlob as n, uploadPluginEndpoint as o, runWellPlateValidation as p, downloadPluginEndpoint as r, useCurrentExperiment as s, createPluginClient as t, usePluginSettings as u, useWellPlateAdapter as v, useResourceCrud as w, wellIdToCoordinate as x, coordinateToWellId as y };
|
|
1901
2043
|
|
|
1902
|
-
//# sourceMappingURL=composables-
|
|
2044
|
+
//# sourceMappingURL=composables-C0VEJ73O.js.map
|