@platforma-sdk/ui-vue 1.80.9 → 1.80.13
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 +16 -16
- 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 +28 -0
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.js.map +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.style.js.map +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts.map +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts +2 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js +6 -2
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js.map +1 -1
- package/dist/components/PlAgCsvExporter/export-csv.d.ts +16 -5
- package/dist/components/PlAgCsvExporter/export-csv.d.ts.map +1 -1
- package/dist/components/PlAgCsvExporter/export-csv.js +48 -39
- 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 +22 -17
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/sources/table-source-v2.js +1 -1
- package/dist/index.js +8 -8
- package/dist/lib.js +4 -4
- package/package.json +8 -8
- package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +3 -1
- package/src/components/PlAgCsvExporter/PlAgCsvExporter.vue +3 -2
- package/src/components/PlAgCsvExporter/export-csv.ts +40 -9
- package/src/components/PlAgDataTable/PlAgDataTableV2.vue +4 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.80.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.80.13 build /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder build --target browser-lib
|
|
5
5
|
|
|
6
6
|
Building browser-lib project...
|
|
@@ -16,7 +16,7 @@ Building browser-lib project...
|
|
|
16
16
|
rendering chunks...
|
|
17
17
|
|
|
18
18
|
[vite:dts] Start generate declaration files...
|
|
19
|
-
[vite:dts] Declaration files built in
|
|
19
|
+
[vite:dts] Declaration files built in 5555ms.
|
|
20
20
|
|
|
21
21
|
computing gzip size...
|
|
22
22
|
dist/components/PlAnnotations/components/PlAnnotations.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
|
|
@@ -83,7 +83,7 @@ dist/components/PlAgRowNumHeader.js
|
|
|
83
83
|
dist/components/PlAgCellFile/PlAgCellFile.js 0.21 kB │ gzip: 0.16 kB │ map: 2.49 kB
|
|
84
84
|
dist/components/PlAgDataTable/PlAgRowCount.js 0.21 kB │ gzip: 0.17 kB │ map: 1.72 kB
|
|
85
85
|
dist/plugins/Monetization/EndOfPeriod.vue_vue_type_style_index_0_lang.module.js 0.22 kB │ gzip: 0.18 kB │ map: 0.42 kB
|
|
86
|
-
dist/components/PlAgCsvExporter/PlAgCsvExporter.js 0.22 kB │ gzip: 0.16 kB │ map: 1.
|
|
86
|
+
dist/components/PlAgCsvExporter/PlAgCsvExporter.js 0.22 kB │ gzip: 0.16 kB │ map: 1.59 kB
|
|
87
87
|
dist/components/PlAnnotations/components/PlAnnotations.vue_vue_type_style_index_0_lang.module.js 0.22 kB │ gzip: 0.18 kB │ map: 0.42 kB
|
|
88
88
|
dist/components/PlAgCellProgress/PlAgCellProgress.js 0.23 kB │ gzip: 0.16 kB │ map: 0.55 kB
|
|
89
89
|
dist/components/PlAgColumnHeader/PlAgColumnHeader.js 0.23 kB │ gzip: 0.17 kB │ map: 3.22 kB
|
|
@@ -121,9 +121,9 @@ dist/components/PlAdvancedFilter/FilterEditor.js
|
|
|
121
121
|
dist/components/PlAdvancedFilter/OperandButton.js 0.35 kB │ gzip: 0.24 kB │ map: 1.31 kB
|
|
122
122
|
dist/components/PlAnnotations/components/FilterSidebar.js 0.35 kB │ gzip: 0.24 kB │ map: 5.40 kB
|
|
123
123
|
dist/components/PlAnnotations/components/PlAnnotations.js 0.35 kB │ gzip: 0.24 kB │ map: 3.11 kB
|
|
124
|
-
dist/components/PlAgDataTable/PlAgDataTableV2.js 0.35 kB │ gzip: 0.25 kB │ map: 22.
|
|
124
|
+
dist/components/PlAgDataTable/PlAgDataTableV2.js 0.35 kB │ gzip: 0.25 kB │ map: 22.36 kB
|
|
125
125
|
dist/plugins/Monetization/UserCabinetCard.js 0.35 kB │ gzip: 0.24 kB │ map: 3.00 kB
|
|
126
|
-
dist/components/PlAdvancedFilter/PlAdvancedFilter.js 0.36 kB │ gzip: 0.24 kB │ map: 13.
|
|
126
|
+
dist/components/PlAdvancedFilter/PlAdvancedFilter.js 0.36 kB │ gzip: 0.24 kB │ map: 13.46 kB
|
|
127
127
|
dist/components/PlAgDataTable/PlAgOverlayNoRows.js 0.36 kB │ gzip: 0.21 kB │ map: 0.74 kB
|
|
128
128
|
dist/components/PlTableFilters/PlTableFiltersV2.js 0.36 kB │ gzip: 0.25 kB │ map: 6.86 kB
|
|
129
129
|
dist/components/PlAgCellStatusTag/PlAgCellStatusTag.js 0.36 kB │ gzip: 0.20 kB │ map: 0.74 kB
|
|
@@ -176,7 +176,6 @@ dist/components/PlAgGridColumnManager/useFilteredItems.js
|
|
|
176
176
|
dist/lib/util/helpers/dist/objects.js 1.20 kB │ gzip: 0.58 kB │ map: 9.83 kB
|
|
177
177
|
dist/createModel.js 1.22 kB │ gzip: 0.61 kB │ map: 3.11 kB
|
|
178
178
|
dist/utils.js 1.26 kB │ gzip: 0.62 kB │ map: 3.40 kB
|
|
179
|
-
dist/components/PlAgCsvExporter/PlAgCsvExporter.vue_vue_type_script_setup_true_lang.js 1.28 kB │ gzip: 0.72 kB │ map: 2.05 kB
|
|
180
179
|
dist/lib/util/helpers/dist/prettyBytes.js 1.29 kB │ gzip: 0.67 kB │ map: 3.79 kB
|
|
181
180
|
dist/AgGridVue/AgGridTheme.js 1.30 kB │ gzip: 0.59 kB │ map: 2.07 kB
|
|
182
181
|
dist/components/PlBtnExportArchive/Summary.vue_vue_type_script_setup_true_lang.js 1.31 kB │ gzip: 0.65 kB │ map: 2.35 kB
|
|
@@ -184,6 +183,7 @@ dist/components/PlAgDataTable/PlAgRowCount.vue_vue_type_script_setup_true_lang.j
|
|
|
184
183
|
dist/internal/UpdateSerializer.js 1.33 kB │ gzip: 0.61 kB │ map: 4.28 kB
|
|
185
184
|
dist/components/PlAgDataTable/PlAgOverlayLoading.vue_vue_type_script_setup_true_lang.js 1.33 kB │ gzip: 0.76 kB │ map: 2.49 kB
|
|
186
185
|
dist/components/PlAgDataTable/types.js 1.33 kB │ gzip: 0.53 kB │ map: 7.63 kB
|
|
186
|
+
dist/components/PlAgCsvExporter/PlAgCsvExporter.vue_vue_type_script_setup_true_lang.js 1.34 kB │ gzip: 0.74 kB │ map: 2.16 kB
|
|
187
187
|
dist/components/PlBtnExportArchive/Item.vue_vue_type_script_setup_true_lang.js 1.36 kB │ gzip: 0.63 kB │ map: 2.58 kB
|
|
188
188
|
dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue_vue_type_script_setup_true_lang.js 1.46 kB │ gzip: 0.77 kB │ map: 3.56 kB
|
|
189
189
|
dist/internal/createAppModel.js 1.48 kB │ gzip: 0.75 kB │ map: 3.89 kB
|
|
@@ -202,11 +202,11 @@ dist/components/PlAgDataTable/PlAgDataTableSheets.vue_vue_type_script_setup_true
|
|
|
202
202
|
dist/components/PlDatasetSelector/PlDatasetSelector.vue_vue_type_script_setup_true_lang.js 2.58 kB │ gzip: 1.07 kB │ map: 6.02 kB
|
|
203
203
|
dist/components/PlAnnotations/components/PlAnnotations.vue_vue_type_script_setup_true_lang.js 2.69 kB │ gzip: 1.12 kB │ map: 4.16 kB
|
|
204
204
|
dist/lib.js 2.73 kB │ gzip: 0.57 kB │ map: 3.98 kB
|
|
205
|
-
dist/components/PlAgCsvExporter/export-csv.js 2.83 kB │ gzip: 1.27 kB │ map: 9.11 kB
|
|
206
205
|
dist/components/PlAgDataTable/compositions/useGrid.js 2.91 kB │ gzip: 1.29 kB │ map: 6.51 kB
|
|
207
206
|
dist/components/PlAgColumnHeader/PlAgColumnHeader.vue_vue_type_script_setup_true_lang.js 2.93 kB │ gzip: 1.26 kB │ map: 7.97 kB
|
|
208
207
|
dist/components/PlAgDataTable/sources/row-number.js 3.01 kB │ gzip: 1.31 kB │ map: 7.47 kB
|
|
209
208
|
dist/defineApp.js 3.01 kB │ gzip: 1.05 kB │ map: 14.38 kB
|
|
209
|
+
dist/components/PlAgCsvExporter/export-csv.js 3.13 kB │ gzip: 1.39 kB │ map: 10.80 kB
|
|
210
210
|
dist/plugins/Monetization/LimitCard.vue_vue_type_script_setup_true_lang.js 3.31 kB │ gzip: 1.15 kB │ map: 9.08 kB
|
|
211
211
|
dist/composition/fileContent.js 3.78 kB │ gzip: 1.45 kB │ map: 12.95 kB
|
|
212
212
|
dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue_vue_type_script_setup_true_lang.js 3.83 kB │ gzip: 1.64 kB │ map: 6.89 kB
|
|
@@ -221,18 +221,18 @@ dist/components/PlBtnExportArchive/PlBtnExportArchive.vue_vue_type_script_setup_
|
|
|
221
221
|
dist/internal/createAppV2.js 5.26 kB │ gzip: 1.98 kB │ map: 17.78 kB
|
|
222
222
|
dist/components/PlAgDataTable/sources/table-state-v2.js 5.66 kB │ gzip: 1.82 kB │ map: 19.14 kB
|
|
223
223
|
dist/internal/createAppV3.js 6.19 kB │ gzip: 2.34 kB │ map: 21.40 kB
|
|
224
|
-
dist/components/PlAgDataTable/sources/table-source-v2.js 7.
|
|
225
|
-
dist/components/PlAdvancedFilter/PlAdvancedFilter.vue_vue_type_script_setup_true_lang.js 8.
|
|
224
|
+
dist/components/PlAgDataTable/sources/table-source-v2.js 7.59 kB │ gzip: 2.88 kB │ map: 27.20 kB
|
|
225
|
+
dist/components/PlAdvancedFilter/PlAdvancedFilter.vue_vue_type_script_setup_true_lang.js 8.57 kB │ gzip: 2.60 kB │ map: 18.58 kB
|
|
226
226
|
dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_script_setup_true_lang.js 10.58 kB │ gzip: 3.14 kB │ map: 24.73 kB
|
|
227
|
-
dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 12.
|
|
227
|
+
dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 12.54 kB │ gzip: 3.96 kB │ map: 29.97 kB
|
|
228
228
|
|
|
229
229
|
[33m[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugins. Here is a breakdown:
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
- vite:vue (
|
|
233
|
-
- vite:css (
|
|
234
|
-
- vite:
|
|
230
|
+
- sourcemaps (26%)
|
|
231
|
+
- vite:dts (26%)
|
|
232
|
+
- vite:vue (11%)
|
|
233
|
+
- vite:css-post (11%)
|
|
234
|
+
- vite:build-import-analysis (9%)
|
|
235
235
|
See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
236
236
|
[39m
|
|
237
|
-
[32m✓ built in
|
|
237
|
+
[32m✓ built in 6.47s[39m
|
|
238
238
|
Build completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.80.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.80.13 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder formatter --check
|
|
5
5
|
|
|
6
6
|
Checking formatting...
|
|
@@ -8,5 +8,5 @@ Checking formatting...
|
|
|
8
8
|
Checking formatting...
|
|
9
9
|
|
|
10
10
|
All matched files use the correct format.
|
|
11
|
-
Finished in
|
|
11
|
+
Finished in 2850ms on 137 files using 16 threads.
|
|
12
12
|
Format check completed successfully
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.80.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.80.13 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder linter --check
|
|
5
5
|
|
|
6
6
|
Linting project...
|
|
7
7
|
↳ oxlint --config /home/runner/_work/platforma/platforma/sdk/ui-vue/.oxlintrc.json --deny-warnings
|
|
8
8
|
Found 0 warnings and 0 errors.
|
|
9
|
-
Finished in
|
|
9
|
+
Finished in 29ms on 120 files with 108 rules using 16 threads.
|
|
10
10
|
Linting completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.80.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.80.13 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder type-check --target browser-lib
|
|
5
5
|
|
|
6
6
|
↳ vue-tsc.js --noEmit --project ./tsconfig.json --customConditions ,
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @platforma-sdk/ui-vue
|
|
2
2
|
|
|
3
|
+
## 1.80.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 597ca40: PlDataTable: allow the default filter group to be fully cleared, and harden filter merging.
|
|
8
|
+
|
|
9
|
+
- `PlAdvancedFilter`: when the last leaf of a non-removable group (e.g. the pinned default-filters group) is deleted, keep it as an empty group instead of splicing the whole group out. This lets the default-filters group be emptied (previously the last default filter could not be removed); the group's reset still restores the defaults.
|
|
10
|
+
- `createPlDataTableV3.concatFilters`: AND-combine operands that are not `and` groups (a bare leaf, a `not`, or an `or` group) by treating them as single members, instead of assuming every operand has a `.filters` array. Fixes a `TypeError` crash when the persisted filter state is a lone leaf (e.g. a single sheet selection) and a case where an `or` root was incorrectly OR-merged with the defaults.
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [597ca40]
|
|
13
|
+
- @platforma-sdk/model@1.80.13
|
|
14
|
+
- @milaboratories/uikit@2.15.19
|
|
15
|
+
|
|
16
|
+
## 1.80.10
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 4ac0df5: Native table export now uses the disambiguated column labels shown in the table (from the `PlDataTable` `columnsMeta` sidecar) instead of the raw spec `pl7.app/label`. This fixes export failures when exporting a table with many columns whose intrinsic labels collide — the native `exportPTable` path rejects duplicate header names.
|
|
21
|
+
|
|
22
|
+
`exportPTable`/`writePTableToFs` options gain an optional `headerNames` field (aligned 1:1 with `columnIndices`). It is additive and backward compatible: older runtimes ignore it and keep deriving header names from the column spec.
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [4ac0df5]
|
|
25
|
+
- @milaboratories/pl-model-common@1.47.3
|
|
26
|
+
- @milaboratories/columns-collection-driver@0.2.3
|
|
27
|
+
- @milaboratories/pf-spec-driver@1.4.24
|
|
28
|
+
- @platforma-sdk/model@1.80.10
|
|
29
|
+
- @milaboratories/uikit@2.15.18
|
|
30
|
+
|
|
3
31
|
## 1.80.9
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAdvancedFilter.js","names":[],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n if (group.filters.length === 1 && filterIdx === 0) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"PlAdvancedFilter.js","names":[],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n const removingLastLeaf = group.filters.length === 1 && filterIdx === 0;\n\n if (removingLastLeaf && props.isRemovable(draft.filters[groupIdx], groupIdx)) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAdvancedFilter.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n if (group.filters.length === 1 && filterIdx === 0) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"PlAdvancedFilter.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n const removingLastLeaf = group.filters.length === 1 && filterIdx === 0;\n\n if (removingLastLeaf && props.isRemovable(draft.filters[groupIdx], groupIdx)) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAdvancedFilter.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAdvancedFilter.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"names":[],"mappings":"AAsYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,OAAO,EAAwC,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,KAAK,EAGV,UAAU,EAEV,wBAAwB,EACxB,UAAU,EACV,gBAAgB,EACjB,MAAM,SAAS,CAAC;yBAGA,CAAC,SAAS,UAAU,EACpC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,eAAe,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EACjE;WA0jBO,mBAAmB,CAAC;iBAxjBf,CAAC;yBACO,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI;QACrC,6EAA6E;iBACpE,gBAAgB,EAAE;QAC3B,qCAAqC;2BAClB,OAAO,sBAAsB;QAChD,wHAAwH;oBAC5G,OAAO;QACnB,oEAAoE;+BAC7C,OAAO;QAC9B,kEAAkE;yBACjD,OAAO;QACxB,kDAAkD;mBACvC,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO;QACvD,qDAAqD;sBACvC,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO;QAC1D,qDAAqD;sBACvC,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO;QAC1D,mDAAmD;2BAChC,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO;QAChE,yFAAyF;2BACtE,CAAC,MAAM,EAAE;YAC1B,QAAQ,EAAE,wBAAwB,CAAC;YACnC,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,SAAS,EAAE,MAAM,CAAC;YAClB,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;SAC/B,KAAK,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;mBA8hBM,CAAC,4BAA2B;oBACzG,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,IAAI;WAClD,GAAG;;;;;YArDwB,GAAG;;;;YACF,GAAG;qCACG,GAAG;;UAqDtC,EAAE;EAEL,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,WAAW,CAAC,CAAA;CAAE;AArkBzE,wBAqkB4E;AAe5E,KAAK,mBAAmB,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|
|
@@ -87,7 +87,7 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
87
87
|
function I(e, t) {
|
|
88
88
|
O((n) => {
|
|
89
89
|
let r = N(n, e);
|
|
90
|
-
r.filters.length === 1 && t === 0 ? n.filters.splice(e, 1) : r.filters.splice(t, 1);
|
|
90
|
+
r.filters.length === 1 && t === 0 && _.isRemovable(n.filters[e], e) ? n.filters.splice(e, 1) : r.filters.splice(t, 1);
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
93
|
function L(e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAdvancedFilter.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n if (group.filters.length === 1 && filterIdx === 0) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlAdvancedFilter.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlAdvancedFilter/PlAdvancedFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends RootFilter\">\nimport { PlBtnSecondary, PlCheckbox, PlElementList } from \"@milaboratories/uikit\";\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport { produce } from \"immer\";\nimport { computed } from \"vue\";\nimport FilterEditor from \"./FilterEditor.vue\";\nimport OperandButton from \"./OperandButton.vue\";\nimport { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from \"./constants\";\nimport type {\n CommonFilter,\n EditableFilter,\n NodeFilter,\n Operand,\n PlAdvancedFilterColumnId,\n RootFilter,\n SourceOptionInfo,\n} from \"./types\";\nimport { createNewGroup, getNewId, isValidColumnId } from \"./utils\";\n\nconst props = withDefaults(\n defineProps<{\n filters: T;\n onUpdateFilters: (filters: T) => void;\n /** List of ids of sources (columns, axes) that can be selected in filters */\n options: SourceOptionInfo[];\n /** List of supported filter types */\n supportedFilters?: typeof SUPPORTED_FILTER_TYPES;\n /** If true - new filter can be added by droppind element into filter group; else new column is added by button click */\n enableDnd?: boolean;\n /** If true - \"Add group\" button is shown below the filter groups */\n enableAddGroupButton?: boolean;\n /** If true - eye icon is shown per group to toggle suppression */\n enableToggling?: boolean;\n /** Function to determine if a filter is pinned */\n isPinned?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is removable */\n isRemovable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a filter is draggable */\n isDraggable?: (item: NodeFilter, index: number) => boolean;\n /** Function to determine if a group is complete */\n isCompletedGroup?: (group: NodeFilter, index: number) => boolean;\n /** Loading function for unique values for Equal/InSet filters and fixed axes options. */\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n }>(),\n {\n supportedFilters: () => SUPPORTED_FILTER_TYPES,\n isCompletedGroup: () => false,\n isPinned: () => false,\n isRemovable: () => true,\n isDraggable: () => true,\n\n getSuggestModel: undefined,\n\n enableDnd: false,\n enableAddGroupButton: false,\n enableToggling: false,\n },\n);\nconst produceFiltersUpdate = (updater: (draft: T) => void) => {\n props.onUpdateFilters(produce(props.filters, updater));\n};\n\nconst firstColumnId = computed(() => props.options[0]?.id);\nconst emptyGroup: NodeFilter[] = [\n {\n id: -1,\n type: \"and\",\n filters: [],\n isExpanded: true,\n },\n];\n\nconst rootFilters = computed({\n get: () => props.filters.filters,\n set: (filters) => props.onUpdateFilters({ ...props.filters, filters: filters }),\n});\n\nfunction getRootGroups() {\n if (props.filters.type !== \"or\" && props.filters.type !== \"and\") {\n throw new Error('Invalid model structure, expected root to be \"or\" or \"and\" group');\n }\n return props.filters.filters;\n}\n\nfunction getDraftGroupContent(\n draft: RootFilter,\n idx: number,\n): Exclude<NodeFilter, { type: \"not\" }> {\n const group = draft.filters[idx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n return group.filter;\n }\n if (group.type !== \"and\" && group.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n return group;\n}\n\nfunction getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: \"not\" }> {\n return item.type === \"not\"\n ? (item.filter as Exclude<T, { type: \"not\" }>)\n : (item as Exclude<T, { type: \"not\" }>);\n}\n\nfunction addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n group.filters.push({\n ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],\n column: selectedSourceId,\n id: getNewId(),\n isExpanded: true,\n } as CommonFilter);\n });\n}\n\nfunction removeFilterFromGroup(groupIdx: number, filterIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = getDraftGroupContent(draft, groupIdx);\n const removingLastLeaf = group.filters.length === 1 && filterIdx === 0;\n\n if (removingLastLeaf && props.isRemovable(draft.filters[groupIdx], groupIdx)) {\n draft.filters.splice(groupIdx, 1);\n } else {\n group.filters.splice(filterIdx, 1);\n }\n });\n}\n\nfunction inverseRootNode(groupIdx: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n const group = draft.filters[groupIdx];\n if (group.type === \"not\") {\n if (group.filter.type !== \"and\" && group.filter.type !== \"or\") {\n throw new Error('Invalid group structure, expected \"and\" or \"or\" group inside \"not\"');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n ...group.filter,\n };\n } else {\n const type = draft.filters[groupIdx].type;\n if (type !== \"and\" && type !== \"or\" && type !== \"not\") {\n throw new Error('Invalid group structure, expected \"and\", \"or\" or \"not\" group');\n }\n draft.filters[groupIdx] = {\n ...draft.filters[groupIdx],\n id: getNewId(),\n type: \"not\",\n filter: draft.filters[groupIdx],\n };\n }\n });\n}\n\nfunction addGroup(selectedSourceId: PlAdvancedFilterColumnId) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters.push(createNewGroup(selectedSourceId));\n });\n}\n\nfunction updateFilter(groupIdx: number, filterIdx: number, updatedFilter: EditableFilter) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, groupIdx).filters[filterIdx] = updatedFilter as CommonFilter;\n });\n}\n\nfunction handleDropToExistingGroup(groupIdx: number, event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addColumnToGroup(groupIdx, draggedId);\n }\n }\n}\n\nfunction handleDropToNewGroup(event: DragEvent) {\n const dataTransfer = event.dataTransfer;\n if (dataTransfer?.getData(\"text/plain\")) {\n const draggedId = dataTransfer.getData(\"text/plain\");\n if (isValidColumnId(draggedId)) {\n addGroup(draggedId);\n }\n }\n}\n\nfunction dragOver(event: DragEvent) {\n event.preventDefault();\n}\n\nfunction toggleExpand(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isExpanded = !draft.filters[index].isExpanded;\n });\n}\n\nfunction toggleSuppress(_: NodeFilter, index: number) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.filters[index].isSuppressed = !draft.filters[index].isSuppressed;\n });\n}\n\nfunction changeGroupOperand(index: number, v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n getDraftGroupContent(draft, index).type = v;\n });\n}\n\nfunction changeRootOperand(v: Operand) {\n produceFiltersUpdate((draft: RootFilter) => {\n draft.type = v;\n });\n}\n\nfunction validateFilter<T extends CommonFilter>(item: T): EditableFilter {\n if (item.type === \"and\" || item.type === \"or\" || item.type === \"not\") {\n throw new Error(\"Invalid filter structure, expected leaf filter\");\n }\n\n return item as EditableFilter;\n}\n</script>\n<template>\n <div>\n <PlElementList\n v-model:items=\"rootFilters\"\n :get-item-key=\"(filter) => filter.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"(filter) => filter.isExpanded === true\"\n :on-expand=\"toggleExpand\"\n :is-toggled=\"(item) => item.isSuppressed === true\"\n :on-toggle=\"toggleSuppress\"\n :is-pinned=\"(item, index) => props.isPinned?.(item, index) === true\"\n :is-pinnable=\"() => false\"\n :is-removable=\"(item, index) => props.isRemovable?.(item, index) === true\"\n :is-draggable=\"(item, index) => props.isDraggable?.(item, index) === true\"\n :disable-toggling=\"props.enableToggling !== true\"\n :disable-dragging=\"false\"\n :disable-removing=\"false\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index\">Filter group</slot>\n </template>\n <template #item-content=\"{ item, index }\">\n <div\n :class=\"[$style.groupContent, { [$style.suppressedLabel]: item.isSuppressed }]\"\n dropzone=\"true\"\n @drop=\"(event) => handleDropToExistingGroup(index, event)\"\n @dragover=\"dragOver\"\n >\n <PlCheckbox\n :model-value=\"item.type === 'not'\"\n :class=\"$style.notCheckbox\"\n @update:model-value=\"inverseRootNode(index)\"\n >\n Filter Out\n </PlCheckbox>\n <template v-for=\"(_, filterIdx) in getNotContent(item).filters\" :key=\"filterIdx\">\n <FilterEditor\n :filter=\"validateFilter(getNotContent(item).filters[filterIdx])\"\n :operand=\"getNotContent(item).type\"\n :column-options=\"options\"\n :supported-filters=\"props.supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"Boolean(props.enableDnd)\"\n :is-last=\"filterIdx === getNotContent(item).filters.length - 1\"\n @delete=\"() => removeFilterFromGroup(index, filterIdx)\"\n @update-filter=\"(value) => updateFilter(index, filterIdx, value)\"\n @change-operand=\"(v) => changeGroupOperand(index, v)\"\n />\n </template>\n <div v-if=\"props.enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n icon=\"add\"\n @click=\"addColumnToGroup(index, firstColumnId)\"\n >\n Add filter\n </PlBtnSecondary>\n </div>\n </template>\n <template #item-after=\"{ index }\">\n <OperandButton\n v-if=\"props.enableAddGroupButton || index < getRootGroups().length - 1\"\n :class=\"$style.buttonWrapper\"\n :active=\"props.filters.type\"\n :disabled=\"index === getRootGroups().length - 1\"\n :on-select=\"changeRootOperand\"\n />\n </template>\n </PlElementList>\n\n <!-- Last group - always empty, just for adding new groups -->\n <PlElementList\n v-if=\"props.enableAddGroupButton\"\n :items=\"emptyGroup\"\n :get-item-key=\"(group) => group.id\"\n :item-class=\"$style.filterGroup\"\n :item-class-content=\"$style.filterGroupContent\"\n :item-class-title=\"$style.filterGroupTitle\"\n :is-expanded=\"() => true\"\n :disableDragging=\"true\"\n :disableRemoving=\"true\"\n :disableToggling=\"true\"\n :disablePinning=\"true\"\n dropzone=\"true\"\n @drop=\"handleDropToNewGroup\"\n @dragover=\"dragOver\"\n >\n <template #item-title=\"{ item, index }\">\n <slot name=\"group-title\" :item=\"item\" :index=\"index + getRootGroups().length\"\n >Filter group</slot\n >\n </template>\n <template #item-content>\n <div v-if=\"enableDnd\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary icon=\"add\" @click=\"addGroup(firstColumnId)\"> Add filter </PlBtnSecondary>\n </slot>\n </template>\n </PlElementList>\n </div>\n</template>\n<style module>\n.filterGroup {\n background: var(--bg-base-light);\n}\n.filterGroup:hover {\n background: rgba(99, 224, 36, 0.12);\n}\n.filterGroupTitle {\n background: none;\n}\n.filterGroupContent {\n padding: 4px 24px 24px 24px;\n}\n.groupContent {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.notCheckbox {\n margin: 4px 0;\n}\n.suppressedLabel {\n filter: grayscale(100%);\n pointer-events: none;\n}\n.dropzone {\n border-radius: 6px;\n border: 1.5px dashed var(--color-div-grey);\n color: var(--txt-03);\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n height: 40px;\n cursor: default;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.buttonWrapper {\n margin-top: 8px;\n height: 56px;\n display: flex;\n align-items: center;\n}\n:global(.sortable-chosen) .buttonWrapper {\n visibility: hidden;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBA,IAAM,IAAQ,GA4CR,KAAwB,MAAgC;AAC5D,KAAM,gBAAgB,EAAQ,EAAM,SAAS,EAAQ,CAAC;KAGlD,IAAgB,QAAe,EAAM,QAAQ,IAAI,GAAG,EACpD,IAA2B,CAC/B;GACE,IAAI;GACJ,MAAM;GACN,SAAS,EAAE;GACX,YAAY;GACb,CACF,EAEK,IAAc,EAAS;GAC3B,WAAW,EAAM,QAAQ;GACzB,MAAM,MAAY,EAAM,gBAAgB;IAAE,GAAG,EAAM;IAAkB;IAAS,CAAC;GAChF,CAAC;EAEF,SAAS,IAAgB;AACvB,OAAI,EAAM,QAAQ,SAAS,QAAQ,EAAM,QAAQ,SAAS,MACxD,OAAU,MAAM,uEAAmE;AAErF,UAAO,EAAM,QAAQ;;EAGvB,SAAS,EACP,GACA,GACsC;GACtC,IAAM,IAAQ,EAAM,QAAQ;AAC5B,OAAI,EAAM,SAAS,OAAO;AACxB,QAAI,EAAM,OAAO,SAAS,SAAS,EAAM,OAAO,SAAS,KACvD,OAAU,MAAM,2EAAqE;AAEvF,WAAO,EAAM;;AAEf,OAAI,EAAM,SAAS,SAAS,EAAM,SAAS,KACzC,OAAU,MAAM,qEAA+D;AAEjF,UAAO;;EAGT,SAAS,EAAsC,GAAsC;AACnF,UAAO,EAAK,SAAS,QAChB,EAAK,SACL;;EAGP,SAAS,EAAiB,GAAkB,GAA4C;AACtF,MAAsB,MAAsB;AAC5B,MAAqB,GAAO,EAAS,CAC7C,QAAQ,KAAK;KACjB,GAAG,EAAgB;KACnB,QAAQ;KACR,IAAI,GAAU;KACd,YAAY;KACb,CAAiB;KAClB;;EAGJ,SAAS,EAAsB,GAAkB,GAAmB;AAClE,MAAsB,MAAsB;IAC1C,IAAM,IAAQ,EAAqB,GAAO,EAAS;AAGnD,IAFyB,EAAM,QAAQ,WAAW,KAAK,MAAc,KAE7C,EAAM,YAAY,EAAM,QAAQ,IAAW,EAAS,GAC1E,EAAM,QAAQ,OAAO,GAAU,EAAE,GAEjC,EAAM,QAAQ,OAAO,GAAW,EAAE;KAEpC;;EAGJ,SAAS,EAAgB,GAAkB;AACzC,MAAsB,MAAsB;IAC1C,IAAM,IAAQ,EAAM,QAAQ;AAC5B,QAAI,EAAM,SAAS,OAAO;AACxB,SAAI,EAAM,OAAO,SAAS,SAAS,EAAM,OAAO,SAAS,KACvD,OAAU,MAAM,2EAAqE;AAEvF,OAAM,QAAQ,KAAY;MACxB,GAAG,EAAM,QAAQ;MACjB,GAAG,EAAM;MACV;WACI;KACL,IAAM,IAAO,EAAM,QAAQ,GAAU;AACrC,SAAI,MAAS,SAAS,MAAS,QAAQ,MAAS,MAC9C,OAAU,MAAM,qEAA+D;AAEjF,OAAM,QAAQ,KAAY;MACxB,GAAG,EAAM,QAAQ;MACjB,IAAI,GAAU;MACd,MAAM;MACN,QAAQ,EAAM,QAAQ;MACvB;;KAEH;;EAGJ,SAAS,EAAS,GAA4C;AAC5D,MAAsB,MAAsB;AAC1C,MAAM,QAAQ,KAAK,EAAe,EAAiB,CAAC;KACpD;;EAGJ,SAAS,EAAa,GAAkB,GAAmB,GAA+B;AACxF,MAAsB,MAAsB;AAC1C,MAAqB,GAAO,EAAS,CAAC,QAAQ,KAAa;KAC3D;;EAGJ,SAAS,EAA0B,GAAkB,GAAkB;GACrE,IAAM,IAAe,EAAM;AAC3B,OAAI,GAAc,QAAQ,aAAa,EAAE;IACvC,IAAM,IAAY,EAAa,QAAQ,aAAa;AACpD,IAAI,EAAgB,EAAU,IAC5B,EAAiB,GAAU,EAAU;;;EAK3C,SAAS,EAAqB,GAAkB;GAC9C,IAAM,IAAe,EAAM;AAC3B,OAAI,GAAc,QAAQ,aAAa,EAAE;IACvC,IAAM,IAAY,EAAa,QAAQ,aAAa;AACpD,IAAI,EAAgB,EAAU,IAC5B,EAAS,EAAU;;;EAKzB,SAAS,EAAS,GAAkB;AAClC,KAAM,gBAAgB;;EAGxB,SAAS,EAAa,GAAe,GAAe;AAClD,MAAsB,MAAsB;AAC1C,MAAM,QAAQ,GAAO,aAAa,CAAC,EAAM,QAAQ,GAAO;KACxD;;EAGJ,SAAS,EAAe,GAAe,GAAe;AACpD,MAAsB,MAAsB;AAC1C,MAAM,QAAQ,GAAO,eAAe,CAAC,EAAM,QAAQ,GAAO;KAC1D;;EAGJ,SAAS,EAAmB,GAAe,GAAY;AACrD,MAAsB,MAAsB;AAC1C,MAAqB,GAAO,EAAM,CAAC,OAAO;KAC1C;;EAGJ,SAAS,EAAkB,GAAY;AACrC,MAAsB,MAAsB;AAC1C,MAAM,OAAO;KACb;;EAGJ,SAAS,EAAuC,GAAyB;AACvE,OAAI,EAAK,SAAS,SAAS,EAAK,SAAS,QAAQ,EAAK,SAAS,MAC7D,OAAU,MAAM,iDAAiD;AAGnE,UAAO;;yBAIP,EAwGM,OAAA,MAAA,CAvGJ,EAsEgB,EAAA,EAAA,EAAA;GArEN,OAAO,EAAA;uCAAW,QAAA;GACzB,iBAAe,MAAW,EAAO;GACjC,cAAYA,EAAAA,OAAO;GACnB,sBAAoBA,EAAAA,OAAO;GAC3B,oBAAkBA,EAAAA,OAAO;GACzB,gBAAc,MAAW,EAAO,eAAU;GAC1C,aAAW;GACX,eAAa,MAAS,EAAK,iBAAY;GACvC,aAAW;GACX,cAAY,GAAM,MAAU,EAAM,WAAW,GAAM,EAAK,KAAA;GACxD,qBAAa;GACb,iBAAe,GAAM,MAAU,EAAM,cAAc,GAAM,EAAK,KAAA;GAC9D,iBAAe,GAAM,MAAU,EAAM,cAAc,GAAM,EAAK,KAAA;GAC9D,oBAAkB,EAAM,mBAAc;GACtC,oBAAkB;GAClB,oBAAkB;;GAER,cAAU,GACqD,EADjD,SAAM,eAAK,CAClC,EAAwE,EAAA,QAAA,eAAA;IAAxC;IAAc;YAA0B,CAAA,AAAA,EAAA,OAAA,EAAnB,gBAAY,GAAA,CAAA,CAAA,CAAA,CAAA;GAExD,gBAAY,GAsCf,EAtCmB,SAAM,eAAK,CACpC,EAqCM,OAAA;IApCH,OAAK,EAAA,CAAGA,EAAAA,OAAO,cAAY,GAAKA,EAAAA,OAAO,kBAAkB,EAAK,cAAY,CAAA,CAAA;IAC3E,UAAS;IACR,SAAO,MAAU,EAA0B,GAAO,EAAK;IACvD,YAAU;;IAEX,EAMa,EAAA,EAAA,EAAA;KALV,eAAa,EAAK,SAAI;KACtB,OAAK,EAAEA,EAAAA,OAAO,YAAW;KACzB,wBAAkB,MAAE,EAAgB,EAAK;;sBAG5C,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAFC,gBAED,GAAA,CAAA,CAAA,CAAA;;;;;;;YACA,EAaW,GAAA,MAAA,EAbwB,EAAc,EAAI,CAAE,UAArC,GAAG,YACnB,EAWE,GAAA;UAZkE;KAEjE,QAAQ,EAAe,EAAc,EAAI,CAAE,QAAQ,GAAS;KAC5D,SAAS,EAAc,EAAI,CAAE;KAC7B,kBAAgB,EAAA;KAChB,qBAAmB,EAAM;KACzB,uBAAqB,EAAM;KAC3B,cAAY,EAAQ,EAAM;KAC1B,WAAS,MAAc,EAAc,EAAI,CAAE,QAAQ,SAAM;KACzD,gBAAc,EAAsB,GAAO,EAAS;KACpD,iBAAgB,MAAU,EAAa,GAAO,GAAW,EAAK;KAC9D,kBAAiB,MAAM,EAAmB,GAAO,EAAC;;;;;;;;;;;;;IAG5C,EAAM,aAAA,GAAA,EAAjB,EAEM,OAAA;;KAFuB,OAAK,EAAEA,EAAAA,OAAO,SAAQ;qBACjD,EAA+B,OAAA,MAA1B,wBAAoB,GAAA,CAAA,CAAA,EAAA,EAAA,IAGb,EAAM,iBAAiB,GAAM,EAAK,gBAAA,GAAA,EADhD,EAMiB,EAAA,EAAA,EAAA;;KAJf,MAAK;KACJ,UAAK,MAAE,EAAiB,GAAO,EAAA,MAAa;;sBAG/C,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAFC,gBAED,GAAA,CAAA,CAAA,CAAA;;;;GAGO,cAAU,GAOjB,EAPqB,eAAK,CAEpB,EAAM,wBAAwB,IAAQ,GAAa,CAAG,SAAM,KAAA,GAAA,EADpE,EAME,GAAA;;IAJC,OAAK,EAAEA,EAAAA,OAAO,cAAa;IAC3B,QAAQ,EAAM,QAAQ;IACtB,UAAU,MAAU,GAAa,CAAG,SAAM;IAC1C,aAAW;;;;;;;;;;;;;;;;;;;MAOV,EAAM,wBAAA,GAAA,EADd,EA6BgB,EAAA,EAAA,EAAA;;GA3Bb,OAAO;GACP,iBAAe,MAAU,EAAM;GAC/B,cAAYA,EAAAA,OAAO;GACnB,sBAAoBA,EAAAA,OAAO;GAC3B,oBAAkBA,EAAAA,OAAO;GACzB,qBAAa;GACb,iBAAiB;GACjB,iBAAiB;GACjB,iBAAiB;GACjB,gBAAgB;GACjB,UAAS;GACR,QAAM;GACN,YAAU;;GAEA,cAAU,GAGlB,EAHsB,SAAM,eAAK,CAClC,EAEC,EAAA,QAAA,eAAA;IAF+B;IAAO,OAAO,IAAQ,GAAa,CAAG;YAErE,CAAA,AAAA,EAAA,OAAA,EADE,gBAAY,GAAA,CAAA,CAAA,CAAA,CAAA;GAGN,gBAAY,QAGf,CAFK,EAAA,aAAA,GAAA,EAAX,EAEM,OAAA;;IAFiB,OAAK,EAAEA,EAAAA,OAAO,SAAQ;oBAC3C,EAA+B,OAAA,MAA1B,wBAAoB,GAAA,CAAA,CAAA,EAAA,EAAA,IAE3B,EAEO,EAAA,QAAA,qBAAA,EAAA,KAAA,GAAA,QAAA,CADL,EAAyF,EAAA,EAAA,EAAA;IAAzE,MAAK;IAAO,SAAK,AAAA,EAAA,QAAA,MAAE,EAAS,EAAA,MAAa;;qBAAe,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAZ,gBAAY,GAAA,CAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCsvExporter.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { GridApi } from \"ag-grid-enterprise\";\nimport type { PTableHandle } from \"@platforma-sdk/model\";\nimport { PlBtnGhost, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport { shallowRef, toRefs } from \"vue\";\nimport { isNil } from \"es-toolkit\";\nimport { exportCsv, isCsvExportAvailable } from \"./export-csv\";\nimport type { ExportOptions } from \"./export-csv\";\n\nconst props = defineProps<{\n api: GridApi;\n tableHandle?: PTableHandle;\n}>();\nconst { api: gridApi } = toRefs(props);\nconst csvExportAvailable = isCsvExportAvailable();\n\nconst exporting = shallowRef(false);\nconst initiateExport = () => {\n const nativeOptions: ExportOptions | undefined = !isNil(props.tableHandle)\n ? { tableHandle: props.tableHandle }\n : undefined;\n\n if (isNil(nativeOptions)) {\n return;\n }\n\n exporting.value = true;\n exportCsv(gridApi.value, nativeOptions).finally(() => (exporting.value = false));\n};\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlAgCsvExporter\");\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget && csvExportAvailable\" :to=\"teleportTarget\">\n <PlBtnGhost :loading=\"exporting\" icon=\"export\" @click.stop=\"initiateExport\">\n Export\n </PlBtnGhost>\n </Teleport>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"PlAgCsvExporter.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { GridApi } from \"ag-grid-enterprise\";\nimport type { PTableHandle, PlDataTableColumnsMeta } from \"@platforma-sdk/model\";\nimport { PlBtnGhost, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport { shallowRef, toRefs } from \"vue\";\nimport { isNil } from \"es-toolkit\";\nimport { exportCsv, isCsvExportAvailable } from \"./export-csv\";\nimport type { ExportOptions } from \"./export-csv\";\n\nconst props = defineProps<{\n api: GridApi;\n tableHandle?: PTableHandle;\n columnsMeta?: PlDataTableColumnsMeta;\n}>();\nconst { api: gridApi } = toRefs(props);\nconst csvExportAvailable = isCsvExportAvailable();\n\nconst exporting = shallowRef(false);\nconst initiateExport = () => {\n const nativeOptions: ExportOptions | undefined = !isNil(props.tableHandle)\n ? { tableHandle: props.tableHandle, columnsMeta: props.columnsMeta }\n : undefined;\n\n if (isNil(nativeOptions)) {\n return;\n }\n\n exporting.value = true;\n exportCsv(gridApi.value, nativeOptions).finally(() => (exporting.value = false));\n};\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlAgCsvExporter\");\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget && csvExportAvailable\" :to=\"teleportTarget\">\n <PlBtnGhost :loading=\"exporting\" icon=\"export\" @click.stop=\"initiateExport\">\n Export\n </PlBtnGhost>\n </Teleport>\n</template>\n"],"mappings":""}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { GridApi } from 'ag-grid-enterprise';
|
|
2
|
-
import { PTableHandle } from '@platforma-sdk/model';
|
|
2
|
+
import { PTableHandle, PlDataTableColumnsMeta } from '@platforma-sdk/model';
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
api: GridApi;
|
|
5
5
|
tableHandle?: PTableHandle;
|
|
6
|
+
columnsMeta?: PlDataTableColumnsMeta;
|
|
6
7
|
};
|
|
7
8
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
8
9
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCsvExporter.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAgCsvExporter.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAOjF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC,CAAC;;AA4FF,wBAMG"}
|
|
@@ -7,11 +7,15 @@ var _ = /* @__PURE__ */ s({
|
|
|
7
7
|
__name: "PlAgCsvExporter",
|
|
8
8
|
props: {
|
|
9
9
|
api: {},
|
|
10
|
-
tableHandle: {}
|
|
10
|
+
tableHandle: {},
|
|
11
|
+
columnsMeta: {}
|
|
11
12
|
},
|
|
12
13
|
setup(s) {
|
|
13
14
|
let _ = s, { api: v } = u(_), y = t(), b = l(!1), x = () => {
|
|
14
|
-
let t = m(_.tableHandle) ? void 0 : {
|
|
15
|
+
let t = m(_.tableHandle) ? void 0 : {
|
|
16
|
+
tableHandle: _.tableHandle,
|
|
17
|
+
columnsMeta: _.columnsMeta
|
|
18
|
+
};
|
|
15
19
|
m(t) || (b.value = !0, e(v.value, t).finally(() => b.value = !1));
|
|
16
20
|
}, S = g("PlAgCsvExporter");
|
|
17
21
|
return (e, t) => d(S) && d(y) ? (c(), r(n, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCsvExporter.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { GridApi } from \"ag-grid-enterprise\";\nimport type { PTableHandle } from \"@platforma-sdk/model\";\nimport { PlBtnGhost, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport { shallowRef, toRefs } from \"vue\";\nimport { isNil } from \"es-toolkit\";\nimport { exportCsv, isCsvExportAvailable } from \"./export-csv\";\nimport type { ExportOptions } from \"./export-csv\";\n\nconst props = defineProps<{\n api: GridApi;\n tableHandle?: PTableHandle;\n}>();\nconst { api: gridApi } = toRefs(props);\nconst csvExportAvailable = isCsvExportAvailable();\n\nconst exporting = shallowRef(false);\nconst initiateExport = () => {\n const nativeOptions: ExportOptions | undefined = !isNil(props.tableHandle)\n ? { tableHandle: props.tableHandle }\n : undefined;\n\n if (isNil(nativeOptions)) {\n return;\n }\n\n exporting.value = true;\n exportCsv(gridApi.value, nativeOptions).finally(() => (exporting.value = false));\n};\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlAgCsvExporter\");\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget && csvExportAvailable\" :to=\"teleportTarget\">\n <PlBtnGhost :loading=\"exporting\" icon=\"export\" @click.stop=\"initiateExport\">\n Export\n </PlBtnGhost>\n </Teleport>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAgCsvExporter.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/PlAgCsvExporter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { GridApi } from \"ag-grid-enterprise\";\nimport type { PTableHandle, PlDataTableColumnsMeta } from \"@platforma-sdk/model\";\nimport { PlBtnGhost, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport { shallowRef, toRefs } from \"vue\";\nimport { isNil } from \"es-toolkit\";\nimport { exportCsv, isCsvExportAvailable } from \"./export-csv\";\nimport type { ExportOptions } from \"./export-csv\";\n\nconst props = defineProps<{\n api: GridApi;\n tableHandle?: PTableHandle;\n columnsMeta?: PlDataTableColumnsMeta;\n}>();\nconst { api: gridApi } = toRefs(props);\nconst csvExportAvailable = isCsvExportAvailable();\n\nconst exporting = shallowRef(false);\nconst initiateExport = () => {\n const nativeOptions: ExportOptions | undefined = !isNil(props.tableHandle)\n ? { tableHandle: props.tableHandle, columnsMeta: props.columnsMeta }\n : undefined;\n\n if (isNil(nativeOptions)) {\n return;\n }\n\n exporting.value = true;\n exportCsv(gridApi.value, nativeOptions).finally(() => (exporting.value = false));\n};\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlAgCsvExporter\");\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget && csvExportAvailable\" :to=\"teleportTarget\">\n <PlBtnGhost :loading=\"exporting\" icon=\"export\" @click.stop=\"initiateExport\">\n Export\n </PlBtnGhost>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;;;;EASA,IAAM,IAAQ,GAKR,EAAE,KAAK,MAAY,EAAO,EAAM,EAChC,IAAqB,GAAsB,EAE3C,IAAY,EAAW,GAAM,EAC7B,UAAuB;GAC3B,IAAM,IAA4C,EAAM,EAAM,YAAW,GAErE,KAAA,IADA;IAAE,aAAa,EAAM;IAAa,aAAa,EAAM;IAAY;AAGjE,KAAM,EAAc,KAIxB,EAAU,QAAQ,IAClB,EAAU,EAAQ,OAAO,EAAc,CAAC,cAAe,EAAU,QAAQ,GAAO;KAG5E,IAAiB,EAAkC,kBAAkB;mBAIzD,EAAA,EAAc,IAAI,EAAA,EAAkB,IAAA,GAAA,EAApD,EAIW,GAAA;;GAJ4C,IAAI,EAAA,EAAc;MACvE,EAEa,EAAA,EAAA,EAAA;GAFA,SAAS,EAAA;GAAW,MAAK;GAAU,SAAK,EAAO,GAAc,CAAA,OAAA,CAAA;;oBAE1E,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAF4E,YAE5E,GAAA,CAAA,CAAA,CAAA"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { GridApi } from 'ag-grid-enterprise';
|
|
2
|
-
import { PTableHandle, PTableColumnSpec, PFrameSpecDriver, WritePTableToFsResult } from '@platforma-sdk/model';
|
|
2
|
+
import { PTableHandle, PTableColumnSpec, PFrameSpecDriver, PlDataTableColumnsMeta, WritePTableToFsResult } from '@platforma-sdk/model';
|
|
3
3
|
import { Nil } from '@milaboratories/helpers';
|
|
4
4
|
/** Options for the native table export. */
|
|
5
5
|
export interface ExportOptions {
|
|
6
6
|
tableHandle: PTableHandle;
|
|
7
7
|
defaultFileName?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Sidecar display metadata for the visible table. Supplies the disambiguated
|
|
10
|
+
* header labels the UI shows — the ones the spec's intrinsic `pl7.app/label`
|
|
11
|
+
* may not carry — so the export reproduces exactly what the user sees.
|
|
12
|
+
*/
|
|
13
|
+
columnsMeta?: PlDataTableColumnsMeta;
|
|
8
14
|
}
|
|
9
15
|
/**
|
|
10
16
|
* Table export via the platforma desktop runtime. Prompts for a save
|
|
@@ -28,10 +34,15 @@ export declare function exportCsv(gridApi: GridApi, nativeOptions: ExportOptions
|
|
|
28
34
|
*/
|
|
29
35
|
export declare function isCsvExportAvailable(): boolean;
|
|
30
36
|
/**
|
|
31
|
-
* Collect unified
|
|
32
|
-
* ag-grid column defs, remapped onto the provided PTable spec array so
|
|
33
|
-
* indices match the current table handle (ColDef.field indices may be stale
|
|
37
|
+
* Collect `[unified index, header name]` pairs for visible (non-hidden) columns
|
|
38
|
+
* from the ag-grid column defs, remapped onto the provided PTable spec array so
|
|
39
|
+
* the indices match the current table handle (ColDef.field indices may be stale
|
|
34
40
|
* or diverge from the spec order).
|
|
41
|
+
*
|
|
42
|
+
* The header name is the disambiguated label the UI shows — sidecar override
|
|
43
|
+
* (`columnsMeta`) wins over the spec's intrinsic `pl7.app/label`, falling back
|
|
44
|
+
* to the spec name — so the export reproduces exactly the visible headers and
|
|
45
|
+
* avoids the duplicate-label collisions that break the native export path.
|
|
35
46
|
*/
|
|
36
|
-
export declare function
|
|
47
|
+
export declare function collectVisibleColumns(gridApi: GridApi, specs: PTableColumnSpec[], pframeSpec: PFrameSpecDriver, columnsMeta: PlDataTableColumnsMeta | undefined): Nil | [number, string][];
|
|
37
48
|
//# sourceMappingURL=export-csv.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-csv.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,KAAK,EAEV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"export-csv.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,KAAK,EAEV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAK9C,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,YAAY,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC;AAkCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,SAAS,GAAG,qBAAqB,CAAC,CAqE5C;AAUD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,gBAAgB,EAAE,EACzB,UAAU,EAAE,gBAAgB,EAC5B,WAAW,EAAE,sBAAsB,GAAG,SAAS,GAC9C,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAwB1B"}
|