@webitel/ui-sdk 25.4.19 → 25.4.20

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.
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <wt-popup
3
+ size="sm"
4
+ @close="emit('close')"
5
+ >
6
+ <template #title>
7
+ {{ t('validations.alreadyExists', { field: t('reusable.name') }) }}
8
+ </template>
9
+ <template #main> some nice text goes here {{ t('') }} </template>
10
+ <template #actions>
11
+ <wt-button
12
+ color="error"
13
+ :loading="isSaving"
14
+ @click="confirm"
15
+ >
16
+ {{ t('reusable.overwrite') }}
17
+ </wt-button>
18
+ <wt-button
19
+ color="secondary"
20
+ @click="emit('cancel')"
21
+ >{{ t('reusable.cancel') }}
22
+ </wt-button>
23
+ </template>
24
+ </wt-popup>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ref } from 'vue';
29
+ import { useI18n } from 'vue-i18n';
30
+ import { WtPopup } from '../../../../../../components/index';
31
+ import { SubmitConfig } from './save-preset-popup.vue';
32
+
33
+ const emit = defineEmits<{
34
+ confirm: [SubmitConfig];
35
+ cancel: [];
36
+ close: [];
37
+ }>();
38
+
39
+ const { t } = useI18n();
40
+
41
+ const isSaving = ref(false);
42
+
43
+ const confirm = () => {
44
+ emit('confirm', {
45
+ onCompleted: () => (isSaving.value = false),
46
+ });
47
+ };
48
+ </script>
49
+
50
+ <style scoped lang="scss">
51
+ .overwrite-preset-popup {
52
+ }
53
+ </style>
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <div class="save-preset-action">
3
+ <wt-icon-btn
4
+ :disabled="disableAction"
5
+ icon="save"
6
+ @click="showSaveForm = true"
7
+ />
8
+
9
+ <save-preset-popup
10
+ v-if="showSaveForm /* v-if is used to re-mount component on each open/close so that each time component data re-inits*/"
11
+ v-show="!presetToOverwriteWith /* on 'overwrite preset' popup hide this popup, but don't reset it*/"
12
+ :shown="true /* coz visibility is controlled by v-if*/"
13
+ :filters-manager="props.filtersManager"
14
+ @submit="handlePresetSubmit"
15
+ @close="showSaveForm = false"
16
+ />
17
+
18
+ <overwrite-preset-popup
19
+ v-if="presetToOverwriteWith"
20
+ @confirm="handlePresetOverwriteConfirmation"
21
+ @cancel="presetToOverwriteWith = null"
22
+ @close="presetToOverwriteWith = null"
23
+ />
24
+ </div>
25
+ </template>
26
+
27
+ <script lang="ts" setup>
28
+ import {computed, ref, type Ref} from 'vue';
29
+ import {EnginePresetQuery} from "webitel-sdk";
30
+ import { WtIconBtn } from '../../../../../../components/index';
31
+ import {addPreset, getPresetList, updatePreset} from '../../api/PresetQuery.api.ts';
32
+ import SavePresetPopup, {SubmitConfig} from "./save-preset-popup.vue";
33
+ import OverwritePresetPopup from "./overwrite-preset-popup.vue";
34
+ import {IFiltersManager} from "../../../filters/index";
35
+
36
+ const props = defineProps<{
37
+ /**
38
+ * presets "section" namespace
39
+ */
40
+ namespace: string;
41
+ filtersManager: IFiltersManager;
42
+ }>();
43
+
44
+ /**
45
+ * disable "save" btn if there's nothing to save
46
+ * */
47
+ const disableAction = computed(() => {
48
+ return !props.filtersManager.getAllKeys().length;
49
+ });
50
+
51
+ /**
52
+ * visibility flag
53
+ * */
54
+ const showSaveForm = ref(false);
55
+
56
+ /**
57
+ * if preset with the same name already exists, this will be suggested to set to that preset
58
+ */
59
+ const presetToOverwriteWith: Ref<EnginePresetQuery | null> = ref(null);
60
+
61
+ const handlePresetSubmit = async (preset: EnginePresetQuery, { onCompleted }: SubmitConfig) => {
62
+ try {
63
+ await addPreset({ preset, namespace: props.namespace });
64
+ showSaveForm.value = false;
65
+ } catch (err) {
66
+ if (err?.status === 409) {
67
+ presetToOverwriteWith.value = preset;
68
+ }
69
+ throw err;
70
+ } finally {
71
+ if (onCompleted) onCompleted();
72
+ }
73
+ };
74
+
75
+ const handlePresetOverwriteConfirmation = async ({ onCompleted }: SubmitConfig) => {
76
+ try {
77
+ const {items} = await getPresetList({
78
+ search: presetToOverwriteWith.value.name,
79
+ presetNamespace: props.namespace,
80
+ }, {
81
+ transformers: {useStarToSearch: false},
82
+ });
83
+ const {id: existingPresetId} = items[0];
84
+ await updatePreset({
85
+ id: existingPresetId,
86
+ item: {
87
+ ...presetToOverwriteWith.value,
88
+ },
89
+ });
90
+
91
+ presetToOverwriteWith.value = null;
92
+ showSaveForm.value = false;
93
+ } finally {
94
+ if (onCompleted) onCompleted();
95
+ }
96
+ };
97
+ </script>
98
+
99
+ <style lang="scss" scoped>
100
+
101
+ </style>
@@ -0,0 +1,129 @@
1
+ <template>
2
+ <wt-popup
3
+ size="sm"
4
+ @close="emit('close')"
5
+ >
6
+ <template #title>
7
+ {{ `${t('reusable.save')} ${t('filters.preset.preset').toLowerCase()}` }}
8
+ </template>
9
+
10
+ <template #main>
11
+ <form
12
+ class="save-preset-form"
13
+ @submit.prevent="() => !v$.$invalid && save"
14
+ >
15
+ <preset-name-field
16
+ v-model:model-value="presetForm.name"
17
+ :v="v$.name"
18
+ />
19
+
20
+ <preset-description-field
21
+ v-model:model-value="presetForm.description"
22
+ />
23
+ </form>
24
+
25
+ <preset-filters-preview
26
+ :filters="appliedFilters"
27
+ />
28
+ </template>
29
+
30
+ <template #actions>
31
+ <wt-button
32
+ :disabled="v$.$invalid"
33
+ :loading="isSaving"
34
+ @click="save"
35
+ >
36
+ {{ t('reusable.save') }}
37
+ </wt-button>
38
+ <wt-button
39
+ color="secondary"
40
+ @click="emit('close')"
41
+ >
42
+ {{ t('reusable.cancel') }}
43
+ </wt-button>
44
+ </template>
45
+ </wt-popup>
46
+ </template>
47
+
48
+ <script setup lang="ts">
49
+ import {computed, reactive, ref} from "vue";
50
+ import {useI18n} from "vue-i18n";
51
+ import {useVuelidate} from "@vuelidate/core";
52
+ import {required} from "@vuelidate/validators";
53
+ import {EnginePresetQuery} from "webitel-sdk";
54
+ import type {IFiltersManager} from "../../../index";
55
+ import { WtPopup } from '../../../../../../components/index';
56
+ import PresetDescriptionField from "../_shared/input-fields/preset-description-field.vue";
57
+ import PresetFiltersPreview from "../_shared/preset-filters-preview.vue";
58
+ import PresetNameField from "../_shared/input-fields/preset-name-field.vue";
59
+
60
+ export type SubmitConfig = {
61
+ onSuccess?: () => void;
62
+ onFailure?: (err: Error) => void;
63
+ onCompleted?: () => void;
64
+ };
65
+
66
+ const props = defineProps<{
67
+ filtersManager: IFiltersManager;
68
+ }>();
69
+
70
+ const emit = defineEmits<{
71
+ submit: [EnginePresetQuery, SubmitConfig?];
72
+ close: [];
73
+ }>();
74
+
75
+ const {t} = useI18n();
76
+
77
+ const isSaving = ref(false);
78
+
79
+ const presetForm = reactive({
80
+ name: '',
81
+ description: '',
82
+ });
83
+
84
+ const v$ = useVuelidate(computed(() => {
85
+ return {
86
+ name: {
87
+ required,
88
+ },
89
+ };
90
+ }), presetForm, {$autoDirty: true});
91
+ v$.value.$touch();
92
+
93
+ const appliedFilters = computed(() => {
94
+ return props.filtersManager.getFiltersList();
95
+ });
96
+
97
+ const save = () => {
98
+ isSaving.value = true;
99
+
100
+ const preset: EnginePresetQuery = {
101
+ ...presetForm,
102
+ preset: {
103
+ 'filtersManager.toString': props.filtersManager.toString(),
104
+ },
105
+ };
106
+
107
+ emit('submit', preset, {
108
+ onCompleted: () => {
109
+ isSaving.value = false;
110
+ },
111
+ });
112
+ };
113
+
114
+ </script>
115
+
116
+ <style scoped lang="scss">
117
+ .save-preset-form {
118
+ display: flex;
119
+ flex-direction: column;
120
+ gap: var(--spacing-sm);
121
+ }
122
+
123
+ .save-preset-filters-preview-wrapper {
124
+ @extend %wt-scrollbar;
125
+ overflow-y: auto;
126
+ max-height: 140px;
127
+ margin-top: var(--spacing-sm);
128
+ }
129
+ </style>
@@ -0,0 +1,10 @@
1
+ import { createFilterPresetsStore } from "./stores/createFilterPresetsStore.ts";
2
+ import SavePresetAction from './components/save-preset/save-preset-action.vue';
3
+ import ApplyPresetAction from "./components/apply-preset/apply-preset-action.vue";
4
+
5
+ export {
6
+ SavePresetAction,
7
+ ApplyPresetAction,
8
+
9
+ createFilterPresetsStore
10
+ };
@@ -0,0 +1,14 @@
1
+ import { EnginePresetQuery } from 'webitel-sdk';
2
+ import { createTableStore } from 'src/modules/Filters/v2/table/createTableStore.store.ts';
3
+ import PresetQueryAPI from "../api/PresetQuery.api.ts";
4
+ import { headers } from "./headers/headers.ts";
5
+
6
+ export const createFilterPresetsStore = (namespace = 'presets') => {
7
+ const presetsNamespace = namespace.endsWith('presets') ? namespace : `${namespace}/presets`;
8
+
9
+ return createTableStore<EnginePresetQuery>(presetsNamespace, {
10
+ apiModule: PresetQueryAPI,
11
+ headers,
12
+ disablePersistence: true,
13
+ });
14
+ }
@@ -0,0 +1,24 @@
1
+ import {WtTableHeader} from "src/components/wt-table/types/WtTable.d.ts";
2
+
3
+ export const headers: WtTableHeader[] = [
4
+ {
5
+ value: 'id',
6
+ field: 'id',
7
+ show: true,
8
+ },
9
+ {
10
+ value: 'name',
11
+ field: 'name',
12
+ show: true,
13
+ },
14
+ {
15
+ value: 'preset',
16
+ field: 'preset',
17
+ show: true,
18
+ },
19
+ {
20
+ value: 'description',
21
+ field: 'description',
22
+ show: true,
23
+ },
24
+ ];
@@ -0,0 +1,147 @@
1
+ import {
2
+ AgentFilter,
3
+ AgentFilterPreview,
4
+ AmdResultFilter,
5
+ AmdResultFilterPreview,
6
+ ContactFilter,
7
+ ContactFilterPreview,
8
+ CreatedAtFromFilter,
9
+ CreatedAtFromFilterPreview,
10
+ CreatedAtToFilter,
11
+ CreatedAtToFilterPreview,
12
+ DirectionFilter,
13
+ DirectionFilterPreview,
14
+ HasRatingFilterValueField,
15
+ HasRatingFilterValuePreview,
16
+ GatewayFilter,
17
+ GatewayFilterPreview,
18
+ GranteeFilter,
19
+ GranteeFilterPreview,
20
+ CauseFilter,
21
+ CauseFilterPreview,
22
+ QueueFilter,
23
+ QueueFilterPreview,
24
+ RatedByFilter,
25
+ RatedByFilterPreview,
26
+ HasFileFilter,
27
+ HasFileFilterPreview,
28
+ ScoreFilter,
29
+ ScoreFilterPreview,
30
+ TagFilter,
31
+ TagFilterPreview,
32
+ TalkDurationFilter,
33
+ TalkDurationFilterPreview,
34
+ TeamFilter,
35
+ TeamFilterPreview,
36
+ TotalDurationFilter,
37
+ TotalDurationFilterPreview,
38
+ HasTranscriptionFilter,
39
+ HasTranscriptionFilterPreview,
40
+ UserFilter,
41
+ UserFilterPreview,
42
+ VariableFilter,
43
+ VariableFilterPreview,
44
+ } from '../index';
45
+ import {Component} from "vue";
46
+ import type {FilterName} from "../../../index";
47
+
48
+
49
+ interface FilterOptionsComponentsConfig {
50
+ [key: string]: {
51
+ valueField: Component
52
+ previewField: Component
53
+ }
54
+ }
55
+ const filterOptionsComponentsConfig: FilterOptionsComponentsConfig = {
56
+ agent: {
57
+ valueField: AgentFilter,
58
+ previewField: AgentFilterPreview,
59
+ },
60
+ amdResult: {
61
+ valueField: AmdResultFilter,
62
+ previewField: AmdResultFilterPreview,
63
+ },
64
+ contact: {
65
+ valueField: ContactFilter,
66
+ previewField: ContactFilterPreview,
67
+ },
68
+ createdAtFrom: {
69
+ valueField: CreatedAtFromFilter,
70
+ previewField: CreatedAtFromFilterPreview,
71
+ },
72
+ createdAtTo: {
73
+ valueField: CreatedAtToFilter,
74
+ previewField: CreatedAtToFilterPreview,
75
+ },
76
+ direction: {
77
+ valueField: DirectionFilter,
78
+ previewField: DirectionFilterPreview,
79
+ },
80
+ rated: {
81
+ valueField: HasRatingFilterValueField,
82
+ previewField: HasRatingFilterValuePreview,
83
+ },
84
+ gateway: {
85
+ valueField: GatewayFilter,
86
+ previewField: GatewayFilterPreview,
87
+ },
88
+ grantee: {
89
+ valueField: GranteeFilter,
90
+ previewField: GranteeFilterPreview,
91
+ },
92
+ cause: {
93
+ valueField: CauseFilter,
94
+ previewField: CauseFilterPreview,
95
+ },
96
+ queue: {
97
+ valueField: QueueFilter,
98
+ previewField: QueueFilterPreview,
99
+ },
100
+ ratedBy: {
101
+ valueField: RatedByFilter,
102
+ previewField: RatedByFilterPreview,
103
+ },
104
+ hasFile: {
105
+ valueField: HasFileFilter,
106
+ previewField: HasFileFilterPreview,
107
+ },
108
+ score: {
109
+ valueField: ScoreFilter,
110
+ previewField: ScoreFilterPreview,
111
+ },
112
+ tag: {
113
+ valueField: TagFilter,
114
+ previewField: TagFilterPreview,
115
+ },
116
+ talkDuration: {
117
+ valueField: TalkDurationFilter,
118
+ previewField: TalkDurationFilterPreview,
119
+ },
120
+ team: {
121
+ valueField: TeamFilter,
122
+ previewField: TeamFilterPreview,
123
+ },
124
+ totalDuration: {
125
+ valueField: TotalDurationFilter,
126
+ previewField: TotalDurationFilterPreview,
127
+ },
128
+ hasTranscription: {
129
+ valueField: HasTranscriptionFilter,
130
+ previewField: HasTranscriptionFilterPreview,
131
+ },
132
+ user: {
133
+ valueField: UserFilter,
134
+ previewField: UserFilterPreview,
135
+ },
136
+ variable: {
137
+ valueField: VariableFilter,
138
+ previewField: VariableFilterPreview,
139
+ },
140
+ }
141
+
142
+ export const getFilterFieldComponent = (filterName: FilterName, filterField: 'valueField' | 'previewField') => {
143
+ const filter = filterOptionsComponentsConfig[filterName];
144
+ return !filter ? '' : filter[filterField] || '';
145
+ };
146
+
147
+ export default filterOptionsComponentsConfig;