@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.
Files changed (155) hide show
  1. package/Readme.md +19 -0
  2. package/package.json +3 -1
  3. package/src/filter-presets/api/PresetQuery.api.ts +122 -0
  4. package/src/filter-presets/components/_shared/input-fields/preset-description-field.vue +32 -0
  5. package/src/filter-presets/components/_shared/input-fields/preset-name-field.vue +28 -0
  6. package/src/filter-presets/components/_shared/preset-filters-preview.vue +45 -0
  7. package/src/filter-presets/components/apply-preset/apply-preset-action.vue +234 -0
  8. package/src/filter-presets/components/apply-preset/preset-preview.vue +210 -0
  9. package/src/filter-presets/components/save-preset/overwrite-preset-popup.vue +64 -0
  10. package/src/filter-presets/components/save-preset/save-preset-action.vue +139 -0
  11. package/src/filter-presets/components/save-preset/save-preset-popup.vue +136 -0
  12. package/src/filter-presets/index.ts +5 -0
  13. package/src/filter-presets/stores/createFilterPresetsStore.ts +17 -0
  14. package/src/filter-presets/stores/headers/headers.ts +24 -0
  15. package/src/filters/classes/Filter.ts +30 -0
  16. package/src/filters/classes/FilterStorage.ts +34 -0
  17. package/src/filters/classes/FilterStorageOptions.d.ts +6 -0
  18. package/src/filters/classes/FiltersManager.ts +190 -0
  19. package/src/filters/components/config/dynamic-filter-config-form-label.vue +49 -0
  20. package/src/filters/components/config/dynamic-filter-config-form.vue +139 -0
  21. package/src/filters/components/config/dynamic-filter-config-view.vue +40 -0
  22. package/src/filters/components/dynamic-filter-add-action.vue +54 -0
  23. package/src/filters/components/dynamic-filter-panel-wrapper.vue +57 -0
  24. package/src/filters/components/dynamic-filter-search.vue +60 -0
  25. package/src/filters/components/filter-options/_shared/composables/booleanFilterToolkit.ts +39 -0
  26. package/src/filters/components/filter-options/_shared/composables/useFromToSecToPreviewTime.ts +41 -0
  27. package/src/filters/components/filter-options/_shared/date-time-filter/date-time-filter-value-field.vue +56 -0
  28. package/src/filters/components/filter-options/_shared/durations/duration-filter-value-field.vue +84 -0
  29. package/src/filters/components/filter-options/_shared/has-options/has-option-filter-value-field.vue +38 -0
  30. package/src/filters/components/filter-options/_shared/types/BooleanFilter.ts +1 -0
  31. package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-field.vue +18 -0
  32. package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-preview.vue +44 -0
  33. package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-field.vue +18 -0
  34. package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-preview.vue +44 -0
  35. package/src/filters/components/filter-options/agent/agent-filter-value-field.vue +58 -0
  36. package/src/filters/components/filter-options/agent/agent-filter-value-preview.vue +31 -0
  37. package/src/filters/components/filter-options/agent/config.js +4 -0
  38. package/src/filters/components/filter-options/amd-result/amd-result-filter-value-field.vue +52 -0
  39. package/src/filters/components/filter-options/amd-result/amd-result-filter-value-preview.vue +18 -0
  40. package/src/filters/components/filter-options/assignee/assignee-filter-value-field.vue +73 -0
  41. package/src/filters/components/filter-options/assignee/assignee-filter-value-preview.vue +36 -0
  42. package/src/filters/components/filter-options/assignee/config.js +4 -0
  43. package/src/filters/components/filter-options/author/author-filter-value-field.vue +56 -0
  44. package/src/filters/components/filter-options/author/author-filter-value-preview.vue +31 -0
  45. package/src/filters/components/filter-options/author/config.js +4 -0
  46. package/src/filters/components/filter-options/cause/cause-filter-value-field.vue +52 -0
  47. package/src/filters/components/filter-options/cause/cause-filter-value-preview.vue +18 -0
  48. package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-field.vue +102 -0
  49. package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-preview.vue +34 -0
  50. package/src/filters/components/filter-options/close-reason-groups-case/config.js +7 -0
  51. package/src/filters/components/filter-options/contact/config.js +4 -0
  52. package/src/filters/components/filter-options/contact/contact-filter-value-field.vue +56 -0
  53. package/src/filters/components/filter-options/contact/contact-filter-value-preview.vue +31 -0
  54. package/src/filters/components/filter-options/contact-group/config.js +4 -0
  55. package/src/filters/components/filter-options/contact-group/contact-group-filter-value-field.vue +74 -0
  56. package/src/filters/components/filter-options/contact-group/contact-group-filter-value-preview.vue +38 -0
  57. package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-field.vue +24 -0
  58. package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-preview.vue +15 -0
  59. package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-field.vue +24 -0
  60. package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-preview.vue +15 -0
  61. package/src/filters/components/filter-options/direction/direction-filter-value-field.vue +51 -0
  62. package/src/filters/components/filter-options/direction/direction-filter-value-preview.vue +17 -0
  63. package/src/filters/components/filter-options/gateway/config.js +4 -0
  64. package/src/filters/components/filter-options/gateway/gateway-filter-value-field.vue +56 -0
  65. package/src/filters/components/filter-options/gateway/gateway-filter-value-preview.vue +31 -0
  66. package/src/filters/components/filter-options/grantee/config.js +4 -0
  67. package/src/filters/components/filter-options/grantee/grantee-filter-value-field.vue +56 -0
  68. package/src/filters/components/filter-options/grantee/grantee-filter-value-preview.vue +31 -0
  69. package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-field.vue +43 -0
  70. package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-preview.vue +24 -0
  71. package/src/filters/components/filter-options/has-file/has-file-filter-value-field.vue +33 -0
  72. package/src/filters/components/filter-options/has-file/has-file-filter-value-preview.vue +15 -0
  73. package/src/filters/components/filter-options/has-rating/has-rating-filter-value-field.vue +33 -0
  74. package/src/filters/components/filter-options/has-rating/has-rating-filter-value-preview.vue +15 -0
  75. package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-field.vue +33 -0
  76. package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-preview.vue +15 -0
  77. package/src/filters/components/filter-options/impacted/config.js +4 -0
  78. package/src/filters/components/filter-options/impacted/impacted-filter-value-field.vue +56 -0
  79. package/src/filters/components/filter-options/impacted/impacted-filter-value-preview.vue +31 -0
  80. package/src/filters/components/filter-options/index.ts +250 -0
  81. package/src/filters/components/filter-options/priority-case/config.js +4 -0
  82. package/src/filters/components/filter-options/priority-case/priority-case-filter-value-field.vue +57 -0
  83. package/src/filters/components/filter-options/priority-case/priority-case-filter-value-preview.vue +31 -0
  84. package/src/filters/components/filter-options/queue/config.js +4 -0
  85. package/src/filters/components/filter-options/queue/queue-filter-value-field.vue +56 -0
  86. package/src/filters/components/filter-options/queue/queue-filter-value-preview.vue +31 -0
  87. package/src/filters/components/filter-options/rated-by/config.js +4 -0
  88. package/src/filters/components/filter-options/rated-by/rated-by-filter-value-field.vue +56 -0
  89. package/src/filters/components/filter-options/rated-by/rated-by-filter-value-preview.vue +31 -0
  90. package/src/filters/components/filter-options/rating/rating-from-to-filter-value-field.vue +100 -0
  91. package/src/filters/components/filter-options/rating/rating-from-to-filter-value-preview.vue +39 -0
  92. package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-field.vue +18 -0
  93. package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-preview.vue +44 -0
  94. package/src/filters/components/filter-options/reporter/config.js +4 -0
  95. package/src/filters/components/filter-options/reporter/reporter-filter-value-field.vue +56 -0
  96. package/src/filters/components/filter-options/reporter/reporter-filter-value-preview.vue +31 -0
  97. package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-field.vue +18 -0
  98. package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-preview.vue +44 -0
  99. package/src/filters/components/filter-options/score/score-from-to-filter-value-field.vue +100 -0
  100. package/src/filters/components/filter-options/score/score-from-to-filter-value-preview.vue +39 -0
  101. package/src/filters/components/filter-options/service-case/config.js +6 -0
  102. package/src/filters/components/filter-options/service-case/service-case-filter-value-field.vue +82 -0
  103. package/src/filters/components/filter-options/service-case/service-case-filter-value-preview.vue +34 -0
  104. package/src/filters/components/filter-options/sla/config.js +4 -0
  105. package/src/filters/components/filter-options/sla/sla-filter-value-field.vue +57 -0
  106. package/src/filters/components/filter-options/sla/sla-filter-value-preview.vue +31 -0
  107. package/src/filters/components/filter-options/sla-condition/config.js +6 -0
  108. package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-field.vue +98 -0
  109. package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-preview.vue +37 -0
  110. package/src/filters/components/filter-options/source-case/config.js +4 -0
  111. package/src/filters/components/filter-options/source-case/source-case-filter-value-field.vue +57 -0
  112. package/src/filters/components/filter-options/source-case/source-case-filter-value-preview.vue +31 -0
  113. package/src/filters/components/filter-options/status-case/config.js +7 -0
  114. package/src/filters/components/filter-options/status-case/status-case-filter-value-field.vue +102 -0
  115. package/src/filters/components/filter-options/status-case/status-case-filter-value-preview.vue +37 -0
  116. package/src/filters/components/filter-options/tag/tag-filter-value-field.vue +52 -0
  117. package/src/filters/components/filter-options/tag/tag-filter-value-preview.vue +38 -0
  118. package/src/filters/components/filter-options/talk-duration/TalkDurationFilter.d.ts +4 -0
  119. package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-field.vue +19 -0
  120. package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-preview.vue +44 -0
  121. package/src/filters/components/filter-options/team/config.js +4 -0
  122. package/src/filters/components/filter-options/team/team-filter-value-field.vue +56 -0
  123. package/src/filters/components/filter-options/team/team-filter-value-preview.vue +31 -0
  124. package/src/filters/components/filter-options/total-duration/TotalDurationFilter.d.ts +4 -0
  125. package/src/filters/components/filter-options/total-duration/total-duration-filter-value-field.vue +19 -0
  126. package/src/filters/components/filter-options/total-duration/total-duration-filter-value-preview.vue +44 -0
  127. package/src/filters/components/filter-options/user/config.js +4 -0
  128. package/src/filters/components/filter-options/user/user-filter-value-field.vue +56 -0
  129. package/src/filters/components/filter-options/user/user-filter-value-preview.vue +31 -0
  130. package/src/filters/components/filter-options/variable/variable-filter-value-field.vue +49 -0
  131. package/src/filters/components/filter-options/variable/variable-filter-value-preview.vue +39 -0
  132. package/src/filters/components/preview/dynamic-filter-preview-info.vue +35 -0
  133. package/src/filters/components/preview/dynamic-filter-preview.vue +76 -0
  134. package/src/filters/components/table-filters-panel.vue +83 -0
  135. package/src/filters/createTableFiltersStore.ts +81 -0
  136. package/src/filters/enums/FilterOption.ts +43 -0
  137. package/src/filters/enums/amd-result-options.ts +38 -0
  138. package/src/filters/enums/boolean-options.ts +16 -0
  139. package/src/filters/enums/direction-options.ts +20 -0
  140. package/src/filters/enums/hangup-cause-options.ts +265 -0
  141. package/src/filters/enums/tag-options.ts +8 -0
  142. package/src/filters/index.ts +27 -0
  143. package/src/filters/scripts/utils.ts +31 -0
  144. package/src/filters/types/Filter.d.ts +46 -0
  145. package/src/filters/types/FiltersManager.d.ts +76 -0
  146. package/src/headers/createTableHeadersStore.ts +140 -0
  147. package/src/index.d.ts +0 -0
  148. package/src/index.ts +3 -0
  149. package/src/pagination/createTablePaginationStore.ts +64 -0
  150. package/src/persist/PersistedStorage.types.ts +51 -0
  151. package/src/persist/useLocalStoragePersistedStorage.ts +37 -0
  152. package/src/persist/usePersistedStorage.ts +151 -0
  153. package/src/persist/useRoutePersistedStorage.ts +41 -0
  154. package/src/table/createTableStore.store.ts +206 -0
  155. 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>
@@ -0,0 +1,4 @@
1
+ export type TotalDurationFilterModelValue = {
2
+ from: number;
3
+ to: number;
4
+ };
@@ -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>
@@ -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,4 @@
1
+ import UsersAPI from '@webitel/ui-sdk/src/api/clients/users/users';
2
+
3
+ export const searchMethod = UsersAPI.getLookup;
4
+ export const localePath = '';
@@ -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];