@webitel/ui-datalist 26.8.6 → 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/Readme.md +1 -0
- package/package.json +3 -2
- 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/__tests__/createTableFiltersStore.spec.ts +38 -2
- 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/createTableFiltersStore.ts +13 -5
- package/src/modules/filters/index.ts +4 -0
- package/src/modules/filters/modules/filterConfig/components/_custom/filterConfig.ts +1 -1
- 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/headers/__tests__/createTableHeadersStore.spec.ts +34 -2
- package/src/modules/headers/createTableHeadersStore.ts +19 -5
- package/src/modules/pagination/__tests__/createTablePaginationStore.spec.ts +27 -3
- package/src/modules/pagination/createTablePaginationStore.ts +23 -4
- package/src/modules/table/__tests__/createTableStore.spec.ts +26 -0
- package/src/modules/table/createTableStore.store.ts +34 -15
- 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/createTableFiltersStore.d.ts +6 -2
- 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 +48 -20
- package/types/modules/pagination/createTablePaginationStore.d.ts +7 -3
- 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
|
@@ -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
|
{
|
|
@@ -79,6 +79,7 @@ import { ApplyPresetAction, SavePresetAction } from '../../filter-presets';
|
|
|
79
79
|
import { FilterInitParams, IFilter } from '../classes/Filter';
|
|
80
80
|
import { IFiltersManager } from '../classes/FiltersManager';
|
|
81
81
|
import { useFilterConfigsToolkit } from '../composables/useFilterConfigsToolkit';
|
|
82
|
+
import { useSelectedFilters } from '../composables/useSelectedFilters';
|
|
82
83
|
import { AnyFilterConfig } from '../modules/filterConfig/classes/FilterConfig';
|
|
83
84
|
import { FilterOption } from '../modules/filterConfig/enums/FilterOption';
|
|
84
85
|
import StaticFilterField from './config/static-view/static-filter-field.vue';
|
|
@@ -197,36 +198,13 @@ https://webitel.atlassian.net/browse/WTEL-7014
|
|
|
197
198
|
Clear filters button should be active only if filters are defined in the table-filter-panel. Excluding the search filter
|
|
198
199
|
**/
|
|
199
200
|
|
|
200
|
-
const listSelectedFilters =
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
...(props.filterableExtensionFields ?? []).map((filter) => filter.id),
|
|
206
|
-
]);
|
|
207
|
-
return new Map(
|
|
208
|
-
[
|
|
209
|
-
...props.filtersManager.filters,
|
|
210
|
-
].filter(([key]) => allowedKeys.has(key)),
|
|
211
|
-
);
|
|
201
|
+
const { listSelectedFilters, hasAnyFilters } = useSelectedFilters({
|
|
202
|
+
filtersManager: () => props.filtersManager,
|
|
203
|
+
filterOptions: () => props.filterOptions,
|
|
204
|
+
filterableExtensionFields: () => props.filterableExtensionFields,
|
|
205
|
+
filterConfigs,
|
|
212
206
|
});
|
|
213
207
|
|
|
214
|
-
/**
|
|
215
|
-
* @description
|
|
216
|
-
* Filters applied by the user. `notDeletable` configs are skipped – they are
|
|
217
|
-
* seeded defaults, not a user choice, so they must not block preset restore.
|
|
218
|
-
*/
|
|
219
|
-
const hasAnyFilters = computed(() =>
|
|
220
|
-
[
|
|
221
|
-
...listSelectedFilters.value.keys(),
|
|
222
|
-
].some((name) => {
|
|
223
|
-
const filterConfig = filterConfigs.value.find(
|
|
224
|
-
(config) => String(config.name) === String(name),
|
|
225
|
-
);
|
|
226
|
-
return !filterConfig?.notDeletable;
|
|
227
|
-
}),
|
|
228
|
-
);
|
|
229
|
-
|
|
230
208
|
const presetStore = props.usePresetsStore ? props.usePresetsStore() : null;
|
|
231
209
|
|
|
232
210
|
const handleResetFilters = () => {
|
|
@@ -18,6 +18,11 @@ export interface StaticFilterEmits extends FilterEmits {
|
|
|
18
18
|
|
|
19
19
|
export interface DynamicFilterEmits extends FilterEmits {}
|
|
20
20
|
|
|
21
|
+
/** column filter lives in a popover, so it also asks the parent to close it */
|
|
22
|
+
export interface ColumnFilterEmits extends StaticFilterEmits {
|
|
23
|
+
close: [];
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
export interface FilterProps {
|
|
22
27
|
filter: IFilter;
|
|
23
28
|
filterConfig: AnyFilterConfig;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
2
|
+
import { computed, type MaybeRefOrGetter, toValue } from 'vue';
|
|
3
|
+
import { useI18n } from 'vue-i18n';
|
|
4
|
+
|
|
5
|
+
import type { DatalistTableHeader } from '../../types/tableStore.types';
|
|
6
|
+
import type { FilterName } from '../classes/Filter';
|
|
7
|
+
import type { IFiltersManager } from '../classes/FiltersManager';
|
|
8
|
+
import { createFilterConfig } from '../modules/filterConfig/classes/createFilterConfig';
|
|
9
|
+
import {
|
|
10
|
+
type AnyFilterConfig,
|
|
11
|
+
FilterConfig,
|
|
12
|
+
} from '../modules/filterConfig/classes/FilterConfig';
|
|
13
|
+
import { createTypeExtensionFilterConfig } from '../modules/filterConfig/components/_custom';
|
|
14
|
+
import type { FilterConfigDefinition } from '../modules/filterConfig/types/FilterConfigDefinition';
|
|
15
|
+
|
|
16
|
+
const isResolvedFilterConfig = (
|
|
17
|
+
filter: DatalistTableHeader['filter'],
|
|
18
|
+
): filter is AnyFilterConfig => typeof filter === 'object' && filter !== null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolves a table header into its filter config and the filter currently applied in the
|
|
22
|
+
* filters manager.
|
|
23
|
+
*
|
|
24
|
+
* `header.filter` is either a plain name — resolved the same way the panel does
|
|
25
|
+
* (useFilterConfigsToolkit): a custom (type extension) column is matched by field id in
|
|
26
|
+
* `filterableExtensionFields`, a pre-configured definition from `filterOptions` (the page's
|
|
27
|
+
* filtersOptions) is reused as is, everything else is a standard filter option with an i18n
|
|
28
|
+
* label fallback — or an already-resolved config, used as is. Passing a resolved config from
|
|
29
|
+
* `headers.ts` skips the `filterOptions`/`filterableExtensionFields` search entirely.
|
|
30
|
+
*
|
|
31
|
+
* [WTEL-7727](https://webitel.atlassian.net/browse/WTEL-7727)
|
|
32
|
+
*/
|
|
33
|
+
export const useColumnFilter = ({
|
|
34
|
+
header,
|
|
35
|
+
filtersManager,
|
|
36
|
+
filterOptions = [],
|
|
37
|
+
filterableExtensionFields = [],
|
|
38
|
+
}: {
|
|
39
|
+
header: MaybeRefOrGetter<DatalistTableHeader>;
|
|
40
|
+
filtersManager: MaybeRefOrGetter<IFiltersManager>;
|
|
41
|
+
filterOptions?: MaybeRefOrGetter<FilterConfigDefinition[]>;
|
|
42
|
+
filterableExtensionFields?: MaybeRefOrGetter<DataField[]>;
|
|
43
|
+
}) => {
|
|
44
|
+
const { t } = useI18n();
|
|
45
|
+
|
|
46
|
+
const resolvedFilter = computed(() => {
|
|
47
|
+
const filter = toValue(header).filter;
|
|
48
|
+
return isResolvedFilterConfig(filter) ? filter : undefined;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const filterName = computed(
|
|
52
|
+
() => (resolvedFilter.value?.name ?? toValue(header).filter) as FilterName,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const extensionField = computed(() =>
|
|
56
|
+
resolvedFilter.value
|
|
57
|
+
? undefined
|
|
58
|
+
: toValue(filterableExtensionFields).find(
|
|
59
|
+
(field) => field.id === filterName.value,
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const configuredOption = computed(() =>
|
|
64
|
+
resolvedFilter.value
|
|
65
|
+
? undefined
|
|
66
|
+
: toValue(filterOptions).find(
|
|
67
|
+
(opt): opt is AnyFilterConfig =>
|
|
68
|
+
typeof opt !== 'string' && opt.name === filterName.value,
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const filterConfig = computed(() => {
|
|
73
|
+
let config: AnyFilterConfig;
|
|
74
|
+
|
|
75
|
+
if (resolvedFilter.value) {
|
|
76
|
+
config = resolvedFilter.value;
|
|
77
|
+
} else if (extensionField.value) {
|
|
78
|
+
config = createTypeExtensionFilterConfig(
|
|
79
|
+
{
|
|
80
|
+
name: extensionField.value.id,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
field: extensionField.value,
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
const option = configuredOption.value;
|
|
88
|
+
config =
|
|
89
|
+
option instanceof FilterConfig
|
|
90
|
+
? option
|
|
91
|
+
: option
|
|
92
|
+
? new FilterConfig({
|
|
93
|
+
...option,
|
|
94
|
+
name: option.name,
|
|
95
|
+
})
|
|
96
|
+
: createFilterConfig({
|
|
97
|
+
name: filterName.value,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!config.label) {
|
|
102
|
+
config.label = t(`webitelUI.filters.${config.name}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return config;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const filter = computed(() =>
|
|
109
|
+
toValue(filtersManager).getFilter(filterName.value),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
filterConfig,
|
|
114
|
+
filter,
|
|
115
|
+
};
|
|
116
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { isEmpty } from '@webitel/ui-sdk/scripts';
|
|
2
|
+
import { type MaybeRefOrGetter, toValue } from 'vue';
|
|
3
|
+
|
|
4
|
+
import type { FilterValue, IFilter } from '../classes/Filter';
|
|
5
|
+
import type { StaticFilterEmits } from '../components/types/Filter.types';
|
|
6
|
+
import type { AnyFilterConfig } from '../modules/filterConfig';
|
|
7
|
+
|
|
8
|
+
type StaticFilterEmit = <K extends keyof StaticFilterEmits>(
|
|
9
|
+
event: K,
|
|
10
|
+
...args: StaticFilterEmits[K]
|
|
11
|
+
) => void;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Turns a new filter value into the right manager event:
|
|
15
|
+
* - empty value (except booleans) → `delete:filter` (only if the filter exists)
|
|
16
|
+
* - no filter yet → `add:filter`
|
|
17
|
+
* - filter exists → `update:filter`, keeping its label
|
|
18
|
+
*
|
|
19
|
+
* Shared by the static filter field and the column filter.
|
|
20
|
+
*
|
|
21
|
+
* [WTEL-7727](https://webitel.atlassian.net/browse/WTEL-7727)
|
|
22
|
+
*/
|
|
23
|
+
export const useFilterValueChange = ({
|
|
24
|
+
filterConfig,
|
|
25
|
+
filter,
|
|
26
|
+
emit,
|
|
27
|
+
}: {
|
|
28
|
+
filterConfig: MaybeRefOrGetter<AnyFilterConfig>;
|
|
29
|
+
filter: MaybeRefOrGetter<IFilter | undefined>;
|
|
30
|
+
emit: StaticFilterEmit;
|
|
31
|
+
}) => {
|
|
32
|
+
const onValueChange = (value: FilterValue) => {
|
|
33
|
+
const currentFilter = toValue(filter);
|
|
34
|
+
const config = toValue(filterConfig);
|
|
35
|
+
|
|
36
|
+
if (isEmpty(value) && typeof value !== 'boolean') {
|
|
37
|
+
if (!currentFilter) return;
|
|
38
|
+
return emit('delete:filter', currentFilter);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isEmpty(currentFilter?.value)) {
|
|
42
|
+
return emit('add:filter', {
|
|
43
|
+
name: config.name,
|
|
44
|
+
value,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
emit('update:filter', {
|
|
49
|
+
name: config.name,
|
|
50
|
+
value,
|
|
51
|
+
label: currentFilter?.label,
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
onValueChange,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { computed, type MaybeRefOrGetter, ref, toValue, watch } from 'vue';
|
|
2
|
+
|
|
3
|
+
import type { IFilter } from '../classes/Filter';
|
|
4
|
+
import type {
|
|
5
|
+
AnyFilterConfig,
|
|
6
|
+
FilterConfigSearchMethodParams,
|
|
7
|
+
} from '../modules/filterConfig/classes/FilterConfig';
|
|
8
|
+
import { FilterOptionToPreviewApiSearchMethodMap } from '../modules/filterConfig/components';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @author @dlohvinov
|
|
12
|
+
*
|
|
13
|
+
* @description
|
|
14
|
+
* Loads the data shown in a filter's hover preview (records behind the stored ids)
|
|
15
|
+
* once per filter value, in the parent, instead of inside tooltip components —
|
|
16
|
+
* to avoid api requests spam.
|
|
17
|
+
*
|
|
18
|
+
* Shared by the panel chip and the column header icon (WTEL-7727).
|
|
19
|
+
*/
|
|
20
|
+
export const useFilterValuePreview = ({
|
|
21
|
+
filter,
|
|
22
|
+
filterConfig,
|
|
23
|
+
}: {
|
|
24
|
+
filter: MaybeRefOrGetter<IFilter | undefined>;
|
|
25
|
+
filterConfig: MaybeRefOrGetter<AnyFilterConfig>;
|
|
26
|
+
}) => {
|
|
27
|
+
const localValue = ref();
|
|
28
|
+
|
|
29
|
+
const fillLocalValue = async (currentFilter = toValue(filter)) => {
|
|
30
|
+
if (!currentFilter) {
|
|
31
|
+
localValue.value = undefined;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const filterName = currentFilter.name;
|
|
36
|
+
const filterValue = currentFilter.value;
|
|
37
|
+
const config = toValue(filterConfig);
|
|
38
|
+
|
|
39
|
+
const valueSearchMethod =
|
|
40
|
+
'searchRecords' in config
|
|
41
|
+
? (...params: FilterConfigSearchMethodParams) => {
|
|
42
|
+
/* arrow fn here preserves filterConfig class "this" */
|
|
43
|
+
return config.searchRecords(...params);
|
|
44
|
+
}
|
|
45
|
+
: FilterOptionToPreviewApiSearchMethodMap[filterName];
|
|
46
|
+
|
|
47
|
+
if (valueSearchMethod) {
|
|
48
|
+
const { items } = await valueSearchMethod(
|
|
49
|
+
{
|
|
50
|
+
id: filterValue,
|
|
51
|
+
// -1 returns all records
|
|
52
|
+
size: -1,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
filterValue,
|
|
56
|
+
filterName,
|
|
57
|
+
filterConfig: config,
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
localValue.value = items;
|
|
61
|
+
} else {
|
|
62
|
+
localValue.value = filterValue;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
watch(
|
|
67
|
+
() => toValue(filter)?.value,
|
|
68
|
+
() => {
|
|
69
|
+
fillLocalValue(toValue(filter));
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
immediate: true,
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// [https://webitel.atlassian.net/browse/WTEL-6732]
|
|
77
|
+
// if type filter is boolean and value = false, need display preview
|
|
78
|
+
const isRenderPreview = computed(
|
|
79
|
+
() => localValue.value === false || localValue.value,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
localValue,
|
|
84
|
+
isRenderPreview,
|
|
85
|
+
fillLocalValue,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
2
|
+
import {
|
|
3
|
+
type ComputedRef,
|
|
4
|
+
computed,
|
|
5
|
+
type MaybeRefOrGetter,
|
|
6
|
+
toValue,
|
|
7
|
+
} from 'vue';
|
|
8
|
+
|
|
9
|
+
import type { FilterName, IFilter } from '../classes/Filter';
|
|
10
|
+
import type { IFiltersManager } from '../classes/FiltersManager';
|
|
11
|
+
import type { BaseFilterConfig } from '../modules/filterConfig/classes/FilterConfig';
|
|
12
|
+
import type { FilterConfigDefinition } from '../modules/filterConfig/types/FilterConfigDefinition';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Filters from the manager that belong to this panel/menu (its filter options + extension fields),
|
|
16
|
+
* so search filters living in the same manager are ignored.
|
|
17
|
+
*
|
|
18
|
+
* `hasAnyFilters` skips `notDeletable` configs — they are seeded defaults, not a user choice
|
|
19
|
+
* ([WTEL-7014](https://webitel.atlassian.net/browse/WTEL-7014)).
|
|
20
|
+
*/
|
|
21
|
+
export const useSelectedFilters = ({
|
|
22
|
+
filtersManager,
|
|
23
|
+
filterOptions,
|
|
24
|
+
filterableExtensionFields = [],
|
|
25
|
+
filterConfigs,
|
|
26
|
+
}: {
|
|
27
|
+
filtersManager: MaybeRefOrGetter<IFiltersManager>;
|
|
28
|
+
filterOptions: MaybeRefOrGetter<FilterConfigDefinition[]>;
|
|
29
|
+
filterableExtensionFields?: MaybeRefOrGetter<DataField[] | undefined>;
|
|
30
|
+
filterConfigs: ComputedRef<BaseFilterConfig[]>;
|
|
31
|
+
}) => {
|
|
32
|
+
const listSelectedFilters = computed(() => {
|
|
33
|
+
const allowedKeys = new Set<FilterName>([
|
|
34
|
+
...toValue(filterOptions).map((filter) =>
|
|
35
|
+
typeof filter === 'string' ? filter : filter.name,
|
|
36
|
+
),
|
|
37
|
+
...(toValue(filterableExtensionFields) ?? [])
|
|
38
|
+
.map((field) => field.id)
|
|
39
|
+
.filter((id): id is string => id !== undefined),
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
return new Map<FilterName, IFilter>(
|
|
43
|
+
[
|
|
44
|
+
...toValue(filtersManager).filters,
|
|
45
|
+
].filter(([key]) => allowedKeys.has(key)),
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const hasAnyFilters = computed(() =>
|
|
50
|
+
[
|
|
51
|
+
...listSelectedFilters.value.keys(),
|
|
52
|
+
].some((name) => {
|
|
53
|
+
const filterConfig = filterConfigs.value.find(
|
|
54
|
+
(config) => String(config.name) === String(name),
|
|
55
|
+
);
|
|
56
|
+
return !filterConfig?.notDeletable;
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
listSelectedFilters,
|
|
62
|
+
hasAnyFilters,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
@@ -45,7 +45,11 @@ export const tableFiltersStoreBody = (
|
|
|
45
45
|
|
|
46
46
|
let persistedStorageControllers: PersistedStorageController[] = [];
|
|
47
47
|
|
|
48
|
-
const setupPersistence = (
|
|
48
|
+
const setupPersistence = ({
|
|
49
|
+
isNested = false,
|
|
50
|
+
}: {
|
|
51
|
+
isNested?: boolean;
|
|
52
|
+
} = {}) => {
|
|
49
53
|
const filtersStorage = usePersistedStorage({
|
|
50
54
|
name: 'filters',
|
|
51
55
|
|
|
@@ -53,10 +57,14 @@ export const tableFiltersStoreBody = (
|
|
|
53
57
|
() => filtersManager,
|
|
54
58
|
) /* computed is used to provide value as ref(), not reactive() – as per usePersistedStorage interface */,
|
|
55
59
|
|
|
56
|
-
storages:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
storages: isNested
|
|
61
|
+
? [
|
|
62
|
+
PersistedStorageType.SessionStorage,
|
|
63
|
+
]
|
|
64
|
+
: [
|
|
65
|
+
PersistedStorageType.Route,
|
|
66
|
+
PersistedStorageType.SessionStorage,
|
|
67
|
+
],
|
|
60
68
|
storagePath: namespace,
|
|
61
69
|
|
|
62
70
|
/* use custom .toString() logic, provided by FiltersManager */
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
type FiltersManagerConfig,
|
|
13
13
|
type IFiltersManager,
|
|
14
14
|
} from './classes/FiltersManager';
|
|
15
|
+
import ColumnFilterComponent from './components/column/column-filter.vue';
|
|
16
|
+
import FiltersActionsMenuComponent from './components/filters-actions-menu.vue';
|
|
15
17
|
import DynamicFilterSearchComponent from './components/search-bar/dynamic-filter-search.vue';
|
|
16
18
|
import TableFiltersPanelComponent from './components/table-filters-panel.vue';
|
|
17
19
|
import { FilterOption } from './modules/filterConfig/enums/FilterOption';
|
|
@@ -28,9 +30,11 @@ export type {
|
|
|
28
30
|
IFiltersManager,
|
|
29
31
|
};
|
|
30
32
|
export {
|
|
33
|
+
ColumnFilterComponent,
|
|
31
34
|
createFiltersManager,
|
|
32
35
|
DynamicFilterSearchComponent,
|
|
33
36
|
Filter,
|
|
34
37
|
FilterOption,
|
|
38
|
+
FiltersActionsMenuComponent,
|
|
35
39
|
TableFiltersPanelComponent,
|
|
36
40
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SysTypesAPI as sysTypes } from '@webitel/api-services/api';
|
|
2
2
|
import type { DataField } from '@webitel/api-services/gen/models';
|
|
3
3
|
import { WtTypeExtensionFieldKind } from '@webitel/ui-sdk/enums';
|
|
4
|
-
import { get } from 'lodash';
|
|
4
|
+
import { get } from 'lodash-es';
|
|
5
5
|
import type {
|
|
6
6
|
BaseFilterConfig,
|
|
7
7
|
FilterConfigBaseParams,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
v-model:model-value="model"
|
|
5
5
|
:field="props.filterConfig.field"
|
|
6
6
|
:required="false"
|
|
7
|
-
:v="v$.model"
|
|
7
|
+
:v="!disableValidation && v$.model"
|
|
8
8
|
>
|
|
9
9
|
<template #[WtTypeExtensionFieldKind.Boolean]="{ defaultProps }">
|
|
10
10
|
<has-option-filter-value-field v-bind="defaultProps" v-model:model-value="booleanModel"/>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<template #[WtTypeExtensionFieldKind.Select]="{ defaultProps }">
|
|
13
13
|
<wt-single-select
|
|
14
14
|
v-bind="defaultProps"
|
|
15
|
-
:v="v$.model"
|
|
15
|
+
:v="!disableValidation && v$.model"
|
|
16
16
|
:model-value="
|
|
17
17
|
model ??
|
|
18
18
|
[] /* so that component won't break when model is nullish at init */
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<template #[WtTypeExtensionFieldKind.Multiselect]="{ defaultProps }">
|
|
27
27
|
<wt-multi-select
|
|
28
28
|
v-bind="defaultProps"
|
|
29
|
-
:v="v$.model"
|
|
29
|
+
:v="!disableValidation && v$.model"
|
|
30
30
|
:model-value="
|
|
31
31
|
model ??
|
|
32
32
|
[] /* so that component won't break when model is nullish at init */
|
|
@@ -39,7 +39,10 @@
|
|
|
39
39
|
/>
|
|
40
40
|
</template>
|
|
41
41
|
<template #[WtTypeExtensionFieldKind.Calendar]>
|
|
42
|
-
<date-time-options-filter-value-field
|
|
42
|
+
<date-time-options-filter-value-field
|
|
43
|
+
v-model:model-value="dateTimeModel"
|
|
44
|
+
:disable-validation="disableValidation"
|
|
45
|
+
/>
|
|
43
46
|
</template>
|
|
44
47
|
</wt-type-extension-value-input>
|
|
45
48
|
</template>
|
|
@@ -66,6 +69,7 @@ const model = defineModel<unknown>();
|
|
|
66
69
|
|
|
67
70
|
const props = defineProps<{
|
|
68
71
|
filterConfig: ITypeExtensionFilterConfig;
|
|
72
|
+
disableValidation?: boolean;
|
|
69
73
|
}>();
|
|
70
74
|
|
|
71
75
|
const emit = defineEmits<{
|
|
@@ -116,7 +120,7 @@ const v$ = useVuelidate(
|
|
|
116
120
|
$autoDirty: true,
|
|
117
121
|
},
|
|
118
122
|
);
|
|
119
|
-
v$.value.$touch();
|
|
123
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
120
124
|
watch(
|
|
121
125
|
() => v$.value.$invalid,
|
|
122
126
|
(invalid) => {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
class="date-time-filter-value-field__picker"
|
|
7
7
|
show-time
|
|
8
8
|
required
|
|
9
|
-
:v="v$.from"
|
|
9
|
+
:v="!disableValidation && v$.from"
|
|
10
10
|
@update:model-value="handleInput('from', $event)"
|
|
11
11
|
/>
|
|
12
12
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
class="date-time-filter-value-field__picker"
|
|
17
17
|
show-time
|
|
18
18
|
required
|
|
19
|
-
:v="v$.to"
|
|
19
|
+
:v="!disableValidation && v$.to"
|
|
20
20
|
@update:model-value="handleInput('to', $event)"
|
|
21
21
|
/>
|
|
22
22
|
</div>
|
|
@@ -34,6 +34,10 @@ type ModelValue = {
|
|
|
34
34
|
to: number;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
const props = defineProps<{
|
|
38
|
+
disableValidation?: boolean;
|
|
39
|
+
}>();
|
|
40
|
+
|
|
37
41
|
const emit = defineEmits<{
|
|
38
42
|
'update:invalid': [
|
|
39
43
|
boolean,
|
|
@@ -69,8 +73,7 @@ const v$ = useVuelidate(
|
|
|
69
73
|
},
|
|
70
74
|
);
|
|
71
75
|
|
|
72
|
-
v$.value.$touch();
|
|
73
|
-
|
|
76
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
74
77
|
watch(
|
|
75
78
|
() => v$.value.$invalid,
|
|
76
79
|
(invalid) => {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
:label="t('reusable.from')"
|
|
15
15
|
show-time
|
|
16
16
|
required
|
|
17
|
-
:v="v$.from"
|
|
17
|
+
:v="!disableValidation && v$.from"
|
|
18
18
|
@update:model-value="changeAbsoluteValue($event, 'from')"
|
|
19
19
|
/>
|
|
20
20
|
<wt-datepicker
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
:label="t('reusable.to')"
|
|
24
24
|
show-time
|
|
25
25
|
required
|
|
26
|
-
:v="v$.to"
|
|
26
|
+
:v="!disableValidation && v$.to"
|
|
27
27
|
@update:model-value="changeAbsoluteValue($event, 'to')"
|
|
28
28
|
/>
|
|
29
29
|
</div>
|
|
@@ -39,6 +39,10 @@ import { endOfToday, startOfToday } from 'date-fns';
|
|
|
39
39
|
import { computed, ref, watch } from 'vue';
|
|
40
40
|
import { useI18n } from 'vue-i18n';
|
|
41
41
|
|
|
42
|
+
const props = defineProps<{
|
|
43
|
+
disableValidation?: boolean;
|
|
44
|
+
}>();
|
|
45
|
+
|
|
42
46
|
const model = defineModel<
|
|
43
47
|
| RelativeDatetimeValue
|
|
44
48
|
| {
|
|
@@ -115,8 +119,7 @@ const v$ = useVuelidate(
|
|
|
115
119
|
},
|
|
116
120
|
);
|
|
117
121
|
|
|
118
|
-
v$.value.$touch();
|
|
119
|
-
|
|
122
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
120
123
|
watch(
|
|
121
124
|
() => v$.value.$invalid,
|
|
122
125
|
(invalid) => {
|