@platforma-sdk/ui-vue 1.84.17 → 1.84.20
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 +12 -11
- 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 +17 -0
- package/dist/components/PlTableFilters/PlTableFiltersV2.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableFiltersV2.style.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts.map +1 -1
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +64 -70
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
- package/dist/components/PlTableFilters/suggest-source.d.ts +21 -0
- package/dist/components/PlTableFilters/suggest-source.d.ts.map +1 -0
- package/dist/components/PlTableFilters/suggest-source.js +42 -0
- package/dist/components/PlTableFilters/suggest-source.js.map +1 -0
- package/dist/components/PlTableFilters/suggest-source.test.d.ts +2 -0
- package/dist/components/PlTableFilters/suggest-source.test.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/components/PlTableFilters/PlTableFiltersV2.vue +21 -29
- package/src/components/PlTableFilters/suggest-source.test.ts +80 -0
- package/src/components/PlTableFilters/suggest-source.ts +66 -0
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.84.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.84.20 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...
|
|
@@ -33,11 +33,11 @@ Building browser-lib project...
|
|
|
33
33
|
[7m4[0m export function useGridColumns(props: { api: GridApi }) {
|
|
34
34
|
[7m [0m [91m ~~~~~~~~~~~~~~[0m
|
|
35
35
|
|
|
36
|
-
[2K
|
|
36
|
+
[2K
|
|
37
37
|
rendering chunks...
|
|
38
38
|
|
|
39
39
|
[unplugin:dts] Start generate declaration files...
|
|
40
|
-
[unplugin:dts] Declaration files built in
|
|
40
|
+
[unplugin:dts] Declaration files built in 4443ms.
|
|
41
41
|
|
|
42
42
|
computing gzip size...
|
|
43
43
|
dist/components/PlAnnotations/components/PlAnnotations.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
|
|
@@ -146,7 +146,7 @@ dist/components/PlAgDataTable/PlAgDataTableV2.js
|
|
|
146
146
|
dist/plugins/Monetization/UserCabinetCard.js 0.35 kB │ gzip: 0.24 kB │ map: 3.00 kB
|
|
147
147
|
dist/components/PlAdvancedFilter/PlAdvancedFilter.js 0.36 kB │ gzip: 0.24 kB │ map: 14.05 kB
|
|
148
148
|
dist/components/PlAgDataTable/PlAgOverlayNoRows.js 0.36 kB │ gzip: 0.21 kB │ map: 0.74 kB
|
|
149
|
-
dist/components/PlTableFilters/PlTableFiltersV2.js 0.36 kB │ gzip: 0.25 kB │ map: 7.
|
|
149
|
+
dist/components/PlTableFilters/PlTableFiltersV2.js 0.36 kB │ gzip: 0.25 kB │ map: 7.17 kB
|
|
150
150
|
dist/components/PlAgCellStatusTag/PlAgCellStatusTag.js 0.36 kB │ gzip: 0.20 kB │ map: 0.74 kB
|
|
151
151
|
dist/components/PlBtnExportArchive/PlBtnExportArchive.js 0.36 kB │ gzip: 0.24 kB │ map: 7.47 kB
|
|
152
152
|
dist/components/PlAgDataTable/PlAgDataTableSheets.js 0.37 kB │ gzip: 0.25 kB │ map: 3.73 kB
|
|
@@ -189,6 +189,7 @@ dist/AgGridVue/selection.js
|
|
|
189
189
|
dist/components/PlAdvancedFilter/OperandButton.vue_vue_type_script_setup_true_lang.js 1.01 kB │ gzip: 0.60 kB │ map: 1.84 kB
|
|
190
190
|
dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue_vue_type_script_setup_true_lang.js 1.04 kB │ gzip: 0.53 kB │ map: 1.57 kB
|
|
191
191
|
dist/components/NotFound.vue_vue_type_script_setup_true_lang.js 1.04 kB │ gzip: 0.62 kB │ map: 1.09 kB
|
|
192
|
+
dist/components/PlTableFilters/suggest-source.js 1.14 kB │ gzip: 0.64 kB │ map: 3.26 kB
|
|
192
193
|
dist/plugins/Monetization/RunStatus.vue_vue_type_script_setup_true_lang.js 1.16 kB │ gzip: 0.62 kB │ map: 3.04 kB
|
|
193
194
|
dist/components/PlAgDataTable/sources/value-rendering.js 1.16 kB │ gzip: 0.56 kB │ map: 3.38 kB
|
|
194
195
|
dist/components/PlAgGridColumnManager/useFilteredItems.js 1.18 kB │ gzip: 0.61 kB │ map: 3.48 kB
|
|
@@ -236,7 +237,7 @@ dist/AgGridVue/useAgGridOptions.js
|
|
|
236
237
|
dist/components/PlAnnotations/components/FilterSidebar.vue_vue_type_script_setup_true_lang.js 4.24 kB │ gzip: 1.62 kB │ map: 7.80 kB
|
|
237
238
|
dist/components/PlAnnotations/components/AnnotationsSidebar.vue_vue_type_script_setup_true_lang.js 4.29 kB │ gzip: 1.67 kB │ map: 7.04 kB
|
|
238
239
|
dist/index.js 4.50 kB │ gzip: 1.36 kB │ map: 0.25 kB
|
|
239
|
-
dist/components/PlTableFilters/PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js 5.
|
|
240
|
+
dist/components/PlTableFilters/PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js 5.19 kB │ gzip: 2.07 kB │ map: 10.03 kB
|
|
240
241
|
dist/components/PlBtnExportArchive/PlBtnExportArchive.vue_vue_type_script_setup_true_lang.js 5.40 kB │ gzip: 2.20 kB │ map: 10.68 kB
|
|
241
242
|
dist/components/PlAgDataTable/sources/table-state-v2.js 5.71 kB │ gzip: 1.83 kB │ map: 20.20 kB
|
|
242
243
|
dist/internal/createAppV3.js 6.19 kB │ gzip: 2.33 kB │ map: 21.40 kB
|
|
@@ -246,12 +247,12 @@ dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_script_setup_true_lan
|
|
|
246
247
|
dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 12.76 kB │ gzip: 4.02 kB │ map: 32.97 kB
|
|
247
248
|
|
|
248
249
|
[33m[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugins. Here is a breakdown:
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
- vite:css-post (
|
|
252
|
-
- vite:vue (
|
|
253
|
-
- vite:
|
|
250
|
+
- sourcemaps (35%)
|
|
251
|
+
- unplugin-dts (20%)
|
|
252
|
+
- vite:css-post (12%)
|
|
253
|
+
- vite:vue (9%)
|
|
254
|
+
- vite:build-import-analysis (7%)
|
|
254
255
|
See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
255
256
|
[39m
|
|
256
|
-
[32m✓ built in 5.
|
|
257
|
+
[32m✓ built in 5.27s[39m
|
|
257
258
|
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.84.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.84.20 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 2345ms on 134 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.84.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.84.20 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 25ms on 117 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.84.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.84.20 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-ts6.cjs --noEmit --project ./tsconfig.json --customConditions default
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @platforma-sdk/ui-vue
|
|
2
2
|
|
|
3
|
+
## 1.84.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [7dc8428]
|
|
8
|
+
- @platforma-sdk/model@1.84.20
|
|
9
|
+
- @milaboratories/uikit@2.15.41
|
|
10
|
+
|
|
11
|
+
## 1.84.19
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- fc41fe4: Table filters: suggest values for axis columns, merged across every table column carrying the axis, instead of failing with "Data loading error"; offer "In List" / "Not In List" predicates. New `getUniqueAxisValuesWithLabels` in `@platforma-sdk/model`.
|
|
16
|
+
- Updated dependencies [fc41fe4]
|
|
17
|
+
- @platforma-sdk/model@1.84.19
|
|
18
|
+
- @milaboratories/uikit@2.15.40
|
|
19
|
+
|
|
3
20
|
## 1.84.17
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlTableFiltersV2.js","names":[],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n
|
|
1
|
+
{"version":3,"file":"PlTableFiltersV2.js","names":[],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueAxisValuesWithLabels,\n getUniqueSourceValuesWithLabels,\n getPTableColumnId,\n deriveDistinctLabels,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { resolveSuggestSource, TABLE_FILTER_TYPES } from \"./suggest-source\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n const columnEntries: { idx: number; spec: PColumnSpec }[] = [];\n props.columns.forEach((col, idx) => {\n if (col.type === \"column\") columnEntries.push({ idx, spec: col.spec });\n });\n const distinctLabelByIdx = new Map<number, string>();\n deriveDistinctLabels(\n columnEntries.map((e) => e.spec),\n {},\n ).forEach((label, i) => distinctLabelByIdx.set(columnEntries[i].idx, label));\n\n return props.columns.map((col, idx) => {\n const id = getPTableColumnId(col);\n const label =\n distinctLabelByIdx.get(idx)?.trim() ||\n readAnnotation(col.spec, Annotation.Label)?.trim() ||\n `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\nconst supportedFilters = TABLE_FILTER_TYPES;\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const tableColumnId = params.columnId as PTableColumnId;\n if (typeof tableColumnId !== \"object\" || tableColumnId === null) {\n throw new Error(\"ColumnId should be a table column id for suggest options\");\n }\n\n const search = {\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n };\n const source = resolveSuggestSource(props.columns, tableColumnId, params.axisIdx);\n const response =\n source.type === \"column\"\n ? getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: source.columnId,\n axisIdx: source.axisIdx,\n ...search,\n })\n : getUniqueAxisValuesWithLabels(props.pframeHandle, {\n axisSpec: source.axisSpec,\n parentColumnIds: source.parentColumnIds,\n ...search,\n });\n return response.then((v) => v.values);\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n data-testid=\"pl-table-filters\"\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal\n v-model=\"showManager\"\n data-testid=\"pl-table-filters-panel\"\n :close-on-outside-click=\"false\"\n >\n <template #title>Manage Filters</template>\n\n <div data-testid=\"pl-table-filters-content\" :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div\n v-if=\"hasDefaultFilters && index === 0\"\n data-testid=\"pl-table-filters-default-group-title\"\n :class=\"$style.defaultGroupTitle\"\n >\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n data-testid=\"pl-table-filters-reset-default\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else data-testid=\"pl-table-filters-custom-group-title\">Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlTableFiltersV2.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n
|
|
1
|
+
{"version":3,"file":"PlTableFiltersV2.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueAxisValuesWithLabels,\n getUniqueSourceValuesWithLabels,\n getPTableColumnId,\n deriveDistinctLabels,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { resolveSuggestSource, TABLE_FILTER_TYPES } from \"./suggest-source\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n const columnEntries: { idx: number; spec: PColumnSpec }[] = [];\n props.columns.forEach((col, idx) => {\n if (col.type === \"column\") columnEntries.push({ idx, spec: col.spec });\n });\n const distinctLabelByIdx = new Map<number, string>();\n deriveDistinctLabels(\n columnEntries.map((e) => e.spec),\n {},\n ).forEach((label, i) => distinctLabelByIdx.set(columnEntries[i].idx, label));\n\n return props.columns.map((col, idx) => {\n const id = getPTableColumnId(col);\n const label =\n distinctLabelByIdx.get(idx)?.trim() ||\n readAnnotation(col.spec, Annotation.Label)?.trim() ||\n `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\nconst supportedFilters = TABLE_FILTER_TYPES;\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const tableColumnId = params.columnId as PTableColumnId;\n if (typeof tableColumnId !== \"object\" || tableColumnId === null) {\n throw new Error(\"ColumnId should be a table column id for suggest options\");\n }\n\n const search = {\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n };\n const source = resolveSuggestSource(props.columns, tableColumnId, params.axisIdx);\n const response =\n source.type === \"column\"\n ? getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: source.columnId,\n axisIdx: source.axisIdx,\n ...search,\n })\n : getUniqueAxisValuesWithLabels(props.pframeHandle, {\n axisSpec: source.axisSpec,\n parentColumnIds: source.parentColumnIds,\n ...search,\n });\n return response.then((v) => v.values);\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n data-testid=\"pl-table-filters\"\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal\n v-model=\"showManager\"\n data-testid=\"pl-table-filters-panel\"\n :close-on-outside-click=\"false\"\n >\n <template #title>Manage Filters</template>\n\n <div data-testid=\"pl-table-filters-content\" :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div\n v-if=\"hasDefaultFilters && index === 0\"\n data-testid=\"pl-table-filters-default-group-title\"\n :class=\"$style.defaultGroupTitle\"\n >\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n data-testid=\"pl-table-filters-reset-default\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else data-testid=\"pl-table-filters-custom-group-title\">Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlTableFiltersV2.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlTableFiltersV2.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"names":[],"mappings":"AAuNA,OAAO,KAAK,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAmB9B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAInD,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,YAAY,EAAE,GAAG,GAAG,YAAY,CAAC;IACjC,OAAO,EAAE,0BAA0B,CAAC;IACpC,cAAc,EAAE,GAAG,GAAG,0BAA0B,CAAC;IACjD,eAAe,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC7D,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CACtE,CAAC;AAySF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import e from "../PlAdvancedFilter/PlAdvancedFilter.js";
|
|
2
2
|
import "../PlAdvancedFilter/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { TABLE_FILTER_TYPES as t, resolveSuggestSource as n } from "./suggest-source.js";
|
|
4
|
+
import { Fragment as r, Teleport as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, normalizeClass as p, openBlock as m, ref as h, unref as g, withCtx as _, withModifiers as v } from "vue";
|
|
5
|
+
import { Annotation as y, Domain as b, deriveDistinctLabels as x, getPTableColumnId as S, getUniqueAxisValuesWithLabels as C, getUniqueSourceValuesWithLabels as w, readAnnotation as T, readDomain as E } from "@platforma-sdk/model";
|
|
6
|
+
import { isFunction as D, isNil as O } from "es-toolkit";
|
|
7
|
+
import { PlBtnGhost as k, PlSlideModal as A, usePlBlockPageTitleTeleportTarget as j } from "@milaboratories/uikit";
|
|
7
8
|
//#region src/components/PlTableFilters/PlTableFiltersV2.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
-
var
|
|
9
|
+
var M = {
|
|
9
10
|
key: 1,
|
|
10
11
|
"data-testid": "pl-table-filters-custom-group-title"
|
|
11
|
-
},
|
|
12
|
+
}, N = /* @__PURE__ */ f({
|
|
12
13
|
__name: "PlTableFiltersV2",
|
|
13
14
|
props: {
|
|
14
15
|
columns: {},
|
|
@@ -19,32 +20,32 @@ var A = {
|
|
|
19
20
|
onResetDefaultFilters: { type: Function },
|
|
20
21
|
onUpdateDefaultFilters: { type: Function }
|
|
21
22
|
},
|
|
22
|
-
setup(
|
|
23
|
-
let
|
|
24
|
-
...
|
|
25
|
-
filters: [...
|
|
26
|
-
}),
|
|
23
|
+
setup(f) {
|
|
24
|
+
let N = f, P = j("PlTableFiltersV2"), F = h(!1), I = a(() => N.filters.filters.length > 0), L = a(() => !O(N.defaultFilters) && N.defaultFilters.filters.length > 0), R = a(() => O(N.defaultFilters) || N.defaultFilters?.filters.length === 0 ? N.filters : {
|
|
25
|
+
...N.filters,
|
|
26
|
+
filters: [...N.defaultFilters?.filters ?? [], ...N.filters.filters]
|
|
27
|
+
}), z = (e) => {
|
|
27
28
|
let t = e;
|
|
28
|
-
if (
|
|
29
|
+
if (O(N.defaultFilters)) return N.onUpdateFilters(t);
|
|
29
30
|
let [n, ...r] = t.filters;
|
|
30
|
-
|
|
31
|
+
N.onUpdateFilters({
|
|
31
32
|
...t,
|
|
32
33
|
filters: r
|
|
33
|
-
}),
|
|
34
|
-
...
|
|
34
|
+
}), N.onUpdateDefaultFilters?.({
|
|
35
|
+
...N.defaultFilters,
|
|
35
36
|
filters: [n]
|
|
36
37
|
});
|
|
37
|
-
},
|
|
38
|
+
}, B = a(() => {
|
|
38
39
|
let e = [];
|
|
39
|
-
|
|
40
|
+
N.columns.forEach((t, n) => {
|
|
40
41
|
t.type === "column" && e.push({
|
|
41
42
|
idx: n,
|
|
42
43
|
spec: t.spec
|
|
43
44
|
});
|
|
44
45
|
});
|
|
45
46
|
let t = /* @__PURE__ */ new Map();
|
|
46
|
-
return
|
|
47
|
-
let r =
|
|
47
|
+
return x(e.map((e) => e.spec), {}).forEach((n, r) => t.set(e[r].idx, n)), N.columns.map((e, n) => {
|
|
48
|
+
let r = S(e), i = t.get(n)?.trim() || T(e.spec, y.Label)?.trim() || `Unlabeled ${e.type} ${n}`, a = E(e.spec, b.Alphabet) ?? T(e.spec, y.Alphabet);
|
|
48
49
|
return {
|
|
49
50
|
id: r,
|
|
50
51
|
label: i,
|
|
@@ -52,82 +53,75 @@ var A = {
|
|
|
52
53
|
alphabet: a ?? void 0
|
|
53
54
|
};
|
|
54
55
|
});
|
|
55
|
-
}),
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"greaterThan",
|
|
59
|
-
"greaterThanOrEqual",
|
|
60
|
-
"lessThan",
|
|
61
|
-
"lessThanOrEqual",
|
|
62
|
-
"patternEquals",
|
|
63
|
-
"patternNotEquals",
|
|
64
|
-
"patternContainSubsequence",
|
|
65
|
-
"patternNotContainSubsequence",
|
|
66
|
-
"patternMatchesRegularExpression",
|
|
67
|
-
"patternFuzzyContainSubsequence",
|
|
68
|
-
"equal",
|
|
69
|
-
"notEqual"
|
|
70
|
-
];
|
|
71
|
-
function B(e) {
|
|
72
|
-
if (E(j.pframeHandle)) return console.warn("PFrame handle is not available, cannot fetch suggest options"), [];
|
|
56
|
+
}), V = t;
|
|
57
|
+
function H(e) {
|
|
58
|
+
if (O(N.pframeHandle)) return console.warn("PFrame handle is not available, cannot fetch suggest options"), [];
|
|
73
59
|
let t = e.columnId;
|
|
74
|
-
if (typeof t != "object" || !t
|
|
75
|
-
|
|
76
|
-
columnId: b(t.id),
|
|
77
|
-
axisIdx: e.axisIdx,
|
|
60
|
+
if (typeof t != "object" || !t) throw Error("ColumnId should be a table column id for suggest options");
|
|
61
|
+
let r = {
|
|
78
62
|
limit: 100,
|
|
79
63
|
searchQuery: e.searchType === "label" ? e.searchStr : void 0,
|
|
80
64
|
searchQueryValue: e.searchType === "value" ? e.searchStr : void 0
|
|
81
|
-
}
|
|
65
|
+
}, i = n(N.columns, t, e.axisIdx);
|
|
66
|
+
return (i.type === "column" ? w(N.pframeHandle, {
|
|
67
|
+
columnId: i.columnId,
|
|
68
|
+
axisIdx: i.axisIdx,
|
|
69
|
+
...r
|
|
70
|
+
}) : C(N.pframeHandle, {
|
|
71
|
+
axisSpec: i.axisSpec,
|
|
72
|
+
parentColumnIds: i.parentColumnIds,
|
|
73
|
+
...r
|
|
74
|
+
})).then((e) => e.values);
|
|
82
75
|
}
|
|
83
|
-
return (
|
|
76
|
+
return (t, n) => (m(), c(r, null, [g(P) ? (m(), o(i, {
|
|
84
77
|
key: 0,
|
|
85
|
-
to:
|
|
86
|
-
}, [
|
|
78
|
+
to: g(P)
|
|
79
|
+
}, [d(g(k), {
|
|
87
80
|
"data-testid": "pl-table-filters",
|
|
88
|
-
icon:
|
|
89
|
-
onClick:
|
|
81
|
+
icon: I.value || L.value ? "filter-on" : "filter",
|
|
82
|
+
onClick: n[0] ||= v((e) => F.value = !0, ["stop"])
|
|
90
83
|
}, {
|
|
91
|
-
default:
|
|
84
|
+
default: _(() => [...n[3] ||= [u(" Filters ", -1)]]),
|
|
92
85
|
_: 1
|
|
93
|
-
}, 8, ["icon"])], 8, ["to"])) :
|
|
94
|
-
modelValue:
|
|
95
|
-
"onUpdate:modelValue":
|
|
86
|
+
}, 8, ["icon"])], 8, ["to"])) : s("", !0), d(g(A), {
|
|
87
|
+
modelValue: F.value,
|
|
88
|
+
"onUpdate:modelValue": n[2] ||= (e) => F.value = e,
|
|
96
89
|
"data-testid": "pl-table-filters-panel",
|
|
97
90
|
"close-on-outside-click": !1
|
|
98
91
|
}, {
|
|
99
|
-
title:
|
|
100
|
-
default:
|
|
92
|
+
title: _(() => [...n[4] ||= [u("Manage Filters", -1)]]),
|
|
93
|
+
default: _(() => [l("div", {
|
|
101
94
|
"data-testid": "pl-table-filters-content",
|
|
102
|
-
class:
|
|
103
|
-
}, [
|
|
104
|
-
filters:
|
|
105
|
-
options:
|
|
106
|
-
"supported-filters":
|
|
107
|
-
"get-suggest-options":
|
|
108
|
-
"is-pinned": (e, t) =>
|
|
109
|
-
"is-removable": (e, t) =>
|
|
110
|
-
"is-draggable": (e, t) =>
|
|
95
|
+
class: p(t.$style.root)
|
|
96
|
+
}, [d(g(e), {
|
|
97
|
+
filters: R.value,
|
|
98
|
+
options: B.value,
|
|
99
|
+
"supported-filters": g(V),
|
|
100
|
+
"get-suggest-options": H,
|
|
101
|
+
"is-pinned": (e, t) => L.value && t === 0,
|
|
102
|
+
"is-removable": (e, t) => L.value ? t > 0 : !0,
|
|
103
|
+
"is-draggable": (e, t) => L.value ? t > 0 : !0,
|
|
111
104
|
"enable-dnd": !1,
|
|
112
105
|
"enable-toggling": !0,
|
|
113
106
|
"enable-add-group-button": !0,
|
|
114
|
-
onUpdateFilters:
|
|
107
|
+
onUpdateFilters: z
|
|
115
108
|
}, {
|
|
116
|
-
"group-title":
|
|
109
|
+
"group-title": _(({ index: e }) => [L.value && e === 0 ? (m(), c("div", {
|
|
117
110
|
key: 0,
|
|
118
111
|
"data-testid": "pl-table-filters-default-group-title",
|
|
119
|
-
class:
|
|
120
|
-
}, [
|
|
112
|
+
class: p(t.$style.defaultGroupTitle)
|
|
113
|
+
}, [n[5] ||= u(" Default Group ", -1), g(D)(N.onResetDefaultFilters) ? (m(), o(g(k), {
|
|
121
114
|
key: 0,
|
|
122
115
|
"data-testid": "pl-table-filters-reset-default",
|
|
123
116
|
icon: "restart",
|
|
124
|
-
class:
|
|
125
|
-
onClick:
|
|
126
|
-
}, null, 8, ["class"])) :
|
|
117
|
+
class: p(t.$style.restartBtn),
|
|
118
|
+
onClick: n[1] ||= v((e) => N.onResetDefaultFilters(), ["stop"])
|
|
119
|
+
}, null, 8, ["class"])) : s("", !0)], 2)) : (m(), c("div", M, "Custom Group"))]),
|
|
127
120
|
_: 1
|
|
128
121
|
}, 8, [
|
|
129
122
|
"filters",
|
|
130
123
|
"options",
|
|
124
|
+
"supported-filters",
|
|
131
125
|
"is-pinned",
|
|
132
126
|
"is-removable",
|
|
133
127
|
"is-draggable"
|
|
@@ -137,6 +131,6 @@ var A = {
|
|
|
137
131
|
}
|
|
138
132
|
});
|
|
139
133
|
//#endregion
|
|
140
|
-
export {
|
|
134
|
+
export { N as default };
|
|
141
135
|
|
|
142
136
|
//# sourceMappingURL=PlTableFiltersV2.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueSourceValuesWithLabels,\n extractPObjectId,\n getPTableColumnId,\n deriveDistinctLabels,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n PlAdvancedFilterSupportedFilters,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n const columnEntries: { idx: number; spec: PColumnSpec }[] = [];\n props.columns.forEach((col, idx) => {\n if (col.type === \"column\") columnEntries.push({ idx, spec: col.spec });\n });\n const distinctLabelByIdx = new Map<number, string>();\n deriveDistinctLabels(\n columnEntries.map((e) => e.spec),\n {},\n ).forEach((label, i) => distinctLabelByIdx.set(columnEntries[i].idx, label));\n\n return props.columns.map((col, idx) => {\n const id = getPTableColumnId(col);\n const label =\n distinctLabelByIdx.get(idx)?.trim() ||\n readAnnotation(col.spec, Annotation.Label)?.trim() ||\n `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\n// Supported filters (same set as FilterSidebar)\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"patternMatchesRegularExpression\",\n \"patternFuzzyContainSubsequence\",\n \"equal\",\n \"notEqual\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const tableColumnId = params.columnId as PTableColumnId;\n if (\n typeof tableColumnId !== \"object\" ||\n tableColumnId === null ||\n tableColumnId.type !== \"column\"\n ) {\n throw new Error(\"ColumnId should be of type 'column' for suggest options\");\n }\n\n return getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: extractPObjectId(tableColumnId.id),\n axisIdx: params.axisIdx,\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n }).then((v) => v.values);\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n data-testid=\"pl-table-filters\"\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal\n v-model=\"showManager\"\n data-testid=\"pl-table-filters-panel\"\n :close-on-outside-click=\"false\"\n >\n <template #title>Manage Filters</template>\n\n <div data-testid=\"pl-table-filters-content\" :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div\n v-if=\"hasDefaultFilters && index === 0\"\n data-testid=\"pl-table-filters-default-group-title\"\n :class=\"$style.defaultGroupTitle\"\n >\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n data-testid=\"pl-table-filters-reset-default\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else data-testid=\"pl-table-filters-custom-group-title\">Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n PColumnSpec,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueAxisValuesWithLabels,\n getUniqueSourceValuesWithLabels,\n getPTableColumnId,\n deriveDistinctLabels,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { resolveSuggestSource, TABLE_FILTER_TYPES } from \"./suggest-source\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n const columnEntries: { idx: number; spec: PColumnSpec }[] = [];\n props.columns.forEach((col, idx) => {\n if (col.type === \"column\") columnEntries.push({ idx, spec: col.spec });\n });\n const distinctLabelByIdx = new Map<number, string>();\n deriveDistinctLabels(\n columnEntries.map((e) => e.spec),\n {},\n ).forEach((label, i) => distinctLabelByIdx.set(columnEntries[i].idx, label));\n\n return props.columns.map((col, idx) => {\n const id = getPTableColumnId(col);\n const label =\n distinctLabelByIdx.get(idx)?.trim() ||\n readAnnotation(col.spec, Annotation.Label)?.trim() ||\n `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\nconst supportedFilters = TABLE_FILTER_TYPES;\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const tableColumnId = params.columnId as PTableColumnId;\n if (typeof tableColumnId !== \"object\" || tableColumnId === null) {\n throw new Error(\"ColumnId should be a table column id for suggest options\");\n }\n\n const search = {\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n };\n const source = resolveSuggestSource(props.columns, tableColumnId, params.axisIdx);\n const response =\n source.type === \"column\"\n ? getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: source.columnId,\n axisIdx: source.axisIdx,\n ...search,\n })\n : getUniqueAxisValuesWithLabels(props.pframeHandle, {\n axisSpec: source.axisSpec,\n parentColumnIds: source.parentColumnIds,\n ...search,\n });\n return response.then((v) => v.values);\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n data-testid=\"pl-table-filters\"\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal\n v-model=\"showManager\"\n data-testid=\"pl-table-filters-panel\"\n :close-on-outside-click=\"false\"\n >\n <template #title>Manage Filters</template>\n\n <div data-testid=\"pl-table-filters-content\" :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div\n v-if=\"hasDefaultFilters && index === 0\"\n data-testid=\"pl-table-filters-default-group-title\"\n :class=\"$style.defaultGroupTitle\"\n >\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n data-testid=\"pl-table-filters-reset-default\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else data-testid=\"pl-table-filters-custom-group-title\">Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AxisSpec, PObjectId, PTableColumnId, PTableColumnSpec } from '@platforma-sdk/model';
|
|
2
|
+
import { SupportedFilterTypes } from '../PlAdvancedFilter/types';
|
|
3
|
+
/** Predicates the table filter offers (same set as FilterSidebar, plus list membership). */
|
|
4
|
+
export declare const TABLE_FILTER_TYPES: SupportedFilterTypes[];
|
|
5
|
+
/** Where value suggestions for a filtered table column come from. */
|
|
6
|
+
export type SuggestSource = {
|
|
7
|
+
type: "column";
|
|
8
|
+
columnId: PObjectId;
|
|
9
|
+
axisIdx: undefined | number;
|
|
10
|
+
} | {
|
|
11
|
+
type: "axis";
|
|
12
|
+
axisSpec: AxisSpec;
|
|
13
|
+
parentColumnIds: PObjectId[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A data column suggests its own values. An axis suggests the keys of every
|
|
17
|
+
* table column carrying it: a full join can hold keys that only some of those
|
|
18
|
+
* columns have, and the user can filter by any of them.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveSuggestSource(columns: PTableColumnSpec[], tableColumnId: PTableColumnId, axisIdx: undefined | number): SuggestSource;
|
|
21
|
+
//# sourceMappingURL=suggest-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-source.d.ts","sourceRoot":"","sources":["../../../src/components/PlTableFilters/suggest-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAElG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,EAAE,oBAAoB,EAiBpD,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,eAAe,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,aAAa,EAAE,cAAc,EAC7B,OAAO,EAAE,SAAS,GAAG,MAAM,GAC1B,aAAa,CAqBf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { canonicalizeAxisId as e, extractPObjectId as t, getAxisId as n } from "@platforma-sdk/model";
|
|
2
|
+
//#region src/components/PlTableFilters/suggest-source.ts
|
|
3
|
+
var r = [
|
|
4
|
+
"isNA",
|
|
5
|
+
"isNotNA",
|
|
6
|
+
"greaterThan",
|
|
7
|
+
"greaterThanOrEqual",
|
|
8
|
+
"lessThan",
|
|
9
|
+
"lessThanOrEqual",
|
|
10
|
+
"patternEquals",
|
|
11
|
+
"patternNotEquals",
|
|
12
|
+
"patternContainSubsequence",
|
|
13
|
+
"patternNotContainSubsequence",
|
|
14
|
+
"patternMatchesRegularExpression",
|
|
15
|
+
"patternFuzzyContainSubsequence",
|
|
16
|
+
"equal",
|
|
17
|
+
"notEqual",
|
|
18
|
+
"inSet",
|
|
19
|
+
"notInSet"
|
|
20
|
+
];
|
|
21
|
+
function i(n, r, i) {
|
|
22
|
+
if (r.type === "column") return {
|
|
23
|
+
type: "column",
|
|
24
|
+
columnId: t(r.id),
|
|
25
|
+
axisIdx: i
|
|
26
|
+
};
|
|
27
|
+
let o = e(r.id), s, c = /* @__PURE__ */ new Set();
|
|
28
|
+
for (let r of n) r.type === "axis" ? e(r.id) === o && (s = r.spec) : a(r.spec.axesSpec, o) && c.add(t(r.id));
|
|
29
|
+
if (s === void 0 || c.size === 0) throw Error(`No column in the table carries axis ${r.id.name}, cannot fetch suggest options`);
|
|
30
|
+
return {
|
|
31
|
+
type: "axis",
|
|
32
|
+
axisSpec: s,
|
|
33
|
+
parentColumnIds: [...c]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function a(t, r) {
|
|
37
|
+
return t.some((t) => e(n(t)) === r);
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { r as TABLE_FILTER_TYPES, i as resolveSuggestSource };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=suggest-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-source.js","names":[],"sources":["../../../src/components/PlTableFilters/suggest-source.ts"],"sourcesContent":["import type { AxisSpec, PObjectId, PTableColumnId, PTableColumnSpec } from \"@platforma-sdk/model\";\nimport { canonicalizeAxisId, extractPObjectId, getAxisId } from \"@platforma-sdk/model\";\nimport type { SupportedFilterTypes } from \"../PlAdvancedFilter/types\";\n\n/** Predicates the table filter offers (same set as FilterSidebar, plus list membership). */\nexport const TABLE_FILTER_TYPES: SupportedFilterTypes[] = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"patternMatchesRegularExpression\",\n \"patternFuzzyContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"inSet\",\n \"notInSet\",\n];\n\n/** Where value suggestions for a filtered table column come from. */\nexport type SuggestSource =\n | { type: \"column\"; columnId: PObjectId; axisIdx: undefined | number }\n | { type: \"axis\"; axisSpec: AxisSpec; parentColumnIds: PObjectId[] };\n\n/**\n * A data column suggests its own values. An axis suggests the keys of every\n * table column carrying it: a full join can hold keys that only some of those\n * columns have, and the user can filter by any of them.\n */\nexport function resolveSuggestSource(\n columns: PTableColumnSpec[],\n tableColumnId: PTableColumnId,\n axisIdx: undefined | number,\n): SuggestSource {\n if (tableColumnId.type === \"column\") {\n return { type: \"column\", columnId: extractPObjectId(tableColumnId.id), axisIdx };\n }\n\n const strAxisId = canonicalizeAxisId(tableColumnId.id);\n let axisSpec: undefined | AxisSpec;\n const parentColumnIds = new Set<PObjectId>();\n for (const col of columns) {\n if (col.type === \"axis\") {\n if (canonicalizeAxisId(col.id) === strAxisId) axisSpec = col.spec;\n } else if (carriesAxis(col.spec.axesSpec, strAxisId)) {\n parentColumnIds.add(extractPObjectId(col.id));\n }\n }\n if (axisSpec === undefined || parentColumnIds.size === 0) {\n throw new Error(\n `No column in the table carries axis ${tableColumnId.id.name}, cannot fetch suggest options`,\n );\n }\n return { type: \"axis\", axisSpec, parentColumnIds: [...parentColumnIds] };\n}\n\n// Internals\n\nfunction carriesAxis(axesSpec: AxisSpec[], strAxisId: string): boolean {\n return axesSpec.some((axis) => canonicalizeAxisId(getAxisId(axis)) === strAxisId);\n}\n"],"mappings":";;AAKA,IAAa,IAA6C;CACxD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAYD,SAAgB,EACd,GACA,GACA,GACe;AACf,KAAI,EAAc,SAAS,SACzB,QAAO;EAAE,MAAM;EAAU,UAAU,EAAiB,EAAc,GAAG;EAAE;EAAS;CAGlF,IAAM,IAAY,EAAmB,EAAc,GAAG,EAClD,GACE,oBAAkB,IAAI,KAAgB;AAC5C,MAAK,IAAM,KAAO,EAChB,CAAI,EAAI,SAAS,SACX,EAAmB,EAAI,GAAG,KAAK,MAAW,IAAW,EAAI,QACpD,EAAY,EAAI,KAAK,UAAU,EAAU,IAClD,EAAgB,IAAI,EAAiB,EAAI,GAAG,CAAC;AAGjD,KAAI,MAAa,KAAA,KAAa,EAAgB,SAAS,EACrD,OAAU,MACR,uCAAuC,EAAc,GAAG,KAAK,gCAC9D;AAEH,QAAO;EAAE,MAAM;EAAQ;EAAU,iBAAiB,CAAC,GAAG,EAAgB;EAAE;;AAK1E,SAAS,EAAY,GAAsB,GAA4B;AACrE,QAAO,EAAS,MAAM,MAAS,EAAmB,EAAU,EAAK,CAAC,KAAK,EAAU"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-source.test.d.ts","sourceRoot":"","sources":["../../../src/components/PlTableFilters/suggest-source.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/ui-vue",
|
|
3
|
-
"version": "1.84.
|
|
3
|
+
"version": "1.84.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"lru-cache": "^11.2.2",
|
|
27
27
|
"vue": "3.5.24",
|
|
28
28
|
"zod": "~3.25.76",
|
|
29
|
+
"@milaboratories/pf-spec-driver": "1.5.8",
|
|
29
30
|
"@milaboratories/columns-collection-driver": "0.2.9",
|
|
30
|
-
"@milaboratories/uikit": "2.15.39",
|
|
31
|
-
"@platforma-sdk/model": "1.84.17",
|
|
32
31
|
"@milaboratories/pl-model-common": "1.53.0",
|
|
33
|
-
"@
|
|
32
|
+
"@platforma-sdk/model": "1.84.20",
|
|
33
|
+
"@milaboratories/uikit": "2.15.41"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@faker-js/faker": "^9.2.0",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"typescript": "7.0.2",
|
|
47
47
|
"vite": "^8.0.6",
|
|
48
48
|
"vitest": "^4.1.3",
|
|
49
|
-
"@milaboratories/build-configs": "2.0.2",
|
|
50
49
|
"@milaboratories/helpers": "1.14.5",
|
|
51
50
|
"@milaboratories/ts-configs": "1.4.0",
|
|
51
|
+
"@milaboratories/build-configs": "2.0.2",
|
|
52
52
|
"@milaboratories/ts-builder": "1.7.2"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
Domain,
|
|
12
12
|
readAnnotation,
|
|
13
13
|
readDomain,
|
|
14
|
+
getUniqueAxisValuesWithLabels,
|
|
14
15
|
getUniqueSourceValuesWithLabels,
|
|
15
|
-
extractPObjectId,
|
|
16
16
|
getPTableColumnId,
|
|
17
17
|
deriveDistinctLabels,
|
|
18
18
|
} from "@platforma-sdk/model";
|
|
@@ -21,12 +21,12 @@ import { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from "@mi
|
|
|
21
21
|
import {
|
|
22
22
|
PlAdvancedFilter,
|
|
23
23
|
PlAdvancedFilterComponent,
|
|
24
|
-
PlAdvancedFilterSupportedFilters,
|
|
25
24
|
type PlAdvancedFilterItem,
|
|
26
25
|
} from "../PlAdvancedFilter";
|
|
27
26
|
import type { PlAdvancedFilterColumnId } from "../PlAdvancedFilter/types";
|
|
28
27
|
import type { Nil } from "@milaboratories/helpers";
|
|
29
28
|
import { isFunction, isNil } from "es-toolkit";
|
|
29
|
+
import { resolveSuggestSource, TABLE_FILTER_TYPES } from "./suggest-source";
|
|
30
30
|
|
|
31
31
|
const props = defineProps<{
|
|
32
32
|
columns: PTableColumnSpec[];
|
|
@@ -94,23 +94,7 @@ const options = computed<PlAdvancedFilterItem[]>(() => {
|
|
|
94
94
|
});
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
const supportedFilters = [
|
|
99
|
-
"isNA",
|
|
100
|
-
"isNotNA",
|
|
101
|
-
"greaterThan",
|
|
102
|
-
"greaterThanOrEqual",
|
|
103
|
-
"lessThan",
|
|
104
|
-
"lessThanOrEqual",
|
|
105
|
-
"patternEquals",
|
|
106
|
-
"patternNotEquals",
|
|
107
|
-
"patternContainSubsequence",
|
|
108
|
-
"patternNotContainSubsequence",
|
|
109
|
-
"patternMatchesRegularExpression",
|
|
110
|
-
"patternFuzzyContainSubsequence",
|
|
111
|
-
"equal",
|
|
112
|
-
"notEqual",
|
|
113
|
-
] as (typeof PlAdvancedFilterSupportedFilters)[number][];
|
|
97
|
+
const supportedFilters = TABLE_FILTER_TYPES;
|
|
114
98
|
|
|
115
99
|
// getSuggestOptions - provide discrete values from column annotations
|
|
116
100
|
function handleSuggestOptions(params: {
|
|
@@ -125,21 +109,29 @@ function handleSuggestOptions(params: {
|
|
|
125
109
|
}
|
|
126
110
|
|
|
127
111
|
const tableColumnId = params.columnId as PTableColumnId;
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
tableColumnId === null ||
|
|
131
|
-
tableColumnId.type !== "column"
|
|
132
|
-
) {
|
|
133
|
-
throw new Error("ColumnId should be of type 'column' for suggest options");
|
|
112
|
+
if (typeof tableColumnId !== "object" || tableColumnId === null) {
|
|
113
|
+
throw new Error("ColumnId should be a table column id for suggest options");
|
|
134
114
|
}
|
|
135
115
|
|
|
136
|
-
|
|
137
|
-
columnId: extractPObjectId(tableColumnId.id),
|
|
138
|
-
axisIdx: params.axisIdx,
|
|
116
|
+
const search = {
|
|
139
117
|
limit: 100,
|
|
140
118
|
searchQuery: params.searchType === "label" ? params.searchStr : undefined,
|
|
141
119
|
searchQueryValue: params.searchType === "value" ? params.searchStr : undefined,
|
|
142
|
-
}
|
|
120
|
+
};
|
|
121
|
+
const source = resolveSuggestSource(props.columns, tableColumnId, params.axisIdx);
|
|
122
|
+
const response =
|
|
123
|
+
source.type === "column"
|
|
124
|
+
? getUniqueSourceValuesWithLabels(props.pframeHandle, {
|
|
125
|
+
columnId: source.columnId,
|
|
126
|
+
axisIdx: source.axisIdx,
|
|
127
|
+
...search,
|
|
128
|
+
})
|
|
129
|
+
: getUniqueAxisValuesWithLabels(props.pframeHandle, {
|
|
130
|
+
axisSpec: source.axisSpec,
|
|
131
|
+
parentColumnIds: source.parentColumnIds,
|
|
132
|
+
...search,
|
|
133
|
+
});
|
|
134
|
+
return response.then((v) => v.values);
|
|
143
135
|
}
|
|
144
136
|
</script>
|
|
145
137
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createGlobalPObjectId,
|
|
3
|
+
type AxisSpec,
|
|
4
|
+
type PColumnSpec,
|
|
5
|
+
type PObjectId,
|
|
6
|
+
type PTableColumnSpec,
|
|
7
|
+
} from "@platforma-sdk/model";
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import { resolveSuggestSource, TABLE_FILTER_TYPES } from "./suggest-source";
|
|
10
|
+
|
|
11
|
+
describe("TABLE_FILTER_TYPES", () => {
|
|
12
|
+
it("offers list membership predicates", () => {
|
|
13
|
+
expect(TABLE_FILTER_TYPES).toContain("inSet");
|
|
14
|
+
expect(TABLE_FILTER_TYPES).toContain("notInSet");
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("resolveSuggestSource", () => {
|
|
19
|
+
const sampleAxis = axisSpec("pl7.app/sampleId");
|
|
20
|
+
const cloneAxis = axisSpec("pl7.app/vdj/clonotypeKey");
|
|
21
|
+
const abundanceId = columnId("abundance");
|
|
22
|
+
const countId = columnId("count");
|
|
23
|
+
const cloneLabelId = columnId("cloneLabel");
|
|
24
|
+
|
|
25
|
+
const columns: PTableColumnSpec[] = [
|
|
26
|
+
{ type: "axis", id: sampleAxis, spec: sampleAxis },
|
|
27
|
+
{ type: "axis", id: cloneAxis, spec: cloneAxis },
|
|
28
|
+
{ type: "column", id: abundanceId, spec: columnSpec("abundance", [sampleAxis, cloneAxis]) },
|
|
29
|
+
{ type: "column", id: countId, spec: columnSpec("count", [sampleAxis]) },
|
|
30
|
+
{ type: "column", id: cloneLabelId, spec: columnSpec("label", [cloneAxis]) },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
it("reads a data column through the column itself", () => {
|
|
34
|
+
expect(resolveSuggestSource(columns, { type: "column", id: abundanceId }, 1)).toEqual({
|
|
35
|
+
type: "column",
|
|
36
|
+
columnId: abundanceId,
|
|
37
|
+
axisIdx: 1,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("reads an axis through every column carrying it", () => {
|
|
42
|
+
expect(resolveSuggestSource(columns, { type: "axis", id: sampleAxis }, undefined)).toEqual({
|
|
43
|
+
type: "axis",
|
|
44
|
+
axisSpec: sampleAxis,
|
|
45
|
+
parentColumnIds: [abundanceId, countId],
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("does not take a column without the axis as a parent", () => {
|
|
50
|
+
const source = resolveSuggestSource(columns, { type: "axis", id: cloneAxis }, undefined);
|
|
51
|
+
expect(source).toEqual({
|
|
52
|
+
type: "axis",
|
|
53
|
+
axisSpec: cloneAxis,
|
|
54
|
+
parentColumnIds: [abundanceId, cloneLabelId],
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("throws when no column carries the axis", () => {
|
|
59
|
+
const orphanAxis = axisSpec("pl7.app/orphan");
|
|
60
|
+
const withOrphan: PTableColumnSpec[] = [
|
|
61
|
+
...columns,
|
|
62
|
+
{ type: "axis", id: orphanAxis, spec: orphanAxis },
|
|
63
|
+
];
|
|
64
|
+
expect(() =>
|
|
65
|
+
resolveSuggestSource(withOrphan, { type: "axis", id: orphanAxis }, undefined),
|
|
66
|
+
).toThrow(/pl7\.app\/orphan/);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
function axisSpec(name: string): AxisSpec {
|
|
71
|
+
return { name, type: "String" };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function columnSpec(name: string, axesSpec: AxisSpec[]): PColumnSpec {
|
|
75
|
+
return { kind: "PColumn", name, valueType: "Int", axesSpec };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function columnId(name: string): PObjectId {
|
|
79
|
+
return createGlobalPObjectId("block", name);
|
|
80
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { AxisSpec, PObjectId, PTableColumnId, PTableColumnSpec } from "@platforma-sdk/model";
|
|
2
|
+
import { canonicalizeAxisId, extractPObjectId, getAxisId } from "@platforma-sdk/model";
|
|
3
|
+
import type { SupportedFilterTypes } from "../PlAdvancedFilter/types";
|
|
4
|
+
|
|
5
|
+
/** Predicates the table filter offers (same set as FilterSidebar, plus list membership). */
|
|
6
|
+
export const TABLE_FILTER_TYPES: SupportedFilterTypes[] = [
|
|
7
|
+
"isNA",
|
|
8
|
+
"isNotNA",
|
|
9
|
+
"greaterThan",
|
|
10
|
+
"greaterThanOrEqual",
|
|
11
|
+
"lessThan",
|
|
12
|
+
"lessThanOrEqual",
|
|
13
|
+
"patternEquals",
|
|
14
|
+
"patternNotEquals",
|
|
15
|
+
"patternContainSubsequence",
|
|
16
|
+
"patternNotContainSubsequence",
|
|
17
|
+
"patternMatchesRegularExpression",
|
|
18
|
+
"patternFuzzyContainSubsequence",
|
|
19
|
+
"equal",
|
|
20
|
+
"notEqual",
|
|
21
|
+
"inSet",
|
|
22
|
+
"notInSet",
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
/** Where value suggestions for a filtered table column come from. */
|
|
26
|
+
export type SuggestSource =
|
|
27
|
+
| { type: "column"; columnId: PObjectId; axisIdx: undefined | number }
|
|
28
|
+
| { type: "axis"; axisSpec: AxisSpec; parentColumnIds: PObjectId[] };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A data column suggests its own values. An axis suggests the keys of every
|
|
32
|
+
* table column carrying it: a full join can hold keys that only some of those
|
|
33
|
+
* columns have, and the user can filter by any of them.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveSuggestSource(
|
|
36
|
+
columns: PTableColumnSpec[],
|
|
37
|
+
tableColumnId: PTableColumnId,
|
|
38
|
+
axisIdx: undefined | number,
|
|
39
|
+
): SuggestSource {
|
|
40
|
+
if (tableColumnId.type === "column") {
|
|
41
|
+
return { type: "column", columnId: extractPObjectId(tableColumnId.id), axisIdx };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const strAxisId = canonicalizeAxisId(tableColumnId.id);
|
|
45
|
+
let axisSpec: undefined | AxisSpec;
|
|
46
|
+
const parentColumnIds = new Set<PObjectId>();
|
|
47
|
+
for (const col of columns) {
|
|
48
|
+
if (col.type === "axis") {
|
|
49
|
+
if (canonicalizeAxisId(col.id) === strAxisId) axisSpec = col.spec;
|
|
50
|
+
} else if (carriesAxis(col.spec.axesSpec, strAxisId)) {
|
|
51
|
+
parentColumnIds.add(extractPObjectId(col.id));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (axisSpec === undefined || parentColumnIds.size === 0) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`No column in the table carries axis ${tableColumnId.id.name}, cannot fetch suggest options`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return { type: "axis", axisSpec, parentColumnIds: [...parentColumnIds] };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Internals
|
|
63
|
+
|
|
64
|
+
function carriesAxis(axesSpec: AxisSpec[], strAxisId: string): boolean {
|
|
65
|
+
return axesSpec.some((axis) => canonicalizeAxisId(getAxisId(axis)) === strAxisId);
|
|
66
|
+
}
|