@webitel/ui-sdk 24.4.39 → 24.6.1
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/dist/ui-sdk.css +1 -1
- package/dist/ui-sdk.mjs +3439 -3353
- package/dist/ui-sdk.umd.js +11 -11
- package/package.json +4 -6
- package/src/components/transitions/wt-expand-transition.vue +63 -4
- package/src/components/wt-button/wt-button.vue +42 -6
- package/src/components/wt-expansion-panel/wt-expansion-panel.vue +0 -1
- package/src/components/wt-item-link/wt-item-link.vue +39 -9
- package/src/components/wt-player/wt-player.vue +8 -20
- package/src/components/wt-popup/__tests__/WtPopup.spec.js +5 -9
- package/src/components/wt-popup/_variables.scss +5 -0
- package/src/components/wt-popup/wt-popup.vue +88 -39
- package/src/components/wt-table/wt-table.vue +41 -6
- package/src/locale/en/en.js +0 -1
- package/src/locale/ru/ru.js +0 -1
- package/src/locale/ua/ua.js +0 -1
- package/src/modules/AuditForm/components/questions/options/__tests__/audit-form-question-options-write-row.spec.js +1 -1
- package/src/modules/AuditForm/components/questions/options/audit-form-question-options-write-row.vue +3 -15
- package/src/modules/AuditForm/components/questions/score/audit-form-question-score.vue +3 -6
- package/src/modules/Filters/classes/BaseFilterSchema.js +140 -7
- package/src/modules/Filters/components/__tests__/filter-pagination.spec.js +94 -0
- package/src/modules/Filters/components/__tests__/filter-table-fields.spec.js +71 -0
- package/src/modules/Filters/components/filter-pagination.vue +8 -8
- package/src/modules/Filters/components/filter-table-fields.vue +4 -11
- package/src/modules/Filters/composables/useTableFilters.js +2 -3
- package/src/modules/Filters/enums/FilterEvent.enum.js +6 -0
- package/src/modules/Filters/scripts/getters/index.js +9 -0
- package/src/modules/Filters/scripts/getters/localStorageGetter.js +17 -0
- package/src/modules/Filters/scripts/getters/queryGetter.js +10 -0
- package/src/modules/Filters/scripts/getters/valueGetter.js +9 -0
- package/src/modules/Filters/scripts/restores/index.js +7 -0
- package/src/modules/Filters/scripts/restores/localStorageRestore.js +7 -0
- package/src/modules/Filters/scripts/restores/queryRestore.js +7 -0
- package/src/modules/Filters/scripts/setters/index.js +9 -0
- package/src/modules/Filters/scripts/setters/localStorageSetter.js +16 -0
- package/src/modules/Filters/scripts/setters/querySetter.js +41 -0
- package/src/modules/Filters/scripts/setters/valueSetter.js +6 -0
- package/src/modules/Filters/scripts/utils/changeRouteQuery.js +17 -0
- package/src/modules/Filters/store/FiltersStoreModule.js +88 -139
- package/src/modules/Filters/store/__tests__/FiltersStoreModule.spec.js +157 -0
- package/src/modules/Notifications/store/__tests__/NotificationsStoreModule.actions.spec.js +1 -1
- package/src/modules/TableStoreModule/composables/useTableStore.js +13 -9
- package/src/modules/TableStoreModule/store/TableStoreModule.js +124 -106
- package/src/modules/TableStoreModule/store/__tests__/TableStoreModule.spec.js +241 -0
- package/src/modules/Filters/restores/filterFieldsRestore.js +0 -9
- package/src/modules/Filters/restores/readme.md +0 -1
|
@@ -16,7 +16,7 @@ describe('AuditFormQuestionOptionsWriteRow', () => {
|
|
|
16
16
|
option: {},
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
|
-
const deleteBtn = wrapper.findComponent('
|
|
19
|
+
const deleteBtn = wrapper.findComponent({ name: 'wt-icon-btn' });
|
|
20
20
|
expect(deleteBtn.attributes().icon).toBe('bucket');
|
|
21
21
|
deleteBtn.vm.$emit('click');
|
|
22
22
|
expect(wrapper.emitted().delete).toBeTruthy();
|
package/src/modules/AuditForm/components/questions/options/audit-form-question-options-write-row.vue
CHANGED
|
@@ -9,13 +9,10 @@
|
|
|
9
9
|
/>
|
|
10
10
|
<wt-input
|
|
11
11
|
:label="$t('webitelUI.auditForm.score', 1)"
|
|
12
|
-
:label-props="{ hint: $t('webitelUI.auditForm.scoreInputTooltip', { min: minScore, max: maxScore}), hintPosition: 'right' }"
|
|
13
12
|
:value="option.score"
|
|
14
13
|
:v="v$.option.score"
|
|
15
|
-
:number-min="minScore"
|
|
16
|
-
:number-max="maxScore"
|
|
17
14
|
type="number"
|
|
18
|
-
@input="
|
|
15
|
+
@input="emit('update:option', { name: option.name, score: $event })"
|
|
19
16
|
/>
|
|
20
17
|
<wt-tooltip class="audit-form-question-options-write-row__tooltip">
|
|
21
18
|
<template #activator>
|
|
@@ -58,9 +55,6 @@ const emit = defineEmits([
|
|
|
58
55
|
// is needed for useVuelidate, because props.question/props.result isn't reactive
|
|
59
56
|
const { option } = toRefs(props);
|
|
60
57
|
|
|
61
|
-
const minScore = 0;
|
|
62
|
-
const maxScore = 10;
|
|
63
|
-
|
|
64
58
|
const v$ = useVuelidate(
|
|
65
59
|
computed(() => (
|
|
66
60
|
{
|
|
@@ -68,8 +62,8 @@ const v$ = useVuelidate(
|
|
|
68
62
|
name: { required },
|
|
69
63
|
score: {
|
|
70
64
|
required,
|
|
71
|
-
minValue: minValue(
|
|
72
|
-
maxValue: maxValue(
|
|
65
|
+
minValue: minValue(0),
|
|
66
|
+
maxValue: maxValue(10),
|
|
73
67
|
decimalValidator: decimalValidator(2),
|
|
74
68
|
},
|
|
75
69
|
},
|
|
@@ -78,12 +72,6 @@ const v$ = useVuelidate(
|
|
|
78
72
|
{ $autoDirty: true },
|
|
79
73
|
);
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
function changeScore(value) {
|
|
83
|
-
const score = value > maxScore ? maxScore : Number(Math.abs(value)); // to prevent -1, 000 or string value because of this task https://webitel.atlassian.net/browse/WTEL-4505
|
|
84
|
-
emit('update:option', { name: props.option.name, score });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
75
|
// init validation
|
|
88
76
|
onMounted(() => v$.value.$touch());
|
|
89
77
|
</script>
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
:value="question.min"
|
|
9
9
|
:v="v$.question.min"
|
|
10
10
|
:number-min="0"
|
|
11
|
-
:number-max="
|
|
11
|
+
:number-max="19"
|
|
12
12
|
:label="$t('reusable.from')"
|
|
13
|
-
:label-props="{ hint: $t('webitelUI.auditForm.scoreInputTooltip', { min: '0', max: '9'}), hintPosition: 'right' }"
|
|
14
13
|
type="number"
|
|
15
14
|
required
|
|
16
15
|
@input="updateQuestion({ path: 'min', value: $event })"
|
|
@@ -19,9 +18,8 @@
|
|
|
19
18
|
:value="question.max"
|
|
20
19
|
:v="v$.question.max"
|
|
21
20
|
:number-min="1"
|
|
22
|
-
:number-max="
|
|
21
|
+
:number-max="20"
|
|
23
22
|
:label="$t('reusable.to')"
|
|
24
|
-
:label-props="{ hint: $t('webitelUI.auditForm.scoreInputTooltip', { min: '1', max: '10'}), hintPosition: 'right' }"
|
|
25
23
|
type="number"
|
|
26
24
|
required
|
|
27
25
|
@input="updateQuestion({ path: 'max', value: $event })"
|
|
@@ -111,8 +109,7 @@ const scoreRange = computed(() => {
|
|
|
111
109
|
const isResult = computed(() => !isEmpty(props.result));
|
|
112
110
|
|
|
113
111
|
function updateQuestion({ path, value }) {
|
|
114
|
-
|
|
115
|
-
emit('change:question', updateObject({ obj: props.question, path, value: number }));
|
|
112
|
+
emit('change:question', updateObject({ obj: props.question, path, value }));
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
// init validation
|
|
@@ -1,13 +1,146 @@
|
|
|
1
|
+
import { valueSetter, querySetter, localStorageSetter } from '../scripts/setters';
|
|
2
|
+
import { queryRestore, localStorageRestore } from '../scripts/restores';
|
|
3
|
+
import { valueGetter, queryGetter, localStorageGetter } from '../scripts/getters';
|
|
4
|
+
|
|
5
|
+
const convertGetterArray = (context) => (router) => (getters) => {
|
|
6
|
+
const availableGetters = ['value', 'query', 'localStorage'];
|
|
7
|
+
|
|
8
|
+
getters.forEach((getter) => {
|
|
9
|
+
if (!availableGetters.includes(getter)) throw new Error(`Unknown getter: ${getter}`);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const getter = () => {
|
|
13
|
+
if (getters.includes('value')) {
|
|
14
|
+
const value = valueGetter(context)();
|
|
15
|
+
if (value) return value;
|
|
16
|
+
}
|
|
17
|
+
if (getters.includes('query')) {
|
|
18
|
+
const value = queryGetter(context)(router)();
|
|
19
|
+
if (value) return value;
|
|
20
|
+
}
|
|
21
|
+
if (getters.includes('localStorage')) {
|
|
22
|
+
const value = localStorageGetter(context)();
|
|
23
|
+
if (value) return value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.error(`No value found for ${context.name} filter!`);
|
|
27
|
+
|
|
28
|
+
return undefined;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return getter;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const convertSetterArray = (context) => (router) => (setters) => {
|
|
35
|
+
const availableSetters = ['value', 'query', 'localStorage'];
|
|
36
|
+
setters.forEach((setter) => {
|
|
37
|
+
if (!availableSetters.includes(setter)) throw new Error(`Unknown setter: ${setter}`);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const setter = async (value) => {
|
|
41
|
+
if (setters.includes('value')) valueSetter(context)(value);
|
|
42
|
+
if (setters.includes('query')) await querySetter(context)(router)(value);
|
|
43
|
+
if (setters.includes('localStorage')) localStorageSetter(context)(value);
|
|
44
|
+
|
|
45
|
+
return context;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return setter;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const convertRestoreArray = (context) => (router) => (restores) => {
|
|
52
|
+
const availableRestores = ['query', 'localStorage'];
|
|
53
|
+
|
|
54
|
+
restores.forEach((restore) => {
|
|
55
|
+
if (!availableRestores.includes(restore)) throw new Error(`Unknown restore: ${restore}`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const restore = () => {
|
|
59
|
+
if (restores.includes('query')) {
|
|
60
|
+
const restoredValue = queryRestore(context)(router)();
|
|
61
|
+
if (restoredValue) return restoredValue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (restores.includes('localStorage')) {
|
|
65
|
+
const restoredValue = localStorageRestore(context)();
|
|
66
|
+
if (restoredValue) return restoredValue;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return restore;
|
|
71
|
+
};
|
|
72
|
+
|
|
1
73
|
export default class BaseFilterSchema {
|
|
2
74
|
constructor({
|
|
3
|
-
|
|
4
|
-
|
|
75
|
+
name,
|
|
76
|
+
value,
|
|
77
|
+
get,
|
|
78
|
+
set,
|
|
5
79
|
restore,
|
|
6
|
-
|
|
80
|
+
router, // is required for query get/set, if getters/setters are passed as strings
|
|
81
|
+
...rest
|
|
7
82
|
} = {}) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (
|
|
83
|
+
if (!name) throw new Error('Filter name is required');
|
|
84
|
+
if (value === undefined) throw new Error(`Filter value is required: ${name}`);
|
|
85
|
+
|
|
86
|
+
if (!get) throw new Error(`Filter getter is required: ${name}`);
|
|
87
|
+
if (!set) throw new Error(`Filter setter is required: ${name}`);
|
|
88
|
+
if (!restore) throw new Error(`Filter restore is required: ${name}`);
|
|
89
|
+
|
|
90
|
+
Object.assign(this, {
|
|
91
|
+
name,
|
|
92
|
+
value,
|
|
93
|
+
get,
|
|
94
|
+
set,
|
|
95
|
+
restore,
|
|
96
|
+
}, rest);
|
|
97
|
+
|
|
98
|
+
this.setupGetters(get, { router });
|
|
99
|
+
this.setupSetters(set, { router });
|
|
100
|
+
this.setupRestores(restore, { router });
|
|
101
|
+
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
setupGetters(getters, { router }) {
|
|
106
|
+
let getter;
|
|
107
|
+
|
|
108
|
+
if (Array.isArray(getters)) {
|
|
109
|
+
getter = convertGetterArray(this)(router)(getters);
|
|
110
|
+
} else if (typeof getters === 'function') {
|
|
111
|
+
getter = getters(this);
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error('Getter should be a function or an array of available getters');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.get = getter;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
setupSetters(setters, { router }) {
|
|
120
|
+
let setter;
|
|
121
|
+
|
|
122
|
+
if (Array.isArray(setters)) {
|
|
123
|
+
setter = convertSetterArray(this)(router)(setters);
|
|
124
|
+
} else if (typeof setters === 'function') {
|
|
125
|
+
setter = setters(this);
|
|
126
|
+
} else {
|
|
127
|
+
throw new Error('Setter should be a function or an array of available setters');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.set = setter;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setupRestores(restores, { router }) {
|
|
134
|
+
let restore;
|
|
135
|
+
|
|
136
|
+
if (Array.isArray(restores)) {
|
|
137
|
+
restore = convertRestoreArray(this)(router)(restores);
|
|
138
|
+
} else if (typeof restores === 'function') {
|
|
139
|
+
restore = restores(this);
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error('Restore should be a function or an array of available restores');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.restore = restore;
|
|
12
145
|
}
|
|
13
146
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { createStore } from 'vuex';
|
|
3
|
+
import FiltersStoreModule from '../../store/FiltersStoreModule';
|
|
4
|
+
import FilterPagination from '../filter-pagination.vue';
|
|
5
|
+
|
|
6
|
+
const filtersSchema = [
|
|
7
|
+
{
|
|
8
|
+
name: 'page',
|
|
9
|
+
value: 1,
|
|
10
|
+
get: ['value'],
|
|
11
|
+
set: ['value'],
|
|
12
|
+
restore: () => {},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'size',
|
|
16
|
+
value: 11,
|
|
17
|
+
get: ['value'],
|
|
18
|
+
set: ['value'],
|
|
19
|
+
restore: () => {},
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
describe('FilterPagination', () => {
|
|
24
|
+
it('renders a component', () => {
|
|
25
|
+
const store = createStore({
|
|
26
|
+
modules: {
|
|
27
|
+
filters: new FiltersStoreModule().addFilter(filtersSchema).getModule(),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const wrapper = mount(FilterPagination, {
|
|
32
|
+
props: {
|
|
33
|
+
namespace: 'filters',
|
|
34
|
+
},
|
|
35
|
+
global: {
|
|
36
|
+
plugins: [store],
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
expect(wrapper.exists()).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('size change dispatches SET_FILTER action', async () => {
|
|
43
|
+
const store = createStore({
|
|
44
|
+
modules: {
|
|
45
|
+
filters: new FiltersStoreModule().addFilter(filtersSchema).getModule(),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const wrapper = mount(FilterPagination, {
|
|
50
|
+
shallow: true,
|
|
51
|
+
props: {
|
|
52
|
+
namespace: 'filters',
|
|
53
|
+
},
|
|
54
|
+
global: {
|
|
55
|
+
plugins: [store],
|
|
56
|
+
stubs: {
|
|
57
|
+
WtPagination: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const pagination = wrapper.findComponent('.wt-pagination');
|
|
63
|
+
pagination.vm.$emit('input', 321);
|
|
64
|
+
pagination.vm.$emit('change');
|
|
65
|
+
await wrapper.vm.$nextTick();
|
|
66
|
+
expect(store.getters['filters/GET_FILTER']('size')).toBe(321);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('page change dispatches SET_FILTER action', async () => {
|
|
70
|
+
const store = createStore({
|
|
71
|
+
modules: {
|
|
72
|
+
filters: new FiltersStoreModule().addFilter(filtersSchema).getModule(),
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const wrapper = mount(FilterPagination, {
|
|
77
|
+
shallow: true,
|
|
78
|
+
props: {
|
|
79
|
+
namespace: 'filters',
|
|
80
|
+
},
|
|
81
|
+
global: {
|
|
82
|
+
plugins: [store],
|
|
83
|
+
stubs: {
|
|
84
|
+
WtPagination: false,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const pagination = wrapper.findComponent('.wt-pagination');
|
|
90
|
+
pagination.vm.$emit('next');
|
|
91
|
+
await wrapper.vm.$nextTick();
|
|
92
|
+
expect(store.getters['filters/GET_FILTER']('page')).toBe(2);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createStore } from 'vuex';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import FiltersStoreModule from '../../store/FiltersStoreModule';
|
|
4
|
+
import FilterTableFields from '../filter-table-fields.vue';
|
|
5
|
+
|
|
6
|
+
const filterSchema = {
|
|
7
|
+
name: 'fields',
|
|
8
|
+
value: ['field2'],
|
|
9
|
+
get: ['value'],
|
|
10
|
+
set: ['value'],
|
|
11
|
+
restore: () => {},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
describe('FilterTableFields', () => {
|
|
15
|
+
it('renders a component', () => {
|
|
16
|
+
const store = createStore({
|
|
17
|
+
modules: {
|
|
18
|
+
filters: new FiltersStoreModule().addFilter(filterSchema).getModule(),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const headers = [
|
|
23
|
+
{ value: 'f1', field: 'field1', show: false },
|
|
24
|
+
{ value: 'f2', field: 'field2', show: true },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const wrapper = mount(FilterTableFields, {
|
|
28
|
+
props: {
|
|
29
|
+
namespace: 'filters',
|
|
30
|
+
headers,
|
|
31
|
+
},
|
|
32
|
+
global: {
|
|
33
|
+
plugins: [store],
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
expect(wrapper.exists()).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('fields change dispatches SET_FILTER action', async () => {
|
|
40
|
+
const store = createStore({
|
|
41
|
+
modules: {
|
|
42
|
+
filters: new FiltersStoreModule().addFilter(filterSchema).getModule(),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const headers = [
|
|
47
|
+
{ value: 'f1', field: 'field1', show: false },
|
|
48
|
+
{ value: 'f2', field: 'field2', show: true },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const wrapper = mount(FilterTableFields, {
|
|
52
|
+
shallow: true,
|
|
53
|
+
props: {
|
|
54
|
+
namespace: 'filters',
|
|
55
|
+
headers,
|
|
56
|
+
},
|
|
57
|
+
global: {
|
|
58
|
+
plugins: [store],
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
wrapper.findComponent({ name: 'WtTableColumnSelect' }).vm.$emit('change', [
|
|
63
|
+
{ value: 'f1', field: 'field1', show: true },
|
|
64
|
+
{ value: 'f2', field: 'field2', show: false },
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
await wrapper.vm.$nextTick();
|
|
68
|
+
|
|
69
|
+
expect(store.getters['filters/GET_FILTER']('fields')).toEqual(['f1']);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -34,26 +34,26 @@ const store = useStore();
|
|
|
34
34
|
|
|
35
35
|
const localSize = ref(0);
|
|
36
36
|
|
|
37
|
-
const page = computed(() =>
|
|
38
|
-
const size = computed(() =>
|
|
37
|
+
const page = computed(() => store.getters[`${props.namespace}/GET_FILTER`](pageFilterName));
|
|
38
|
+
const size = computed(() => store.getters[`${props.namespace}/GET_FILTER`](sizeFilterName));
|
|
39
39
|
|
|
40
40
|
function setFilter(payload) {
|
|
41
41
|
return store.dispatch(`${props.namespace}/SET_FILTER`, payload);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function setPage(value) {
|
|
45
|
-
return setFilter({ value,
|
|
45
|
+
return setFilter({ value, name: pageFilterName });
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function setSize(value) {
|
|
49
49
|
if (value === size.value) return;
|
|
50
|
-
|
|
51
|
-
return setFilter({ value, filter: sizeFilterName });
|
|
50
|
+
return setFilter({ value, name: sizeFilterName });
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
// TF?
|
|
54
|
+
// watch(size, () => {
|
|
55
|
+
// localSize.value = size.value;
|
|
56
|
+
// }, { immediate: true });
|
|
57
57
|
</script>
|
|
58
58
|
|
|
59
59
|
<style lang="scss" scoped>
|
|
@@ -22,35 +22,28 @@ const props = defineProps({
|
|
|
22
22
|
},
|
|
23
23
|
staticHeaders: {
|
|
24
24
|
type: Array,
|
|
25
|
+
default: () => [],
|
|
25
26
|
},
|
|
26
27
|
});
|
|
27
28
|
|
|
28
|
-
const emit = defineEmits(
|
|
29
|
+
const emit = defineEmits([
|
|
29
30
|
'change',
|
|
30
|
-
);
|
|
31
|
+
]);
|
|
31
32
|
|
|
32
|
-
// const storedProp = 'value';
|
|
33
33
|
const filterQuery = 'fields';
|
|
34
34
|
|
|
35
35
|
const store = useStore();
|
|
36
36
|
|
|
37
|
-
const filterSchema = computed(() => getNamespacedState(store.state, props.namespace)[filterQuery]);
|
|
38
|
-
|
|
39
37
|
function setValue(payload) {
|
|
40
38
|
return store.dispatch(`${props.namespace}/SET_FILTER`, payload);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
function setToLocalStorage({ value }) {
|
|
44
|
-
localStorage.setItem(filterSchema.value.localStorageKey, value);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
41
|
function handleChange(headers) {
|
|
48
42
|
const value = headers.filter((item) => item.show).map(({ value }) => value);
|
|
49
43
|
const params = {
|
|
50
|
-
|
|
44
|
+
name: filterQuery,
|
|
51
45
|
value,
|
|
52
46
|
};
|
|
53
|
-
setToLocalStorage(params);
|
|
54
47
|
setValue(params);
|
|
55
48
|
emit('change', headers);
|
|
56
49
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// context === filter "this"
|
|
2
|
+
const localStorageGetter = (context) => () => {
|
|
3
|
+
if (!context) throw new Error('Filter context is required for localStorageGetter!');
|
|
4
|
+
|
|
5
|
+
const key = context.localStorageKey;
|
|
6
|
+
|
|
7
|
+
if (!key) throw new Error(`Please provide "localStorageKey" for ${context.name} filter!`);
|
|
8
|
+
|
|
9
|
+
const value = localStorage.getItem(key);
|
|
10
|
+
if (!value) return null;
|
|
11
|
+
|
|
12
|
+
const splitted = value.split(',');
|
|
13
|
+
if (splitted.length === 1) return splitted[0];
|
|
14
|
+
return splitted;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default localStorageGetter;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
// context === filter "this"
|
|
3
|
+
const queryGetter = (context) => (router) => () => {
|
|
4
|
+
if (!router) throw new Error('Router is required for queryGetter!');
|
|
5
|
+
if (!router) throw new Error('Router is required for queryGetter!');
|
|
6
|
+
|
|
7
|
+
return router.currentRoute.value.query[context.name];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default queryGetter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// context === filter "this"
|
|
2
|
+
const valueGetter = (context) => () => {
|
|
3
|
+
const { value, storedProp, multiple } = context;
|
|
4
|
+
if (multiple) return value.map((item) => item[storedProp]); // if arr, map
|
|
5
|
+
if (storedProp) return value[storedProp]; // if object and has specific prop, return this prop
|
|
6
|
+
return value; // else return val
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default valueGetter;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// context === filter "this"
|
|
2
|
+
|
|
3
|
+
const localStorageSetter = (context) => (rawValue) => {
|
|
4
|
+
if (!context) throw new Error('Filter context is required for localStorageSetter!');
|
|
5
|
+
|
|
6
|
+
const key = context.localStorageKey;
|
|
7
|
+
|
|
8
|
+
if (!key) throw new Error(`Please provide "localStorageKey" for ${context.name} filter!`);
|
|
9
|
+
|
|
10
|
+
const value = Array.isArray(rawValue) ? rawValue.join(',') : rawValue;
|
|
11
|
+
localStorage.setItem(key, value);
|
|
12
|
+
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default localStorageSetter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import changeRouteQuery from '../utils/changeRouteQuery';
|
|
2
|
+
|
|
3
|
+
const isObject = (value) => typeof value === 'object' &&
|
|
4
|
+
!Array.isArray(value) && value !== null;
|
|
5
|
+
|
|
6
|
+
const handlePrimitive = ({ value }) => value;
|
|
7
|
+
|
|
8
|
+
const handleObject = ({ value, storedProp }) => value[storedProp];
|
|
9
|
+
|
|
10
|
+
const handleArray = ({ value, storedProp }) => {
|
|
11
|
+
if (!value.length) return [];
|
|
12
|
+
|
|
13
|
+
if (isObject(value[0])) {
|
|
14
|
+
value.map((item) => item[storedProp]);
|
|
15
|
+
} else {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const querySetter = (context) => (router) => async (rawValue = context.value) => {
|
|
21
|
+
const { name: filterQuery, storedProp } = this;
|
|
22
|
+
|
|
23
|
+
let value = '';
|
|
24
|
+
|
|
25
|
+
if (Array.isArray(rawValue)) {
|
|
26
|
+
value = handleArray({ value: rawValue, storedProp });
|
|
27
|
+
} else if (isObject(rawValue)) {
|
|
28
|
+
value = handleObject({ value: rawValue, storedProp });
|
|
29
|
+
} else {
|
|
30
|
+
value = handlePrimitive({ value });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await changeRouteQuery(router)({
|
|
34
|
+
filterQuery,
|
|
35
|
+
value,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return context;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default querySetter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import deepEqual from 'deep-equal';
|
|
2
|
+
|
|
3
|
+
const changeRouteQuery = (router) => ({ filterQuery, value }) => {
|
|
4
|
+
if (deepEqual(router.currentRoute.value.query[filterQuery], value)) return;
|
|
5
|
+
|
|
6
|
+
const newQuery = {
|
|
7
|
+
...router.currentRoute.value.query,
|
|
8
|
+
[filterQuery]: value,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return router.replace({
|
|
12
|
+
name: router.currentRoute.value.name,
|
|
13
|
+
query: newQuery,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default changeRouteQuery;
|