@platforma-sdk/ui-vue 1.68.8 → 1.70.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.
Files changed (27) hide show
  1. package/.turbo/turbo-build.log +13 -13
  2. package/.turbo/turbo-formatter$colon$check.log +2 -2
  3. package/.turbo/turbo-linter$colon$check.log +2 -2
  4. package/.turbo/turbo-types$colon$check.log +1 -1
  5. package/CHANGELOG.md +22 -0
  6. package/dist/components/PlAgDataTable/sources/table-source-v2.js +3 -3
  7. package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
  8. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.js.map +1 -1
  9. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js +5 -1
  10. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js.map +1 -1
  11. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.css +1 -1
  12. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.d.ts.map +1 -1
  13. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +40 -23
  14. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
  15. package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
  16. package/dist/components/PlDatasetSelector/PlDatasetSelector.js +1 -1
  17. package/dist/components/PlDatasetSelector/PlDatasetSelector.js.map +1 -1
  18. package/dist/components/PlDatasetSelector/PlDatasetSelector.style.css +1 -1
  19. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts +9 -19
  20. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts.map +1 -1
  21. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js +22 -23
  22. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js.map +1 -1
  23. package/package.json +6 -6
  24. package/src/components/PlAgDataTable/sources/table-source-v2.ts +10 -6
  25. package/src/components/PlAgGridColumnManager/PlAgGridColumnManager.vue +51 -1
  26. package/src/components/PlDatasetSelector/PlDatasetSelector.vue +24 -23
  27. package/src/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.ts +70 -72
@@ -1,6 +1,6 @@
1
1
  import { flushPromises, mount } from "@vue/test-utils";
2
- import type { DatasetOption, PrimaryRef } from "@platforma-sdk/model";
3
- import { createPlRef, createPrimaryRef } from "@platforma-sdk/model";
2
+ import type { DatasetOption, DatasetSelection } from "@platforma-sdk/model";
3
+ import { createDatasetSelection, createPlRef, createPrimaryRef } from "@platforma-sdk/model";
4
4
  import { describe, expect, it } from "vitest";
5
5
  import PlDatasetSelector from "../PlDatasetSelector.vue";
6
6
 
@@ -9,27 +9,41 @@ const datasetB = createPlRef("2", "out-b", true);
9
9
  const filterA1 = createPlRef("1", "filter-a1");
10
10
  const filterA2 = createPlRef("1", "filter-a2");
11
11
 
12
+ import type { PObjectId } from "@platforma-sdk/model";
13
+ const enrichmentA = "enrichment-a" as PObjectId;
14
+ const enrichmentsA = [
15
+ { ref: { __isEnrichment: "v1" as const, hit: enrichmentA }, label: "Enrichment A" },
16
+ ];
17
+
12
18
  const optionsWithFilters: DatasetOption[] = [
13
19
  {
14
- label: "Dataset A",
15
- ref: datasetA,
20
+ primary: { label: "Dataset A", ref: datasetA },
16
21
  filters: [
17
22
  { label: "Top 1000", ref: filterA1 },
18
23
  { label: "High quality", ref: filterA2 },
19
24
  ],
25
+ enrichments: enrichmentsA,
20
26
  },
21
27
  // Dataset B has no filters — filter dropdown must stay hidden.
22
- { label: "Dataset B", ref: datasetB },
28
+ { primary: { label: "Dataset B", ref: datasetB } },
23
29
  ];
24
30
 
25
31
  const datasetC = createPlRef("3", "out-c", true);
26
32
 
27
- const optionsNoFilters: DatasetOption[] = [{ label: "Dataset B", ref: datasetB }];
33
+ const optionsNoFilters: DatasetOption[] = [{ primary: { label: "Dataset B", ref: datasetB } }];
28
34
 
29
35
  const optionsWithEmptyFilters: DatasetOption[] = [
30
- { label: "Dataset C", ref: datasetC, filters: [] },
36
+ { primary: { label: "Dataset C", ref: datasetC }, filters: [] },
31
37
  ];
32
38
 
39
+ function selection(
40
+ ref: typeof datasetA,
41
+ filter?: typeof filterA1,
42
+ enrichments?: typeof enrichmentsA,
43
+ ): DatasetSelection {
44
+ return createDatasetSelection(createPrimaryRef(ref, filter), enrichments);
45
+ }
46
+
33
47
  async function pickOption(index: number) {
34
48
  const options = [...document.body.querySelectorAll(".dropdown-list-item")] as HTMLElement[];
35
49
  options[index].click();
@@ -53,7 +67,7 @@ describe("PlDatasetSelector", () => {
53
67
 
54
68
  it("shows the filter dropdown when the selected dataset has filters", async () => {
55
69
  const wrapper = mount(PlDatasetSelector, {
56
- props: { modelValue: createPrimaryRef(datasetA), options: optionsWithFilters },
70
+ props: { modelValue: selection(datasetA), options: optionsWithFilters },
57
71
  attachTo: document.body,
58
72
  });
59
73
  await flushPromises();
@@ -64,7 +78,7 @@ describe("PlDatasetSelector", () => {
64
78
 
65
79
  it("hides the filter dropdown when the selected dataset has no filters", async () => {
66
80
  const wrapper = mount(PlDatasetSelector, {
67
- props: { modelValue: createPrimaryRef(datasetB), options: optionsWithFilters },
81
+ props: { modelValue: selection(datasetB), options: optionsWithFilters },
68
82
  attachTo: document.body,
69
83
  });
70
84
  await flushPromises();
@@ -73,63 +87,69 @@ describe("PlDatasetSelector", () => {
73
87
  wrapper.unmount();
74
88
  });
75
89
 
76
- it("emits PrimaryRef with filter: undefined when dataset changes", async () => {
90
+ it("emits DatasetSelection bundling primary + enrichments when dataset changes", async () => {
77
91
  const wrapper = mount(PlDatasetSelector, {
78
92
  props: {
79
- modelValue: createPrimaryRef(datasetA, filterA1),
93
+ modelValue: selection(datasetA, filterA1, enrichmentsA),
80
94
  options: optionsWithFilters,
81
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
95
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
96
+ wrapper.setProps({ modelValue: e }),
82
97
  },
83
98
  attachTo: document.body,
84
99
  });
85
100
  await flushPromises();
86
101
 
87
- // Open the dataset dropdown (the first input — dataset comes first).
88
102
  const inputs = wrapper.findAll("input");
89
103
  await inputs[0].trigger("focus");
90
-
91
- // Dataset A is already selected (index 0); pick Dataset B (index 1).
104
+ // Dataset A is index 0; pick Dataset B (index 1) — has no enrichments.
92
105
  await pickOption(1);
93
106
 
94
107
  const emitted = wrapper.emitted("update:modelValue");
95
108
  expect(emitted).toBeDefined();
96
- const last = emitted![emitted!.length - 1][0] as PrimaryRef;
97
- expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetB });
109
+ const last = emitted![emitted!.length - 1][0] as DatasetSelection;
110
+ expect(last).toEqual({
111
+ __isDatasetSelection: "v1",
112
+ primary: { __isPrimaryRef: "v1", column: datasetB },
113
+ });
98
114
  wrapper.unmount();
99
115
  });
100
116
 
101
- it("emits PrimaryRef with filter set when a filter is picked", async () => {
117
+ it("emits DatasetSelection with filter set when a filter is picked", async () => {
102
118
  const wrapper = mount(PlDatasetSelector, {
103
119
  props: {
104
- modelValue: createPrimaryRef(datasetA),
120
+ modelValue: selection(datasetA, undefined, enrichmentsA),
105
121
  options: optionsWithFilters,
106
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
122
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
123
+ wrapper.setProps({ modelValue: e }),
107
124
  },
108
125
  attachTo: document.body,
109
126
  });
110
127
  await flushPromises();
111
128
 
112
- // Open the filter dropdown — it's the second input in the component.
113
129
  const inputs = wrapper.findAll("input");
114
130
  expect(inputs.length).toBe(2);
115
131
  await inputs[1].trigger("focus");
116
-
117
- // Options are: [No filter, Top 1000, High quality]. Pick "Top 1000" (index 1).
132
+ // Options: [No filter, Top 1000, High quality]. Pick "Top 1000".
118
133
  await pickOption(1);
119
134
 
120
135
  const emitted = wrapper.emitted("update:modelValue");
121
136
  expect(emitted).toBeDefined();
122
- const last = emitted![emitted!.length - 1][0] as PrimaryRef;
123
- expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetA, filter: filterA1 });
137
+ const last = emitted![emitted!.length - 1][0] as DatasetSelection;
138
+ expect(last).toEqual({
139
+ __isDatasetSelection: "v1",
140
+ primary: { __isPrimaryRef: "v1", column: datasetA, filter: filterA1 },
141
+ enrichments: enrichmentsA,
142
+ });
124
143
  wrapper.unmount();
125
144
  });
126
145
 
127
- it("emits PrimaryRef with filter: undefined when 'No filter' is picked", async () => {
146
+ it("emits DatasetSelection with no filter key when 'No filter' is picked", async () => {
128
147
  const wrapper = mount(PlDatasetSelector, {
129
148
  props: {
130
- modelValue: createPrimaryRef(datasetA, filterA1),
149
+ modelValue: selection(datasetA, filterA1, enrichmentsA),
131
150
  options: optionsWithFilters,
132
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
151
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
152
+ wrapper.setProps({ modelValue: e }),
133
153
  },
134
154
  attachTo: document.body,
135
155
  });
@@ -137,43 +157,20 @@ describe("PlDatasetSelector", () => {
137
157
 
138
158
  const inputs = wrapper.findAll("input");
139
159
  await inputs[1].trigger("focus");
140
- // Pick "No filter" (index 0).
141
- await pickOption(0);
160
+ await pickOption(0); // "No filter"
142
161
 
143
162
  const emitted = wrapper.emitted("update:modelValue");
144
163
  expect(emitted).toBeDefined();
145
- const last = emitted![emitted!.length - 1][0] as PrimaryRef;
146
- expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetA });
147
- expect("filter" in last).toBe(false);
148
- wrapper.unmount();
149
- });
150
-
151
- it("accepts plain PlRef as modelValue for backward compat (filterless dataset)", async () => {
152
- const wrapper = mount(PlDatasetSelector, {
153
- props: { modelValue: datasetB, options: optionsWithFilters },
154
- attachTo: document.body,
155
- });
156
- await flushPromises();
157
-
158
- expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(1);
159
- wrapper.unmount();
160
- });
161
-
162
- it("accepts plain PlRef as modelValue for backward compat (dataset with filters)", async () => {
163
- const wrapper = mount(PlDatasetSelector, {
164
- props: { modelValue: datasetA, options: optionsWithFilters },
165
- attachTo: document.body,
166
- });
167
- await flushPromises();
168
-
169
- // PlRef matching dataset A — filter dropdown should appear since A has filters.
170
- expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(2);
164
+ const last = emitted![emitted!.length - 1][0] as DatasetSelection;
165
+ expect(last.primary).toEqual({ __isPrimaryRef: "v1", column: datasetA });
166
+ expect("filter" in last.primary).toBe(false);
167
+ expect(last.enrichments).toEqual(enrichmentsA);
171
168
  wrapper.unmount();
172
169
  });
173
170
 
174
171
  it("hides filter dropdown when dataset has filters: [] (empty array)", async () => {
175
172
  const wrapper = mount(PlDatasetSelector, {
176
- props: { modelValue: createPrimaryRef(datasetC), options: optionsWithEmptyFilters },
173
+ props: { modelValue: selection(datasetC), options: optionsWithEmptyFilters },
177
174
  attachTo: document.body,
178
175
  });
179
176
  await flushPromises();
@@ -182,25 +179,22 @@ describe("PlDatasetSelector", () => {
182
179
  wrapper.unmount();
183
180
  });
184
181
 
185
- it("filter dropdown defaults to 'No filter' when dataset has filters but none selected", async () => {
182
+ it("does not emit on mount when no filter is selected", async () => {
186
183
  const wrapper = mount(PlDatasetSelector, {
187
184
  props: {
188
- modelValue: createPrimaryRef(datasetA),
185
+ modelValue: selection(datasetA),
189
186
  options: optionsWithFilters,
190
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
187
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
188
+ wrapper.setProps({ modelValue: e }),
191
189
  },
192
190
  attachTo: document.body,
193
191
  });
194
192
  await flushPromises();
195
193
 
196
- // No emission on mount — the component does not auto-select a filter.
197
194
  expect(wrapper.emitted("update:modelValue")).toBeUndefined();
198
195
 
199
- // Filter dropdown is visible.
200
196
  const inputs = wrapper.findAll("input");
201
197
  expect(inputs.length).toBe(2);
202
-
203
- // Open filter dropdown and verify "No filter" is the first option.
204
198
  await inputs[1].trigger("focus");
205
199
  const items = document.body.querySelectorAll(".dropdown-list-item");
206
200
  expect(items.length).toBe(3); // No filter, Top 1000, High quality
@@ -208,12 +202,13 @@ describe("PlDatasetSelector", () => {
208
202
  wrapper.unmount();
209
203
  });
210
204
 
211
- it("emits PrimaryRef without filter key when selecting a filterless dataset", async () => {
205
+ it("emits DatasetSelection without enrichments when the option carries none", async () => {
212
206
  const wrapper = mount(PlDatasetSelector, {
213
207
  props: {
214
208
  modelValue: undefined,
215
209
  options: optionsNoFilters,
216
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
210
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
211
+ wrapper.setProps({ modelValue: e }),
217
212
  },
218
213
  attachTo: document.body,
219
214
  });
@@ -225,25 +220,28 @@ describe("PlDatasetSelector", () => {
225
220
 
226
221
  const emitted = wrapper.emitted("update:modelValue");
227
222
  expect(emitted).toBeDefined();
228
- const last = emitted![emitted!.length - 1][0] as PrimaryRef;
229
- expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetB });
230
- expect("filter" in last).toBe(false);
223
+ const last = emitted![emitted!.length - 1][0] as DatasetSelection;
224
+ expect(last).toEqual({
225
+ __isDatasetSelection: "v1",
226
+ primary: { __isPrimaryRef: "v1", column: datasetB },
227
+ });
228
+ expect("enrichments" in last).toBe(false);
231
229
  wrapper.unmount();
232
230
  });
233
231
 
234
232
  it("emits undefined when cleared via the dataset dropdown", async () => {
235
233
  const wrapper = mount(PlDatasetSelector, {
236
234
  props: {
237
- modelValue: createPrimaryRef(datasetA, filterA1),
235
+ modelValue: selection(datasetA, filterA1, enrichmentsA),
238
236
  options: optionsWithFilters,
239
237
  clearable: true,
240
- "onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
238
+ "onUpdate:modelValue": (e: DatasetSelection | undefined) =>
239
+ wrapper.setProps({ modelValue: e }),
241
240
  },
242
241
  attachTo: document.body,
243
242
  });
244
243
  await flushPromises();
245
244
 
246
- // PlDropdown's clear button carries the ".clear" class.
247
245
  const clearBtn = wrapper.find(".clear");
248
246
  expect(clearBtn.exists()).toBe(true);
249
247
  await clearBtn.trigger("click");