@webitel/ui-datalist 26.8.19 → 26.8.21
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/card/composables/__tests__/useCardValidation.spec.ts +28 -0
- package/src/modules/filter-presets/components/_shared/preset-filters-preview.vue +1 -1
- package/src/modules/filters/components/config/static-view/__tests__/static-filter-field.spec.ts +29 -4
- package/src/modules/filters/components/config/static-view/static-filter-field.vue +2 -0
- package/src/modules/filters/components/filters-actions-menu.vue +2 -2
- package/src/modules/filters/components/table-filters-panel.vue +2 -2
- package/src/modules/filters/composables/useFilterConfigsToolkit.ts +10 -5
- package/src/modules/filters/composables/useFilterValuePreview.ts +7 -5
- package/src/modules/filters/composables/useVariableColumnFilters.ts +115 -0
- package/src/modules/filters/index.ts +10 -0
- package/src/modules/filters/scripts/__tests__/variableFilters.spec.ts +129 -0
- package/src/modules/filters/scripts/variableFilters.ts +43 -0
- package/types/.tsbuildinfo +1 -1
- package/types/modules/filters/composables/useFilterConfigsToolkit.d.ts +3 -3
- package/types/modules/filters/composables/useFilterValuePreview.d.ts +1 -1
- package/types/modules/filters/composables/useVariableColumnFilters.d.ts +18 -0
- package/types/modules/filters/index.d.ts +3 -1
- package/types/modules/filters/scripts/variableFilters.d.ts +19 -0
package/package.json
CHANGED
|
@@ -51,6 +51,34 @@ describe('card validation of a root-level required rule', () => {
|
|
|
51
51
|
expect(calendarErrors).toHaveLength(1);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
it.each([
|
|
55
|
+
QueueType.OUTBOUND_IVR_QUEUE,
|
|
56
|
+
QueueType.OUTBOUND_JOB_QUEUE,
|
|
57
|
+
])('reports a cleared calendar and schema of queue type %s on the fields', async (type) => {
|
|
58
|
+
const state = ref({
|
|
59
|
+
...getQueueDefaults(type),
|
|
60
|
+
name: 'a queue',
|
|
61
|
+
calendar: {},
|
|
62
|
+
schema: {},
|
|
63
|
+
});
|
|
64
|
+
const scope = effectScope(true);
|
|
65
|
+
// biome-ignore lint/suspicious/noExplicitAny: regle's inferred state type
|
|
66
|
+
let r$: any;
|
|
67
|
+
|
|
68
|
+
scope.run(() => {
|
|
69
|
+
({ r$ } = useRegleSchema(state, queueSchema as never));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const result = await r$.$validate();
|
|
73
|
+
|
|
74
|
+
expect(result.valid).toBe(false);
|
|
75
|
+
expect(r$.$error).toBe(true);
|
|
76
|
+
expect(r$.$fields.calendar.$error).toBe(true);
|
|
77
|
+
expect(r$.$fields.calendar.$errors.id).toHaveLength(1);
|
|
78
|
+
expect(r$.$fields.schema.$error).toBe(true);
|
|
79
|
+
expect(r$.$fields.schema.$errors.id).toHaveLength(1);
|
|
80
|
+
});
|
|
81
|
+
|
|
54
82
|
it('accepts the same draft once the calendar is filled', async () => {
|
|
55
83
|
const { valid, rootError } = await validateDraft({
|
|
56
84
|
...getQueueDefaults(QueueType.PREVIEW_DIALER),
|
|
@@ -35,7 +35,7 @@ const props = defineProps<{
|
|
|
35
35
|
const { t } = useI18n();
|
|
36
36
|
|
|
37
37
|
const { appliedFilterToFilterConfigMappings } = useFilterConfigsToolkit({
|
|
38
|
-
filterOptions: props.filterConfigs,
|
|
38
|
+
filterOptions: () => props.filterConfigs,
|
|
39
39
|
filtersManager: props.filtersManager,
|
|
40
40
|
});
|
|
41
41
|
</script>
|
package/src/modules/filters/components/config/static-view/__tests__/static-filter-field.spec.ts
CHANGED
|
@@ -168,10 +168,35 @@ describe('StaticFilterField', () => {
|
|
|
168
168
|
|
|
169
169
|
/* static mode used to force hideLabel on every value field, which left
|
|
170
170
|
select-based filters (has-option-filter-value-field) with no visible
|
|
171
|
-
label at all — the value field itself
|
|
172
|
-
it('does not force hideLabel on its value field', () => {
|
|
173
|
-
const
|
|
171
|
+
label at all — with showFilterName the value field itself decides whether to show one */
|
|
172
|
+
it('does not force hideLabel on its value field when showFilterName is set', () => {
|
|
173
|
+
const filterConfig = createFilterConfig({
|
|
174
|
+
name: FilterOption.Tag,
|
|
175
|
+
showFilterName: true,
|
|
176
|
+
valueInputComponent: StubInput,
|
|
177
|
+
});
|
|
178
|
+
filterConfig.label = 'Tags';
|
|
179
|
+
|
|
180
|
+
const wrapper = mountField(filterConfig, filtersManager);
|
|
181
|
+
|
|
182
|
+
expect(wrapper.findComponent(StubInput).props('hideLabel')).toBe(false);
|
|
183
|
+
expect(wrapper.findComponent(StubInput).attributes('placeholder')).not.toBe(
|
|
184
|
+
'Tags',
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('hides the label and shows the filter name as placeholder without showFilterName', () => {
|
|
189
|
+
const filterConfig = createFilterConfig({
|
|
190
|
+
name: FilterOption.Tag,
|
|
191
|
+
valueInputComponent: StubInput,
|
|
192
|
+
});
|
|
193
|
+
filterConfig.label = 'Tags';
|
|
194
|
+
|
|
195
|
+
const wrapper = mountField(filterConfig, filtersManager);
|
|
174
196
|
|
|
175
|
-
expect(wrapper.findComponent(StubInput).props('hideLabel')).
|
|
197
|
+
expect(wrapper.findComponent(StubInput).props('hideLabel')).toBe(true);
|
|
198
|
+
expect(wrapper.findComponent(StubInput).attributes('placeholder')).toBe(
|
|
199
|
+
'Tags',
|
|
200
|
+
);
|
|
176
201
|
});
|
|
177
202
|
});
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
:disable-default-value="true"
|
|
11
11
|
:disable-validation="true /*for static filters validation is not needed (different presentation with dynamic filters)*/"
|
|
12
12
|
:filter-config="filterConfig"
|
|
13
|
+
:hide-label="!filterConfig.showFilterName"
|
|
14
|
+
:placeholder="!filterConfig.showFilterName && filterConfig.label"
|
|
13
15
|
:static-view="true"
|
|
14
16
|
:model-value="filterValue"
|
|
15
17
|
@update:model-value="onValueChange"
|
|
@@ -104,9 +104,9 @@ const savePreset =
|
|
|
104
104
|
provideFilterReadAccess(() => props.hasReadAccess);
|
|
105
105
|
|
|
106
106
|
const { filterConfigs, filtersIncluded } = useFilterConfigsToolkit({
|
|
107
|
-
filterOptions: props.filterOptions,
|
|
107
|
+
filterOptions: () => props.filterOptions,
|
|
108
108
|
filtersManager: props.filtersManager,
|
|
109
|
-
filterableExtensionFields: props.filterableExtensionFields,
|
|
109
|
+
filterableExtensionFields: () => props.filterableExtensionFields,
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
const { listSelectedFilters, hasAnyFilters } = useSelectedFilters({
|
|
@@ -191,9 +191,9 @@ const {
|
|
|
191
191
|
appliedFilterToFilterConfigMappings,
|
|
192
192
|
unAppliedFiltersConfigs,
|
|
193
193
|
} = useFilterConfigsToolkit({
|
|
194
|
-
filterOptions: props.filterOptions,
|
|
194
|
+
filterOptions: () => props.filterOptions,
|
|
195
195
|
filtersManager: props.filtersManager,
|
|
196
|
-
filterableExtensionFields: props.filterableExtensionFields,
|
|
196
|
+
filterableExtensionFields: () => props.filterableExtensionFields,
|
|
197
197
|
staticMode: props.staticMode,
|
|
198
198
|
});
|
|
199
199
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { DataField } from '@webitel/api-services/gen/models';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type ComputedRef,
|
|
4
|
+
computed,
|
|
5
|
+
type MaybeRefOrGetter,
|
|
6
|
+
toValue,
|
|
7
|
+
} from 'vue';
|
|
3
8
|
import { useI18n } from 'vue-i18n';
|
|
4
9
|
|
|
5
10
|
import type { FilterName, IFilter } from '../classes/Filter';
|
|
@@ -42,9 +47,9 @@ export type FilterConfigToolkit = {
|
|
|
42
47
|
};
|
|
43
48
|
|
|
44
49
|
export type FilterConfigToolkitParams = {
|
|
45
|
-
filterOptions: (FilterOption | BaseFilterConfig)[]
|
|
50
|
+
filterOptions: MaybeRefOrGetter<(FilterOption | BaseFilterConfig)[]>;
|
|
46
51
|
filtersManager: IFiltersManager;
|
|
47
|
-
filterableExtensionFields?: DataField[]
|
|
52
|
+
filterableExtensionFields?: MaybeRefOrGetter<DataField[] | undefined>;
|
|
48
53
|
staticMode?: boolean;
|
|
49
54
|
};
|
|
50
55
|
|
|
@@ -57,7 +62,7 @@ export const useFilterConfigsToolkit = ({
|
|
|
57
62
|
|
|
58
63
|
const filterConfigs = computed(() => {
|
|
59
64
|
return (
|
|
60
|
-
filterOptions
|
|
65
|
+
toValue(filterOptions)
|
|
61
66
|
/**
|
|
62
67
|
* make filterConfigs from standard filterOptions
|
|
63
68
|
*/
|
|
@@ -91,7 +96,7 @@ export const useFilterConfigsToolkit = ({
|
|
|
91
96
|
* add filterConfigs for extension fields
|
|
92
97
|
*/
|
|
93
98
|
.concat(
|
|
94
|
-
filterableExtensionFields.map((field: DataField) => {
|
|
99
|
+
(toValue(filterableExtensionFields) ?? []).map((field: DataField) => {
|
|
95
100
|
return createTypeExtensionFilterConfig(
|
|
96
101
|
{
|
|
97
102
|
name: field.id,
|
|
@@ -27,10 +27,14 @@ export const useFilterValuePreview = ({
|
|
|
27
27
|
}) => {
|
|
28
28
|
const getHasReadAccess = injectFilterReadAccess();
|
|
29
29
|
const localValue = ref();
|
|
30
|
+
const isLoaded = ref(false);
|
|
30
31
|
|
|
31
32
|
const fillLocalValue = async (currentFilter = toValue(filter)) => {
|
|
33
|
+
isLoaded.value = false;
|
|
34
|
+
|
|
32
35
|
if (!currentFilter) {
|
|
33
36
|
localValue.value = undefined;
|
|
37
|
+
isLoaded.value = true;
|
|
34
38
|
return;
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -67,6 +71,8 @@ export const useFilterValuePreview = ({
|
|
|
67
71
|
} else {
|
|
68
72
|
localValue.value = filterValue;
|
|
69
73
|
}
|
|
74
|
+
|
|
75
|
+
isLoaded.value = true;
|
|
70
76
|
};
|
|
71
77
|
|
|
72
78
|
watch(
|
|
@@ -79,11 +85,7 @@ export const useFilterValuePreview = ({
|
|
|
79
85
|
},
|
|
80
86
|
);
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
// if type filter is boolean and value = false, need display preview
|
|
84
|
-
const isRenderPreview = computed(
|
|
85
|
-
() => localValue.value === false || localValue.value,
|
|
86
|
-
);
|
|
88
|
+
const isRenderPreview = computed(() => isLoaded.value);
|
|
87
89
|
|
|
88
90
|
return {
|
|
89
91
|
localValue,
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
2
|
+
import type { WtTableHeader } from '@webitel/ui-sdk/components/wt-table/types/WtTable';
|
|
3
|
+
import { WtTypeExtensionFieldKind } from '@webitel/ui-sdk/enums';
|
|
4
|
+
import { isVariableHeader } from '@webitel/ui-sdk/modules/TableVariableColumnSelect';
|
|
5
|
+
import { computed, type MaybeRefOrGetter, toValue } from 'vue';
|
|
6
|
+
import { useI18n } from 'vue-i18n';
|
|
7
|
+
|
|
8
|
+
import type { FilterInitParams, FilterName, IFilter } from '../classes/Filter';
|
|
9
|
+
import type { IFiltersManager } from '../classes/FiltersManager';
|
|
10
|
+
import { FilterOption } from '../modules/filterConfig/enums/FilterOption';
|
|
11
|
+
import {
|
|
12
|
+
isVariableFilterName,
|
|
13
|
+
toVariableFilterFields,
|
|
14
|
+
VARIABLE_FIELD_PREFIX,
|
|
15
|
+
variableKeyFromFilterName,
|
|
16
|
+
} from '../scripts/variableFilters';
|
|
17
|
+
|
|
18
|
+
const parseVariableFilterValue = (raw: string) =>
|
|
19
|
+
raw.split('&').reduce<Record<string, string>>((vars, pair) => {
|
|
20
|
+
const [key, value] = pair.split('=');
|
|
21
|
+
if (key) vars[key] = value ?? '';
|
|
22
|
+
return vars;
|
|
23
|
+
}, {});
|
|
24
|
+
|
|
25
|
+
export const useVariableColumnFilters = ({
|
|
26
|
+
shownHeaders,
|
|
27
|
+
filtersManager,
|
|
28
|
+
addFilter,
|
|
29
|
+
updateFilter,
|
|
30
|
+
deleteFilter,
|
|
31
|
+
}: {
|
|
32
|
+
shownHeaders: MaybeRefOrGetter<WtTableHeader[] | undefined>;
|
|
33
|
+
filtersManager: MaybeRefOrGetter<IFiltersManager>;
|
|
34
|
+
addFilter: (params: FilterInitParams) => IFilter;
|
|
35
|
+
updateFilter: (params: FilterInitParams) => IFilter;
|
|
36
|
+
deleteFilter: (params: { name: FilterName }) => IFilter | undefined;
|
|
37
|
+
}) => {
|
|
38
|
+
const { t } = useI18n();
|
|
39
|
+
|
|
40
|
+
const withVariableFilterLabel = (
|
|
41
|
+
params: FilterInitParams,
|
|
42
|
+
): FilterInitParams =>
|
|
43
|
+
isVariableFilterName(params.name)
|
|
44
|
+
? {
|
|
45
|
+
...params,
|
|
46
|
+
label: t('webitelUI.filters.variable'),
|
|
47
|
+
}
|
|
48
|
+
: params;
|
|
49
|
+
|
|
50
|
+
const variableFilterFields = computed<DataField[]>(() => {
|
|
51
|
+
const headers = toValue(shownHeaders) || [];
|
|
52
|
+
const columnHeaders = headers.filter(
|
|
53
|
+
(header) => isVariableHeader(header) && header.filtered,
|
|
54
|
+
);
|
|
55
|
+
const columnFields = toVariableFilterFields(columnHeaders);
|
|
56
|
+
|
|
57
|
+
const knownNames = new Set(columnFields.map((field) => field.id));
|
|
58
|
+
const appliedOnlyFields = toValue(filtersManager)
|
|
59
|
+
.getAllKeys()
|
|
60
|
+
.filter((name) => isVariableFilterName(name) && !knownNames.has(name))
|
|
61
|
+
.map((name) => ({
|
|
62
|
+
id: name,
|
|
63
|
+
name: variableKeyFromFilterName(name),
|
|
64
|
+
kind: WtTypeExtensionFieldKind.Text,
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
return [
|
|
68
|
+
...columnFields,
|
|
69
|
+
...appliedOnlyFields,
|
|
70
|
+
];
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const splitVariableFilter = (params: FilterInitParams) => {
|
|
74
|
+
const variables = parseVariableFilterValue(String(params.value ?? ''));
|
|
75
|
+
|
|
76
|
+
Object.entries(variables).forEach(([key, value]) => {
|
|
77
|
+
addFilter(
|
|
78
|
+
withVariableFilterLabel({
|
|
79
|
+
name: `${VARIABLE_FIELD_PREFIX}${key}`,
|
|
80
|
+
value,
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (toValue(filtersManager).hasFilter(FilterOption.Variable)) {
|
|
86
|
+
deleteFilter({
|
|
87
|
+
name: FilterOption.Variable,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleAddFilter = (params: FilterInitParams) => {
|
|
93
|
+
if (params.name === FilterOption.Variable) {
|
|
94
|
+
splitVariableFilter(params);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
addFilter(withVariableFilterLabel(params));
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const handleUpdateFilter = (params: FilterInitParams) => {
|
|
102
|
+
if (params.name === FilterOption.Variable) {
|
|
103
|
+
splitVariableFilter(params);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
updateFilter(withVariableFilterLabel(params));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
variableFilterFields,
|
|
112
|
+
handleAddFilter,
|
|
113
|
+
handleUpdateFilter,
|
|
114
|
+
};
|
|
115
|
+
};
|
|
@@ -16,9 +16,18 @@ import ColumnFilterComponent from './components/column/column-filter.vue';
|
|
|
16
16
|
import FiltersActionsMenuComponent from './components/filters-actions-menu.vue';
|
|
17
17
|
import DynamicFilterSearchComponent from './components/search-bar/dynamic-filter-search.vue';
|
|
18
18
|
import TableFiltersPanelComponent from './components/table-filters-panel.vue';
|
|
19
|
+
import { useVariableColumnFilters } from './composables/useVariableColumnFilters';
|
|
19
20
|
import { FilterOption } from './modules/filterConfig/enums/FilterOption';
|
|
20
21
|
|
|
21
22
|
export * from './modules/filterConfig';
|
|
23
|
+
export {
|
|
24
|
+
extractVariableFilters,
|
|
25
|
+
isVariableFilterName,
|
|
26
|
+
toVariableFilterFields,
|
|
27
|
+
VARIABLE_FIELD_PREFIX,
|
|
28
|
+
variableKeyFromFilterName,
|
|
29
|
+
withVariableColumnFilters,
|
|
30
|
+
} from './scripts/variableFilters';
|
|
22
31
|
export type {
|
|
23
32
|
FilterInitParams,
|
|
24
33
|
FilterInstanceConfig,
|
|
@@ -37,4 +46,5 @@ export {
|
|
|
37
46
|
FilterOption,
|
|
38
47
|
FiltersActionsMenuComponent,
|
|
39
48
|
TableFiltersPanelComponent,
|
|
49
|
+
useVariableColumnFilters,
|
|
40
50
|
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { WtTypeExtensionFieldKind } from '@webitel/ui-sdk/enums';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
extractVariableFilters,
|
|
6
|
+
isVariableFilterName,
|
|
7
|
+
toVariableFilterFields,
|
|
8
|
+
VARIABLE_FIELD_PREFIX,
|
|
9
|
+
variableKeyFromFilterName,
|
|
10
|
+
withVariableColumnFilters,
|
|
11
|
+
} from '../variableFilters';
|
|
12
|
+
|
|
13
|
+
const header = {
|
|
14
|
+
value: 'variables.sip_code',
|
|
15
|
+
field: 'variables.sip_code',
|
|
16
|
+
text: 'sip_code',
|
|
17
|
+
show: true,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('VARIABLE_FIELD_PREFIX', () => {
|
|
21
|
+
it('is defined correctly', () => {
|
|
22
|
+
expect(VARIABLE_FIELD_PREFIX).toBe('variables.');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('isVariableFilterName', () => {
|
|
27
|
+
it('returns true for names starting with VARIABLE_FIELD_PREFIX', () => {
|
|
28
|
+
expect(isVariableFilterName('variables.sip_code')).toBe(true);
|
|
29
|
+
expect(isVariableFilterName('variables.custom_field')).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('returns false for names not starting with VARIABLE_FIELD_PREFIX', () => {
|
|
33
|
+
expect(isVariableFilterName('agent')).toBe(false);
|
|
34
|
+
expect(isVariableFilterName('queue')).toBe(false);
|
|
35
|
+
expect(isVariableFilterName('var.sip_code')).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('variableKeyFromFilterName', () => {
|
|
40
|
+
it('extracts the variable key from filter name', () => {
|
|
41
|
+
expect(variableKeyFromFilterName('variables.sip_code')).toBe('sip_code');
|
|
42
|
+
expect(variableKeyFromFilterName('variables.custom_field')).toBe(
|
|
43
|
+
'custom_field',
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('returns empty string when called with just the prefix', () => {
|
|
48
|
+
expect(variableKeyFromFilterName('variables.')).toBe('');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('withVariableColumnFilters', () => {
|
|
53
|
+
it('names the header filter after the variable field, keeping the header itself', () => {
|
|
54
|
+
const [decorated] = withVariableColumnFilters([
|
|
55
|
+
header,
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
expect(decorated).toMatchObject(header);
|
|
59
|
+
expect(decorated.filter).toBe('variables.sip_code');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('toVariableFilterFields', () => {
|
|
64
|
+
it('describes the variable as a text field the column filter can resolve', () => {
|
|
65
|
+
expect(
|
|
66
|
+
toVariableFilterFields([
|
|
67
|
+
header,
|
|
68
|
+
]),
|
|
69
|
+
).toEqual([
|
|
70
|
+
{
|
|
71
|
+
id: 'variables.sip_code',
|
|
72
|
+
name: 'sip_code',
|
|
73
|
+
kind: WtTypeExtensionFieldKind.Text,
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('falls back to the key from the field when the header has no text', () => {
|
|
79
|
+
const [field] = toVariableFilterFields([
|
|
80
|
+
{
|
|
81
|
+
...header,
|
|
82
|
+
text: undefined,
|
|
83
|
+
},
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
expect(field.name).toBe('sip_code');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('extractVariableFilters', () => {
|
|
91
|
+
it('extracts only variable filters from params', () => {
|
|
92
|
+
const params = {
|
|
93
|
+
'variables.sip_code': '200',
|
|
94
|
+
'variables.custom_field': 'value',
|
|
95
|
+
agent: 'agent-123',
|
|
96
|
+
queue: 'queue-456',
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
expect(extractVariableFilters(params)).toEqual({
|
|
100
|
+
sip_code: '200',
|
|
101
|
+
custom_field: 'value',
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('converts undefined values to empty strings', () => {
|
|
106
|
+
const params = {
|
|
107
|
+
'variables.sip_code': undefined,
|
|
108
|
+
'variables.custom_field': 'value',
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
expect(extractVariableFilters(params)).toEqual({
|
|
112
|
+
sip_code: '',
|
|
113
|
+
custom_field: 'value',
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('returns empty object when no variable filters present', () => {
|
|
118
|
+
const params = {
|
|
119
|
+
agent: 'agent-123',
|
|
120
|
+
queue: 'queue-456',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
expect(extractVariableFilters(params)).toEqual({});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('returns empty object for empty params', () => {
|
|
127
|
+
expect(extractVariableFilters({})).toEqual({});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DataField } from '@webitel/api-services/gen/models';
|
|
2
|
+
import type { WtTableHeader } from '@webitel/ui-sdk/components/wt-table/types/WtTable';
|
|
3
|
+
import { WtTypeExtensionFieldKind } from '@webitel/ui-sdk/enums';
|
|
4
|
+
|
|
5
|
+
export const VARIABLE_FIELD_PREFIX = 'variables.';
|
|
6
|
+
|
|
7
|
+
export const isVariableFilterName = (name: string) =>
|
|
8
|
+
name.startsWith(VARIABLE_FIELD_PREFIX);
|
|
9
|
+
|
|
10
|
+
export const variableKeyFromFilterName = (name: string) =>
|
|
11
|
+
name.slice(VARIABLE_FIELD_PREFIX.length);
|
|
12
|
+
|
|
13
|
+
const variableFieldName = (header: WtTableHeader) =>
|
|
14
|
+
header.field ?? header.value;
|
|
15
|
+
|
|
16
|
+
export const withVariableColumnFilters = (headers: WtTableHeader[]) =>
|
|
17
|
+
headers.map((header) => ({
|
|
18
|
+
...header,
|
|
19
|
+
filter: variableFieldName(header),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
export const toVariableFilterFields = (headers: WtTableHeader[]): DataField[] =>
|
|
23
|
+
headers.map((header) => {
|
|
24
|
+
const field = variableFieldName(header);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
id: field,
|
|
28
|
+
name: header.text ?? variableKeyFromFilterName(field),
|
|
29
|
+
kind: WtTypeExtensionFieldKind.Text,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const extractVariableFilters = (params: Record<string, unknown>) =>
|
|
34
|
+
Object.entries(params).reduce<Record<string, string>>(
|
|
35
|
+
(vars, [name, value]) => {
|
|
36
|
+
if (!isVariableFilterName(name)) return vars;
|
|
37
|
+
|
|
38
|
+
vars[variableKeyFromFilterName(name)] =
|
|
39
|
+
value == null ? '' : String(value);
|
|
40
|
+
return vars;
|
|
41
|
+
},
|
|
42
|
+
{},
|
|
43
|
+
);
|