@webitel/ui-datalist 26.8.7 → 26.8.8
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/package.json +1 -1
- package/src/modules/filter-presets/components/apply-preset/apply-preset-action.vue +16 -4
- package/src/modules/filter-presets/components/save-preset/save-preset-action.vue +18 -4
- package/src/modules/filters/components/column/column-filter-preview.vue +70 -0
- package/src/modules/filters/components/column/column-filter.vue +76 -0
- package/src/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-value-input.vue +2 -0
- package/src/modules/filters/components/config/dynamic-view/dynamic-filter-config-form.vue +43 -5
- package/src/modules/filters/components/config/static-view/static-filter-field.vue +6 -21
- package/src/modules/filters/components/filters-actions-menu.vue +177 -0
- package/src/modules/filters/components/preview/dynamic-filter-preview.vue +5 -60
- package/src/modules/filters/components/table-filters-panel.vue +6 -28
- package/src/modules/filters/components/types/Filter.types.ts +5 -0
- package/src/modules/filters/composables/useColumnFilter.ts +116 -0
- package/src/modules/filters/composables/useFilterValueChange.ts +58 -0
- package/src/modules/filters/composables/useFilterValuePreview.ts +87 -0
- package/src/modules/filters/composables/useSelectedFilters.ts +64 -0
- package/src/modules/filters/index.ts +4 -0
- package/src/modules/filters/modules/filterConfig/components/_custom/type-extension-filter-value-field.vue +9 -5
- package/src/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-options/date-time-options-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/durations/duration-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/string-filter/string-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/agent/agent-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/amd-result/amd-result-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/call-direction/call-direction-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-assignee/case-assignee-filter-value-field.vue +4 -4
- package/src/modules/filters/modules/filterConfig/components/case-author/case-author-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-close-reason-groups/case-close-reason-groups-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/case-impacted/case-impacted-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-priority/case-priority-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-reporter/case-reporter-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-service/case-service-filter-value-field.vue +1 -32
- package/src/modules/filters/modules/filterConfig/components/case-sla/case-sla-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-sla-condition/case-sla-condition-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/case-source/case-source-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-status/case-status-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/contact/contact-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/contact-owner/contact-owner-filter-value-field.vue +3 -3
- package/src/modules/filters/modules/filterConfig/components/gateway/gateway-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/grantee/grantee-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/hangup-cause/hangup-cause-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/has-attachment/has-attachment-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/rated-by/rated-by-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/rating/rating-from-to-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/score/score-from-to-filter-value-field.vue +4 -4
- package/src/modules/filters/modules/filterConfig/components/tag/tag-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/user/user-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/variable/variable-filter-value-field.vue +6 -3
- package/src/modules/table/createTableStore.store.ts +24 -3
- package/src/modules/types/tableStore.types.ts +21 -2
- package/types/.tsbuildinfo +1 -1
- package/types/modules/filter-presets/components/apply-preset/apply-preset-action.vue.d.ts +15 -1
- package/types/modules/filter-presets/components/save-preset/save-preset-action.vue.d.ts +17 -1
- package/types/modules/filter-presets/stores/createFilterPresetsStore.d.ts +2 -35
- package/types/modules/filters/components/column/column-filter-preview.vue.d.ts +21 -0
- package/types/modules/filters/components/column/column-filter.vue.d.ts +36 -0
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-label.vue.d.ts +2 -2
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-value-input.vue.d.ts +3 -2
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form.vue.d.ts +13 -1
- package/types/modules/filters/components/config/static-view/static-filter-field.vue.d.ts +2 -2
- package/types/modules/filters/components/filters-actions-menu.vue.d.ts +29 -0
- package/types/modules/filters/components/table-filters-panel.vue.d.ts +6 -6
- package/types/modules/filters/components/types/Filter.types.d.ts +4 -0
- package/types/modules/filters/composables/useColumnFilter.d.ts +27 -0
- package/types/modules/filters/composables/useFilterValueChange.d.ts +23 -0
- package/types/modules/filters/composables/useFilterValuePreview.d.ts +21 -0
- package/types/modules/filters/composables/useSelectedFilters.d.ts +22 -0
- package/types/modules/filters/index.d.ts +3 -1
- package/types/modules/filters/modules/filterConfig/components/_custom/type-extension-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-options/date-time-options-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/durations/duration-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/string-filter/string-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/agent/agent-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/agent-status/agent-status-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/amd-result/amd-result-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/auditor/auditor-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/auditor/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/bucket/bucket-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/bucket/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/call-direction/call-direction-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/call-reporting-result/call-reporting-result-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/case-assignee/case-assignee-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/case-assignee/filterConfig.d.ts +4 -2
- package/types/modules/filters/modules/filterConfig/components/case-author/case-author-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-close-reason-groups/case-close-reason-groups-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-impacted/case-impacted-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-priority/case-priority-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-reporter/case-reporter-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-sla/case-sla-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-sla-condition/case-sla-condition-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-source/case-source-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-status/case-status-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/contact/contact-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/contact-group/contact-group-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-group/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-label/contact-label-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-label/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-owner/contact-owner-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/contact-owner/index.d.ts +4 -2
- package/types/modules/filters/modules/filterConfig/components/gateway/gateway-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/grantee/grantee-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/hangup-cause/hangup-cause-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/has-attachment/has-attachment-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/has-file/has-file-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-rating/has-rating-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-transcription/has-transcription-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-user/has-user-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/index.d.ts +24 -22
- package/types/modules/filters/modules/filterConfig/components/queue/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue/queue-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue-period/queue-period-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue-type/queue-type-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/rated-by/rated-by-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/rating/rating-from-to-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/region/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/region/region-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/score/score-from-to-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/skill/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/skill/skill-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/stop-cause/stop-cause-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/supervisor/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/supervisor/supervisor-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/tag/tag-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/tags/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/tags/tags-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/talk-duration/talk-duration-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/team/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/team/team-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/total-duration/total-duration-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/user/user-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/utilization-progress/utilization-progress-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/variable/variable-filter-value-field.vue.d.ts +8 -4
- package/types/modules/headers/createTableHeadersStore.d.ts +42 -18
- package/types/modules/permissions-page/stores/createPermissionsStore.d.ts +4 -70
- package/types/modules/table/createTableStore.store.d.ts +76 -141
- package/types/modules/types/tableStore.types.d.ts +20 -2
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="apply-preset-action">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
<slot
|
|
4
|
+
name="activator"
|
|
5
|
+
:open="() => (showPresetsList = true)"
|
|
6
|
+
>
|
|
7
|
+
<wt-icon-action
|
|
8
|
+
:action="IconAction.APPLY_PRESET"
|
|
9
|
+
@click="showPresetsList = true"
|
|
10
|
+
/>
|
|
11
|
+
</slot>
|
|
7
12
|
<wt-popup
|
|
8
13
|
:shown="showPresetsList"
|
|
9
14
|
size="md"
|
|
@@ -128,6 +133,13 @@ const { t } = useI18n();
|
|
|
128
133
|
|
|
129
134
|
const showPresetsList = ref(false);
|
|
130
135
|
|
|
136
|
+
/** lets a parent (e.g. filters actions menu) open the popup without the icon */
|
|
137
|
+
defineExpose({
|
|
138
|
+
open: () => {
|
|
139
|
+
showPresetsList.value = true;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
131
143
|
const { dataList, error, isLoading, filtersManager, presetId } = storeToRefs(
|
|
132
144
|
props.presetsStore,
|
|
133
145
|
);
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="save-preset-action">
|
|
3
|
-
<
|
|
4
|
-
|
|
3
|
+
<slot
|
|
4
|
+
name="activator"
|
|
5
|
+
:open="() => (showSaveForm = true)"
|
|
5
6
|
:disabled="disableAction"
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
>
|
|
8
|
+
<wt-icon-action
|
|
9
|
+
:action="IconAction.SAVE_PRESET"
|
|
10
|
+
:disabled="disableAction"
|
|
11
|
+
@click="showSaveForm = true"
|
|
12
|
+
/>
|
|
13
|
+
</slot>
|
|
8
14
|
|
|
9
15
|
<save-preset-popup
|
|
10
16
|
v-if="
|
|
@@ -100,6 +106,14 @@ const disableAction = computed(() => {
|
|
|
100
106
|
* */
|
|
101
107
|
const showSaveForm = ref(false);
|
|
102
108
|
|
|
109
|
+
/** lets a parent (e.g. filters actions menu) open the popup without the icon */
|
|
110
|
+
defineExpose({
|
|
111
|
+
open: () => {
|
|
112
|
+
showSaveForm.value = true;
|
|
113
|
+
},
|
|
114
|
+
disabled: disableAction,
|
|
115
|
+
});
|
|
116
|
+
|
|
103
117
|
/**
|
|
104
118
|
* if preset with the same name already exists, this will be suggested to set to that preset
|
|
105
119
|
*/
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<dynamic-filter-preview-info
|
|
3
|
+
v-if="filter"
|
|
4
|
+
class="column-filter-preview"
|
|
5
|
+
>
|
|
6
|
+
<template #header>
|
|
7
|
+
{{ filterConfig.label }}
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<template #default>
|
|
11
|
+
<wt-loader
|
|
12
|
+
v-if="!isRenderPreview"
|
|
13
|
+
:size="ComponentSize.SM"
|
|
14
|
+
/>
|
|
15
|
+
<component
|
|
16
|
+
v-else
|
|
17
|
+
:is="filterConfig.valuePreviewComponent"
|
|
18
|
+
:filter="filter"
|
|
19
|
+
:filter-config="filterConfig"
|
|
20
|
+
:value="localValue"
|
|
21
|
+
/>
|
|
22
|
+
</template>
|
|
23
|
+
</dynamic-filter-preview-info>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script lang="ts" setup>
|
|
27
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
28
|
+
import { WtLoader } from '@webitel/ui-sdk/components';
|
|
29
|
+
import { ComponentSize } from '@webitel/ui-sdk/enums';
|
|
30
|
+
|
|
31
|
+
import type { DatalistTableHeader } from '../../../types/tableStore.types';
|
|
32
|
+
import type { IFiltersManager } from '../../classes/FiltersManager';
|
|
33
|
+
import { useColumnFilter } from '../../composables/useColumnFilter';
|
|
34
|
+
import { useFilterValuePreview } from '../../composables/useFilterValuePreview';
|
|
35
|
+
import type { FilterConfigDefinition } from '../../modules/filterConfig/types/FilterConfigDefinition';
|
|
36
|
+
import DynamicFilterPreviewInfo from '../preview/dynamic-filter-preview-info.vue';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Hover preview of an applied column filter (`column-filter` slot, `formView: false`):
|
|
40
|
+
* the same "label + values" card the panel chip shows on hover.
|
|
41
|
+
*
|
|
42
|
+
* [WTEL-7727](https://webitel.atlassian.net/browse/WTEL-7727)
|
|
43
|
+
*/
|
|
44
|
+
const props = defineProps<{
|
|
45
|
+
header: DatalistTableHeader;
|
|
46
|
+
filtersManager: IFiltersManager;
|
|
47
|
+
/** the page's filter definitions; a configured one is reused for the matching header */
|
|
48
|
+
filterOptions?: FilterConfigDefinition[];
|
|
49
|
+
/** custom (type extension) fields the table can filter by; matched to the header by field id */
|
|
50
|
+
filterableExtensionFields?: DataField[];
|
|
51
|
+
}>();
|
|
52
|
+
|
|
53
|
+
const { filterConfig, filter } = useColumnFilter({
|
|
54
|
+
header: () => props.header,
|
|
55
|
+
filtersManager: () => props.filtersManager,
|
|
56
|
+
filterOptions: () => props.filterOptions ?? [],
|
|
57
|
+
filterableExtensionFields: () => props.filterableExtensionFields ?? [],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const { localValue, isRenderPreview } = useFilterValuePreview({
|
|
61
|
+
filter,
|
|
62
|
+
filterConfig,
|
|
63
|
+
});
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<style lang="scss" scoped>
|
|
67
|
+
.wt-loader {
|
|
68
|
+
margin: auto;
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<column-filter-preview
|
|
3
|
+
v-if="!formView"
|
|
4
|
+
:header="header"
|
|
5
|
+
:filters-manager="filtersManager"
|
|
6
|
+
:filter-options="filterOptions"
|
|
7
|
+
:filterable-extension-fields="filterableExtensionFields"
|
|
8
|
+
/>
|
|
9
|
+
<dynamic-filter-config-form
|
|
10
|
+
v-else
|
|
11
|
+
class="column-filter"
|
|
12
|
+
:filter="filter"
|
|
13
|
+
:filter-config="filterConfig"
|
|
14
|
+
column-mode
|
|
15
|
+
@cancel="close"
|
|
16
|
+
@submit="onSubmit"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script lang="ts" setup>
|
|
21
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
22
|
+
|
|
23
|
+
import type { DatalistTableHeader } from '../../../types/tableStore.types';
|
|
24
|
+
import type { FilterInitParams } from '../../classes/Filter';
|
|
25
|
+
import type { IFiltersManager } from '../../classes/FiltersManager';
|
|
26
|
+
import { useColumnFilter } from '../../composables/useColumnFilter';
|
|
27
|
+
import { useFilterValueChange } from '../../composables/useFilterValueChange';
|
|
28
|
+
import type { FilterConfigDefinition } from '../../modules/filterConfig/types/FilterConfigDefinition';
|
|
29
|
+
import DynamicFilterConfigForm from '../config/dynamic-view/dynamic-filter-config-form.vue';
|
|
30
|
+
import type { ColumnFilterEmits } from '../types/Filter.types';
|
|
31
|
+
import ColumnFilterPreview from './column-filter-preview.vue';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Column header filter for the `wt-table` `column-filter` slot, bound with `v-bind="scope"`:
|
|
35
|
+
* `formView: true` renders the value form in the filter popover, `false` the hover card.
|
|
36
|
+
* Resolves the filter from `header.filter`, reads the applied value from the filters manager and,
|
|
37
|
+
* like the panel, only emits — the app binds `add/update/delete:filter` to its table store:
|
|
38
|
+
* Apply → `add:filter` / `update:filter`; Clear then Apply → `delete:filter`; then the popover is closed via `hide`.
|
|
39
|
+
* Values stay local to the form until Apply, so the table doesn't reload on every click.
|
|
40
|
+
*
|
|
41
|
+
* [WTEL-7727](https://webitel.atlassian.net/browse/WTEL-7727)
|
|
42
|
+
*/
|
|
43
|
+
const props = defineProps<{
|
|
44
|
+
header: DatalistTableHeader;
|
|
45
|
+
filtersManager: IFiltersManager;
|
|
46
|
+
filterOptions?: FilterConfigDefinition[];
|
|
47
|
+
filterableExtensionFields?: DataField[];
|
|
48
|
+
formView?: boolean;
|
|
49
|
+
hide?: () => void;
|
|
50
|
+
}>();
|
|
51
|
+
|
|
52
|
+
const emit = defineEmits<ColumnFilterEmits>();
|
|
53
|
+
|
|
54
|
+
const { filterConfig, filter } = useColumnFilter({
|
|
55
|
+
header: () => props.header,
|
|
56
|
+
filtersManager: () => props.filtersManager,
|
|
57
|
+
filterOptions: () => props.filterOptions ?? [],
|
|
58
|
+
filterableExtensionFields: () => props.filterableExtensionFields ?? [],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const { onValueChange } = useFilterValueChange({
|
|
62
|
+
filterConfig,
|
|
63
|
+
filter,
|
|
64
|
+
emit,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const close = () => {
|
|
68
|
+
props.hide?.();
|
|
69
|
+
emit('close');
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const onSubmit = ({ value }: FilterInitParams) => {
|
|
73
|
+
onValueChange(value);
|
|
74
|
+
close();
|
|
75
|
+
};
|
|
76
|
+
</script>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
v-model:model-value="filterValue"
|
|
5
5
|
:label="label"
|
|
6
6
|
:filter-config="props.filterConfig"
|
|
7
|
+
:disable-validation="disableValidation"
|
|
7
8
|
@update:invalid="emit('update:invalid', $event)"
|
|
8
9
|
/>
|
|
9
10
|
</template>
|
|
@@ -16,6 +17,7 @@ const filterValue = defineModel<unknown>();
|
|
|
16
17
|
const props = defineProps<{
|
|
17
18
|
filterConfig: AnyFilterConfig;
|
|
18
19
|
label?: string;
|
|
20
|
+
disableValidation?: boolean;
|
|
19
21
|
}>();
|
|
20
22
|
|
|
21
23
|
const emit = defineEmits<{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<form class="dynamic-filter-config-form" @submit.prevent>
|
|
3
3
|
<wt-single-select
|
|
4
|
+
v-if="!columnMode"
|
|
4
5
|
:show-clear="false"
|
|
5
6
|
:disabled="editMode"
|
|
6
7
|
:label="t('webitelUI.filters.filterName')"
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
filterName,
|
|
21
22
|
filterValue,
|
|
22
23
|
inputLabel: valueInputLabelText,
|
|
24
|
+
disableValidation: columnMode,
|
|
23
25
|
onValueChange,
|
|
24
26
|
onValueInvalidChange,
|
|
25
27
|
}"
|
|
@@ -30,12 +32,14 @@
|
|
|
30
32
|
:model-value="filterValue"
|
|
31
33
|
:filter-config="selectedFilterConfig"
|
|
32
34
|
:label="valueInputLabelText"
|
|
35
|
+
:disable-validation="columnMode"
|
|
33
36
|
@update:model-value="onValueChange"
|
|
34
37
|
@update:invalid="onValueInvalidChange"
|
|
35
38
|
/>
|
|
36
39
|
</slot>
|
|
37
40
|
|
|
38
41
|
<dynamic-filter-config-form-label
|
|
42
|
+
v-if="!columnMode"
|
|
39
43
|
:value="filterLabel"
|
|
40
44
|
@update:model-value="onLabelValueUpdate"
|
|
41
45
|
@update:invalid="(v) => (invalid = v)"
|
|
@@ -43,19 +47,19 @@
|
|
|
43
47
|
|
|
44
48
|
<footer class="dynamic-filter-config-form-footer">
|
|
45
49
|
<wt-button
|
|
46
|
-
:disabled="
|
|
50
|
+
:disabled="isSubmitDisabled"
|
|
47
51
|
wide
|
|
48
52
|
@click="submit"
|
|
49
53
|
>
|
|
50
|
-
{{ t('
|
|
54
|
+
{{ t('vocabulary.apply') }}
|
|
51
55
|
</wt-button>
|
|
52
56
|
|
|
53
57
|
<wt-button
|
|
54
58
|
color="secondary"
|
|
55
59
|
wide
|
|
56
|
-
@click="emit('cancel')"
|
|
60
|
+
@click="columnMode ? handleClear() : emit('cancel')"
|
|
57
61
|
>
|
|
58
|
-
{{ t('reusable.cancel') }}
|
|
62
|
+
{{ columnMode ? t('reusable.clear') : t('reusable.cancel') }}
|
|
59
63
|
</wt-button>
|
|
60
64
|
</footer>
|
|
61
65
|
</form>
|
|
@@ -65,6 +69,7 @@
|
|
|
65
69
|
import { useVuelidate } from '@vuelidate/core';
|
|
66
70
|
import { required } from '@vuelidate/validators';
|
|
67
71
|
import { WtButton, WtSingleSelect } from '@webitel/ui-sdk/components';
|
|
72
|
+
import { isEmpty } from '@webitel/ui-sdk/scripts';
|
|
68
73
|
import deepcopy from 'deep-copy';
|
|
69
74
|
import { computed, ref, watch } from 'vue';
|
|
70
75
|
import { useI18n } from 'vue-i18n';
|
|
@@ -90,6 +95,17 @@ const props = defineProps<{
|
|
|
90
95
|
* Edited filter instance
|
|
91
96
|
*/
|
|
92
97
|
filter?: IFilter;
|
|
98
|
+
/**
|
|
99
|
+
* @description
|
|
100
|
+
* Column filter mode: the filter is fixed by `filterConfig`, so only the value input is shown
|
|
101
|
+
* (no filter name select, no label); the secondary button is "Clear" (empties the value) instead
|
|
102
|
+
* of "Cancel", and Apply goes through with an empty value — deleting the filter.
|
|
103
|
+
* A `notDeletable` filter config keeps Apply disabled on an empty value instead,
|
|
104
|
+
* the same way its panel chip has no "x".
|
|
105
|
+
*
|
|
106
|
+
* [WTEL-7727](https://webitel.atlassian.net/browse/WTEL-7727)
|
|
107
|
+
*/
|
|
108
|
+
columnMode?: boolean;
|
|
93
109
|
}>();
|
|
94
110
|
|
|
95
111
|
const emit = defineEmits<{
|
|
@@ -101,7 +117,7 @@ const emit = defineEmits<{
|
|
|
101
117
|
|
|
102
118
|
const { t } = useI18n();
|
|
103
119
|
|
|
104
|
-
const filterName = ref();
|
|
120
|
+
const filterName = ref<string | undefined>(props.filterConfig?.name);
|
|
105
121
|
const filterLabel = ref('');
|
|
106
122
|
const filterValue = ref();
|
|
107
123
|
|
|
@@ -124,6 +140,16 @@ v$.value.$touch();
|
|
|
124
140
|
|
|
125
141
|
const invalid = ref(false);
|
|
126
142
|
|
|
143
|
+
const isSubmitDisabled = computed(() => {
|
|
144
|
+
if (props.columnMode && isEmpty(filterValue.value)) {
|
|
145
|
+
return !editMode || !filterName.value || !!props.filterConfig?.notDeletable;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (v$.value.$invalid) return true;
|
|
149
|
+
|
|
150
|
+
return invalid.value;
|
|
151
|
+
});
|
|
152
|
+
|
|
127
153
|
const filterConfigOptions = computed(() => {
|
|
128
154
|
if (props.filterConfig) {
|
|
129
155
|
return [
|
|
@@ -148,6 +174,16 @@ const onValueChange = (v: unknown) => {
|
|
|
148
174
|
filterValue.value = v;
|
|
149
175
|
};
|
|
150
176
|
|
|
177
|
+
const clearValue = () => {
|
|
178
|
+
filterValue.value = null;
|
|
179
|
+
invalid.value = false;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const handleClear = () => {
|
|
183
|
+
clearValue();
|
|
184
|
+
if (!isSubmitDisabled.value) submit();
|
|
185
|
+
};
|
|
186
|
+
|
|
151
187
|
const onValueInvalidChange = (v: boolean) => {
|
|
152
188
|
invalid.value = v;
|
|
153
189
|
};
|
|
@@ -167,6 +203,8 @@ const onFilterNameUpdate = (val: string) => {
|
|
|
167
203
|
};
|
|
168
204
|
|
|
169
205
|
const submit = () => {
|
|
206
|
+
if (!filterName.value) return;
|
|
207
|
+
|
|
170
208
|
emit('submit', {
|
|
171
209
|
name: filterName.value,
|
|
172
210
|
label: filterLabel.value,
|
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
</template>
|
|
14
14
|
|
|
15
15
|
<script lang="ts" setup>
|
|
16
|
-
import { isEmpty } from '@webitel/ui-sdk/scripts';
|
|
17
16
|
import { computed } from 'vue';
|
|
18
17
|
|
|
19
|
-
import
|
|
18
|
+
import { useFilterValueChange } from '../../../composables/useFilterValueChange';
|
|
20
19
|
import { StaticFilterEmits, StaticFilterProps } from '../../types/Filter.types';
|
|
21
20
|
|
|
22
21
|
/* Author @Lera24
|
|
@@ -30,25 +29,11 @@ const emit = defineEmits<StaticFilterEmits>();
|
|
|
30
29
|
|
|
31
30
|
const filterValue = computed(() => props.filter?.value);
|
|
32
31
|
|
|
33
|
-
const onValueChange = (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (isEmpty(filterValue.value)) {
|
|
40
|
-
return emit('add:filter', {
|
|
41
|
-
name: props.filterConfig.name,
|
|
42
|
-
value,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
emit('update:filter', {
|
|
47
|
-
name: props.filterConfig.name,
|
|
48
|
-
value,
|
|
49
|
-
label: props.filter?.label,
|
|
50
|
-
});
|
|
51
|
-
};
|
|
32
|
+
const { onValueChange } = useFilterValueChange({
|
|
33
|
+
filterConfig: () => props.filterConfig,
|
|
34
|
+
filter: () => props.filter,
|
|
35
|
+
emit,
|
|
36
|
+
});
|
|
52
37
|
</script>
|
|
53
38
|
|
|
54
39
|
<style lang="scss" scoped>
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="filters-actions-menu">
|
|
3
|
+
<wt-context-menu
|
|
4
|
+
:disabled="isMenuDisabled"
|
|
5
|
+
:options="options"
|
|
6
|
+
@click="onOptionClick"
|
|
7
|
+
>
|
|
8
|
+
<template #activator="{ toggle, show }">
|
|
9
|
+
<span
|
|
10
|
+
class="filters-actions-menu__activator"
|
|
11
|
+
@pointerenter="show($event)"
|
|
12
|
+
>
|
|
13
|
+
<wt-badge :hidden="!hasAnyFilters">
|
|
14
|
+
<wt-icon-action
|
|
15
|
+
:action="IconAction.FILTERS"
|
|
16
|
+
:disabled="isMenuDisabled"
|
|
17
|
+
@click="toggle($event)"
|
|
18
|
+
/>
|
|
19
|
+
</wt-badge>
|
|
20
|
+
</span>
|
|
21
|
+
</template>
|
|
22
|
+
</wt-context-menu>
|
|
23
|
+
|
|
24
|
+
<template v-if="enablePresets && presetStore">
|
|
25
|
+
<apply-preset-action
|
|
26
|
+
ref="applyPreset"
|
|
27
|
+
:filter-configs="filterConfigs"
|
|
28
|
+
:has-any-filters="hasAnyFilters"
|
|
29
|
+
:namespace="presetNamespace ?? ''"
|
|
30
|
+
:presets-store="presetStore"
|
|
31
|
+
@apply="emit('preset:apply', $event)"
|
|
32
|
+
@restore="emit('preset:restore', $event)"
|
|
33
|
+
>
|
|
34
|
+
<template #activator />
|
|
35
|
+
</apply-preset-action>
|
|
36
|
+
|
|
37
|
+
<save-preset-action
|
|
38
|
+
ref="savePreset"
|
|
39
|
+
:filter-configs="filterConfigs"
|
|
40
|
+
:filters-included="filtersIncluded"
|
|
41
|
+
:filters-manager="filtersManager"
|
|
42
|
+
:namespace="presetNamespace ?? ''"
|
|
43
|
+
>
|
|
44
|
+
<template #activator />
|
|
45
|
+
</save-preset-action>
|
|
46
|
+
</template>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script lang="ts" setup>
|
|
51
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
52
|
+
import {
|
|
53
|
+
WtBadge,
|
|
54
|
+
WtContextMenu,
|
|
55
|
+
WtIconAction,
|
|
56
|
+
} from '@webitel/ui-sdk/components';
|
|
57
|
+
import { IconAction } from '@webitel/ui-sdk/enums';
|
|
58
|
+
import type { StoreGeneric } from 'pinia';
|
|
59
|
+
import { computed, useTemplateRef } from 'vue';
|
|
60
|
+
import { useI18n } from 'vue-i18n';
|
|
61
|
+
|
|
62
|
+
import { ApplyPresetAction, SavePresetAction } from '../../filter-presets';
|
|
63
|
+
import type { IFiltersManager } from '../classes/FiltersManager';
|
|
64
|
+
import { useFilterConfigsToolkit } from '../composables/useFilterConfigsToolkit';
|
|
65
|
+
import { useSelectedFilters } from '../composables/useSelectedFilters';
|
|
66
|
+
import type { FilterConfigDefinition } from '../modules/filterConfig/types/FilterConfigDefinition';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Filter actions for pages without a filters panel (column filters only, WTEL-7727):
|
|
70
|
+
* the "filters" icon with a badge when filters are applied, and a context menu
|
|
71
|
+
* with reset + presets (when `presetNamespace` is given) — the same actions the panel has.
|
|
72
|
+
* Only emits, like the panel; the page binds them to its table store.
|
|
73
|
+
*/
|
|
74
|
+
const props = defineProps<{
|
|
75
|
+
filtersManager: IFiltersManager;
|
|
76
|
+
filterOptions: FilterConfigDefinition[];
|
|
77
|
+
filterableExtensionFields?: DataField[];
|
|
78
|
+
/** enables preset actions */
|
|
79
|
+
presetNamespace?: string;
|
|
80
|
+
usePresetsStore?: () => StoreGeneric;
|
|
81
|
+
}>();
|
|
82
|
+
|
|
83
|
+
const emit = defineEmits<{
|
|
84
|
+
'filter:reset-all': [];
|
|
85
|
+
'preset:apply': [
|
|
86
|
+
string,
|
|
87
|
+
];
|
|
88
|
+
'preset:restore': [
|
|
89
|
+
string,
|
|
90
|
+
];
|
|
91
|
+
}>();
|
|
92
|
+
|
|
93
|
+
const { t } = useI18n();
|
|
94
|
+
|
|
95
|
+
const applyPreset =
|
|
96
|
+
useTemplateRef<InstanceType<typeof ApplyPresetAction>>('applyPreset');
|
|
97
|
+
const savePreset =
|
|
98
|
+
useTemplateRef<InstanceType<typeof SavePresetAction>>('savePreset');
|
|
99
|
+
|
|
100
|
+
const { filterConfigs, filtersIncluded } = useFilterConfigsToolkit({
|
|
101
|
+
filterOptions: props.filterOptions,
|
|
102
|
+
filtersManager: props.filtersManager,
|
|
103
|
+
filterableExtensionFields: props.filterableExtensionFields,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const { listSelectedFilters, hasAnyFilters } = useSelectedFilters({
|
|
107
|
+
filtersManager: () => props.filtersManager,
|
|
108
|
+
filterOptions: () => props.filterOptions,
|
|
109
|
+
filterableExtensionFields: () => props.filterableExtensionFields,
|
|
110
|
+
filterConfigs,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const enablePresets = computed(() => !!props.presetNamespace);
|
|
114
|
+
const presetStore = props.usePresetsStore ? props.usePresetsStore() : null;
|
|
115
|
+
|
|
116
|
+
const MenuAction = {
|
|
117
|
+
RESET: 'reset',
|
|
118
|
+
APPLY_PRESET: 'apply-preset',
|
|
119
|
+
SAVE_PRESET: 'save-preset',
|
|
120
|
+
} as const;
|
|
121
|
+
|
|
122
|
+
const hasFiltersToReset = computed(() => !!listSelectedFilters.value.size);
|
|
123
|
+
|
|
124
|
+
// reset is the only action without presets: then there is nothing to open the menu for
|
|
125
|
+
const isMenuDisabled = computed(
|
|
126
|
+
() => !enablePresets.value && !hasFiltersToReset.value,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const options = computed(() => [
|
|
130
|
+
{
|
|
131
|
+
action: MenuAction.RESET,
|
|
132
|
+
text: t(`webitelUI.iconAction.hints.${IconAction.CLEAR}`),
|
|
133
|
+
disabled: !hasFiltersToReset.value,
|
|
134
|
+
},
|
|
135
|
+
...(enablePresets.value
|
|
136
|
+
? [
|
|
137
|
+
{
|
|
138
|
+
action: MenuAction.APPLY_PRESET,
|
|
139
|
+
text: t(`webitelUI.iconAction.hints.${IconAction.APPLY_PRESET}`),
|
|
140
|
+
disabled: false,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
action: MenuAction.SAVE_PRESET,
|
|
144
|
+
text: t(`webitelUI.iconAction.hints.${IconAction.SAVE_PRESET}`),
|
|
145
|
+
disabled: !!savePreset.value?.disabled,
|
|
146
|
+
},
|
|
147
|
+
]
|
|
148
|
+
: []),
|
|
149
|
+
]);
|
|
150
|
+
|
|
151
|
+
const onOptionClick = ({
|
|
152
|
+
option,
|
|
153
|
+
}: {
|
|
154
|
+
option: (typeof options.value)[number];
|
|
155
|
+
}) => {
|
|
156
|
+
if (option.disabled) return;
|
|
157
|
+
|
|
158
|
+
switch (option.action) {
|
|
159
|
+
case MenuAction.RESET:
|
|
160
|
+
emit('filter:reset-all');
|
|
161
|
+
presetStore?.resetPreset();
|
|
162
|
+
break;
|
|
163
|
+
case MenuAction.APPLY_PRESET:
|
|
164
|
+
applyPreset.value?.open();
|
|
165
|
+
break;
|
|
166
|
+
case MenuAction.SAVE_PRESET:
|
|
167
|
+
savePreset.value?.open();
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<style lang="scss" scoped>
|
|
174
|
+
.filters-actions-menu__activator {
|
|
175
|
+
display: inline-flex;
|
|
176
|
+
}
|
|
177
|
+
</style>
|
|
@@ -65,11 +65,8 @@
|
|
|
65
65
|
|
|
66
66
|
<script lang="ts" setup>
|
|
67
67
|
import { WtChip, WtLoader, WtPopover } from '@webitel/ui-sdk/components';
|
|
68
|
-
import { computed, ref, watch } from 'vue';
|
|
69
|
-
|
|
70
68
|
import { FilterInitParams } from '../../classes/Filter';
|
|
71
|
-
import
|
|
72
|
-
import { FilterOptionToPreviewApiSearchMethodMap } from '../../modules/filterConfig/components';
|
|
69
|
+
import { useFilterValuePreview } from '../../composables/useFilterValuePreview';
|
|
73
70
|
import DynamicFilterConfigForm from '../config/dynamic-view/dynamic-filter-config-form.vue';
|
|
74
71
|
import DynamicFilterConfigView from '../config/dynamic-view/dynamic-filter-config-view.vue';
|
|
75
72
|
import { DynamicFilterEmits, DynamicFilterProps } from '../types/Filter.types';
|
|
@@ -79,7 +76,10 @@ const props = defineProps<DynamicFilterProps>();
|
|
|
79
76
|
|
|
80
77
|
const emit = defineEmits<DynamicFilterEmits>();
|
|
81
78
|
|
|
82
|
-
const localValue =
|
|
79
|
+
const { localValue, isRenderPreview, fillLocalValue } = useFilterValuePreview({
|
|
80
|
+
filter: () => props.filter,
|
|
81
|
+
filterConfig: () => props.filterConfig,
|
|
82
|
+
});
|
|
83
83
|
|
|
84
84
|
const showChipPopover = (
|
|
85
85
|
event: Event,
|
|
@@ -92,61 +92,6 @@ const showChipPopover = (
|
|
|
92
92
|
showPopoverCb(event);
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
/**
|
|
96
|
-
* @author @dlohvinov
|
|
97
|
-
*
|
|
98
|
-
* @description
|
|
99
|
-
* loading filters preview data -> main preview component
|
|
100
|
-
* instead of tooltip-components to avoid api requests spam
|
|
101
|
-
*/
|
|
102
|
-
const fillLocalValue = async (filter = props.filter) => {
|
|
103
|
-
const filterName = props.filter.name;
|
|
104
|
-
const filterValue = filter.value;
|
|
105
|
-
|
|
106
|
-
const { filterConfig } = props;
|
|
107
|
-
const valueSearchMethod =
|
|
108
|
-
'searchRecords' in filterConfig
|
|
109
|
-
? (...params: FilterConfigSearchMethodParams) => {
|
|
110
|
-
/* arrow fn here preserves filterConfig class "this" */
|
|
111
|
-
return filterConfig.searchRecords(...params);
|
|
112
|
-
}
|
|
113
|
-
: FilterOptionToPreviewApiSearchMethodMap[filterName];
|
|
114
|
-
|
|
115
|
-
if (valueSearchMethod) {
|
|
116
|
-
const { items } = await valueSearchMethod(
|
|
117
|
-
{
|
|
118
|
-
id: filterValue,
|
|
119
|
-
// -1 returns all records
|
|
120
|
-
size: -1,
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
filterValue,
|
|
124
|
-
filterName,
|
|
125
|
-
filterConfig: props.filterConfig,
|
|
126
|
-
},
|
|
127
|
-
);
|
|
128
|
-
localValue.value = items;
|
|
129
|
-
} else {
|
|
130
|
-
localValue.value = filterValue;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
watch(
|
|
135
|
-
() => props.filter.value,
|
|
136
|
-
() => {
|
|
137
|
-
fillLocalValue(props.filter);
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
immediate: true,
|
|
141
|
-
},
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
// [https://webitel.atlassian.net/browse/WTEL-6732]
|
|
145
|
-
// if type filter is boolean and value = false, need display preview
|
|
146
|
-
const isRenderPreview = computed(
|
|
147
|
-
() => localValue.value === false || localValue.value,
|
|
148
|
-
);
|
|
149
|
-
|
|
150
95
|
const submit = (
|
|
151
96
|
filter: FilterInitParams,
|
|
152
97
|
{
|