@webitel/ui-datalist 1.0.0 → 1.0.2
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 +19 -0
- package/package.json +3 -1
- package/src/filter-presets/api/PresetQuery.api.ts +122 -0
- package/src/filter-presets/components/_shared/input-fields/preset-description-field.vue +32 -0
- package/src/filter-presets/components/_shared/input-fields/preset-name-field.vue +28 -0
- package/src/filter-presets/components/_shared/preset-filters-preview.vue +45 -0
- package/src/filter-presets/components/apply-preset/apply-preset-action.vue +234 -0
- package/src/filter-presets/components/apply-preset/preset-preview.vue +210 -0
- package/src/filter-presets/components/save-preset/overwrite-preset-popup.vue +64 -0
- package/src/filter-presets/components/save-preset/save-preset-action.vue +139 -0
- package/src/filter-presets/components/save-preset/save-preset-popup.vue +136 -0
- package/src/filter-presets/index.ts +5 -0
- package/src/filter-presets/stores/createFilterPresetsStore.ts +17 -0
- package/src/filter-presets/stores/headers/headers.ts +24 -0
- package/src/filters/classes/Filter.ts +30 -0
- package/src/filters/classes/FilterStorage.ts +34 -0
- package/src/filters/classes/FilterStorageOptions.d.ts +6 -0
- package/src/filters/classes/FiltersManager.ts +190 -0
- package/src/filters/components/config/dynamic-filter-config-form-label.vue +49 -0
- package/src/filters/components/config/dynamic-filter-config-form.vue +139 -0
- package/src/filters/components/config/dynamic-filter-config-view.vue +40 -0
- package/src/filters/components/dynamic-filter-add-action.vue +54 -0
- package/src/filters/components/dynamic-filter-panel-wrapper.vue +57 -0
- package/src/filters/components/dynamic-filter-search.vue +60 -0
- package/src/filters/components/filter-options/_shared/composables/booleanFilterToolkit.ts +39 -0
- package/src/filters/components/filter-options/_shared/composables/useFromToSecToPreviewTime.ts +41 -0
- package/src/filters/components/filter-options/_shared/date-time-filter/date-time-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/_shared/durations/duration-filter-value-field.vue +84 -0
- package/src/filters/components/filter-options/_shared/has-options/has-option-filter-value-field.vue +38 -0
- package/src/filters/components/filter-options/_shared/types/BooleanFilter.ts +1 -0
- package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-field.vue +18 -0
- package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-field.vue +18 -0
- package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/agent/agent-filter-value-field.vue +58 -0
- package/src/filters/components/filter-options/agent/agent-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/agent/config.js +4 -0
- package/src/filters/components/filter-options/amd-result/amd-result-filter-value-field.vue +52 -0
- package/src/filters/components/filter-options/amd-result/amd-result-filter-value-preview.vue +18 -0
- package/src/filters/components/filter-options/assignee/assignee-filter-value-field.vue +73 -0
- package/src/filters/components/filter-options/assignee/assignee-filter-value-preview.vue +36 -0
- package/src/filters/components/filter-options/assignee/config.js +4 -0
- package/src/filters/components/filter-options/author/author-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/author/author-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/author/config.js +4 -0
- package/src/filters/components/filter-options/cause/cause-filter-value-field.vue +52 -0
- package/src/filters/components/filter-options/cause/cause-filter-value-preview.vue +18 -0
- package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-field.vue +102 -0
- package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-preview.vue +34 -0
- package/src/filters/components/filter-options/close-reason-groups-case/config.js +7 -0
- package/src/filters/components/filter-options/contact/config.js +4 -0
- package/src/filters/components/filter-options/contact/contact-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/contact/contact-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/contact-group/config.js +4 -0
- package/src/filters/components/filter-options/contact-group/contact-group-filter-value-field.vue +74 -0
- package/src/filters/components/filter-options/contact-group/contact-group-filter-value-preview.vue +38 -0
- package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-field.vue +24 -0
- package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-preview.vue +15 -0
- package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-field.vue +24 -0
- package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-preview.vue +15 -0
- package/src/filters/components/filter-options/direction/direction-filter-value-field.vue +51 -0
- package/src/filters/components/filter-options/direction/direction-filter-value-preview.vue +17 -0
- package/src/filters/components/filter-options/gateway/config.js +4 -0
- package/src/filters/components/filter-options/gateway/gateway-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/gateway/gateway-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/grantee/config.js +4 -0
- package/src/filters/components/filter-options/grantee/grantee-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/grantee/grantee-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-field.vue +43 -0
- package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-preview.vue +24 -0
- package/src/filters/components/filter-options/has-file/has-file-filter-value-field.vue +33 -0
- package/src/filters/components/filter-options/has-file/has-file-filter-value-preview.vue +15 -0
- package/src/filters/components/filter-options/has-rating/has-rating-filter-value-field.vue +33 -0
- package/src/filters/components/filter-options/has-rating/has-rating-filter-value-preview.vue +15 -0
- package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-field.vue +33 -0
- package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-preview.vue +15 -0
- package/src/filters/components/filter-options/impacted/config.js +4 -0
- package/src/filters/components/filter-options/impacted/impacted-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/impacted/impacted-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/index.ts +250 -0
- package/src/filters/components/filter-options/priority-case/config.js +4 -0
- package/src/filters/components/filter-options/priority-case/priority-case-filter-value-field.vue +57 -0
- package/src/filters/components/filter-options/priority-case/priority-case-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/queue/config.js +4 -0
- package/src/filters/components/filter-options/queue/queue-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/queue/queue-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/rated-by/config.js +4 -0
- package/src/filters/components/filter-options/rated-by/rated-by-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/rated-by/rated-by-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/rating/rating-from-to-filter-value-field.vue +100 -0
- package/src/filters/components/filter-options/rating/rating-from-to-filter-value-preview.vue +39 -0
- package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-field.vue +18 -0
- package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/reporter/config.js +4 -0
- package/src/filters/components/filter-options/reporter/reporter-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/reporter/reporter-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-field.vue +18 -0
- package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/score/score-from-to-filter-value-field.vue +100 -0
- package/src/filters/components/filter-options/score/score-from-to-filter-value-preview.vue +39 -0
- package/src/filters/components/filter-options/service-case/config.js +6 -0
- package/src/filters/components/filter-options/service-case/service-case-filter-value-field.vue +82 -0
- package/src/filters/components/filter-options/service-case/service-case-filter-value-preview.vue +34 -0
- package/src/filters/components/filter-options/sla/config.js +4 -0
- package/src/filters/components/filter-options/sla/sla-filter-value-field.vue +57 -0
- package/src/filters/components/filter-options/sla/sla-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/sla-condition/config.js +6 -0
- package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-field.vue +98 -0
- package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-preview.vue +37 -0
- package/src/filters/components/filter-options/source-case/config.js +4 -0
- package/src/filters/components/filter-options/source-case/source-case-filter-value-field.vue +57 -0
- package/src/filters/components/filter-options/source-case/source-case-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/status-case/config.js +7 -0
- package/src/filters/components/filter-options/status-case/status-case-filter-value-field.vue +102 -0
- package/src/filters/components/filter-options/status-case/status-case-filter-value-preview.vue +37 -0
- package/src/filters/components/filter-options/tag/tag-filter-value-field.vue +52 -0
- package/src/filters/components/filter-options/tag/tag-filter-value-preview.vue +38 -0
- package/src/filters/components/filter-options/talk-duration/TalkDurationFilter.d.ts +4 -0
- package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-field.vue +19 -0
- package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/team/config.js +4 -0
- package/src/filters/components/filter-options/team/team-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/team/team-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/total-duration/TotalDurationFilter.d.ts +4 -0
- package/src/filters/components/filter-options/total-duration/total-duration-filter-value-field.vue +19 -0
- package/src/filters/components/filter-options/total-duration/total-duration-filter-value-preview.vue +44 -0
- package/src/filters/components/filter-options/user/config.js +4 -0
- package/src/filters/components/filter-options/user/user-filter-value-field.vue +56 -0
- package/src/filters/components/filter-options/user/user-filter-value-preview.vue +31 -0
- package/src/filters/components/filter-options/variable/variable-filter-value-field.vue +49 -0
- package/src/filters/components/filter-options/variable/variable-filter-value-preview.vue +39 -0
- package/src/filters/components/preview/dynamic-filter-preview-info.vue +35 -0
- package/src/filters/components/preview/dynamic-filter-preview.vue +76 -0
- package/src/filters/components/table-filters-panel.vue +83 -0
- package/src/filters/createTableFiltersStore.ts +81 -0
- package/src/filters/enums/FilterOption.ts +43 -0
- package/src/filters/enums/amd-result-options.ts +38 -0
- package/src/filters/enums/boolean-options.ts +16 -0
- package/src/filters/enums/direction-options.ts +20 -0
- package/src/filters/enums/hangup-cause-options.ts +265 -0
- package/src/filters/enums/tag-options.ts +8 -0
- package/src/filters/index.ts +27 -0
- package/src/filters/scripts/utils.ts +31 -0
- package/src/filters/types/Filter.d.ts +46 -0
- package/src/filters/types/FiltersManager.d.ts +76 -0
- package/src/headers/createTableHeadersStore.ts +140 -0
- package/src/index.d.ts +0 -0
- package/src/index.ts +3 -0
- package/src/pagination/createTablePaginationStore.ts +64 -0
- package/src/persist/PersistedStorage.types.ts +51 -0
- package/src/persist/useLocalStoragePersistedStorage.ts +37 -0
- package/src/persist/usePersistedStorage.ts +151 -0
- package/src/persist/useRoutePersistedStorage.ts +41 -0
- package/src/table/createTableStore.store.ts +206 -0
- package/src/types/tableStore.types.ts +61 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wt-select
|
|
3
|
+
:close-on-select="false"
|
|
4
|
+
:label="t('webitelUI.filters.filterValue')"
|
|
5
|
+
:search-method="searchMethod"
|
|
6
|
+
:value="model"
|
|
7
|
+
:v="v$.model"
|
|
8
|
+
multiple
|
|
9
|
+
use-value-from-options-by-prop="id"
|
|
10
|
+
@input="handleInput"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import { useVuelidate } from '@vuelidate/core';
|
|
16
|
+
import { required } from '@vuelidate/validators';
|
|
17
|
+
import { WtSelect } from '@webitel/ui-sdk/src/components/index';
|
|
18
|
+
import { computed, watch } from 'vue';
|
|
19
|
+
import { useI18n } from 'vue-i18n';
|
|
20
|
+
|
|
21
|
+
import { searchMethod } from './config.js';
|
|
22
|
+
|
|
23
|
+
type ModelValue = number[];
|
|
24
|
+
|
|
25
|
+
const model = defineModel<ModelValue>();
|
|
26
|
+
|
|
27
|
+
const emit = defineEmits<{
|
|
28
|
+
'update:invalid': [boolean];
|
|
29
|
+
}>();
|
|
30
|
+
const { t } = useI18n();
|
|
31
|
+
|
|
32
|
+
const v$ = useVuelidate(
|
|
33
|
+
computed(() => ({
|
|
34
|
+
model: {
|
|
35
|
+
required,
|
|
36
|
+
},
|
|
37
|
+
})),
|
|
38
|
+
{ model },
|
|
39
|
+
{ $autoDirty: true },
|
|
40
|
+
);
|
|
41
|
+
v$.value.$touch();
|
|
42
|
+
|
|
43
|
+
watch(
|
|
44
|
+
() => v$.value.$invalid,
|
|
45
|
+
(invalid) => {
|
|
46
|
+
emit('update:invalid', invalid);
|
|
47
|
+
},
|
|
48
|
+
{ immediate: true },
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const handleInput = (value: ModelValue) => {
|
|
52
|
+
model.value = value;
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ul v-if="localValue">
|
|
3
|
+
<li
|
|
4
|
+
v-for="({ name }, index) of localValue"
|
|
5
|
+
:key="index"
|
|
6
|
+
>
|
|
7
|
+
{{ name }}
|
|
8
|
+
</li>
|
|
9
|
+
</ul>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script lang="ts" setup>
|
|
13
|
+
import { ref } from 'vue';
|
|
14
|
+
|
|
15
|
+
import { searchMethod } from './config.js';
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
value: number[];
|
|
19
|
+
}>();
|
|
20
|
+
|
|
21
|
+
const localValue = ref([]);
|
|
22
|
+
|
|
23
|
+
const getLocalValue = async () => {
|
|
24
|
+
const { items } = await searchMethod({ id: props.value });
|
|
25
|
+
localValue.value = items;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
getLocalValue();
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<style lang="scss" scoped></style>
|
package/src/filters/components/filter-options/total-duration/total-duration-filter-value-field.vue
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<duration-filter-value-field
|
|
3
|
+
:model-value="model"
|
|
4
|
+
@update:model-value="model = $event"
|
|
5
|
+
@update:invalid="emit('update:invalid', $event)"
|
|
6
|
+
/>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
import DurationFilterValueField from '../_shared/durations/duration-filter-value-field.vue';
|
|
11
|
+
import type { TotalDurationFilterModelValue } from './TotalDurationFilter';
|
|
12
|
+
|
|
13
|
+
const model = defineModel<TotalDurationFilterModelValue>();
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
'update:invalid': [boolean];
|
|
16
|
+
}>();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<style lang="scss" scoped></style>
|
package/src/filters/components/filter-options/total-duration/total-duration-filter-value-preview.vue
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="total-duration-filter-value-preview">
|
|
3
|
+
<div v-if="from">
|
|
4
|
+
<p class="total-duration-filter-value-preview__title">
|
|
5
|
+
{{ t('reusable.from') }}
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<span>{{ from }}</span>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div v-if="to">
|
|
12
|
+
<p class="total-duration-filter-value-preview__title">
|
|
13
|
+
{{ t('reusable.to') }}
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<span>{{ to }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script lang="ts" setup>
|
|
22
|
+
import { useI18n } from 'vue-i18n';
|
|
23
|
+
|
|
24
|
+
import { useFromToSecToPreviewTime } from '../_shared/composables/useFromToSecToPreviewTime';
|
|
25
|
+
import type { TalkDurationFilterModelValue } from '../talk-duration/TalkDurationFilter';
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
value: TalkDurationFilterModelValue;
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
const { t } = useI18n();
|
|
32
|
+
|
|
33
|
+
const { from, to } = useFromToSecToPreviewTime(props.value);
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<style lang="scss" scoped>
|
|
37
|
+
@use '@webitel/styleguide/typography' as *;
|
|
38
|
+
|
|
39
|
+
.duration-filter-value-preview {
|
|
40
|
+
&__title {
|
|
41
|
+
@extend %typo-subtitle-1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wt-select
|
|
3
|
+
:close-on-select="false"
|
|
4
|
+
:label="t('webitelUI.filters.filterValue')"
|
|
5
|
+
:search-method="searchMethod"
|
|
6
|
+
:value="model"
|
|
7
|
+
:v="v$.model"
|
|
8
|
+
multiple
|
|
9
|
+
use-value-from-options-by-prop="id"
|
|
10
|
+
@input="handleInput"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import { useVuelidate } from '@vuelidate/core';
|
|
16
|
+
import { required } from '@vuelidate/validators';
|
|
17
|
+
import { WtSelect } from '@webitel/ui-sdk/src/components/index';
|
|
18
|
+
import { computed, watch } from 'vue';
|
|
19
|
+
import { useI18n } from 'vue-i18n';
|
|
20
|
+
|
|
21
|
+
import { searchMethod } from './config.js';
|
|
22
|
+
|
|
23
|
+
type ModelValue = number[];
|
|
24
|
+
|
|
25
|
+
const model = defineModel<ModelValue>();
|
|
26
|
+
|
|
27
|
+
const emit = defineEmits<{
|
|
28
|
+
'update:invalid': [boolean];
|
|
29
|
+
}>();
|
|
30
|
+
const { t } = useI18n();
|
|
31
|
+
|
|
32
|
+
const v$ = useVuelidate(
|
|
33
|
+
computed(() => ({
|
|
34
|
+
model: {
|
|
35
|
+
required,
|
|
36
|
+
},
|
|
37
|
+
})),
|
|
38
|
+
{ model },
|
|
39
|
+
{ $autoDirty: true },
|
|
40
|
+
);
|
|
41
|
+
v$.value.$touch();
|
|
42
|
+
|
|
43
|
+
watch(
|
|
44
|
+
() => v$.value.$invalid,
|
|
45
|
+
(invalid) => {
|
|
46
|
+
emit('update:invalid', invalid);
|
|
47
|
+
},
|
|
48
|
+
{ immediate: true },
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const handleInput = (value: ModelValue) => {
|
|
52
|
+
model.value = value;
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ul v-if="localValue">
|
|
3
|
+
<li
|
|
4
|
+
v-for="({ name }, index) of localValue"
|
|
5
|
+
:key="index"
|
|
6
|
+
>
|
|
7
|
+
{{ name }}
|
|
8
|
+
</li>
|
|
9
|
+
</ul>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script lang="ts" setup>
|
|
13
|
+
import { ref } from 'vue';
|
|
14
|
+
|
|
15
|
+
import { searchMethod } from './config.js';
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
value: number[];
|
|
19
|
+
}>();
|
|
20
|
+
|
|
21
|
+
const localValue = ref([]);
|
|
22
|
+
|
|
23
|
+
const getLocalValue = async () => {
|
|
24
|
+
const { items } = await searchMethod({ id: props.value });
|
|
25
|
+
localValue.value = items;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
getLocalValue();
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wt-input
|
|
3
|
+
v-model="model"
|
|
4
|
+
:label="t('webitelUI.filters.filterValue')"
|
|
5
|
+
:v="v$.model"
|
|
6
|
+
/>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
import { useVuelidate } from '@vuelidate/core';
|
|
11
|
+
import variableSearchValidator from '@webitel/ui-sdk/src/validators/variableSearchValidator/variableSearchValidator';
|
|
12
|
+
import { computed, watch } from 'vue';
|
|
13
|
+
import { useI18n } from 'vue-i18n';
|
|
14
|
+
|
|
15
|
+
type ModelValue = string;
|
|
16
|
+
|
|
17
|
+
const model = defineModel<ModelValue>();
|
|
18
|
+
if (!model.value) {
|
|
19
|
+
model.value = '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { t } = useI18n();
|
|
23
|
+
|
|
24
|
+
const v$ = useVuelidate(
|
|
25
|
+
computed(() => ({
|
|
26
|
+
model: {
|
|
27
|
+
required: variableSearchValidator(),
|
|
28
|
+
},
|
|
29
|
+
})),
|
|
30
|
+
{ model },
|
|
31
|
+
{ $autoDirty: true },
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
v$.value.$touch();
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits<{
|
|
37
|
+
'update:invalid': [boolean];
|
|
38
|
+
}>();
|
|
39
|
+
|
|
40
|
+
watch(
|
|
41
|
+
() => v$.value.$invalid,
|
|
42
|
+
(invalid) => {
|
|
43
|
+
emit('update:invalid', invalid);
|
|
44
|
+
},
|
|
45
|
+
{ immediate: true },
|
|
46
|
+
);
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="variables-filter-value-preview">
|
|
3
|
+
<div>
|
|
4
|
+
<p class="variables-filter-value-preview__title">
|
|
5
|
+
{{ t('vocabulary.keys') }}:
|
|
6
|
+
</p>
|
|
7
|
+
<span>{{ variable[0] }}</span>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div>
|
|
11
|
+
<p class="variables-filter-value-preview__title">
|
|
12
|
+
{{ t('vocabulary.values') }}:
|
|
13
|
+
</p>
|
|
14
|
+
<span>{{ variable[1] }}</span>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script lang="ts" setup>
|
|
20
|
+
import { useI18n } from 'vue-i18n';
|
|
21
|
+
|
|
22
|
+
const props = defineProps<{
|
|
23
|
+
value: string;
|
|
24
|
+
}>();
|
|
25
|
+
|
|
26
|
+
const { t } = useI18n();
|
|
27
|
+
|
|
28
|
+
const variable = props.value.split('=');
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<style lang="scss" scoped>
|
|
32
|
+
@use '@webitel/styleguide/typography' as *;
|
|
33
|
+
|
|
34
|
+
.variables-filter-value-preview {
|
|
35
|
+
&__title {
|
|
36
|
+
@extend %typo-subtitle-1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="dynamic-filter-preview-info">
|
|
3
|
+
<header class="dynamic-filter-preview-info__header">
|
|
4
|
+
<slot name="header" />
|
|
5
|
+
</header>
|
|
6
|
+
|
|
7
|
+
<wt-divider />
|
|
8
|
+
|
|
9
|
+
<div class="dynamic-filter-preview-info__body">
|
|
10
|
+
<slot name="default" />
|
|
11
|
+
</div>
|
|
12
|
+
</section>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script lang="ts" setup></script>
|
|
16
|
+
|
|
17
|
+
<style lang="scss" scoped>
|
|
18
|
+
@use '@webitel/styleguide/typography' as *;
|
|
19
|
+
|
|
20
|
+
.dynamic-filter-preview-info {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
gap: var(--spacing-xs);
|
|
24
|
+
|
|
25
|
+
&__header {
|
|
26
|
+
@extend %typo-subtitle-1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&__body {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: var(--spacing-xs);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<dynamic-filter-config-view :disabled="dummy">
|
|
3
|
+
<template #activator="{ visible: configFormVisible }">
|
|
4
|
+
<wt-tooltip :disabled="configFormVisible">
|
|
5
|
+
<template #activator>
|
|
6
|
+
<wt-chip color="primary">
|
|
7
|
+
{{ filter.label || t(`webitelUI.filters.${filter.name}`) }}
|
|
8
|
+
<wt-icon-btn
|
|
9
|
+
v-if="!dummy"
|
|
10
|
+
icon="close--filled"
|
|
11
|
+
size="sm"
|
|
12
|
+
color="on-primary"
|
|
13
|
+
@mousedown.stop="deleteFilter"
|
|
14
|
+
/>
|
|
15
|
+
</wt-chip>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<template #default>
|
|
19
|
+
<dynamic-filter-preview-info>
|
|
20
|
+
<template #header>
|
|
21
|
+
{{ t(`webitelUI.filters.${props.filter.name}`) }}
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<template #default>
|
|
25
|
+
<slot name="info" />
|
|
26
|
+
</template>
|
|
27
|
+
</dynamic-filter-preview-info>
|
|
28
|
+
</template>
|
|
29
|
+
</wt-tooltip>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<template #content="slotScope">
|
|
33
|
+
<slot
|
|
34
|
+
name="form"
|
|
35
|
+
v-bind="slotScope"
|
|
36
|
+
/>
|
|
37
|
+
</template>
|
|
38
|
+
</dynamic-filter-config-view>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script lang="ts" setup>
|
|
42
|
+
import { WtChip } from '@webitel/ui-sdk/src/components/index';
|
|
43
|
+
import { WtIconBtn } from '@webitel/ui-sdk/src/components/index';
|
|
44
|
+
import { WtTooltip } from '@webitel/ui-sdk/src/components/index';
|
|
45
|
+
import { useI18n } from 'vue-i18n';
|
|
46
|
+
|
|
47
|
+
import type { IFilter } from '../../types/Filter';
|
|
48
|
+
import DynamicFilterConfigView from '../config/dynamic-filter-config-view.vue';
|
|
49
|
+
import DynamicFilterPreviewInfo from './dynamic-filter-preview-info.vue';
|
|
50
|
+
|
|
51
|
+
interface Props {
|
|
52
|
+
filter: IFilter;
|
|
53
|
+
dummy?: boolean /* https://webitel.atlassian.net/browse/WTEL-6308?focusedCommentId=657415 */;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const { t } = useI18n();
|
|
57
|
+
|
|
58
|
+
const props = defineProps<Props>();
|
|
59
|
+
|
|
60
|
+
const emit = defineEmits<{
|
|
61
|
+
'delete:filter': [IFilter];
|
|
62
|
+
}>();
|
|
63
|
+
|
|
64
|
+
const deleteFilter = () => {
|
|
65
|
+
emit('delete:filter', props.filter);
|
|
66
|
+
};
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<style lang="scss" scoped>
|
|
70
|
+
.wt-chip {
|
|
71
|
+
display: flex;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--spacing-2xs);
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="table-filters-panel">
|
|
3
|
+
<slot></slot>
|
|
4
|
+
<div class="table-filters-panel-filters">
|
|
5
|
+
<dynamic-filter-add-action>
|
|
6
|
+
<template #form>
|
|
7
|
+
<dynamic-filter-config-form
|
|
8
|
+
:options="unappliedFilters"
|
|
9
|
+
@submit="applyFilter"
|
|
10
|
+
>
|
|
11
|
+
<template
|
|
12
|
+
#value-input="{
|
|
13
|
+
filterName,
|
|
14
|
+
filterValue,
|
|
15
|
+
onValueChange,
|
|
16
|
+
onValueInvalidChange,
|
|
17
|
+
}"
|
|
18
|
+
>
|
|
19
|
+
<component
|
|
20
|
+
:is="getFilterValueComponent(filterName)"
|
|
21
|
+
:key="filterName"
|
|
22
|
+
:model-value="filterValue"
|
|
23
|
+
@update:model-value="onValueChange"
|
|
24
|
+
@undate:invalid="onValueInvalidChange"
|
|
25
|
+
/>
|
|
26
|
+
</template>
|
|
27
|
+
</dynamic-filter-config-form>
|
|
28
|
+
</template>
|
|
29
|
+
</dynamic-filter-add-action>
|
|
30
|
+
|
|
31
|
+
<dynamic-filter-preview
|
|
32
|
+
v-for="filter of appliedFilters"
|
|
33
|
+
:key="filter.name"
|
|
34
|
+
:filter="filter"
|
|
35
|
+
@delete:filter="deleteAppliedFilter($event.name)"
|
|
36
|
+
>
|
|
37
|
+
<template #form>
|
|
38
|
+
<dynamic-filter-config-form
|
|
39
|
+
:filter="filter"
|
|
40
|
+
@submit="updateAppliedFilter"
|
|
41
|
+
>
|
|
42
|
+
<template
|
|
43
|
+
#value-input="{
|
|
44
|
+
filterName,
|
|
45
|
+
filterValue,
|
|
46
|
+
onValueChange,
|
|
47
|
+
onValueInvalidChange,
|
|
48
|
+
}"
|
|
49
|
+
>
|
|
50
|
+
<component
|
|
51
|
+
:is="getFilterValueComponent(filterName)"
|
|
52
|
+
:key="filterName"
|
|
53
|
+
:model-value="filterValue"
|
|
54
|
+
@update:model-value="onValueChange"
|
|
55
|
+
@undate:invalid="onValueInvalidChange"
|
|
56
|
+
/>
|
|
57
|
+
</template>
|
|
58
|
+
</dynamic-filter-config-form>
|
|
59
|
+
</template>
|
|
60
|
+
</dynamic-filter-preview>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="table-filters-panel-actions"></div>
|
|
63
|
+
</section>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script lang="ts" setup>
|
|
67
|
+
import DynamicFilterConfigForm from './config/dynamic-filter-config-form.vue';
|
|
68
|
+
import DynamicFilterAddAction from './dynamic-filter-add-action.vue';
|
|
69
|
+
import DynamicFilterPreview from './preview/dynamic-filter-preview.vue';
|
|
70
|
+
|
|
71
|
+
// interface Props {}
|
|
72
|
+
// const props = defineProps<Props>();
|
|
73
|
+
|
|
74
|
+
// const emit = defineEmits<{
|
|
75
|
+
// 'add:filter': [];
|
|
76
|
+
// 'update:filter': [];
|
|
77
|
+
// 'delete:filter': [];
|
|
78
|
+
// 'reset:filters': [];
|
|
79
|
+
// hide: [];
|
|
80
|
+
// }>();
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { defineStore } from 'pinia';
|
|
2
|
+
import { computed, reactive, ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
import { PersistedStorageType } from '../persist/PersistedStorage.types.ts';
|
|
5
|
+
import { usePersistedStorage } from '../persist/usePersistedStorage.ts';
|
|
6
|
+
import { createFiltersManager } from './classes/FiltersManager.ts';
|
|
7
|
+
import { FiltersManagerConfig } from './types/FiltersManager';
|
|
8
|
+
|
|
9
|
+
export const createTableFiltersStore = (
|
|
10
|
+
namespace: string,
|
|
11
|
+
config?: { filtersManagerConfig: FiltersManagerConfig },
|
|
12
|
+
) => {
|
|
13
|
+
const id = `${namespace}/filters`;
|
|
14
|
+
|
|
15
|
+
return defineStore(id, () => {
|
|
16
|
+
const filtersManager = reactive(
|
|
17
|
+
createFiltersManager(config?.filtersManagerConfig),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
/* for watchers in filter components */
|
|
21
|
+
const isRestoring = ref(false);
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
wrapping filtersManager methods to extend their functionality
|
|
25
|
+
if it will be needed in future
|
|
26
|
+
*/
|
|
27
|
+
const hasFilter = filtersManager.hasFilter.bind(filtersManager);
|
|
28
|
+
const addFilter = filtersManager.addFilter.bind(filtersManager);
|
|
29
|
+
const updateFilter = filtersManager.updateFilter.bind(filtersManager);
|
|
30
|
+
const deleteFilter = filtersManager.deleteFilter.bind(filtersManager);
|
|
31
|
+
|
|
32
|
+
const filtersList = computed(() => filtersManager.getFiltersList());
|
|
33
|
+
|
|
34
|
+
const setupPersistence = () => {
|
|
35
|
+
const { restore: restoreFilters } = usePersistedStorage({
|
|
36
|
+
name: 'filters',
|
|
37
|
+
|
|
38
|
+
value: computed(
|
|
39
|
+
() => filtersManager,
|
|
40
|
+
) /* computed is used to provide value as ref(), not reactive() – as per usePersistedStorage interface */,
|
|
41
|
+
|
|
42
|
+
storages: [PersistedStorageType.Route],
|
|
43
|
+
|
|
44
|
+
/* use custom .toString() logic, provided by FiltersManager */
|
|
45
|
+
onStore: async (save, { name }) => {
|
|
46
|
+
const snapshotStr = filtersManager.toString();
|
|
47
|
+
return save({ name, value: snapshotStr });
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
/* use custom .fromString() logic, provided by FiltersManager */
|
|
51
|
+
onRestore: async (restore, name) => {
|
|
52
|
+
isRestoring.value = true;
|
|
53
|
+
const snapshotStr = await restore(name);
|
|
54
|
+
/*
|
|
55
|
+
snapshot as string because we know that filtersManager.toString() returns string,
|
|
56
|
+
not string[]
|
|
57
|
+
*/
|
|
58
|
+
if (snapshotStr) filtersManager.fromString(snapshotStr as string);
|
|
59
|
+
|
|
60
|
+
isRestoring.value = false;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return restoreFilters();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
filtersManager,
|
|
69
|
+
isRestoring,
|
|
70
|
+
|
|
71
|
+
filtersList,
|
|
72
|
+
|
|
73
|
+
hasFilter,
|
|
74
|
+
addFilter,
|
|
75
|
+
updateFilter,
|
|
76
|
+
deleteFilter,
|
|
77
|
+
|
|
78
|
+
setupPersistence,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const FilterOption = {
|
|
2
|
+
Agent: 'agent',
|
|
3
|
+
AmdResult: 'amdResult',
|
|
4
|
+
Contact: 'contact',
|
|
5
|
+
Direction: 'direction',
|
|
6
|
+
Rated: 'rated',
|
|
7
|
+
Gateway: 'gateway',
|
|
8
|
+
Grantee: 'grantee',
|
|
9
|
+
Cause: 'cause',
|
|
10
|
+
Queue: 'queue',
|
|
11
|
+
RatedBy: 'ratedBy',
|
|
12
|
+
HasFile: 'hasFile',
|
|
13
|
+
Score: 'score',
|
|
14
|
+
Tag: 'tag',
|
|
15
|
+
TalkDuration: 'talkDuration',
|
|
16
|
+
Team: 'team',
|
|
17
|
+
TotalDuration: 'totalDuration',
|
|
18
|
+
HasTranscription: 'hasTranscription',
|
|
19
|
+
User: 'user',
|
|
20
|
+
Variable: 'variable',
|
|
21
|
+
CreatedAtFrom: 'createdAtFrom',
|
|
22
|
+
CreatedAtTo: 'createdAtTo',
|
|
23
|
+
Status: 'status',
|
|
24
|
+
Source: 'source',
|
|
25
|
+
Service: 'service',
|
|
26
|
+
Author: 'author',
|
|
27
|
+
Reporter: 'reporter',
|
|
28
|
+
Impacted: 'impacted',
|
|
29
|
+
Assignee: 'assignee',
|
|
30
|
+
ContactGroup: 'contactGroup',
|
|
31
|
+
Priority: 'priority',
|
|
32
|
+
CloseReasonGroups: 'closeReasonGroups',
|
|
33
|
+
Rating: 'rating',
|
|
34
|
+
Sla: 'sla',
|
|
35
|
+
SlaCondition: 'slaCondition',
|
|
36
|
+
ReactionTime: 'reactionTime',
|
|
37
|
+
ResolutionTime: 'resolutionTime',
|
|
38
|
+
ActualReactionTime: 'actualReactionTime',
|
|
39
|
+
ActualResolutionTime: 'actualResolutionTime',
|
|
40
|
+
HasAttachment: 'hasAttachment',
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
export type FilterOption = (typeof FilterOption)[keyof typeof FilterOption];
|