@platforma-sdk/ui-vue 1.66.0 → 1.66.2
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/.turbo/turbo-build.log +15 -13
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +2 -2
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +20 -20
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.js.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.d.ts.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js +43 -33
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js.map +1 -1
- package/dist/components/PlAgColumnHeader/types.d.ts +1 -0
- package/dist/components/PlAgColumnHeader/types.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/compositions/useFilterableColumns.js +5 -5
- package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/sources/table-source-v2.js +10 -11
- package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
- package/dist/components/PlAgDataTable/sources/table-state-v2.js +13 -13
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +8 -8
- package/dist/internal/createAppV3.d.ts.map +1 -1
- package/dist/internal/createAppV3.js +74 -83
- package/dist/internal/createAppV3.js.map +1 -1
- package/dist/internal/getServices.d.ts +5 -0
- package/dist/internal/getServices.d.ts.map +1 -0
- package/dist/internal/getServices.js +19 -0
- package/dist/internal/getServices.js.map +1 -0
- package/dist/internal/service_factories.d.ts +2 -2
- package/dist/internal/service_factories.d.ts.map +1 -1
- package/dist/internal/service_factories.js.map +1 -1
- package/dist/internal/utils.d.ts +3 -0
- package/dist/internal/utils.d.ts.map +1 -0
- package/dist/internal/utils.js +16 -0
- package/dist/internal/utils.js.map +1 -0
- package/package.json +8 -8
- package/src/components/PlAgColumnHeader/PlAgColumnHeader.vue +13 -7
- package/src/components/PlAgColumnHeader/types.ts +1 -0
- package/src/components/PlAgDataTable/sources/table-source-v2.ts +23 -21
- package/src/internal/createAppV3.ts +10 -37
- package/src/internal/getServices.ts +36 -0
- package/src/internal/service_factories.ts +2 -2
- package/src/internal/utils.ts +25 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAppV3.js","names":[],"sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n PlatformaExtended,\n InferPluginHandles,\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n InferFactoryUiServices,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\nimport {\n hasAbortError,\n unwrapResult,\n deriveDataFromStorage,\n getPluginData,\n isPluginOutputKey,\n pluginOutputPrefix,\n createNodeServiceProxy,\n buildServices,\n} from \"@platforma-sdk/model\";\nimport { type UiServices as AllUiServices } from \"@milaboratories/pl-model-common\";\nimport { createUiServiceRegistry } from \"./service_factories\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref, markRaw } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { ensureOutputHasStableFlag, MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\nimport type { PluginState, PluginAccess } from \"../usePlugin\";\n\nexport const patchPoolingDelay = 150;\n\n/** Internal per-plugin state with reconciliation support. */\ninterface InternalPluginState<\n Data = unknown,\n Outputs = unknown,\n Services = Record<string, unknown>,\n> extends PluginState<Data, Outputs, Services> {\n readonly ignoreUpdates: (fn: () => void) => void;\n}\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n>(\n state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,\n platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>,\n settings: AppSettings,\n) {\n const debug = (msg: string, ...rest: unknown[]) => {\n if (settings.debug) {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n }\n };\n\n const error = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n };\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const pluginDataQueues = new Map<PluginHandle, UpdateSerializer>();\n const getPluginDataQueue = (handle: PluginHandle): UpdateSerializer => {\n let queue = pluginDataQueues.get(handle);\n if (!queue) {\n queue = new UpdateSerializer({ debounceSpan });\n pluginDataQueues.set(handle, queue);\n }\n return queue;\n };\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n\n /** Lazily-created per-plugin reactive states. */\n const pluginStates = new Map<PluginHandle, InternalPluginState>();\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-block-data\", value }, nextAuthorMarker());\n };\n\n const updatePluginData = async (handle: PluginHandle, value: unknown) => {\n return platforma.mutateStorage(\n { operation: \"update-plugin-data\", pluginId: handle, value },\n nextAuthorMarker(),\n );\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, outputWithStatus]) =>\n platforma.blockModelInfo.outputs[k]?.withStatus\n ? [k, ensureOutputHasStableFlag(outputWithStatus)]\n : [\n k,\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ]);\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n Promise.allSettled([uiRegistry.dispose(), platforma.dispose().then(unwrapResult)]).catch(\n (err) => {\n error(\"error in dispose\", err);\n },\n );\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n // Reconcile plugin data from external source\n for (const [handle, pluginState] of pluginStates) {\n pluginState.ignoreUpdates(() => {\n pluginState.model.data = deepClone(\n getPluginData(snapshot.value.blockStorage, handle),\n );\n });\n }\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n const allQueues = [\n setDataQueue.allSettled(),\n ...Array.from(pluginDataQueues.values()).map((q) => q.allSettled()),\n ];\n await Promise.all(allQueues);\n },\n };\n\n const proxy = createNodeServiceProxy(platforma.serviceDispatch);\n const uiRegistry = createUiServiceRegistry({ proxy });\n const services = buildServices<UiServices>(platforma.serviceDispatch, uiRegistry);\n\n /** Creates a lazily-cached per-plugin reactive state. */\n const createPluginState = <F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>> => {\n const prefix = pluginOutputPrefix(handle);\n\n const pluginOutputs = computed(() => {\n const result: Record<string, unknown> = {};\n for (const [key, outputWithStatus] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n const outputKey = key.slice(prefix.length);\n if (platforma.blockModelInfo.outputs[key]?.withStatus) {\n result[outputKey] = outputWithStatus\n ? ensureOutputHasStableFlag(outputWithStatus)\n : undefined;\n } else {\n result[outputKey] =\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined;\n }\n }\n return result;\n });\n\n const pluginOutputErrors = computed(() => {\n const result: Record<string, Error | undefined> = {};\n for (const [key, vOrErr] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n result[key.slice(prefix.length)] =\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined;\n }\n return result;\n });\n\n const pluginModel = reactive({\n data: deepClone(getPluginData(snapshot.value.blockStorage, handle)),\n outputs: pluginOutputs,\n outputErrors: pluginOutputErrors,\n }) as InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>>[\"model\"];\n\n const { ignoreUpdates } = watchIgnorable(\n () => pluginModel.data,\n (newData) => {\n if (newData === undefined) return;\n debug(\"plugin setData\", handle, newData);\n getPluginDataQueue(handle).run(() =>\n updatePluginData(handle, deepClone(newData)).then(unwrapResult),\n );\n },\n { deep: true },\n );\n\n return {\n model: pluginModel,\n services: markRaw(services),\n ignoreUpdates,\n };\n };\n\n /** Plugin internals — provided via separate injection key, not exposed on useApp(). */\n const pluginAccess: PluginAccess = {\n getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const existing = pluginStates.get(handle);\n if (existing) {\n return existing as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n }\n const state = createPluginState(handle);\n pluginStates.set(handle, state);\n return state as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n },\n };\n\n const plugins = Object.fromEntries(\n platforma.blockModelInfo.pluginIds.map((id) => [id, { handle: id }]),\n ) as InferPluginHandles<Plugins>;\n\n const getters = {\n closedRef,\n snapshot,\n plugins,\n services: markRaw(services),\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = Object.assign(reactive(Object.assign(appModel, getters)), methods);\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return { app, pluginAccess };\n}\n\nexport type BaseAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins, UiServices>>[\"app\"];\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createAppV3.js","names":[],"sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n PlatformaExtended,\n InferPluginHandles,\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n InferFactoryUiServices,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\nimport {\n hasAbortError,\n unwrapResult,\n deriveDataFromStorage,\n getPluginData,\n isPluginOutputKey,\n pluginOutputPrefix,\n} from \"@platforma-sdk/model\";\nimport { type UiServices as AllUiServices } from \"@milaboratories/pl-model-common\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref, markRaw } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { ensureOutputHasStableFlag, MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\nimport type { PluginState, PluginAccess } from \"../usePlugin\";\nimport { logDebug, logError } from \"./utils\";\nimport { getServices } from \"./getServices\";\n\nexport const patchPoolingDelay = 150;\n\n/** Internal per-plugin state with reconciliation support. */\ninterface InternalPluginState<\n Data = unknown,\n Outputs = unknown,\n Services = Record<string, unknown>,\n> extends PluginState<Data, Outputs, Services> {\n readonly ignoreUpdates: (fn: () => void) => void;\n}\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n>(\n state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,\n platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>,\n settings: AppSettings,\n) {\n const debug = settings.debug ? logDebug : () => {};\n const error = logError;\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const pluginDataQueues = new Map<PluginHandle, UpdateSerializer>();\n const getPluginDataQueue = (handle: PluginHandle): UpdateSerializer => {\n let queue = pluginDataQueues.get(handle);\n if (!queue) {\n queue = new UpdateSerializer({ debounceSpan });\n pluginDataQueues.set(handle, queue);\n }\n return queue;\n };\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n\n /** Lazily-created per-plugin reactive states. */\n const pluginStates = new Map<PluginHandle, InternalPluginState>();\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-block-data\", value }, nextAuthorMarker());\n };\n\n const updatePluginData = async (handle: PluginHandle, value: unknown) => {\n return platforma.mutateStorage(\n { operation: \"update-plugin-data\", pluginId: handle, value },\n nextAuthorMarker(),\n );\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, outputWithStatus]) =>\n platforma.blockModelInfo.outputs[k]?.withStatus\n ? [k, ensureOutputHasStableFlag(outputWithStatus)]\n : [\n k,\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ]);\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n platforma\n .dispose()\n .then(unwrapResult)\n .catch((err) => {\n error(\"error in dispose\", err);\n });\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n // Reconcile plugin data from external source\n for (const [handle, pluginState] of pluginStates) {\n pluginState.ignoreUpdates(() => {\n pluginState.model.data = deepClone(\n getPluginData(snapshot.value.blockStorage, handle),\n );\n });\n }\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n const allQueues = [\n setDataQueue.allSettled(),\n ...Array.from(pluginDataQueues.values()).map((q) => q.allSettled()),\n ];\n await Promise.all(allQueues);\n },\n };\n\n const services = getServices<UiServices>({ platforma });\n\n /** Creates a lazily-cached per-plugin reactive state. */\n const createPluginState = <F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>> => {\n const prefix = pluginOutputPrefix(handle);\n\n const pluginOutputs = computed(() => {\n const result: Record<string, unknown> = {};\n for (const [key, outputWithStatus] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n const outputKey = key.slice(prefix.length);\n if (platforma.blockModelInfo.outputs[key]?.withStatus) {\n result[outputKey] = outputWithStatus\n ? ensureOutputHasStableFlag(outputWithStatus)\n : undefined;\n } else {\n result[outputKey] =\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined;\n }\n }\n return result;\n });\n\n const pluginOutputErrors = computed(() => {\n const result: Record<string, Error | undefined> = {};\n for (const [key, vOrErr] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n result[key.slice(prefix.length)] =\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined;\n }\n return result;\n });\n\n const pluginModel = reactive({\n data: deepClone(getPluginData(snapshot.value.blockStorage, handle)),\n outputs: pluginOutputs,\n outputErrors: pluginOutputErrors,\n }) as InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>>[\"model\"];\n\n const { ignoreUpdates } = watchIgnorable(\n () => pluginModel.data,\n (newData) => {\n if (newData === undefined) return;\n debug(\"plugin setData\", handle, newData);\n getPluginDataQueue(handle).run(() =>\n updatePluginData(handle, deepClone(newData)).then(unwrapResult),\n );\n },\n { deep: true },\n );\n\n return {\n model: pluginModel,\n services: markRaw(services),\n ignoreUpdates,\n };\n };\n\n /** Plugin internals — provided via separate injection key, not exposed on useApp(). */\n const pluginAccess: PluginAccess = {\n getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const existing = pluginStates.get(handle);\n if (existing) {\n return existing as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n }\n const state = createPluginState(handle);\n pluginStates.set(handle, state);\n return state as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n },\n };\n\n const plugins = Object.fromEntries(\n platforma.blockModelInfo.pluginIds.map((id) => [id, { handle: id }]),\n ) as InferPluginHandles<Plugins>;\n\n const getters = {\n closedRef,\n snapshot,\n plugins,\n services: markRaw(services),\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = Object.assign(reactive(Object.assign(appModel, getters)), methods);\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return { app, pluginAccess };\n}\n\nexport type BaseAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins, UiServices>>[\"app\"];\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BlockDefaultUiServices, PlatformaV3, UiServices } from '@platforma-sdk/model';
|
|
2
|
+
export declare function getServices<Services extends Partial<UiServices> = BlockDefaultUiServices>(deps?: {
|
|
3
|
+
platforma?: PlatformaV3<any, any, any, any, any, Services>;
|
|
4
|
+
}): Services;
|
|
5
|
+
//# sourceMappingURL=getServices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getServices.d.ts","sourceRoot":"","sources":["../../src/internal/getServices.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EAItB,WAAW,EACX,UAAU,EACX,MAAM,sBAAsB,CAAC;AAO9B,wBAAgB,WAAW,CAAC,QAAQ,SAAS,OAAO,CAAC,UAAU,CAAC,GAAG,sBAAsB,EAAE,IAAI,CAAC,EAAE;IAChG,SAAS,CAAC,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;CAC5D,GAAG,QAAQ,CAmBX"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { logError as e } from "./utils.js";
|
|
2
|
+
import { createUiServiceRegistry as t } from "./service_factories.js";
|
|
3
|
+
import { buildServices as n, createServiceProxy as r, getRawPlatformaInstance as i } from "@platforma-sdk/model";
|
|
4
|
+
import { isNil as a } from "es-toolkit";
|
|
5
|
+
//#region src/internal/getServices.ts
|
|
6
|
+
var o = null;
|
|
7
|
+
function s(s) {
|
|
8
|
+
if (!a(o)) return o;
|
|
9
|
+
let c = s?.platforma ?? i(), l = t({ proxy: r(c.serviceDispatch) }), u = n(c.serviceDispatch, l);
|
|
10
|
+
return window.addEventListener("beforeunload", () => {
|
|
11
|
+
l.dispose().catch((t) => {
|
|
12
|
+
e("uiRegistry error in dispose", t);
|
|
13
|
+
});
|
|
14
|
+
}), o = u;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { s as getServices };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=getServices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getServices.js","names":[],"sources":["../../src/internal/getServices.ts"],"sourcesContent":["import {\n BlockDefaultUiServices,\n buildServices,\n createServiceProxy,\n getRawPlatformaInstance,\n PlatformaV3,\n UiServices,\n} from \"@platforma-sdk/model\";\nimport { createUiServiceRegistry } from \"./service_factories\";\nimport { isNil } from \"es-toolkit\";\nimport { logError } from \"./utils\";\n\nlet cachedServices: null | Partial<UiServices> = null;\n\nexport function getServices<Services extends Partial<UiServices> = BlockDefaultUiServices>(deps?: {\n platforma?: PlatformaV3<any, any, any, any, any, Services>;\n}): Services {\n if (!isNil(cachedServices)) {\n return cachedServices as Services;\n }\n\n const platforma =\n deps?.platforma ??\n (getRawPlatformaInstance() as PlatformaV3<any, any, any, any, any, Services>);\n const proxy = createServiceProxy(platforma.serviceDispatch);\n const uiRegistry = createUiServiceRegistry({ proxy });\n const services = buildServices<Services>(platforma.serviceDispatch, uiRegistry);\n\n window.addEventListener(\"beforeunload\", () => {\n uiRegistry.dispose().catch((err) => {\n logError(\"uiRegistry error in dispose\", err);\n });\n });\n\n return (cachedServices = services) as Services;\n}\n"],"mappings":";;;;;AAYA,IAAI,IAA6C;AAEjD,SAAgB,EAA2E,GAE9E;AACX,KAAI,CAAC,EAAM,EAAe,CACxB,QAAO;CAGT,IAAM,IACJ,GAAM,aACL,GAAyB,EAEtB,IAAa,EAAwB,EAAE,OAD/B,EAAmB,EAAU,gBAAgB,EACP,CAAC,EAC/C,IAAW,EAAwB,EAAU,iBAAiB,EAAW;AAQ/E,QANA,OAAO,iBAAiB,sBAAsB;AAC5C,IAAW,SAAS,CAAC,OAAO,MAAQ;AAClC,KAAS,+BAA+B,EAAI;IAC5C;GACF,EAEM,IAAiB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UiServiceRegistry } from '@milaboratories/pl-model-common';
|
|
2
|
-
import {
|
|
2
|
+
import { ServiceProxy } from '@platforma-sdk/model';
|
|
3
3
|
export type UiServiceOptions = {
|
|
4
|
-
proxy:
|
|
4
|
+
proxy: ServiceProxy;
|
|
5
5
|
};
|
|
6
6
|
export declare function createUiServiceRegistry(options: UiServiceOptions): UiServiceRegistry<{
|
|
7
7
|
PFrameSpec: import('@milaboratories/pl-model-common').Branded<"pframeSpec", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameSpecDriver, import('@milaboratories/pl-model-common').PFrameSpecDriver, "wasm">>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_factories.d.ts","sourceRoot":"","sources":["../../src/internal/service_factories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"service_factories.d.ts","sourceRoot":"","sources":["../../src/internal/service_factories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;;;GAKhE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_factories.js","names":[],"sources":["../../src/internal/service_factories.ts"],"sourcesContent":["/**\n * UI service factories — add a factory for each new service here.\n *\n * Each entry maps a Services key to a factory function that creates the\n * UI-side driver instance:\n * - WASM services: instantiated directly (e.g. SpecDriver)\n * - Node services: proxied via IPC using NodeServiceProxy\n */\n\nimport { Services, UiServiceRegistry } from \"@milaboratories/pl-model-common\";\nimport { SpecDriver } from \"@milaboratories/pf-spec-driver\";\nimport type {
|
|
1
|
+
{"version":3,"file":"service_factories.js","names":[],"sources":["../../src/internal/service_factories.ts"],"sourcesContent":["/**\n * UI service factories — add a factory for each new service here.\n *\n * Each entry maps a Services key to a factory function that creates the\n * UI-side driver instance:\n * - WASM services: instantiated directly (e.g. SpecDriver)\n * - Node services: proxied via IPC using NodeServiceProxy\n */\n\nimport { Services, UiServiceRegistry } from \"@milaboratories/pl-model-common\";\nimport { SpecDriver } from \"@milaboratories/pf-spec-driver\";\nimport type { ServiceProxy } from \"@platforma-sdk/model\";\n\nexport type UiServiceOptions = {\n proxy: ServiceProxy;\n};\n\nexport function createUiServiceRegistry(options: UiServiceOptions) {\n return new UiServiceRegistry(Services, {\n PFrameSpec: () => new SpecDriver(),\n PFrame: () => options.proxy(Services.PFrame),\n });\n}\n"],"mappings":";;;AAiBA,SAAgB,EAAwB,GAA2B;AACjE,QAAO,IAAI,EAAkB,GAAU;EACrC,kBAAkB,IAAI,GAAY;EAClC,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/internal/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,GAAG,MAAM,OAAO,EAAE,SAOvD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,GAAG,MAAM,OAAO,EAAE,SAOvD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/internal/utils.ts
|
|
2
|
+
var e = (e, ...t) => {
|
|
3
|
+
console.log(`%c>>> %c${e}`, "color: orange; font-weight: bold", "color: orange", ...t.map((e) => n(e)));
|
|
4
|
+
}, t = (e, ...t) => {
|
|
5
|
+
console.error(`%c>>> %c${e}`, "color: red; font-weight: bold", "color: red", ...t.map((e) => n(e)));
|
|
6
|
+
}, n = (e) => {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(e, null, 2);
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return e instanceof Error ? e.message : String(e);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { e as logDebug, t as logError };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../src/internal/utils.ts"],"sourcesContent":["export const logDebug = (msg: string, ...rest: unknown[]) => {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n};\n\nexport const logError = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n};\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n"],"mappings":";AAAA,IAAa,KAAY,GAAa,GAAG,MAAoB;AAC3D,SAAQ,IACN,WAAW,KACX,oCACA,iBACA,GAAG,EAAK,KAAK,MAAM,EAAkB,EAAE,CAAC,CACzC;GAGU,KAAY,GAAa,GAAG,MAAoB;AAC3D,SAAQ,MACN,WAAW,KACX,iCACA,cACA,GAAG,EAAK,KAAK,MAAM,EAAkB,EAAE,CAAC,CACzC;GAGG,KAAqB,MAAe;AACxC,KAAI;AACF,SAAO,KAAK,UAAU,GAAG,MAAM,EAAE;UAC1B,GAAK;AACZ,SAAO,aAAe,QAAQ,EAAI,UAAU,OAAO,EAAI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/ui-vue",
|
|
3
|
-
"version": "1.66.
|
|
3
|
+
"version": "1.66.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"lru-cache": "^11.2.2",
|
|
27
27
|
"vue": "^3.5.24",
|
|
28
28
|
"zod": "~3.25.76",
|
|
29
|
-
"@milaboratories/
|
|
30
|
-
"@
|
|
31
|
-
"@milaboratories/
|
|
32
|
-
"@
|
|
29
|
+
"@milaboratories/pl-model-common": "1.34.1",
|
|
30
|
+
"@milaboratories/pf-spec-driver": "1.3.2",
|
|
31
|
+
"@milaboratories/uikit": "2.12.8",
|
|
32
|
+
"@platforma-sdk/model": "1.66.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@faker-js/faker": "^9.2.0",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"typescript": "~5.9.3",
|
|
44
44
|
"vite": "^8.0.6",
|
|
45
45
|
"vitest": "^4.1.3",
|
|
46
|
-
"@milaboratories/helpers": "1.14.1",
|
|
47
46
|
"@milaboratories/ts-builder": "1.3.2",
|
|
48
|
-
"@milaboratories/
|
|
49
|
-
"@milaboratories/ts-configs": "1.2.3"
|
|
47
|
+
"@milaboratories/helpers": "1.14.1",
|
|
48
|
+
"@milaboratories/ts-configs": "1.2.3",
|
|
49
|
+
"@milaboratories/build-configs": "2.0.0"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"dev": "ts-builder serve --target browser-lib",
|
|
@@ -64,14 +64,20 @@ function showMenu() {
|
|
|
64
64
|
|
|
65
65
|
<template>
|
|
66
66
|
<div class="pl-ag-column-header d-flex align-center gap-6" @click="onSortRequested">
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
<
|
|
70
|
-
<
|
|
67
|
+
<div class="pl-ag-column-header__title d-flex align-center gap-6 flex-grow-1">
|
|
68
|
+
<PlMaskIcon16 :name="icon" class="pl-ag-column-header__type-icon" />
|
|
69
|
+
<PlTooltip>
|
|
70
|
+
<template v-if="params.tooltip" #tooltip>{{ params.tooltip }}</template>
|
|
71
71
|
<span>{{ params.displayName }}</span>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
</PlTooltip>
|
|
73
|
+
<PlTooltip v-if="params.info" max-width="500px" position="bottom" :close-delay="10000000000">
|
|
74
|
+
<template #tooltip>
|
|
75
|
+
<span style="white-space: pre-wrap">{{ params.info }}</span>
|
|
76
|
+
</template>
|
|
77
|
+
<PlMaskIcon16 name="info" />
|
|
78
|
+
</PlTooltip>
|
|
79
|
+
<PlMaskIcon16 v-if="sortIcon" :name="sortIcon" />
|
|
80
|
+
</div>
|
|
75
81
|
<div
|
|
76
82
|
v-if="params.enableMenu"
|
|
77
83
|
ref="menuActivatorBtn"
|
|
@@ -63,15 +63,15 @@ function columns2rows(
|
|
|
63
63
|
axesResultIndices: number[],
|
|
64
64
|
): PlAgDataTableV2Row[] {
|
|
65
65
|
const rowData: PlAgDataTableV2Row[] = [];
|
|
66
|
-
for (let
|
|
67
|
-
const axesKey: PTableKey = axesResultIndices.map((ri) => pTableValue(columns[ri],
|
|
66
|
+
for (let rowIdx = 0; rowIdx < columns[0].data.length; ++rowIdx) {
|
|
67
|
+
const axesKey: PTableKey = axesResultIndices.map((ri) => pTableValue(columns[ri], rowIdx));
|
|
68
68
|
const id = canonicalizeJson<PlTableRowId>(axesKey);
|
|
69
69
|
const row = fields.reduce<PlAgDataTableV2Row>(
|
|
70
|
-
(acc, field,
|
|
70
|
+
(acc, field, colIdx) => {
|
|
71
71
|
acc[field.toString() as `${number}`] =
|
|
72
|
-
fieldResultMapping[
|
|
72
|
+
fieldResultMapping[colIdx] === -1
|
|
73
73
|
? PTableHidden
|
|
74
|
-
: pTableValue(columns[fieldResultMapping[
|
|
74
|
+
: pTableValue(columns[fieldResultMapping[colIdx]], rowIdx);
|
|
75
75
|
return acc;
|
|
76
76
|
},
|
|
77
77
|
{ id, axesKey },
|
|
@@ -156,10 +156,10 @@ export async function calculateGridOptions({
|
|
|
156
156
|
// request indices: non-hidden display fields + visible axes for row selection keys.
|
|
157
157
|
// Axes replaced by label columns request label data (display); original axis values
|
|
158
158
|
// are fetched via visibleAxes (row keys).
|
|
159
|
-
const { requestIndices,
|
|
159
|
+
const { requestIndices, axesResultIndices, fieldResultMapping } = buildRequestIndices(
|
|
160
160
|
indices,
|
|
161
|
+
visibleAxes.map(([idx]) => idx),
|
|
161
162
|
specsToVisibleSpecsMapping,
|
|
162
|
-
visibleAxes.map(([i]) => i),
|
|
163
163
|
);
|
|
164
164
|
|
|
165
165
|
let rowCount = -1;
|
|
@@ -313,7 +313,12 @@ export function makeColDef(
|
|
|
313
313
|
throw Error(`unsupported data type: ${valueType}`);
|
|
314
314
|
}
|
|
315
315
|
})(),
|
|
316
|
-
tooltip:
|
|
316
|
+
tooltip:
|
|
317
|
+
readAnnotation(spec.spec, Annotation.Description)?.trim() ??
|
|
318
|
+
readAnnotation(labeledSpec.spec, Annotation.Description)?.trim(),
|
|
319
|
+
info:
|
|
320
|
+
readAnnotation(spec.spec, Annotation.Table.Info)?.trim() ??
|
|
321
|
+
readAnnotation(labeledSpec.spec, Annotation.Table.Info)?.trim(),
|
|
317
322
|
} satisfies PlAgHeaderComponentParams,
|
|
318
323
|
cellDataType: (() => {
|
|
319
324
|
switch (valueType) {
|
|
@@ -465,26 +470,23 @@ function collectVisibleAxes(
|
|
|
465
470
|
*/
|
|
466
471
|
function buildRequestIndices(
|
|
467
472
|
indices: number[],
|
|
468
|
-
specsToVisibleSpecsMapping: Map<number, number>,
|
|
469
473
|
visibleAxesIndices: number[],
|
|
474
|
+
specsToVisibleSpecsMapping: Map<number, number>,
|
|
470
475
|
): {
|
|
471
476
|
requestIndices: number[];
|
|
472
|
-
fieldResultMapping: number[];
|
|
473
477
|
axesResultIndices: number[];
|
|
478
|
+
fieldResultMapping: number[];
|
|
474
479
|
} {
|
|
475
480
|
const resolved = indices.map((displayField) => {
|
|
476
481
|
const idx = specsToVisibleSpecsMapping.get(displayField);
|
|
477
|
-
return idx
|
|
482
|
+
return isNil(idx) || idx === -1 ? null : idx;
|
|
478
483
|
});
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
fieldResultMapping.push(v === null ? -1 : pos++);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const requestIndices = uniq([...requestedFields, ...visibleAxesIndices]);
|
|
484
|
+
const requestIndices = uniq([
|
|
485
|
+
...resolved.filter((v): v is number => v !== null),
|
|
486
|
+
...visibleAxesIndices,
|
|
487
|
+
]);
|
|
488
|
+
const fieldResultMapping = resolved.map((v) => (v === null ? -1 : requestIndices.indexOf(v)));
|
|
488
489
|
const axesResultIndices = visibleAxesIndices.map((vi) => requestIndices.indexOf(vi));
|
|
489
|
-
|
|
490
|
+
|
|
491
|
+
return { requestIndices, axesResultIndices, fieldResultMapping };
|
|
490
492
|
}
|
|
@@ -22,11 +22,8 @@ import {
|
|
|
22
22
|
getPluginData,
|
|
23
23
|
isPluginOutputKey,
|
|
24
24
|
pluginOutputPrefix,
|
|
25
|
-
createNodeServiceProxy,
|
|
26
|
-
buildServices,
|
|
27
25
|
} from "@platforma-sdk/model";
|
|
28
26
|
import { type UiServices as AllUiServices } from "@milaboratories/pl-model-common";
|
|
29
|
-
import { createUiServiceRegistry } from "./service_factories";
|
|
30
27
|
import type { Ref } from "vue";
|
|
31
28
|
import { reactive, computed, ref, markRaw } from "vue";
|
|
32
29
|
import type { OutputValues, OutputErrors, AppSettings } from "../types";
|
|
@@ -36,6 +33,8 @@ import { applyPatch } from "fast-json-patch";
|
|
|
36
33
|
import { UpdateSerializer } from "./UpdateSerializer";
|
|
37
34
|
import { watchIgnorable } from "@vueuse/core";
|
|
38
35
|
import type { PluginState, PluginAccess } from "../usePlugin";
|
|
36
|
+
import { logDebug, logError } from "./utils";
|
|
37
|
+
import { getServices } from "./getServices";
|
|
39
38
|
|
|
40
39
|
export const patchPoolingDelay = 150;
|
|
41
40
|
|
|
@@ -53,14 +52,6 @@ export const createNextAuthorMarker = (marker: AuthorMarker | undefined): Author
|
|
|
53
52
|
localVersion: (marker?.localVersion ?? 0) + 1,
|
|
54
53
|
});
|
|
55
54
|
|
|
56
|
-
const stringifyForDebug = (v: unknown) => {
|
|
57
|
-
try {
|
|
58
|
-
return JSON.stringify(v, null, 2);
|
|
59
|
-
} catch (err) {
|
|
60
|
-
return err instanceof Error ? err.message : String(err);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
55
|
/**
|
|
65
56
|
* Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.
|
|
66
57
|
*
|
|
@@ -87,25 +78,8 @@ export function createAppV3<
|
|
|
87
78
|
platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>,
|
|
88
79
|
settings: AppSettings,
|
|
89
80
|
) {
|
|
90
|
-
const debug =
|
|
91
|
-
|
|
92
|
-
console.log(
|
|
93
|
-
`%c>>> %c${msg}`,
|
|
94
|
-
"color: orange; font-weight: bold",
|
|
95
|
-
"color: orange",
|
|
96
|
-
...rest.map((r) => stringifyForDebug(r)),
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const error = (msg: string, ...rest: unknown[]) => {
|
|
102
|
-
console.error(
|
|
103
|
-
`%c>>> %c${msg}`,
|
|
104
|
-
"color: red; font-weight: bold",
|
|
105
|
-
"color: red",
|
|
106
|
-
...rest.map((r) => stringifyForDebug(r)),
|
|
107
|
-
);
|
|
108
|
-
};
|
|
81
|
+
const debug = settings.debug ? logDebug : () => {};
|
|
82
|
+
const error = logError;
|
|
109
83
|
|
|
110
84
|
const data = {
|
|
111
85
|
isExternalSnapshot: false,
|
|
@@ -230,11 +204,12 @@ export function createAppV3<
|
|
|
230
204
|
(async () => {
|
|
231
205
|
window.addEventListener("beforeunload", () => {
|
|
232
206
|
closedRef.value = true;
|
|
233
|
-
|
|
234
|
-
(
|
|
207
|
+
platforma
|
|
208
|
+
.dispose()
|
|
209
|
+
.then(unwrapResult)
|
|
210
|
+
.catch((err) => {
|
|
235
211
|
error("error in dispose", err);
|
|
236
|
-
}
|
|
237
|
-
);
|
|
212
|
+
});
|
|
238
213
|
});
|
|
239
214
|
|
|
240
215
|
while (!closedRef.value) {
|
|
@@ -334,9 +309,7 @@ export function createAppV3<
|
|
|
334
309
|
},
|
|
335
310
|
};
|
|
336
311
|
|
|
337
|
-
const
|
|
338
|
-
const uiRegistry = createUiServiceRegistry({ proxy });
|
|
339
|
-
const services = buildServices<UiServices>(platforma.serviceDispatch, uiRegistry);
|
|
312
|
+
const services = getServices<UiServices>({ platforma });
|
|
340
313
|
|
|
341
314
|
/** Creates a lazily-cached per-plugin reactive state. */
|
|
342
315
|
const createPluginState = <F extends PluginFactoryLike>(
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BlockDefaultUiServices,
|
|
3
|
+
buildServices,
|
|
4
|
+
createServiceProxy,
|
|
5
|
+
getRawPlatformaInstance,
|
|
6
|
+
PlatformaV3,
|
|
7
|
+
UiServices,
|
|
8
|
+
} from "@platforma-sdk/model";
|
|
9
|
+
import { createUiServiceRegistry } from "./service_factories";
|
|
10
|
+
import { isNil } from "es-toolkit";
|
|
11
|
+
import { logError } from "./utils";
|
|
12
|
+
|
|
13
|
+
let cachedServices: null | Partial<UiServices> = null;
|
|
14
|
+
|
|
15
|
+
export function getServices<Services extends Partial<UiServices> = BlockDefaultUiServices>(deps?: {
|
|
16
|
+
platforma?: PlatformaV3<any, any, any, any, any, Services>;
|
|
17
|
+
}): Services {
|
|
18
|
+
if (!isNil(cachedServices)) {
|
|
19
|
+
return cachedServices as Services;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const platforma =
|
|
23
|
+
deps?.platforma ??
|
|
24
|
+
(getRawPlatformaInstance() as PlatformaV3<any, any, any, any, any, Services>);
|
|
25
|
+
const proxy = createServiceProxy(platforma.serviceDispatch);
|
|
26
|
+
const uiRegistry = createUiServiceRegistry({ proxy });
|
|
27
|
+
const services = buildServices<Services>(platforma.serviceDispatch, uiRegistry);
|
|
28
|
+
|
|
29
|
+
window.addEventListener("beforeunload", () => {
|
|
30
|
+
uiRegistry.dispose().catch((err) => {
|
|
31
|
+
logError("uiRegistry error in dispose", err);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return (cachedServices = services) as Services;
|
|
36
|
+
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
import { Services, UiServiceRegistry } from "@milaboratories/pl-model-common";
|
|
11
11
|
import { SpecDriver } from "@milaboratories/pf-spec-driver";
|
|
12
|
-
import type {
|
|
12
|
+
import type { ServiceProxy } from "@platforma-sdk/model";
|
|
13
13
|
|
|
14
14
|
export type UiServiceOptions = {
|
|
15
|
-
proxy:
|
|
15
|
+
proxy: ServiceProxy;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export function createUiServiceRegistry(options: UiServiceOptions) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const logDebug = (msg: string, ...rest: unknown[]) => {
|
|
2
|
+
console.log(
|
|
3
|
+
`%c>>> %c${msg}`,
|
|
4
|
+
"color: orange; font-weight: bold",
|
|
5
|
+
"color: orange",
|
|
6
|
+
...rest.map((r) => stringifyForDebug(r)),
|
|
7
|
+
);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const logError = (msg: string, ...rest: unknown[]) => {
|
|
11
|
+
console.error(
|
|
12
|
+
`%c>>> %c${msg}`,
|
|
13
|
+
"color: red; font-weight: bold",
|
|
14
|
+
"color: red",
|
|
15
|
+
...rest.map((r) => stringifyForDebug(r)),
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const stringifyForDebug = (v: unknown) => {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.stringify(v, null, 2);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
return err instanceof Error ? err.message : String(err);
|
|
24
|
+
}
|
|
25
|
+
};
|