@platforma-sdk/ui-vue 1.67.0 → 1.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +19 -19
- 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 +22 -0
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts +2 -0
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js +25 -17
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js.map +1 -1
- package/dist/components/PlAgCsvExporter/export-csv.d.ts +27 -1
- package/dist/components/PlAgCsvExporter/export-csv.d.ts.map +1 -1
- package/dist/components/PlAgCsvExporter/export-csv.js +31 -33
- package/dist/components/PlAgCsvExporter/export-csv.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.style.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +68 -64
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/compositions/useGrid.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/compositions/useGrid.js +1 -1
- package/dist/components/PlAgDataTable/compositions/useGrid.js.map +1 -1
- package/dist/components/PlAgDataTable/sources/table-source-v2.js +2 -2
- package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/composition/usePlugin.d.ts.map +1 -0
- package/dist/{usePlugin.js → composition/usePlugin.js} +2 -2
- package/dist/composition/usePlugin.js.map +1 -0
- package/dist/composition/useServices.d.ts +2 -0
- package/dist/composition/useServices.d.ts.map +1 -0
- package/dist/index.js +1 -1
- package/dist/internal/createAppV3.d.ts +2 -3
- package/dist/internal/createAppV3.d.ts.map +1 -1
- package/dist/internal/createAppV3.js +1 -1
- package/dist/internal/createAppV3.js.map +1 -1
- package/dist/internal/service_factories.d.ts +1 -0
- package/dist/internal/service_factories.d.ts.map +1 -1
- package/dist/internal/service_factories.js +2 -1
- package/dist/internal/service_factories.js.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +1 -1
- package/package.json +8 -8
- package/src/components/PlAgCsvExporter/PlAgCsvExporter.vue +16 -3
- package/src/components/PlAgCsvExporter/export-csv.ts +101 -64
- package/src/components/PlAgDataTable/PlAgDataTableV2.vue +6 -1
- package/src/components/PlAgDataTable/compositions/useGrid.ts +4 -1
- package/src/components/PlAgDataTable/sources/table-source-v2.ts +2 -2
- package/src/{usePlugin.ts → composition/usePlugin.ts} +1 -1
- package/src/composition/useServices.ts +5 -0
- package/src/internal/createAppV3.ts +4 -4
- package/src/internal/service_factories.ts +1 -0
- package/src/lib.ts +2 -2
- package/dist/usePlugin.d.ts.map +0 -1
- package/dist/usePlugin.js.map +0 -1
- /package/dist/{usePlugin.d.ts → composition/usePlugin.d.ts} +0 -0
|
@@ -1,74 +1,111 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "
|
|
1
|
+
import { type ColDef, type ColGroupDef, type GridApi } from "ag-grid-enterprise";
|
|
2
|
+
import type {
|
|
3
|
+
PTableHandle,
|
|
4
|
+
PTableDownloadFormat,
|
|
5
|
+
PTableColumnSpec,
|
|
6
|
+
PFrameSpecDriver,
|
|
7
|
+
WritePTableToFsResult,
|
|
8
|
+
} from "@platforma-sdk/model";
|
|
9
|
+
import { getPTableColumnId } from "@platforma-sdk/model";
|
|
10
|
+
import { isNil } from "es-toolkit";
|
|
11
|
+
import { Nil } from "@milaboratories/helpers";
|
|
12
|
+
import { getServices } from "../../internal/getServices";
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
/** Options for the native CSV export path. */
|
|
15
|
+
export interface ExportOptions {
|
|
16
|
+
tableHandle: PTableHandle;
|
|
17
|
+
format: PTableDownloadFormat;
|
|
18
|
+
defaultFileName?: string;
|
|
19
|
+
}
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
/**
|
|
22
|
+
* CSV export via the platforma desktop runtime. Prompts for a save
|
|
23
|
+
* destination via the `Dialog` service, then streams the PTable to the
|
|
24
|
+
* chosen path via `PFrame.writePTableToFs`.
|
|
25
|
+
*/
|
|
26
|
+
export async function exportCsv(
|
|
27
|
+
gridApi: GridApi,
|
|
28
|
+
nativeOptions: ExportOptions,
|
|
29
|
+
): Promise<undefined | WritePTableToFsResult> {
|
|
30
|
+
const { dialog, pframe, pframeSpec } = getServices();
|
|
31
|
+
if (isNil(dialog)) {
|
|
32
|
+
throw new Error("dialog service is not available in the current environment");
|
|
33
|
+
}
|
|
34
|
+
if (isNil(pframe)) {
|
|
35
|
+
throw new Error("pframe service is not available");
|
|
36
|
+
}
|
|
37
|
+
if (isNil(pframeSpec)) {
|
|
38
|
+
throw new Error("pframeSpec service is not available");
|
|
39
|
+
}
|
|
15
40
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
41
|
+
const specs = await pframe.getSpec(nativeOptions.tableHandle);
|
|
42
|
+
const columnIndices = collectVisibleColumnIndices(gridApi, specs, pframeSpec);
|
|
43
|
+
if (isNil(columnIndices)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
19
46
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
47
|
+
const { canceled, path } = await dialog.showSaveDialog({
|
|
48
|
+
defaultFileName:
|
|
49
|
+
(nativeOptions.defaultFileName ?? `table_${formatTimestamp(new Date())}`) +
|
|
50
|
+
`.${nativeOptions.format}.gz`,
|
|
51
|
+
});
|
|
52
|
+
if (canceled || isNil(path)) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
23
55
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
56
|
+
return pframe.writePTableToFs(nativeOptions.tableHandle, {
|
|
57
|
+
path,
|
|
58
|
+
format: nativeOptions.format,
|
|
59
|
+
columnIndices,
|
|
60
|
+
compression: { type: "gzip" },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
31
63
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
64
|
+
function formatTimestamp(d: Date): string {
|
|
65
|
+
const pad = (n: number) => String(n).padStart(2, "0");
|
|
66
|
+
return (
|
|
67
|
+
`${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()}` +
|
|
68
|
+
`_${pad(d.getHours())}-${pad(d.getMinutes())}-${pad(d.getSeconds())}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
38
71
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})) ?? [],
|
|
53
|
-
serverSideDatasource: gridApi.getGridOption("serverSideDatasource"),
|
|
54
|
-
cacheBlockSize: state[0].rowCount,
|
|
55
|
-
onModelUpdated: (event) => {
|
|
56
|
-
const state = event.api.getServerSideGroupLevelState();
|
|
57
|
-
if (!exportStarted && state.length > 0 && state[0].rowCount === state[0].cacheBlockSize) {
|
|
58
|
-
exportStarted = true;
|
|
59
|
-
event.api.exportDataAsCsv();
|
|
60
|
-
destroyGridDiv(gridDiv);
|
|
61
|
-
return completed();
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
defaultCsvExportParams: gridApi.getGridOption("defaultCsvExportParams"),
|
|
65
|
-
};
|
|
66
|
-
return createGrid(gridDiv, gridOptions, { modules: [ServerSideRowModelModule] });
|
|
67
|
-
}
|
|
72
|
+
/**
|
|
73
|
+
* Checks whether the native CSV export capability is available in the
|
|
74
|
+
* current platforma runtime environment. Both `Dialog` and `PFrame`
|
|
75
|
+
* services must be present — desktop-app wires them, web/preview do not.
|
|
76
|
+
*/
|
|
77
|
+
export function isCsvExportAvailable(): boolean {
|
|
78
|
+
try {
|
|
79
|
+
const services = getServices();
|
|
80
|
+
return !isNil(services?.dialog) && !isNil(services?.pframe);
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
68
85
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Collect unified column indices for visible (non-hidden) columns from the
|
|
88
|
+
* ag-grid column defs, remapped onto the provided PTable spec array so the
|
|
89
|
+
* indices match the current table handle (ColDef.field indices may be stale
|
|
90
|
+
* or diverge from the spec order).
|
|
91
|
+
*/
|
|
92
|
+
export function collectVisibleColumnIndices(
|
|
93
|
+
gridApi: GridApi,
|
|
94
|
+
specs: PTableColumnSpec[],
|
|
95
|
+
pframeSpec: PFrameSpecDriver,
|
|
96
|
+
): Nil | number[] {
|
|
97
|
+
const columnDefs = gridApi.getColumnDefs();
|
|
98
|
+
if (isNil(columnDefs)) {
|
|
99
|
+
return;
|
|
73
100
|
}
|
|
101
|
+
|
|
102
|
+
return columnDefs
|
|
103
|
+
.filter(
|
|
104
|
+
(def: ColDef | ColGroupDef): def is ColDef =>
|
|
105
|
+
!("children" in def) && def.hide !== true && !isNil(def.context),
|
|
106
|
+
)
|
|
107
|
+
.map((def) =>
|
|
108
|
+
pframeSpec.findTableColumn(specs, getPTableColumnId(def.context as PTableColumnSpec)),
|
|
109
|
+
)
|
|
110
|
+
.filter((index): index is number => index !== -1);
|
|
74
111
|
}
|
|
@@ -554,8 +554,13 @@ watchEffect(() => {
|
|
|
554
554
|
@updateFilters="(v) => (filtersState = v)"
|
|
555
555
|
@resetDefaultFilters="resetDefaultFilters"
|
|
556
556
|
@updateDefaultFilters="(v) => (defaultFiltersState = v)"
|
|
557
|
+
v-model="filtersState"
|
|
558
|
+
/>
|
|
559
|
+
<PlAgCsvExporter
|
|
560
|
+
v-if="gridApi && showExportButton"
|
|
561
|
+
:api="gridApi"
|
|
562
|
+
:table-handle="'model' in settings ? settings?.model?.visibleTableHandle : undefined"
|
|
557
563
|
/>
|
|
558
|
-
<PlAgCsvExporter v-if="gridApi && showExportButton" :api="gridApi" />
|
|
559
564
|
<PlAgDataTableSheets v-model="sheetsState" :settings="sheetsSettings">
|
|
560
565
|
<template v-if="$slots['before-sheets']" #before>
|
|
561
566
|
<slot name="before-sheets" />
|
|
@@ -81,11 +81,14 @@ export function useGrid({
|
|
|
81
81
|
text: noRowsText,
|
|
82
82
|
} satisfies PlAgOverlayNoRowsParams,
|
|
83
83
|
defaultCsvExportParams: {
|
|
84
|
-
allColumns: true,
|
|
85
84
|
suppressQuotes: true,
|
|
86
85
|
columnSeparator: "\t",
|
|
87
86
|
fileName: "table.tsv",
|
|
88
87
|
},
|
|
88
|
+
getContextMenuItems: (params) =>
|
|
89
|
+
(params.defaultItems ?? []).filter(
|
|
90
|
+
(item) => item !== "export" && item !== "csvExport" && item !== "excelExport",
|
|
91
|
+
),
|
|
89
92
|
onGridReady: (event) => {
|
|
90
93
|
const api = event.api;
|
|
91
94
|
autoSizeRowNumberColumn(api);
|
|
@@ -396,11 +396,11 @@ function selectDisplayableIndices(
|
|
|
396
396
|
.filter(([, spec]) => {
|
|
397
397
|
switch (spec.type) {
|
|
398
398
|
case "axis":
|
|
399
|
-
return !isPartitionedAxis(spec.id);
|
|
399
|
+
return !isColumnHidden(spec.spec) && !isPartitionedAxis(spec.id);
|
|
400
400
|
case "column":
|
|
401
401
|
return (
|
|
402
|
-
!isLabelColumnSpec(spec.spec) &&
|
|
403
402
|
!isColumnHidden(spec.spec) &&
|
|
403
|
+
!isLabelColumnSpec(spec.spec) &&
|
|
404
404
|
!isLinkerColumnSpec(spec.spec)
|
|
405
405
|
);
|
|
406
406
|
}
|
|
@@ -12,8 +12,9 @@ import type {
|
|
|
12
12
|
PluginHandle,
|
|
13
13
|
InferFactoryData,
|
|
14
14
|
InferFactoryOutputs,
|
|
15
|
-
InferFactoryUiServices,
|
|
16
15
|
PluginFactoryLike,
|
|
16
|
+
UiServices as AllUiServices,
|
|
17
|
+
InferFactoryUiServices,
|
|
17
18
|
} from "@platforma-sdk/model";
|
|
18
19
|
import {
|
|
19
20
|
hasAbortError,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
isPluginOutputKey,
|
|
24
25
|
pluginOutputPrefix,
|
|
25
26
|
} from "@platforma-sdk/model";
|
|
26
|
-
import { type UiServices as AllUiServices } from "@milaboratories/pl-model-common";
|
|
27
27
|
import type { Ref } from "vue";
|
|
28
28
|
import { reactive, computed, ref, markRaw } from "vue";
|
|
29
29
|
import type { OutputValues, OutputErrors, AppSettings } from "../types";
|
|
@@ -32,7 +32,7 @@ import { ensureOutputHasStableFlag, MultiError } from "../utils";
|
|
|
32
32
|
import { applyPatch } from "fast-json-patch";
|
|
33
33
|
import { UpdateSerializer } from "./UpdateSerializer";
|
|
34
34
|
import { watchIgnorable } from "@vueuse/core";
|
|
35
|
-
import type { PluginState, PluginAccess } from "../usePlugin";
|
|
35
|
+
import type { PluginState, PluginAccess } from "../composition/usePlugin";
|
|
36
36
|
import { logDebug, logError } from "./utils";
|
|
37
37
|
import { getServices } from "./getServices";
|
|
38
38
|
|
|
@@ -208,7 +208,7 @@ export function createAppV3<
|
|
|
208
208
|
.dispose()
|
|
209
209
|
.then(unwrapResult)
|
|
210
210
|
.catch((err) => {
|
|
211
|
-
error("error in dispose", err);
|
|
211
|
+
error("platforma error in dispose", err);
|
|
212
212
|
});
|
|
213
213
|
});
|
|
214
214
|
|
package/src/lib.ts
CHANGED
|
@@ -37,8 +37,8 @@ export * from "./components/PlDatasetSelector";
|
|
|
37
37
|
|
|
38
38
|
export * from "./defineApp";
|
|
39
39
|
|
|
40
|
-
export { usePlugin } from "./usePlugin";
|
|
41
|
-
export type { PluginState } from "./usePlugin";
|
|
40
|
+
export { usePlugin } from "./composition/usePlugin";
|
|
41
|
+
export type { PluginState } from "./composition/usePlugin";
|
|
42
42
|
export type {
|
|
43
43
|
PluginHandle,
|
|
44
44
|
PluginFactoryLike,
|
package/dist/usePlugin.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePlugin.d.ts","sourceRoot":"","sources":["../src/usePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE5C,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAE9B,sEAAsE;AACtE,MAAM,WAAW,WAAW,CAC1B,IAAI,GAAG,OAAO,EACd,OAAO,GAAG,OAAO,EACjB,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;QACvB,IAAI,EAAE,IAAI,CAAC;QACX,OAAO,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C;aAAG,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS;SAAE,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5B,YAAY,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjD;aAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK;SAAE,GAChC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,sBAAsB,CAAC,CAAC,SAAS,iBAAiB,EAChD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;CACxF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,uFAW7E"}
|
package/dist/usePlugin.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePlugin.js","names":[],"sources":["../src/usePlugin.ts"],"sourcesContent":["import { inject, type Reactive } from \"vue\";\nimport { pluginDataKey } from \"./defineApp\";\nimport type {\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n InferFactoryUiServices,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\n\n/** Per-plugin reactive model exposed to consumers via usePlugin(). */\nexport interface PluginState<\n Data = unknown,\n Outputs = unknown,\n Services = Record<string, unknown>,\n> {\n readonly model: Reactive<{\n data: Data;\n outputs: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]: Outputs[K] | undefined }\n : Record<string, unknown>;\n outputErrors: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]?: Error }\n : Record<string, Error | undefined>;\n }>;\n readonly services: Services;\n}\n\n/** Internal interface for plugin access — provided via Vue injection to usePlugin(). */\nexport interface PluginAccess {\n getOrCreatePluginState<F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>, InferFactoryUiServices<F>>;\n}\n\n/**\n * Composable for accessing a plugin's reactive model: data, outputs, and outputErrors.\n *\n * Mirrors the `app.model` access pattern — `plugin.model.data` is reactive and deep-watched,\n * mutations are automatically queued and sent to storage.\n *\n * @param handle - Opaque plugin handle obtained from `app.plugins`.\n * @typeParam F - The plugin factory type (inferred from the handle)\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { usePlugin, type InferPluginHandle } from '@platforma-sdk/ui-vue';\n * import type { CounterPlugin } from './plugins/counter';\n *\n * const props = defineProps<{ instance: InferPluginHandle<CounterPlugin> }>();\n * const plugin = usePlugin(props.instance);\n *\n * plugin.model.data.count += 1; // reactive, triggers storage update\n * plugin.model.outputs.displayText // computed, plugin's own outputs only\n * plugin.model.outputErrors.displayText // Error | undefined\n * </script>\n * ```\n */\nexport function usePlugin<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const access = inject<PluginAccess>(pluginDataKey);\n\n if (!access) {\n throw new Error(\n \"usePlugin requires a V3 block (BlockModelV3). \" +\n \"Make sure the block uses apiVersion 3 and the plugin is installed.\",\n );\n }\n\n return access.getOrCreatePluginState<F>(handle);\n}\n"],"mappings":";;;AA2DA,SAAgB,EAAuC,GAAyB;CAC9E,IAAM,IAAS,EAAqB,EAAc;AAElD,KAAI,CAAC,EACH,OAAU,MACR,mHAED;AAGH,QAAO,EAAO,uBAA0B,EAAO"}
|
|
File without changes
|