@webitel/ui-datalist 1.0.0 → 1.0.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.
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 +123 -0
  4. package/src/filter-presets/components/_shared/input-fields/preset-description-field.vue +33 -0
  5. package/src/filter-presets/components/_shared/input-fields/preset-name-field.vue +29 -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 +189 -0
  19. package/src/filters/components/config/dynamic-filter-config-form-label.vue +50 -0
  20. package/src/filters/components/config/dynamic-filter-config-form.vue +140 -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 +61 -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 +74 -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 +101 -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 +50 -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 +87 -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,140 @@
1
+ <template>
2
+ <form class="dynamic-filter-config-form">
3
+ <wt-select
4
+ :clearable="false"
5
+ :disabled="editMode"
6
+ :label="t('webitelUI.filters.filterName')"
7
+ :options="options"
8
+ :value="filterName"
9
+ track-by="value"
10
+ use-value-from-options-by-prop="value"
11
+ @input="onFilterNameUpdate($event)"
12
+ />
13
+
14
+ <slot
15
+ name="value-input"
16
+ v-bind="{
17
+ filterName,
18
+ filterValue,
19
+ inputLabel: t('webitelUI.filters.filterValue'),
20
+ onValueChange: (v) => (filterValue = v),
21
+ onValueInvalidChange: (v) => (invalid = v),
22
+ }"
23
+ />
24
+
25
+ <dynamic-filter-config-form-label
26
+ :value="filterLabel"
27
+ @update:model-value="onLabelValueUpdate"
28
+ @update:invalid="(v) => (invalid = v)"
29
+ />
30
+
31
+ <footer class="dynamic-filter-config-form-footer">
32
+ <wt-button
33
+ :disabled="invalid"
34
+ wide
35
+ @click="submit"
36
+ >
37
+ {{ t('reusable.save') }}
38
+ </wt-button>
39
+
40
+ <wt-button
41
+ color="secondary"
42
+ wide
43
+ @click="emit('cancel')"
44
+ >
45
+ {{ t('reusable.cancel') }}
46
+ </wt-button>
47
+ </footer>
48
+ </form>
49
+ </template>
50
+
51
+ <script lang="ts" setup>
52
+ import deepcopy from 'deep-copy';
53
+ import { ref, watch } from 'vue';
54
+ import { useI18n } from 'vue-i18n';
55
+
56
+ import WtButton from '../../../../../../components/wt-button/wt-button.vue';
57
+ import WtSelect from '../../../../../../components/wt-select/wt-select.vue';
58
+ import type { FilterInitParams, FilterName, IFilter } from '../../types/Filter';
59
+ import DynamicFilterConfigFormLabel from './dynamic-filter-config-form-label.vue';
60
+
61
+ interface FilterNameSelectRepresentation {
62
+ name: string;
63
+ value: FilterName;
64
+ }
65
+
66
+ interface AddModeProps {
67
+ options: Array<FilterNameSelectRepresentation>;
68
+ }
69
+
70
+ interface EditModeProps {
71
+ filter: IFilter;
72
+ }
73
+
74
+ type Props = AddModeProps | EditModeProps;
75
+
76
+ const props = defineProps<Props>();
77
+
78
+ const emit = defineEmits<{
79
+ submit: [FilterInitParams];
80
+ cancel: [];
81
+ }>();
82
+
83
+ const { t } = useI18n();
84
+
85
+ const filterName = ref();
86
+ const filterLabel = ref('');
87
+ const filterValue = ref();
88
+
89
+ const editMode = !!props.filter;
90
+
91
+ const invalid = ref(false);
92
+
93
+ const onLabelValueUpdate = (val: string) => {
94
+ filterLabel.value = val;
95
+ };
96
+
97
+ const onFilterNameUpdate = (val: string) => {
98
+ filterName.value = val;
99
+ filterValue.value = null;
100
+ invalid.value = false;
101
+ };
102
+
103
+ const submit = () => {
104
+ emit('submit', {
105
+ name: filterName.value,
106
+ label: filterLabel.value,
107
+ value: filterValue.value,
108
+ });
109
+ };
110
+
111
+ if (props.filter) {
112
+ watch(
113
+ props.filter,
114
+ () => {
115
+ filterName.value = props.filter.name;
116
+ filterValue.value = deepcopy(props.filter.value);
117
+ filterLabel.value = props.filter.label;
118
+ },
119
+ { immediate: true },
120
+ );
121
+ }
122
+ </script>
123
+
124
+ <style lang="scss" scoped>
125
+ $form-width: 380px;
126
+
127
+ .dynamic-filter-config-form {
128
+ display: flex;
129
+ flex-direction: column;
130
+ gap: var(--spacing-xs);
131
+ box-sizing: border-box;
132
+ padding: var(--spacing-xs) 0;
133
+ width: $form-width;
134
+ }
135
+
136
+ .dynamic-filter-config-form-footer {
137
+ display: flex;
138
+ gap: var(--spacing-xs);
139
+ }
140
+ </style>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div class="dynamic-filter-config-view">
3
+ <wt-tooltip
4
+ :triggers="['click']"
5
+ :disabled="props.disabled"
6
+ :disable-click-away="props.disableClickAway"
7
+ >
8
+ <template #activator="slotScope">
9
+ <slot
10
+ name="activator"
11
+ v-bind="slotScope"
12
+ />
13
+ </template>
14
+ <template #default="slotScope">
15
+ <slot
16
+ name="content"
17
+ v-bind="slotScope"
18
+ />
19
+ </template>
20
+ </wt-tooltip>
21
+ </div>
22
+ </template>
23
+
24
+ <script lang="ts" setup>
25
+ /**
26
+ * this component should only be used for config view representation: tooltip/popup/etc,
27
+ * and their styling
28
+ */
29
+
30
+ import WtTooltip from '../../../../../../components/wt-tooltip/wt-tooltip.vue';
31
+
32
+ interface Props {
33
+ disabled?: boolean;
34
+ disableClickAway?: boolean;
35
+ }
36
+
37
+ const props = defineProps<Props>();
38
+ </script>
39
+
40
+ <style lang="scss" scoped></style>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <dynamic-filter-config-view
3
+ disable-click-away
4
+ class="dynamic-filter-add-action"
5
+ >
6
+ <template #activator>
7
+ <div class="dynamic-filter-add-action-wrapper">
8
+ <p v-if="props.showLabel">
9
+ {{ t('webitelUI.filters.addFilter') }}
10
+ </p>
11
+ <wt-icon-action action="add-filter" />
12
+ </div>
13
+ </template>
14
+
15
+ <template #content="slotScope">
16
+ <slot
17
+ name="form"
18
+ v-bind="slotScope"
19
+ >
20
+ filter form should be here
21
+ </slot>
22
+ </template>
23
+ </dynamic-filter-config-view>
24
+ </template>
25
+
26
+ <script lang="ts" setup>
27
+ import { useI18n } from 'vue-i18n';
28
+
29
+ import WtIconAction from '../../../../../components/wt-icon-action/wt-icon-action.vue';
30
+ import DynamicFilterConfigView from './config/dynamic-filter-config-view.vue';
31
+
32
+ interface Props {
33
+ showLabel?: boolean;
34
+ }
35
+
36
+ const props = defineProps<Props>();
37
+
38
+ const { t } = useI18n();
39
+ </script>
40
+
41
+ <style lang="scss" scoped>
42
+ .dynamic-filter-add-action {
43
+ display: flex;
44
+
45
+ &-wrapper {
46
+ display: flex;
47
+ justify-content: center;
48
+ align-items: center;
49
+ gap: var(--spacing-2xs);
50
+ cursor: pointer;
51
+ width: fit-content;
52
+ }
53
+ }
54
+ </style>
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <div
3
+ class="dynamic-filter-panel-wrapper"
4
+ :class="`dynamic-filter-panel-wrapper--${props.size}`"
5
+ >
6
+ <div class="dynamic-filter-panel-wrapper__filters">
7
+ <slot name="filters" />
8
+ </div>
9
+
10
+ <div class="dynamic-filter-panel-wrapper__actions">
11
+ <slot name="actions" />
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { ComponentSize } from '../../../../../enums';
18
+
19
+ const props = withDefaults(
20
+ defineProps<{
21
+ size?: ComponentSize;
22
+ }>(),
23
+ {
24
+ size: ComponentSize.MD,
25
+ },
26
+ );
27
+ </script>
28
+
29
+ <style lang="scss" scoped>
30
+ .dynamic-filter-panel-wrapper {
31
+ display: grid;
32
+ grid-gap: var(--spacing-sm);
33
+ grid-template-columns: 1fr auto;
34
+ align-items: center;
35
+ }
36
+
37
+ .dynamic-filter-panel-wrapper__filters {
38
+ display: flex;
39
+ flex-wrap: wrap;
40
+ align-items: center;
41
+ grid-gap: var(--spacing-sm);
42
+ }
43
+
44
+ .dynamic-filter-panel-wrapper__actions {
45
+ display: flex;
46
+ grid-gap: var(--spacing-sm);
47
+ }
48
+
49
+ .dynamic-filter-panel-wrapper {
50
+ &--sm {
51
+ .dynamic-filter-panel-wrapper__filters,
52
+ .dynamic-filter-panel-wrapper__actions {
53
+ grid-gap: var(--spacing-xs);
54
+ }
55
+ }
56
+ }
57
+ </style>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <wt-search-bar
3
+ :placeholder="t('reusable.search')"
4
+ :search-mode="props.searchMode"
5
+ :search-mode-options="searchModeOptions"
6
+ :value="model"
7
+ @input="model = $event"
8
+ @search="handleSearch"
9
+ @update:search-mode="onSearchModeChange($event.value)"
10
+ >
11
+ <template
12
+ v-if="props.showTextSearchIcon"
13
+ #search-icon
14
+ >
15
+ <wt-icon icon="stt-search" />
16
+ </template>
17
+ </wt-search-bar>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import { computed } from 'vue';
22
+ import { useI18n } from 'vue-i18n';
23
+
24
+ import WtSearchBar from '../../../../../components/wt-search-bar/wt-search-bar.vue';
25
+
26
+ type ModelValue = string;
27
+ const model = defineModel<ModelValue>();
28
+
29
+ const props = defineProps<{
30
+ searchMode: string;
31
+ searchModeOptions: Record<string, string>;
32
+ showTextSearchIcon?: boolean;
33
+ }>();
34
+
35
+ const emit = defineEmits<{
36
+ 'update:search-mode': [string];
37
+ 'handle-search': [string];
38
+ }>();
39
+
40
+ const { t } = useI18n();
41
+
42
+ const onSearchModeChange = (value: string) => {
43
+ emit('update:search-mode', value);
44
+ model.value = '';
45
+ };
46
+
47
+ const handleSearch = () => {
48
+ emit('handle-search', model.value);
49
+ };
50
+
51
+ const searchModeOptions = computed(() =>
52
+ Object.values(props.searchModeOptions).map((mode) => {
53
+ return {
54
+ value: mode,
55
+ text: t(`filters.search.${mode}`),
56
+ };
57
+ }),
58
+ );
59
+ </script>
60
+
61
+ <style lang="scss" scoped></style>
@@ -0,0 +1,39 @@
1
+ import { useVuelidate } from '@vuelidate/core';
2
+ import { computed, ModelRef, type Reactive, type Ref } from 'vue';
3
+ import { useI18n } from 'vue-i18n';
4
+
5
+ import { BooleanFilterModelValue } from '../types/BooleanFilter';
6
+
7
+ export const usePrettifyBooleanValuePreview = (
8
+ value: Reactive<boolean>,
9
+ ): { localeValue: Ref<string> } => {
10
+ const { t } = useI18n();
11
+
12
+ const localeValue = computed(() => {
13
+ return value ? t('vocabulary.yes') : t('vocabulary.no');
14
+ });
15
+
16
+ return { localeValue };
17
+ };
18
+
19
+ export const useBooleanFilterValueValidation = <
20
+ T extends BooleanFilterModelValue,
21
+ >(
22
+ model: ModelRef<T>,
23
+ ) => {
24
+ const v$ = useVuelidate(
25
+ computed(() => ({
26
+ model: {
27
+ required: (v: T) => !(!v && v !== false),
28
+ },
29
+ })),
30
+ { model },
31
+ { $autoDirty: true },
32
+ );
33
+
34
+ v$.value.$touch();
35
+
36
+ return {
37
+ v$,
38
+ };
39
+ };
@@ -0,0 +1,41 @@
1
+ import { computed } from 'vue';
2
+ import { useI18n } from 'vue-i18n';
3
+
4
+ export const useFromToSecToPreviewTime = (value: {
5
+ from?: number | string | null;
6
+ to?: number | string | null;
7
+ }) => {
8
+ const { t } = useI18n();
9
+
10
+ const format = (secsVal: number) => {
11
+ const minutes = Math.floor(secsVal / 60);
12
+ const seconds = secsVal % 60;
13
+
14
+ return `${t('webitelUI.timepicker.min')} ${minutes} ${t('webitelUI.timepicker.sec')} ${seconds}`;
15
+ };
16
+
17
+ const from = computed(() => {
18
+ const numValue = Number(value.from);
19
+
20
+ if (!numValue && numValue !== 0) {
21
+ return '';
22
+ }
23
+
24
+ return format(numValue);
25
+ });
26
+
27
+ const to = computed(() => {
28
+ const numValue = Number(value.to);
29
+
30
+ if (!numValue && numValue !== 0) {
31
+ return '';
32
+ }
33
+
34
+ return format(numValue);
35
+ });
36
+
37
+ return {
38
+ from,
39
+ to,
40
+ };
41
+ };
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div class="date-time-filter-value-field">
3
+ <wt-datepicker
4
+ :label="`${t('webitelUI.filters.createdAtFrom')}:`"
5
+ :value="model?.from"
6
+ class="date-time-filter-value-field__picker"
7
+ mode="datetime"
8
+ @input="handleInput('from', $event)"
9
+ />
10
+
11
+ <wt-datepicker
12
+ :label="`${t('webitelUI.filters.createdAtTo')}:`"
13
+ :value="model?.to"
14
+ class="date-time-filter-value-field__picker"
15
+ mode="datetime"
16
+ @input="handleInput('to', $event)"
17
+ />
18
+ </div>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ import { endOfToday, startOfToday } from 'date-fns';
23
+ import { onMounted } from 'vue';
24
+ import { useI18n } from 'vue-i18n';
25
+
26
+ type ModelValue = {
27
+ from: number;
28
+ to: number;
29
+ };
30
+
31
+ const model = defineModel<ModelValue>();
32
+ const { t } = useI18n();
33
+
34
+ const handleInput = (key: keyof ModelValue, value: number) => {
35
+ model.value = { ...model.value, [key]: value };
36
+ };
37
+
38
+ const initModel = () => {
39
+ if (!model.value) {
40
+ model.value = {
41
+ from: startOfToday().getTime(),
42
+ to: endOfToday().getTime(),
43
+ };
44
+ }
45
+ };
46
+
47
+ onMounted(() => initModel());
48
+ </script>
49
+
50
+ <style lang="scss" scoped>
51
+ .date-time-filter-value-field {
52
+ display: flex;
53
+ flex-direction: column;
54
+ grid-gap: var(--spacing-xs);
55
+ }
56
+ </style>
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <div class="duration-filter">
3
+ <wt-timepicker
4
+ v-if="model"
5
+ :label="t('reusable.from')"
6
+ :value="model.from"
7
+ :v="v$.model?.from"
8
+ format="mm:ss"
9
+ @input="handleInput('from', $event)"
10
+ />
11
+ <wt-timepicker
12
+ v-if="model"
13
+ :label="t('reusable.to')"
14
+ :value="model.to"
15
+ :v="v$.model?.to"
16
+ format="mm:ss"
17
+ @input="handleInput('to', $event)"
18
+ />
19
+ </div>
20
+ </template>
21
+
22
+ <script lang="ts" setup>
23
+ import { useVuelidate } from '@vuelidate/core';
24
+ import { computed, watch } from 'vue';
25
+ import { useI18n } from 'vue-i18n';
26
+
27
+ const { t } = useI18n();
28
+
29
+ type ModelValue = {
30
+ from: number;
31
+ to: number;
32
+ };
33
+
34
+ const model = defineModel<ModelValue>();
35
+
36
+ const emit = defineEmits<{
37
+ 'update:invalid': [boolean];
38
+ }>();
39
+
40
+ if (!model.value) {
41
+ model.value = {
42
+ from: 0,
43
+ to: 0,
44
+ };
45
+ }
46
+
47
+ const isValueEmpty = () => {
48
+ return !!model?.value?.to || !!model?.value?.from;
49
+ };
50
+
51
+ const v$ = useVuelidate(
52
+ computed(() => ({
53
+ model: {
54
+ from: {
55
+ required: isValueEmpty,
56
+ },
57
+ to: {
58
+ required: isValueEmpty,
59
+ },
60
+ },
61
+ })),
62
+ { model },
63
+ { $autoDirty: true },
64
+ );
65
+ v$.value.$touch();
66
+
67
+ const handleInput = (key: keyof ModelValue, value: number) => {
68
+ const newValue = { ...model.value };
69
+ newValue[key] = value;
70
+ model.value = newValue;
71
+ };
72
+
73
+ watch(
74
+ () => v$.value.$invalid,
75
+ (invalid) => {
76
+ emit('update:invalid', invalid);
77
+ },
78
+ { immediate: true },
79
+ );
80
+ </script>
81
+
82
+ <style lang="scss" scoped>
83
+ //.duration-filter {}
84
+ </style>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <wt-select
3
+ v-bind="attrs"
4
+ :clearable="false"
5
+ :options="BooleanOptions"
6
+ :value="strModel"
7
+ :label="t('webitelUI.filters.filterValue')"
8
+ class="has-option-filter-value-field"
9
+ track-by="value"
10
+ use-value-from-options-by-prop="value"
11
+ @input="strModel = $event"
12
+ />
13
+ </template>
14
+
15
+ <script lang="ts" setup>
16
+ import { computed, useAttrs } from 'vue';
17
+ import { useI18n } from 'vue-i18n';
18
+
19
+ import WtSelect from '../../../../../../../../components/wt-select/wt-select.vue';
20
+ import { BooleanOptions } from '../../../../enums/boolean-options';
21
+
22
+ const model = defineModel<boolean | null>();
23
+
24
+ const attrs = useAttrs();
25
+
26
+ const { t } = useI18n();
27
+
28
+ const strModel = computed({
29
+ get: () => {
30
+ return typeof model.value === 'boolean' ? String(model.value) : model.value;
31
+ },
32
+ set: (value: string) => {
33
+ model.value = value === 'true';
34
+ },
35
+ });
36
+ </script>
37
+
38
+ <style lang="scss" scoped></style>
@@ -0,0 +1 @@
1
+ export type BooleanFilterModelValue = boolean;
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <date-time-filter-value-field
3
+ :model-value="model"
4
+ @update:model-value="model = $event"
5
+ />
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import DateTimeFilterValueField from '../_shared/date-time-filter/date-time-filter-value-field.vue';
10
+
11
+ type ModelValue = {
12
+ from: number;
13
+ to: number;
14
+ };
15
+ const model = defineModel<ModelValue>();
16
+ </script>
17
+
18
+ <style lang="scss" scoped></style>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <div class="actual-reaction-time-filter-value-preview">
3
+ <div v-if="props.value.from">
4
+ <p class="actual-reaction-time-filter-value-preview__title">
5
+ {{ t('reusable.from') }}
6
+ </p>
7
+
8
+ <span>{{ convertTimestampToDate(props.value.from) }}</span>
9
+ </div>
10
+
11
+ <div v-if="props.value.to">
12
+ <p class="actual-reaction-time-filter-value-preview__title">
13
+ {{ t('reusable.to') }}
14
+ </p>
15
+
16
+ <span>{{ convertTimestampToDate(props.value.to) }}</span>
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ import { format } from 'date-fns';
23
+ import { useI18n } from 'vue-i18n';
24
+
25
+ const props = defineProps<{
26
+ value: number[];
27
+ }>();
28
+
29
+ const { t } = useI18n();
30
+
31
+ function convertTimestampToDate(value) {
32
+ return format(new Date(value), 'dd.MM.yyyy HH:mm');
33
+ }
34
+ </script>
35
+
36
+ <style lang="scss" scoped>
37
+ @use '@webitel/styleguide/typography' as *;
38
+
39
+ .actual-reaction-time-filter-value-preview {
40
+ &__title {
41
+ @extend %typo-subtitle-1;
42
+ }
43
+ }
44
+ </style>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <date-time-filter-value-field
3
+ :model-value="model"
4
+ @update:model-value="model = $event"
5
+ />
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import DateTimeFilterValueField from '../_shared/date-time-filter/date-time-filter-value-field.vue';
10
+
11
+ type ModelValue = {
12
+ from: number;
13
+ to: number;
14
+ };
15
+ const model = defineModel<ModelValue>();
16
+ </script>
17
+
18
+ <style lang="scss" scoped></style>