@platforma-sdk/ui-vue 1.45.42 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +23 -39
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +22 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue.d.ts +27 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue.js +10 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue.js.map +1 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +302 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js.map +1 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue3.js +33 -0
- package/dist/components/PlAdvancedFilter/FilterEditor.vue3.js.map +1 -0
- package/dist/components/PlAdvancedFilter/OperandButton.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.vue3.js +9 -9
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts +29 -20
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +184 -146
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue3.js +13 -9
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue3.js.map +1 -1
- package/dist/components/PlAdvancedFilter/constants.d.ts +4 -4
- package/dist/components/PlAdvancedFilter/constants.js +26 -22
- package/dist/components/PlAdvancedFilter/constants.js.map +1 -1
- package/dist/components/PlAdvancedFilter/index.d.ts +4 -0
- package/dist/components/PlAdvancedFilter/index.js +9 -0
- package/dist/components/PlAdvancedFilter/index.js.map +1 -0
- package/dist/components/PlAdvancedFilter/types.d.ts +30 -34
- package/dist/components/PlAdvancedFilter/utils.d.ts +26 -0
- package/dist/components/PlAdvancedFilter/utils.js +32 -131
- package/dist/components/PlAdvancedFilter/utils.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js +43 -41
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue3.js +2 -2
- package/dist/components/PlAnnotations/components/FilterSidebar.vue.d.ts +10 -2
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +98 -91
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.vue3.js +5 -5
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js +23 -23
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue3.js +5 -7
- package/dist/components/PlAnnotations/components/PlAnnotations.vue3.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js +19 -17
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue3.js +7 -9
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue3.js.map +1 -1
- package/dist/components/PlAnnotations/components/style.module.css.js +13 -0
- package/dist/components/PlAnnotations/components/style.module.css.js.map +1 -0
- package/dist/components/PlAnnotations/index.d.ts +1 -0
- package/dist/index.js +35 -33
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
- package/src/components/PlAdvancedFilter/{SingleFilter.vue → FilterEditor.vue} +58 -62
- package/src/components/PlAdvancedFilter/OperandButton.vue +1 -1
- package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +152 -60
- package/src/components/PlAdvancedFilter/constants.ts +17 -11
- package/src/components/PlAdvancedFilter/index.ts +6 -0
- package/src/components/PlAdvancedFilter/types.ts +23 -54
- package/src/components/PlAdvancedFilter/utils.ts +51 -163
- package/src/components/PlAnnotations/components/AnnotationsSidebar.vue +8 -8
- package/src/components/PlAnnotations/components/FilterSidebar.vue +60 -69
- package/src/components/PlAnnotations/components/PlAnnotations.vue +3 -7
- package/src/components/PlAnnotations/components/PlAnnotationsModal.vue +4 -8
- package/src/components/PlAnnotations/components/style.module.css +16 -0
- package/src/components/PlAnnotations/index.ts +2 -0
- package/dist/components/PlAdvancedFilter/SingleFilter.vue.d.ts +0 -37
- package/dist/components/PlAdvancedFilter/SingleFilter.vue.js +0 -10
- package/dist/components/PlAdvancedFilter/SingleFilter.vue.js.map +0 -1
- package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js +0 -306
- package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js.map +0 -1
- package/dist/components/PlAdvancedFilter/SingleFilter.vue3.js +0 -35
- package/dist/components/PlAdvancedFilter/SingleFilter.vue3.js.map +0 -1
- package/dist/components/PlAdvancedFilter/types.js +0 -8
- package/dist/components/PlAdvancedFilter/types.js.map +0 -1
- package/dist/components/PlAnnotations/components/DynamicForm.vue.d.ts +0 -24
- package/dist/components/PlAnnotations/components/DynamicForm.vue.js +0 -10
- package/dist/components/PlAnnotations/components/DynamicForm.vue.js.map +0 -1
- package/dist/components/PlAnnotations/components/DynamicForm.vue2.js +0 -109
- package/dist/components/PlAnnotations/components/DynamicForm.vue2.js.map +0 -1
- package/dist/components/PlAnnotations/components/DynamicForm.vue3.js +0 -9
- package/dist/components/PlAnnotations/components/DynamicForm.vue3.js.map +0 -1
- package/dist/components/PlAnnotations/utils.js +0 -20
- package/dist/components/PlAnnotations/utils.js.map +0 -1
|
@@ -1,59 +1,128 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import
|
|
3
|
-
import { PlBtnSecondary, PlElementList, PlCheckbox, PlIcon16 } from '@milaboratories/uikit';
|
|
4
|
-
import type { PlAdvancedFilterColumnId, CommonFilterSpec, Group, PlAdvancedFilterUI, SourceOptionInfo } from './types';
|
|
5
|
-
import { computed } from 'vue';
|
|
6
|
-
import OperandButton from './OperandButton.vue';
|
|
7
|
-
import { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS } from './constants';
|
|
2
|
+
import { PlBtnSecondary, PlCheckbox, PlElementList } from '@milaboratories/uikit';
|
|
8
3
|
import type { ListOptionBase } from '@platforma-sdk/model';
|
|
9
|
-
import {
|
|
4
|
+
import { computed, toRaw } from 'vue';
|
|
5
|
+
import FilterEditor from './FilterEditor.vue';
|
|
6
|
+
import OperandButton from './OperandButton.vue';
|
|
7
|
+
import { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS, SUPPORTED_FILTER_TYPES } from './constants';
|
|
8
|
+
import type { CommonFilter, EditableFilter, NodeFilter, PlAdvancedFilterColumnId, RootFilter, SourceOptionInfo } from './types';
|
|
9
|
+
import { createNewGroup, getNewId, isValidColumnId } from './utils';
|
|
10
|
+
|
|
11
|
+
const model = defineModel<RootFilter>('filters', { required: true });
|
|
10
12
|
|
|
11
13
|
const props = withDefaults(defineProps<{
|
|
12
14
|
/** List of ids of sources (columns, axes) that can be selected in filters */
|
|
13
15
|
items: SourceOptionInfo[];
|
|
16
|
+
/** List of supported filter types */
|
|
17
|
+
supportedFilters?: typeof SUPPORTED_FILTER_TYPES;
|
|
14
18
|
/** If true - new filter can be added by droppind element into filter group; else new column is added by button click */
|
|
15
19
|
enableDnd?: boolean;
|
|
20
|
+
/** If true - "Add group" button is shown below the filter groups */
|
|
21
|
+
enableAddGroupButton?: boolean;
|
|
16
22
|
/** Loading function for unique values for Equal/InSet filters and fixed axes options. */
|
|
17
|
-
getSuggestOptions: (params: { columnId: PlAdvancedFilterColumnId; searchStr: string;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}>(), { enableDnd: false });
|
|
23
|
+
getSuggestOptions: (params: { columnId: PlAdvancedFilterColumnId; axisIdx?: number; searchStr: string; searchType: 'value' | 'label' }) =>
|
|
24
|
+
ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;
|
|
25
|
+
}>(), {
|
|
26
|
+
supportedFilters: () => SUPPORTED_FILTER_TYPES,
|
|
27
|
+
getSuggestModel: undefined,
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
enableDnd: false,
|
|
30
|
+
enableAddGroupButton: false,
|
|
31
|
+
});
|
|
26
32
|
|
|
27
33
|
const firstColumnId = computed(() => props.items[0]?.id);
|
|
28
|
-
const emptyGroup:
|
|
29
|
-
id:
|
|
30
|
-
|
|
31
|
-
operand: 'and',
|
|
34
|
+
const emptyGroup: NodeFilter[] = [{
|
|
35
|
+
id: -1,
|
|
36
|
+
type: 'and',
|
|
32
37
|
filters: [],
|
|
33
|
-
|
|
38
|
+
isExpanded: true,
|
|
34
39
|
}];
|
|
35
40
|
|
|
41
|
+
function getRootGroups() {
|
|
42
|
+
if (model.value.type !== 'or' && model.value.type !== 'and') {
|
|
43
|
+
throw new Error('Invalid model structure, expected root to be "or" or "and" group');
|
|
44
|
+
}
|
|
45
|
+
return model.value.filters;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getRootGroup(idx: number): NodeFilter {
|
|
49
|
+
const groups = getRootGroups();
|
|
50
|
+
const group = groups[idx];
|
|
51
|
+
if (group.type !== 'and' && group.type !== 'or' && group.type !== 'not') {
|
|
52
|
+
throw new Error('Invalid group structure, expected "and", "or" or "not" group');
|
|
53
|
+
}
|
|
54
|
+
return group;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getRootGroupContent(idx: number): Exclude<NodeFilter, { type: 'not' }> {
|
|
58
|
+
const group = getRootGroup(idx);
|
|
59
|
+
|
|
60
|
+
if (group.type !== 'not') {
|
|
61
|
+
return group;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (group.filter.type !== 'and' && group.filter.type !== 'or') {
|
|
65
|
+
throw new Error('Invalid group structure, expected "and" or "or" group inside "not"');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return group.filter;
|
|
69
|
+
}
|
|
70
|
+
|
|
36
71
|
function addColumnToGroup(groupIdx: number, selectedSourceId: PlAdvancedFilterColumnId) {
|
|
37
|
-
|
|
72
|
+
const group = getRootGroupContent(groupIdx);
|
|
73
|
+
|
|
74
|
+
group.filters.push({
|
|
38
75
|
...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],
|
|
39
76
|
column: selectedSourceId,
|
|
40
|
-
|
|
77
|
+
id: getNewId(),
|
|
78
|
+
isExpanded: true,
|
|
79
|
+
} as CommonFilter);
|
|
41
80
|
}
|
|
42
81
|
|
|
43
82
|
function removeFilterFromGroup(groupIdx: number, filterIdx: number) {
|
|
44
|
-
|
|
83
|
+
const group = getRootGroupContent(groupIdx);
|
|
84
|
+
|
|
85
|
+
if (group.filters.length === 1 && filterIdx === 0) {
|
|
45
86
|
removeGroup(groupIdx);
|
|
46
87
|
} else {
|
|
47
|
-
|
|
88
|
+
group.filters.splice(filterIdx, 1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function inverseRootNode(groupIdx: number) {
|
|
92
|
+
const groups = getRootGroups();
|
|
93
|
+
const group = groups[groupIdx];
|
|
94
|
+
if (group.type === 'not') {
|
|
95
|
+
if (group.filter.type !== 'and' && group.filter.type !== 'or') {
|
|
96
|
+
throw new Error('Invalid group structure, expected "and" or "or" group inside "not"');
|
|
97
|
+
}
|
|
98
|
+
groups[groupIdx] = group.filter;
|
|
99
|
+
} else {
|
|
100
|
+
const type = groups[groupIdx].type;
|
|
101
|
+
if (type !== 'and' && type !== 'or' && type !== 'not') {
|
|
102
|
+
throw new Error('Invalid group structure, expected "and", "or" or "not" group');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
groups[groupIdx] = {
|
|
106
|
+
id: getNewId(),
|
|
107
|
+
isExpanded: true,
|
|
108
|
+
type: 'not',
|
|
109
|
+
filter: groups[groupIdx],
|
|
110
|
+
};
|
|
48
111
|
}
|
|
49
112
|
}
|
|
50
113
|
|
|
114
|
+
function getNotContent<T extends CommonFilter>(item: T): Exclude<T, { type: 'not' }> {
|
|
115
|
+
return item.type === 'not' ? item.filter as Exclude<T, { type: 'not' }> : item as Exclude<T, { type: 'not' }>;
|
|
116
|
+
}
|
|
117
|
+
|
|
51
118
|
function removeGroup(groupIdx: number) {
|
|
52
|
-
|
|
119
|
+
const groups = getRootGroups();
|
|
120
|
+
groups.splice(groupIdx, 1);
|
|
53
121
|
}
|
|
54
122
|
function addGroup(selectedSourceId: PlAdvancedFilterColumnId) {
|
|
55
123
|
const newGroup = createNewGroup(selectedSourceId);
|
|
56
|
-
|
|
124
|
+
const groups = getRootGroups();
|
|
125
|
+
groups.push(newGroup);
|
|
57
126
|
}
|
|
58
127
|
|
|
59
128
|
function handleDropToExistingGroup(groupIdx: number, event: DragEvent) {
|
|
@@ -77,70 +146,85 @@ function handleDropToNewGroup(event: DragEvent) {
|
|
|
77
146
|
function dragOver(event: DragEvent) {
|
|
78
147
|
event.preventDefault();
|
|
79
148
|
}
|
|
149
|
+
|
|
150
|
+
function validateFilter<T extends CommonFilter>(item: T): EditableFilter {
|
|
151
|
+
if (item.type === 'and' || item.type === 'or' || item.type === 'not') {
|
|
152
|
+
throw new Error('Invalid filter structure, expected leaf filter');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return item as EditableFilter;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function updateFilter(filters: CommonFilter[], idx: number, updatedFilter: EditableFilter) {
|
|
159
|
+
filters[idx] = toRaw(updatedFilter as CommonFilter);
|
|
160
|
+
}
|
|
80
161
|
</script>
|
|
81
162
|
<template>
|
|
82
163
|
<div>
|
|
83
164
|
<PlElementList
|
|
84
|
-
v-model:items="
|
|
85
|
-
:get-item-key="(
|
|
165
|
+
v-model:items="model.filters"
|
|
166
|
+
:get-item-key="(filter) => filter.id"
|
|
86
167
|
|
|
87
168
|
:item-class="$style.filterGroup"
|
|
88
169
|
:item-class-content="$style.filterGroupContent"
|
|
89
170
|
:item-class-title="$style.filterGroupTitle"
|
|
90
171
|
|
|
91
|
-
:is-expanded="(
|
|
172
|
+
:is-expanded="(filter) => filter.isExpanded === true"
|
|
173
|
+
:on-expand="(group) => { group.isExpanded = !group.isExpanded}"
|
|
92
174
|
|
|
93
175
|
:disableDragging="false"
|
|
94
176
|
:disableRemoving="false"
|
|
95
177
|
:disableToggling="true"
|
|
96
178
|
:disablePinning="true"
|
|
97
|
-
|
|
98
|
-
:on-expand="(group) => { group.expanded = !group.expanded}"
|
|
99
179
|
>
|
|
100
180
|
<template #item-title>
|
|
101
181
|
Filter group
|
|
102
182
|
</template>
|
|
103
183
|
<template #item-content="{ item, index }">
|
|
104
184
|
<div
|
|
105
|
-
:class="$style.groupContent"
|
|
185
|
+
:class="$style.groupContent"
|
|
186
|
+
dropzone="true"
|
|
106
187
|
@drop="(event) => handleDropToExistingGroup(index, event)"
|
|
107
188
|
@dragover="dragOver"
|
|
108
189
|
>
|
|
109
|
-
<PlCheckbox
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
190
|
+
<PlCheckbox :model-value="item.type === 'not'" :class="$style.notCheckbox" @update:model-value="inverseRootNode(index)">NOT</PlCheckbox>
|
|
191
|
+
<template v-for="(_, filterIdx) in getNotContent(item).filters" :key="filterIdx">
|
|
192
|
+
<FilterEditor
|
|
193
|
+
:filter="validateFilter(getNotContent(item).filters[filterIdx])"
|
|
194
|
+
:operand="getNotContent(item).type"
|
|
195
|
+
:column-options="items"
|
|
196
|
+
:supported-filters="props.supportedFilters"
|
|
197
|
+
:get-suggest-options="props.getSuggestOptions"
|
|
198
|
+
:enable-dnd="Boolean(props.enableDnd)"
|
|
199
|
+
:is-last="filterIdx === getNotContent(item).filters.length - 1"
|
|
200
|
+
:on-change-operand="(v) => getNotContent(item).type = v"
|
|
201
|
+
:on-delete="() => removeFilterFromGroup(index, filterIdx)"
|
|
202
|
+
@update:filter="(value) => updateFilter(getNotContent(item).filters, filterIdx, value)"
|
|
203
|
+
/>
|
|
204
|
+
</template>
|
|
205
|
+
<div v-if="props.enableDnd" :class="$style.dropzone">
|
|
124
206
|
<div>Drop dimensions here</div>
|
|
125
207
|
</div>
|
|
126
|
-
<PlBtnSecondary v-else @click="addColumnToGroup(index, firstColumnId)">
|
|
127
|
-
|
|
208
|
+
<PlBtnSecondary v-else icon="add" @click="addColumnToGroup(index, firstColumnId)">
|
|
209
|
+
Add filter
|
|
128
210
|
</PlBtnSecondary>
|
|
129
211
|
</div>
|
|
130
212
|
</template>
|
|
131
213
|
<template #item-after="{ index }">
|
|
132
214
|
<OperandButton
|
|
215
|
+
v-if="props.enableAddGroupButton || index < getRootGroups().length - 1"
|
|
133
216
|
:class="$style.buttonWrapper"
|
|
134
|
-
:active="
|
|
135
|
-
:disabled="index ===
|
|
136
|
-
:on-select="(v) =>
|
|
217
|
+
:active="model.type"
|
|
218
|
+
:disabled="index === getRootGroups().length - 1"
|
|
219
|
+
:on-select="(v) => model.type = v"
|
|
137
220
|
/>
|
|
138
221
|
</template>
|
|
139
222
|
</PlElementList>
|
|
140
223
|
|
|
141
|
-
<!-- Last group - always
|
|
224
|
+
<!-- Last group - always empty, just for adding new groups -->
|
|
142
225
|
<PlElementList
|
|
143
|
-
v-
|
|
226
|
+
v-if="props.enableAddGroupButton"
|
|
227
|
+
:items="emptyGroup"
|
|
144
228
|
:get-item-key="(group) => group.id"
|
|
145
229
|
:item-class="$style.filterGroup"
|
|
146
230
|
:item-class-content="$style.filterGroupContent"
|
|
@@ -157,14 +241,15 @@ function dragOver(event: DragEvent) {
|
|
|
157
241
|
@dragover="dragOver"
|
|
158
242
|
>
|
|
159
243
|
<template #item-title>Filter group</template>
|
|
160
|
-
<template #item-content
|
|
161
|
-
<PlCheckbox v-model="item.not" disabled >NOT</PlCheckbox>
|
|
244
|
+
<template #item-content>
|
|
162
245
|
<div v-if="enableDnd" :class="$style.dropzone">
|
|
163
246
|
<div>Drop dimensions here</div>
|
|
164
247
|
</div>
|
|
165
|
-
<
|
|
166
|
-
<
|
|
167
|
-
|
|
248
|
+
<slot v-else name="add-group-buttons">
|
|
249
|
+
<PlBtnSecondary icon="add" @click="addGroup(firstColumnId)">
|
|
250
|
+
Add filter
|
|
251
|
+
</PlBtnSecondary>
|
|
252
|
+
</slot>
|
|
168
253
|
</template>
|
|
169
254
|
</PlElementList>
|
|
170
255
|
</div>
|
|
@@ -179,11 +264,17 @@ function dragOver(event: DragEvent) {
|
|
|
179
264
|
.filterGroupTitle {
|
|
180
265
|
background: none;
|
|
181
266
|
}
|
|
267
|
+
.filterGroupContent {
|
|
268
|
+
padding: 4px 24px 24px 24px;
|
|
269
|
+
}
|
|
182
270
|
.groupContent {
|
|
183
271
|
display: flex;
|
|
184
272
|
flex-direction: column;
|
|
185
273
|
gap: 12px;
|
|
186
274
|
}
|
|
275
|
+
.notCheckbox {
|
|
276
|
+
margin: 4px 0;
|
|
277
|
+
}
|
|
187
278
|
.dropzone {
|
|
188
279
|
border-radius: 6px;
|
|
189
280
|
border: 1.5px dashed var(--color-div-grey);
|
|
@@ -199,7 +290,8 @@ function dragOver(event: DragEvent) {
|
|
|
199
290
|
align-items: center;
|
|
200
291
|
}
|
|
201
292
|
.buttonWrapper {
|
|
202
|
-
|
|
293
|
+
margin-top: 8px;
|
|
294
|
+
height: 56px;
|
|
203
295
|
display: flex;
|
|
204
296
|
align-items: center;
|
|
205
297
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FilterSpecType } from '@platforma-sdk/model';
|
|
2
|
+
import type { EditableFilter, PlAdvancedFilterColumnId, SupportedFilterTypes } from './types';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
// List of ALL supported filter types in Advanced Filter component
|
|
5
|
+
export const SUPPORTED_FILTER_TYPES = [
|
|
4
6
|
'isNA',
|
|
5
7
|
'isNotNA',
|
|
6
8
|
'greaterThan',
|
|
@@ -17,26 +19,30 @@ export const SUPPORTED_FILTER_TYPES = new Set<SupportedFilterTypes>([
|
|
|
17
19
|
'patternMatchesRegularExpression',
|
|
18
20
|
'inSet',
|
|
19
21
|
'notInSet',
|
|
20
|
-
|
|
22
|
+
'topN',
|
|
23
|
+
'bottomN',
|
|
24
|
+
] satisfies FilterSpecType[];
|
|
21
25
|
|
|
22
|
-
export const DEFAULT_FILTER_TYPE:
|
|
26
|
+
export const DEFAULT_FILTER_TYPE: SupportedFilterTypes = 'isNA';
|
|
23
27
|
|
|
24
28
|
const emptyCommonPart = { column: '' as PlAdvancedFilterColumnId };
|
|
25
|
-
export const DEFAULT_FILTERS: Record<SupportedFilterTypes,
|
|
29
|
+
export const DEFAULT_FILTERS: Record<SupportedFilterTypes, EditableFilter> = {
|
|
26
30
|
isNA: { type: 'isNA', ...emptyCommonPart },
|
|
27
31
|
isNotNA: { type: 'isNotNA', ...emptyCommonPart },
|
|
28
|
-
lessThan: { type: 'lessThan', x:
|
|
29
|
-
lessThanOrEqual: { type: 'lessThanOrEqual', x:
|
|
32
|
+
lessThan: { type: 'lessThan', x: 0, ...emptyCommonPart },
|
|
33
|
+
lessThanOrEqual: { type: 'lessThanOrEqual', x: 0, ...emptyCommonPart },
|
|
30
34
|
patternEquals: { type: 'patternEquals', value: undefined, ...emptyCommonPart },
|
|
31
35
|
patternNotEquals: { type: 'patternNotEquals', value: undefined, ...emptyCommonPart },
|
|
32
|
-
greaterThan: { type: 'greaterThan', x:
|
|
33
|
-
greaterThanOrEqual: { type: 'greaterThanOrEqual', x:
|
|
36
|
+
greaterThan: { type: 'greaterThan', x: 0, ...emptyCommonPart },
|
|
37
|
+
greaterThanOrEqual: { type: 'greaterThanOrEqual', x: 0, ...emptyCommonPart },
|
|
34
38
|
patternContainSubsequence: { type: 'patternContainSubsequence', value: '', ...emptyCommonPart },
|
|
35
39
|
patternNotContainSubsequence: { type: 'patternNotContainSubsequence', value: '', ...emptyCommonPart },
|
|
36
40
|
patternFuzzyContainSubsequence: { type: 'patternFuzzyContainSubsequence', maxEdits: 2, substitutionsOnly: false, wildcard: undefined, value: '', ...emptyCommonPart },
|
|
37
41
|
patternMatchesRegularExpression: { type: 'patternMatchesRegularExpression', value: '', ...emptyCommonPart },
|
|
38
|
-
equal: { type: 'equal', x:
|
|
39
|
-
notEqual: { type: 'notEqual', x:
|
|
42
|
+
equal: { type: 'equal', x: 0, ...emptyCommonPart },
|
|
43
|
+
notEqual: { type: 'notEqual', x: 0, ...emptyCommonPart },
|
|
40
44
|
inSet: { type: 'inSet', value: [], ...emptyCommonPart },
|
|
41
45
|
notInSet: { type: 'notInSet', value: [], ...emptyCommonPart },
|
|
46
|
+
topN: { type: 'topN', n: 10, ...emptyCommonPart },
|
|
47
|
+
bottomN: { type: 'bottomN', n: 10, ...emptyCommonPart },
|
|
42
48
|
};
|
|
@@ -1 +1,7 @@
|
|
|
1
|
+
import { SUPPORTED_FILTER_TYPES } from './constants.ts';
|
|
2
|
+
import type { RootFilter, SourceOptionInfo } from './types.ts';
|
|
3
|
+
|
|
1
4
|
export { default as PlAdvancedFilter } from './PlAdvancedFilter.vue';
|
|
5
|
+
export const PlAdvancedFilterSupportedFilters = SUPPORTED_FILTER_TYPES;
|
|
6
|
+
export type PlAdvancedFilterItem = SourceOptionInfo;
|
|
7
|
+
export type PlAdvancedFilterFilter = RootFilter;
|
|
@@ -1,67 +1,36 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { SUPPORTED_FILTER_TYPES } from './constants';
|
|
3
|
-
import type { CanonicalizedJson } from '@platforma-sdk/model';
|
|
4
|
-
import type { AxisId } from '@platforma-sdk/model';
|
|
1
|
+
import type { AxisId, AxisSpec, CanonicalizedJson, FilterSpec, FilterSpecLeaf, PColumnSpec, SUniversalPColumnId } from '@platforma-sdk/model';
|
|
2
|
+
import type { SUPPORTED_FILTER_TYPES } from './constants';
|
|
5
3
|
|
|
6
|
-
export type
|
|
7
|
-
export type CommonFilterSpec = FilterSpec<FilterSpecLeaf<PlAdvancedFilterColumnId>, { expanded?: boolean }>;
|
|
8
|
-
|
|
9
|
-
// Not supported: topN, bottomN, lessThanColumn, lessThanColumnOrEqual
|
|
10
|
-
// or, and, not - in groups
|
|
11
|
-
export type SupportedFilterTypes = FilterSpecType &
|
|
12
|
-
'isNA' | 'isNotNA' |
|
|
13
|
-
'patternEquals' | 'patternNotEquals' |
|
|
14
|
-
'patternContainSubsequence' | 'patternNotContainSubsequence' |
|
|
15
|
-
'patternMatchesRegularExpression' |
|
|
16
|
-
'patternFuzzyContainSubsequence' |
|
|
17
|
-
'inSet' | 'notInSet' |
|
|
18
|
-
'equal' | 'notEqual' |
|
|
19
|
-
'lessThan' | 'lessThanOrEqual' |
|
|
20
|
-
'greaterThan' | 'greaterThanOrEqual';
|
|
21
|
-
|
|
22
|
-
export type FilterType = SupportedFilterTypes;
|
|
4
|
+
export type Operand = 'or' | 'and';
|
|
23
5
|
|
|
24
|
-
export
|
|
25
|
-
if (!type) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
return SUPPORTED_FILTER_TYPES.has(type as SupportedFilterTypes);
|
|
29
|
-
}
|
|
6
|
+
export type PlAdvancedFilterColumnId = SUniversalPColumnId | CanonicalizedJson<AxisId>;
|
|
30
7
|
|
|
31
|
-
export type
|
|
8
|
+
export type FilterLeafContent = Extract<FilterSpecLeaf<PlAdvancedFilterColumnId>, { type: SupportedFilterTypes }>;
|
|
9
|
+
export type CommonFilter = FilterSpec<FilterLeafContent, { id: number; isExpanded?: boolean }>;
|
|
10
|
+
export type FilterLeaf = Exclude<CommonFilter, { type: Operand | 'not' }>;
|
|
11
|
+
export type NodeFilter = Extract<CommonFilter, { type: Operand | 'not' }>;
|
|
12
|
+
export type RootFilter = Omit<Extract<NodeFilter, { type: Operand }>, 'filters'> & { filters: NodeFilter[] };
|
|
32
13
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
14
|
+
// Not supported: less(/greater)ThanColumn, less(/greater)ThanColumnOrEqual
|
|
15
|
+
// or, and, not - in groups
|
|
16
|
+
export type SupportedFilterTypes = typeof SUPPORTED_FILTER_TYPES[number];
|
|
37
17
|
|
|
38
18
|
type RequireFields<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
39
19
|
type OptionalFields<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
40
20
|
|
|
21
|
+
type NumericalWithOptionalN = 'topN' | 'bottomN';
|
|
41
22
|
type NumericalWithOptionalX = 'lessThan' | 'lessThanOrEqual' | 'greaterThan' | 'greaterThanOrEqual' | 'equal' | 'notEqual';
|
|
42
23
|
type StringWithOptionalValue = 'patternEquals' | 'patternNotEquals';
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
24
|
+
// types from ui with some changed by optionality fields
|
|
25
|
+
type EditedTypes = 'patternFuzzyContainSubsequence' | NumericalWithOptionalX | StringWithOptionalValue | NumericalWithOptionalN;
|
|
26
|
+
export type EditableFilter =
|
|
27
|
+
| Exclude<FilterLeafContent, { type: EditedTypes }>
|
|
28
|
+
| RequireFields<Extract<FilterLeafContent, { type: 'patternFuzzyContainSubsequence' }>, 'maxEdits' | 'substitutionsOnly'>
|
|
29
|
+
| OptionalFields<Extract<FilterLeafContent, { type: NumericalWithOptionalN }>, 'n'>
|
|
30
|
+
| OptionalFields<Extract<FilterLeafContent, { type: NumericalWithOptionalX }>, 'x'>
|
|
31
|
+
| OptionalFields<Extract<FilterLeafContent, { type: StringWithOptionalValue }>, 'value'>
|
|
48
32
|
;
|
|
49
33
|
|
|
50
|
-
export type Group = {
|
|
51
|
-
id: string;
|
|
52
|
-
not: boolean;
|
|
53
|
-
filters: Filter[];
|
|
54
|
-
operand: Operand;
|
|
55
|
-
expanded: boolean;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export type PlAdvancedFilterUI = {
|
|
59
|
-
groups: Group[];
|
|
60
|
-
operand: Operand;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export type UniqueValuesList = ListOptionBase<string | number>[];
|
|
64
|
-
export type OptionInfo = { error: boolean; label: string; spec: PColumnSpec | AxisSpec };
|
|
65
34
|
export type FixedAxisInfo = {
|
|
66
35
|
idx: number;
|
|
67
36
|
label: string;
|
|
@@ -70,8 +39,8 @@ export type FixedAxisInfo = {
|
|
|
70
39
|
export type SourceOptionInfo = {
|
|
71
40
|
id: PlAdvancedFilterColumnId;
|
|
72
41
|
label: string;
|
|
73
|
-
error: boolean;
|
|
74
42
|
spec: PColumnSpec | AxisSpec;
|
|
75
|
-
|
|
43
|
+
error?: boolean;
|
|
76
44
|
alphabet?: 'nucleotide' | 'aminoacid' | string;
|
|
45
|
+
axesToBeFixed?: FixedAxisInfo[];
|
|
77
46
|
};
|