@platforma-sdk/ui-vue 1.84.10 → 1.84.17
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 +67 -67
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +1 -1
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/components/BlockLayout.js.map +1 -1
- package/dist/components/BlockLayout.style.js.map +1 -1
- package/dist/components/BlockLayout.vue.d.ts.map +1 -1
- package/dist/components/BlockLayout.vue2.js +5 -1
- package/dist/components/BlockLayout.vue2.js.map +1 -1
- package/dist/components/BlockLoader.js.map +1 -1
- package/dist/components/BlockLoader.vue.d.ts.map +1 -1
- package/dist/components/BlockLoader.vue2.js +2 -0
- package/dist/components/BlockLoader.vue2.js.map +1 -1
- package/dist/components/LoaderPage.js +4 -1
- package/dist/components/LoaderPage.js.map +1 -1
- package/dist/components/LoaderPage.vue.d.ts.map +1 -1
- package/dist/components/NotFound.js.map +1 -1
- package/dist/components/NotFound.vue.d.ts.map +1 -1
- package/dist/components/NotFound.vue2.js +11 -5
- package/dist/components/NotFound.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/FilterEditor.js.map +1 -1
- package/dist/components/PlAdvancedFilter/FilterEditor.style.js.map +1 -1
- package/dist/components/PlAdvancedFilter/FilterEditor.vue.d.ts.map +1 -1
- package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +26 -2
- package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.js.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.style.js.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.vue.d.ts.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.vue2.js +2 -1
- package/dist/components/PlAdvancedFilter/OperandButton.vue2.js.map +1 -1
- 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 +70 -61
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
- package/dist/components/PlAgCellFile/PlAgCellFile.js.map +1 -1
- package/dist/components/PlAgCellFile/PlAgCellFile.vue.d.ts.map +1 -1
- package/dist/components/PlAgCellFile/PlAgCellFile.vue2.js +5 -1
- package/dist/components/PlAgCellFile/PlAgCellFile.vue2.js.map +1 -1
- package/dist/components/PlAgCellProgress/PlAgCellProgress.js.map +1 -1
- package/dist/components/PlAgCellProgress/PlAgCellProgress.vue.d.ts.map +1 -1
- package/dist/components/PlAgCellProgress/PlAgCellProgress.vue2.js +6 -6
- package/dist/components/PlAgCellProgress/PlAgCellProgress.vue2.js.map +1 -1
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.js.map +1 -1
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.d.ts.map +1 -1
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue2.js +8 -2
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue2.js.map +1 -1
- package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.js.map +1 -1
- package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.d.ts.map +1 -1
- package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue2.js +4 -1
- package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue2.js.map +1 -1
- package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.js.map +1 -1
- package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.d.ts.map +1 -1
- package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue2.js +7 -2
- package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue2.js.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.js.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.d.ts.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js +28 -20
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js +1 -0
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.style.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.js +2 -0
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.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 +5 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayLoading.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue2.js +12 -2
- package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayNoRows.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue.d.ts.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue2.js +7 -1
- package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue2.js.map +1 -1
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.js.map +1 -1
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js.map +1 -1
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.d.ts.map +1 -1
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +35 -27
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.js.map +1 -1
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.d.ts.map +1 -1
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue2.js +12 -7
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue2.js.map +1 -1
- package/dist/components/PlAgRowNumHeader.js.map +1 -1
- package/dist/components/PlAgRowNumHeader.vue.d.ts.map +1 -1
- package/dist/components/PlAgRowNumHeader.vue2.js +14 -7
- package/dist/components/PlAgRowNumHeader.vue2.js.map +1 -1
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.js.map +1 -1
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.d.ts.map +1 -1
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue2.js +8 -1
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.style.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue.d.ts.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js +14 -3
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.js.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.style.js.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.vue.d.ts.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +11 -2
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.style.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue.d.ts.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.style.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue.d.ts.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js +1 -0
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js.map +1 -1
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.js.map +1 -1
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.d.ts.map +1 -1
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue2.js +16 -2
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue2.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Item.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Item.style.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Item.vue.d.ts.map +1 -1
- package/dist/components/PlBtnExportArchive/Item.vue2.js +12 -2
- package/dist/components/PlBtnExportArchive/Item.vue2.js.map +1 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.js.map +1 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.style.js.map +1 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue.d.ts.map +1 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js +7 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Summary.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Summary.style.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Summary.vue.d.ts.map +1 -1
- package/dist/components/PlBtnExportArchive/Summary.vue2.js +11 -2
- package/dist/components/PlBtnExportArchive/Summary.vue2.js.map +1 -1
- package/dist/components/PlDatasetSelector/PlDatasetSelector.js.map +1 -1
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts.map +1 -1
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js +1 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js.map +1 -1
- package/dist/components/PlTableFastSearch/PlTableFastSearch.js.map +1 -1
- package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.d.ts.map +1 -1
- package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js +1 -0
- package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js.map +1 -1
- 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 +12 -2
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
- package/package.json +7 -7
- package/src/components/BlockLayout.vue +4 -2
- package/src/components/BlockLoader.vue +2 -1
- package/src/components/LoaderPage.vue +1 -1
- package/src/components/NotFound.vue +7 -3
- package/src/components/PlAdvancedFilter/FilterEditor.vue +36 -6
- package/src/components/PlAdvancedFilter/OperandButton.vue +2 -1
- package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +20 -4
- package/src/components/PlAgCellFile/PlAgCellFile.vue +2 -1
- package/src/components/PlAgCellProgress/PlAgCellProgress.vue +1 -1
- package/src/components/PlAgCellStatusTag/PlAgCellStatusTag.vue +2 -2
- package/src/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue +13 -3
- package/src/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue +13 -3
- package/src/components/PlAgColumnHeader/PlAgColumnHeader.vue +24 -6
- package/src/components/PlAgCsvExporter/PlAgCsvExporter.vue +6 -1
- package/src/components/PlAgDataTable/PlAgDataTableSheets.vue +6 -1
- package/src/components/PlAgDataTable/PlAgDataTableV2.vue +2 -1
- package/src/components/PlAgDataTable/PlAgOverlayLoading.vue +10 -3
- package/src/components/PlAgDataTable/PlAgOverlayNoRows.vue +4 -2
- package/src/components/PlAgGridColumnManager/PlAgGridColumnManager.vue +18 -5
- package/src/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue +5 -1
- package/src/components/PlAgRowNumHeader.vue +3 -1
- package/src/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue +3 -2
- package/src/components/PlAnnotations/components/AnnotationsSidebar.vue +13 -4
- package/src/components/PlAnnotations/components/FilterSidebar.vue +11 -3
- package/src/components/PlAnnotations/components/PlAnnotations.vue +1 -1
- package/src/components/PlAnnotations/components/PlAnnotationsModal.vue +1 -0
- package/src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue +34 -7
- package/src/components/PlBtnExportArchive/Item.vue +22 -6
- package/src/components/PlBtnExportArchive/PlBtnExportArchive.vue +18 -3
- package/src/components/PlBtnExportArchive/Summary.vue +15 -5
- package/src/components/PlDatasetSelector/PlDatasetSelector.vue +1 -0
- package/src/components/PlTableFastSearch/PlTableFastSearch.vue +6 -1
- package/src/components/PlTableFilters/PlTableFiltersV2.vue +14 -4
|
@@ -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 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
|
+
{"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 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 data-testid=\"pl-advanced-filter\">\n <PlElementList\n v-model:items=\"rootFilters\"\n data-testid=\"pl-advanced-filter-groups\"\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 data-testid=\"pl-advanced-filter-group\"\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 data-testid=\"pl-advanced-filter-filter-out\"\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\n v-if=\"props.enableDnd\"\n data-testid=\"pl-advanced-filter-dropzone\"\n :class=\"$style.dropzone\"\n >\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n data-testid=\"pl-advanced-filter-add-filter\"\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 data-testid=\"pl-advanced-filter-group-operands\"\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 data-testid=\"pl-advanced-filter-new-group\"\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\" data-testid=\"pl-advanced-filter-dropzone\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary\n data-testid=\"pl-advanced-filter-add-group\"\n icon=\"add\"\n @click=\"addGroup(firstColumnId)\"\n >\n Add filter\n </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 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
|
+
{"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 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 data-testid=\"pl-advanced-filter\">\n <PlElementList\n v-model:items=\"rootFilters\"\n data-testid=\"pl-advanced-filter-groups\"\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 data-testid=\"pl-advanced-filter-group\"\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 data-testid=\"pl-advanced-filter-filter-out\"\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\n v-if=\"props.enableDnd\"\n data-testid=\"pl-advanced-filter-dropzone\"\n :class=\"$style.dropzone\"\n >\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n data-testid=\"pl-advanced-filter-add-filter\"\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 data-testid=\"pl-advanced-filter-group-operands\"\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 data-testid=\"pl-advanced-filter-new-group\"\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\" data-testid=\"pl-advanced-filter-dropzone\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary\n data-testid=\"pl-advanced-filter-add-group\"\n icon=\"add\"\n @click=\"addGroup(firstColumnId)\"\n >\n Add filter\n </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":"AAqZA,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;AAGjB,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,UAAU,EAC1C,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,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAimBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB;iBA/lB1C,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;MAqkBd,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC1I,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;wBAVS,CAAC,KAAK;;;SAAgB,KAAK,GAAG;;wBAC9B,CAAC,KAAK;;;SAAiB,KAAK,GAAG;;8BACzB,CAAC,KAAK,IAAiB,KAAK,GAAG;;UAUlD,EAAE;EAEL,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;wBACpE,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
|
|
@@ -6,7 +6,7 @@ import { produce as c } from "immer";
|
|
|
6
6
|
import { Fragment as l, computed as u, createBlock as d, createCommentVNode as f, createElementBlock as p, createElementVNode as m, createTextVNode as h, createVNode as g, defineComponent as _, normalizeClass as v, openBlock as y, renderList as b, renderSlot as x, unref as S, withCtx as C } from "vue";
|
|
7
7
|
import { PlBtnSecondary as w, PlCheckbox as T, PlElementList as E } from "@milaboratories/uikit";
|
|
8
8
|
//#region src/components/PlAdvancedFilter/PlAdvancedFilter.vue?vue&type=script&setup=true&lang.ts
|
|
9
|
-
var D = ["onDrop"],
|
|
9
|
+
var D = { "data-testid": "pl-advanced-filter" }, O = ["onDrop"], k = /* @__PURE__ */ _({
|
|
10
10
|
__name: "PlAdvancedFilter",
|
|
11
11
|
props: {
|
|
12
12
|
filters: {},
|
|
@@ -44,25 +44,25 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
44
44
|
getSuggestOptions: {}
|
|
45
45
|
},
|
|
46
46
|
setup(n) {
|
|
47
|
-
let _ = n,
|
|
47
|
+
let _ = n, k = (e) => {
|
|
48
48
|
_.onUpdateFilters(c(_.filters, e));
|
|
49
|
-
},
|
|
49
|
+
}, A = u(() => _.options[0]?.id), j = [{
|
|
50
50
|
id: -1,
|
|
51
51
|
type: "and",
|
|
52
52
|
filters: [],
|
|
53
53
|
isExpanded: !0
|
|
54
|
-
}],
|
|
54
|
+
}], M = u({
|
|
55
55
|
get: () => _.filters.filters,
|
|
56
56
|
set: (e) => _.onUpdateFilters({
|
|
57
57
|
..._.filters,
|
|
58
58
|
filters: e
|
|
59
59
|
})
|
|
60
60
|
});
|
|
61
|
-
function
|
|
61
|
+
function N() {
|
|
62
62
|
if (_.filters.type !== "or" && _.filters.type !== "and") throw Error("Invalid model structure, expected root to be \"or\" or \"and\" group");
|
|
63
63
|
return _.filters.filters;
|
|
64
64
|
}
|
|
65
|
-
function
|
|
65
|
+
function P(e, t) {
|
|
66
66
|
let n = e.filters[t];
|
|
67
67
|
if (n.type === "not") {
|
|
68
68
|
if (n.filter.type !== "and" && n.filter.type !== "or") throw Error("Invalid group structure, expected \"and\" or \"or\" group inside \"not\"");
|
|
@@ -71,12 +71,12 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
71
71
|
if (n.type !== "and" && n.type !== "or") throw Error("Invalid group structure, expected \"and\", \"or\" or \"not\" group");
|
|
72
72
|
return n;
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function F(e) {
|
|
75
75
|
return e.type === "not" ? e.filter : e;
|
|
76
76
|
}
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
function I(n, r) {
|
|
78
|
+
k((i) => {
|
|
79
|
+
P(i, n).filters.push({
|
|
80
80
|
...e[t],
|
|
81
81
|
column: r,
|
|
82
82
|
id: a(),
|
|
@@ -84,14 +84,14 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
let r =
|
|
87
|
+
function L(e, t) {
|
|
88
|
+
k((n) => {
|
|
89
|
+
let r = P(n, e);
|
|
90
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
|
-
function
|
|
94
|
-
|
|
93
|
+
function R(e) {
|
|
94
|
+
k((t) => {
|
|
95
95
|
let n = t.filters[e];
|
|
96
96
|
if (n.type === "not") {
|
|
97
97
|
if (n.filter.type !== "and" && n.filter.type !== "or") throw Error("Invalid group structure, expected \"and\" or \"or\" group inside \"not\"");
|
|
@@ -111,68 +111,69 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
function
|
|
115
|
-
|
|
114
|
+
function z(e) {
|
|
115
|
+
k((t) => {
|
|
116
116
|
t.filters.push(i(e));
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
function B(e, t, n) {
|
|
120
|
+
k((r) => {
|
|
121
|
+
P(r, e).filters[t] = n;
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
|
-
function
|
|
124
|
+
function V(e, t) {
|
|
125
125
|
let n = t.dataTransfer;
|
|
126
126
|
if (n?.getData("text/plain")) {
|
|
127
127
|
let t = n.getData("text/plain");
|
|
128
|
-
o(t) &&
|
|
128
|
+
o(t) && I(e, t);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
function
|
|
131
|
+
function H(e) {
|
|
132
132
|
let t = e.dataTransfer;
|
|
133
133
|
if (t?.getData("text/plain")) {
|
|
134
134
|
let e = t.getData("text/plain");
|
|
135
|
-
o(e) &&
|
|
135
|
+
o(e) && z(e);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
function
|
|
138
|
+
function U(e) {
|
|
139
139
|
e.preventDefault();
|
|
140
140
|
}
|
|
141
|
-
function
|
|
142
|
-
|
|
141
|
+
function W(e, t) {
|
|
142
|
+
k((e) => {
|
|
143
143
|
e.filters[t].isExpanded = !e.filters[t].isExpanded;
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
|
-
function
|
|
147
|
-
|
|
146
|
+
function G(e, t) {
|
|
147
|
+
k((e) => {
|
|
148
148
|
e.filters[t].isSuppressed = !e.filters[t].isSuppressed;
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
function K(e, t) {
|
|
152
|
+
k((n) => {
|
|
153
|
+
P(n, e).type = t;
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
156
|
+
function q(e) {
|
|
157
|
+
k((t) => {
|
|
158
158
|
t.type = e;
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
|
-
function
|
|
161
|
+
function J(e) {
|
|
162
162
|
if (e.type === "and" || e.type === "or" || e.type === "not") throw Error("Invalid filter structure, expected leaf filter");
|
|
163
163
|
return e;
|
|
164
164
|
}
|
|
165
|
-
return (e, t) => (y(), p("div",
|
|
166
|
-
items:
|
|
167
|
-
"onUpdate:items": t[0] ||= (e) =>
|
|
165
|
+
return (e, t) => (y(), p("div", D, [g(S(E), {
|
|
166
|
+
items: M.value,
|
|
167
|
+
"onUpdate:items": t[0] ||= (e) => M.value = e,
|
|
168
|
+
"data-testid": "pl-advanced-filter-groups",
|
|
168
169
|
"get-item-key": (e) => e.id,
|
|
169
170
|
"item-class": e.$style.filterGroup,
|
|
170
171
|
"item-class-content": e.$style.filterGroupContent,
|
|
171
172
|
"item-class-title": e.$style.filterGroupTitle,
|
|
172
173
|
"is-expanded": (e) => e.isExpanded === !0,
|
|
173
|
-
"on-expand":
|
|
174
|
+
"on-expand": W,
|
|
174
175
|
"is-toggled": (e) => e.isSuppressed === !0,
|
|
175
|
-
"on-toggle":
|
|
176
|
+
"on-toggle": G,
|
|
176
177
|
"is-pinned": (e, t) => _.isPinned?.(e, t) === !0,
|
|
177
178
|
"is-pinnable": () => !1,
|
|
178
179
|
"is-removable": (e, t) => _.isRemovable?.(e, t) === !0,
|
|
@@ -186,15 +187,17 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
186
187
|
index: r
|
|
187
188
|
}, () => [t[2] ||= h("Filter group", -1)])]),
|
|
188
189
|
"item-content": C(({ item: r, index: i }) => [m("div", {
|
|
190
|
+
"data-testid": "pl-advanced-filter-group",
|
|
189
191
|
class: v([e.$style.groupContent, { [e.$style.suppressedLabel]: r.isSuppressed }]),
|
|
190
192
|
dropzone: "true",
|
|
191
|
-
onDrop: (e) =>
|
|
192
|
-
onDragover:
|
|
193
|
+
onDrop: (e) => V(i, e),
|
|
194
|
+
onDragover: U
|
|
193
195
|
}, [
|
|
194
196
|
g(S(T), {
|
|
195
197
|
"model-value": r.type === "not",
|
|
198
|
+
"data-testid": "pl-advanced-filter-filter-out",
|
|
196
199
|
class: v(e.$style.notCheckbox),
|
|
197
|
-
"onUpdate:modelValue": (e) =>
|
|
200
|
+
"onUpdate:modelValue": (e) => R(i)
|
|
198
201
|
}, {
|
|
199
202
|
default: C(() => [...t[3] ||= [h(" Filter Out ", -1)]]),
|
|
200
203
|
_: 1
|
|
@@ -203,18 +206,18 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
203
206
|
"class",
|
|
204
207
|
"onUpdate:modelValue"
|
|
205
208
|
]),
|
|
206
|
-
(y(!0), p(l, null, b(
|
|
209
|
+
(y(!0), p(l, null, b(F(r).filters, (e, t) => (y(), d(s, {
|
|
207
210
|
key: t,
|
|
208
|
-
filter:
|
|
209
|
-
operand:
|
|
211
|
+
filter: J(F(r).filters[t]),
|
|
212
|
+
operand: F(r).type,
|
|
210
213
|
"column-options": n.options,
|
|
211
214
|
"supported-filters": _.supportedFilters,
|
|
212
215
|
"get-suggest-options": _.getSuggestOptions,
|
|
213
216
|
"enable-dnd": !!_.enableDnd,
|
|
214
|
-
"is-last": t ===
|
|
215
|
-
onDelete: () =>
|
|
216
|
-
onUpdateFilter: (e) =>
|
|
217
|
-
onChangeOperand: (e) =>
|
|
217
|
+
"is-last": t === F(r).filters.length - 1,
|
|
218
|
+
onDelete: () => L(i, t),
|
|
219
|
+
onUpdateFilter: (e) => B(i, t, e),
|
|
220
|
+
onChangeOperand: (e) => K(i, e)
|
|
218
221
|
}, null, 8, [
|
|
219
222
|
"filter",
|
|
220
223
|
"operand",
|
|
@@ -229,22 +232,25 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
229
232
|
]))), 128)),
|
|
230
233
|
_.enableDnd ? (y(), p("div", {
|
|
231
234
|
key: 0,
|
|
235
|
+
"data-testid": "pl-advanced-filter-dropzone",
|
|
232
236
|
class: v(e.$style.dropzone)
|
|
233
237
|
}, [...t[4] ||= [m("div", null, "Drop dimensions here", -1)]], 2)) : _.isCompletedGroup(r, i) ? f("", !0) : (y(), d(S(w), {
|
|
234
238
|
key: 1,
|
|
239
|
+
"data-testid": "pl-advanced-filter-add-filter",
|
|
235
240
|
icon: "add",
|
|
236
|
-
onClick: (e) =>
|
|
241
|
+
onClick: (e) => I(i, A.value)
|
|
237
242
|
}, {
|
|
238
243
|
default: C(() => [...t[5] ||= [h(" Add filter ", -1)]]),
|
|
239
244
|
_: 1
|
|
240
245
|
}, 8, ["onClick"]))
|
|
241
|
-
], 42,
|
|
242
|
-
"item-after": C(({ index: t }) => [_.enableAddGroupButton || t <
|
|
246
|
+
], 42, O)]),
|
|
247
|
+
"item-after": C(({ index: t }) => [_.enableAddGroupButton || t < N().length - 1 ? (y(), d(r, {
|
|
243
248
|
key: 0,
|
|
249
|
+
"data-testid": "pl-advanced-filter-group-operands",
|
|
244
250
|
class: v(e.$style.buttonWrapper),
|
|
245
251
|
active: _.filters.type,
|
|
246
|
-
disabled: t ===
|
|
247
|
-
"on-select":
|
|
252
|
+
disabled: t === N().length - 1,
|
|
253
|
+
"on-select": q
|
|
248
254
|
}, null, 8, [
|
|
249
255
|
"class",
|
|
250
256
|
"active",
|
|
@@ -265,7 +271,8 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
265
271
|
"disable-toggling"
|
|
266
272
|
]), _.enableAddGroupButton ? (y(), d(S(E), {
|
|
267
273
|
key: 0,
|
|
268
|
-
|
|
274
|
+
"data-testid": "pl-advanced-filter-new-group",
|
|
275
|
+
items: j,
|
|
269
276
|
"get-item-key": (e) => e.id,
|
|
270
277
|
"item-class": e.$style.filterGroup,
|
|
271
278
|
"item-class-content": e.$style.filterGroupContent,
|
|
@@ -276,19 +283,21 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
276
283
|
disableToggling: !0,
|
|
277
284
|
disablePinning: !0,
|
|
278
285
|
dropzone: "true",
|
|
279
|
-
onDrop:
|
|
280
|
-
onDragover:
|
|
286
|
+
onDrop: H,
|
|
287
|
+
onDragover: U
|
|
281
288
|
}, {
|
|
282
289
|
"item-title": C(({ item: n, index: r }) => [x(e.$slots, "group-title", {
|
|
283
290
|
item: n,
|
|
284
|
-
index: r +
|
|
291
|
+
index: r + N().length
|
|
285
292
|
}, () => [t[6] ||= h("Filter group", -1)])]),
|
|
286
293
|
"item-content": C(() => [n.enableDnd ? (y(), p("div", {
|
|
287
294
|
key: 0,
|
|
295
|
+
"data-testid": "pl-advanced-filter-dropzone",
|
|
288
296
|
class: v(e.$style.dropzone)
|
|
289
297
|
}, [...t[7] ||= [m("div", null, "Drop dimensions here", -1)]], 2)) : x(e.$slots, "add-group-buttons", { key: 1 }, () => [g(S(w), {
|
|
298
|
+
"data-testid": "pl-advanced-filter-add-group",
|
|
290
299
|
icon: "add",
|
|
291
|
-
onClick: t[1] ||= (e) =>
|
|
300
|
+
onClick: t[1] ||= (e) => z(A.value)
|
|
292
301
|
}, {
|
|
293
302
|
default: C(() => [...t[8] ||= [h(" Add filter ", -1)]]),
|
|
294
303
|
_: 1
|
|
@@ -303,6 +312,6 @@ var D = ["onDrop"], O = /* @__PURE__ */ _({
|
|
|
303
312
|
}
|
|
304
313
|
});
|
|
305
314
|
//#endregion
|
|
306
|
-
export {
|
|
315
|
+
export { k as default };
|
|
307
316
|
|
|
308
317
|
//# sourceMappingURL=PlAdvancedFilter.vue2.js.map
|
|
@@ -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 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":"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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 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 data-testid=\"pl-advanced-filter\">\n <PlElementList\n v-model:items=\"rootFilters\"\n data-testid=\"pl-advanced-filter-groups\"\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 data-testid=\"pl-advanced-filter-group\"\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 data-testid=\"pl-advanced-filter-filter-out\"\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\n v-if=\"props.enableDnd\"\n data-testid=\"pl-advanced-filter-dropzone\"\n :class=\"$style.dropzone\"\n >\n <div>Drop dimensions here</div>\n </div>\n <PlBtnSecondary\n v-else-if=\"!props.isCompletedGroup(item, index)\"\n data-testid=\"pl-advanced-filter-add-filter\"\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 data-testid=\"pl-advanced-filter-group-operands\"\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 data-testid=\"pl-advanced-filter-new-group\"\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\" data-testid=\"pl-advanced-filter-dropzone\" :class=\"$style.dropzone\">\n <div>Drop dimensions here</div>\n </div>\n <slot v-else name=\"add-group-buttons\">\n <PlBtnSecondary\n data-testid=\"pl-advanced-filter-add-group\"\n icon=\"add\"\n @click=\"addGroup(firstColumnId)\"\n >\n Add filter\n </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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCellFile.js","names":[],"sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlFileInput } from \"@milaboratories/uikit\";\nimport type { ICellRendererParams } from \"ag-grid-enterprise\";\nimport type { ImportFileHandle, ImportProgress } from \"@platforma-sdk/model\";\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n // this component is intended to be used in ag-grid, params are the main object\n // to communicate with the corresponding cell data\n params: ICellRendererParams<unknown, ImportFileHandle> & {\n extensions?: string[];\n progress?: ImportProgress;\n /**\n * The resolveProgress function is an optional input parameter for the component\n * that allows tracking the file upload progress in real-time.\n * By passing resolveProgress, you can ensure that the component\n * displays accurate progress values for each file as they upload.\n * How to use it in AgGrid\n * cellRendererParams: {\n * resolveProgress: (fileHandle: ImportFileHandle | undefined) => {\n * const progresses = app.progresses;\n * if (!fileHandle) return undefined;\n * else return progresses[fileHandle];\n * }\n * }\n */\n resolveProgress?: (v: ImportFileHandle | undefined) => ImportProgress | undefined;\n };\n}>();\n\nconst extensions = computed(() => props.params.extensions);\n\n// extracting cell value and casting it to the type we expect\nconst handle = computed(() => props.params.value as ImportFileHandle | undefined);\n\n/**\n * When value changes in the file input this method forward the value to the ag-grid,\n * which in tern forwards in to the valueSetter in corresponding column.\n * */\nfunction onHandleUpdate(newHandle: ImportFileHandle | undefined) {\n props.params.setValue!(newHandle);\n}\n\nconst currentProgress = computed(() => {\n return props.params.resolveProgress ? props.params.resolveProgress(handle.value) : undefined;\n});\n</script>\n\n<template>\n <div style=\"height: 100%\">\n <PlFileInput\n show-filename-only\n clearable\n cell-style\n file-dialog-title=\"Select any file\"\n :placeholder=\"`Choose file ${extensions ? extensions[0] : ''}`\"\n :extensions=\"extensions\"\n :model-value=\"handle\"\n :progress=\"currentProgress\"\n @update:model-value=\"onHandleUpdate\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"PlAgCellFile.js","names":[],"sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlFileInput } from \"@milaboratories/uikit\";\nimport type { ICellRendererParams } from \"ag-grid-enterprise\";\nimport type { ImportFileHandle, ImportProgress } from \"@platforma-sdk/model\";\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n // this component is intended to be used in ag-grid, params are the main object\n // to communicate with the corresponding cell data\n params: ICellRendererParams<unknown, ImportFileHandle> & {\n extensions?: string[];\n progress?: ImportProgress;\n /**\n * The resolveProgress function is an optional input parameter for the component\n * that allows tracking the file upload progress in real-time.\n * By passing resolveProgress, you can ensure that the component\n * displays accurate progress values for each file as they upload.\n * How to use it in AgGrid\n * cellRendererParams: {\n * resolveProgress: (fileHandle: ImportFileHandle | undefined) => {\n * const progresses = app.progresses;\n * if (!fileHandle) return undefined;\n * else return progresses[fileHandle];\n * }\n * }\n */\n resolveProgress?: (v: ImportFileHandle | undefined) => ImportProgress | undefined;\n };\n}>();\n\nconst extensions = computed(() => props.params.extensions);\n\n// extracting cell value and casting it to the type we expect\nconst handle = computed(() => props.params.value as ImportFileHandle | undefined);\n\n/**\n * When value changes in the file input this method forward the value to the ag-grid,\n * which in tern forwards in to the valueSetter in corresponding column.\n * */\nfunction onHandleUpdate(newHandle: ImportFileHandle | undefined) {\n props.params.setValue!(newHandle);\n}\n\nconst currentProgress = computed(() => {\n return props.params.resolveProgress ? props.params.resolveProgress(handle.value) : undefined;\n});\n</script>\n\n<template>\n <div data-testid=\"pl-ag-cell-file\" style=\"height: 100%\">\n <PlFileInput\n data-testid=\"pl-ag-cell-file-input\"\n show-filename-only\n clearable\n cell-style\n file-dialog-title=\"Select any file\"\n :placeholder=\"`Choose file ${extensions ? extensions[0] : ''}`\"\n :extensions=\"extensions\"\n :model-value=\"handle\"\n :progress=\"currentProgress\"\n @update:model-value=\"onHandleUpdate\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCellFile.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAgCellFile.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"names":[],"mappings":"AAoEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG7E,KAAK,WAAW,GAAG;IAGjB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,GAAG;QACvD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B;;;;;;;;;;;;;WAaG;QACH,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,gBAAgB,GAAG,SAAS,KAAK,cAAc,GAAG,SAAS,CAAC;KACnF,CAAC;CACH,CAAC;AAoFF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { computed as e, createElementBlock as t, createVNode as n, defineComponent as r, openBlock as i, unref as a } from "vue";
|
|
2
2
|
import { PlFileInput as o } from "@milaboratories/uikit";
|
|
3
3
|
//#region src/components/PlAgCellFile/PlAgCellFile.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
-
var s = {
|
|
4
|
+
var s = {
|
|
5
|
+
"data-testid": "pl-ag-cell-file",
|
|
6
|
+
style: { height: "100%" }
|
|
7
|
+
}, c = /* @__PURE__ */ r({
|
|
5
8
|
__name: "PlAgCellFile",
|
|
6
9
|
props: { params: {} },
|
|
7
10
|
setup(r) {
|
|
@@ -11,6 +14,7 @@ var s = { style: { height: "100%" } }, c = /* @__PURE__ */ r({
|
|
|
11
14
|
}
|
|
12
15
|
let f = e(() => c.params.resolveProgress ? c.params.resolveProgress(u.value) : void 0);
|
|
13
16
|
return (e, r) => (i(), t("div", s, [n(a(o), {
|
|
17
|
+
"data-testid": "pl-ag-cell-file-input",
|
|
14
18
|
"show-filename-only": "",
|
|
15
19
|
clearable: "",
|
|
16
20
|
"cell-style": "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAgCellFile.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlFileInput } from \"@milaboratories/uikit\";\nimport type { ICellRendererParams } from \"ag-grid-enterprise\";\nimport type { ImportFileHandle, ImportProgress } from \"@platforma-sdk/model\";\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n // this component is intended to be used in ag-grid, params are the main object\n // to communicate with the corresponding cell data\n params: ICellRendererParams<unknown, ImportFileHandle> & {\n extensions?: string[];\n progress?: ImportProgress;\n /**\n * The resolveProgress function is an optional input parameter for the component\n * that allows tracking the file upload progress in real-time.\n * By passing resolveProgress, you can ensure that the component\n * displays accurate progress values for each file as they upload.\n * How to use it in AgGrid\n * cellRendererParams: {\n * resolveProgress: (fileHandle: ImportFileHandle | undefined) => {\n * const progresses = app.progresses;\n * if (!fileHandle) return undefined;\n * else return progresses[fileHandle];\n * }\n * }\n */\n resolveProgress?: (v: ImportFileHandle | undefined) => ImportProgress | undefined;\n };\n}>();\n\nconst extensions = computed(() => props.params.extensions);\n\n// extracting cell value and casting it to the type we expect\nconst handle = computed(() => props.params.value as ImportFileHandle | undefined);\n\n/**\n * When value changes in the file input this method forward the value to the ag-grid,\n * which in tern forwards in to the valueSetter in corresponding column.\n * */\nfunction onHandleUpdate(newHandle: ImportFileHandle | undefined) {\n props.params.setValue!(newHandle);\n}\n\nconst currentProgress = computed(() => {\n return props.params.resolveProgress ? props.params.resolveProgress(handle.value) : undefined;\n});\n</script>\n\n<template>\n <div style=\"height: 100%\">\n <PlFileInput\n show-filename-only\n clearable\n cell-style\n file-dialog-title=\"Select any file\"\n :placeholder=\"`Choose file ${extensions ? extensions[0] : ''}`\"\n :extensions=\"extensions\"\n :model-value=\"handle\"\n :progress=\"currentProgress\"\n @update:model-value=\"onHandleUpdate\"\n />\n </div>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAgCellFile.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAgCellFile/PlAgCellFile.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlFileInput } from \"@milaboratories/uikit\";\nimport type { ICellRendererParams } from \"ag-grid-enterprise\";\nimport type { ImportFileHandle, ImportProgress } from \"@platforma-sdk/model\";\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n // this component is intended to be used in ag-grid, params are the main object\n // to communicate with the corresponding cell data\n params: ICellRendererParams<unknown, ImportFileHandle> & {\n extensions?: string[];\n progress?: ImportProgress;\n /**\n * The resolveProgress function is an optional input parameter for the component\n * that allows tracking the file upload progress in real-time.\n * By passing resolveProgress, you can ensure that the component\n * displays accurate progress values for each file as they upload.\n * How to use it in AgGrid\n * cellRendererParams: {\n * resolveProgress: (fileHandle: ImportFileHandle | undefined) => {\n * const progresses = app.progresses;\n * if (!fileHandle) return undefined;\n * else return progresses[fileHandle];\n * }\n * }\n */\n resolveProgress?: (v: ImportFileHandle | undefined) => ImportProgress | undefined;\n };\n}>();\n\nconst extensions = computed(() => props.params.extensions);\n\n// extracting cell value and casting it to the type we expect\nconst handle = computed(() => props.params.value as ImportFileHandle | undefined);\n\n/**\n * When value changes in the file input this method forward the value to the ag-grid,\n * which in tern forwards in to the valueSetter in corresponding column.\n * */\nfunction onHandleUpdate(newHandle: ImportFileHandle | undefined) {\n props.params.setValue!(newHandle);\n}\n\nconst currentProgress = computed(() => {\n return props.params.resolveProgress ? props.params.resolveProgress(handle.value) : undefined;\n});\n</script>\n\n<template>\n <div data-testid=\"pl-ag-cell-file\" style=\"height: 100%\">\n <PlFileInput\n data-testid=\"pl-ag-cell-file-input\"\n show-filename-only\n clearable\n cell-style\n file-dialog-title=\"Select any file\"\n :placeholder=\"`Choose file ${extensions ? extensions[0] : ''}`\"\n :extensions=\"extensions\"\n :model-value=\"handle\"\n :progress=\"currentProgress\"\n @update:model-value=\"onHandleUpdate\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;EAMA,IAAM,IAAQ,GAwBR,IAAa,QAAe,EAAM,OAAO,WAAW,EAGpD,IAAS,QAAe,EAAM,OAAO,MAAsC;EAMjF,SAAS,EAAe,GAAyC;AAC/D,KAAM,OAAO,SAAU,EAAU;;EAGnC,IAAM,IAAkB,QACf,EAAM,OAAO,kBAAkB,EAAM,OAAO,gBAAgB,EAAO,MAAM,GAAG,KAAA,EACnF;yBAIA,EAaM,OAbN,GAaM,CAZJ,EAWE,EAAA,EAAA,EAAA;GAVA,eAAY;GACZ,sBAAA;GACA,WAAA;GACA,cAAA;GACA,qBAAkB;GACjB,aAAW,eAAiB,EAAA,QAAa,EAAA,MAAU,KAAA;GACnD,YAAY,EAAA;GACZ,eAAa,EAAA;GACb,UAAU,EAAA;GACV,uBAAoB"}
|