mediacube-ui 0.1.345 → 0.1.347

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 (109) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/0.mediacube-ui.umd.js +50 -0
  3. package/dist/assets/img/icons.3b7d59b2f49c67a2a3a4566b8ab233fd.svg +1 -0
  4. package/dist/assets/img/no_table_data.236cd56f46cfb71fc363b008d4ca70d5.png +0 -0
  5. package/dist/assets/img/no_user.e0030d6e54e2400e1181fd22b83cf8ae.png +0 -0
  6. package/dist/mediacube-ui.umd.js +1 -0
  7. package/package.json +14 -16
  8. package/src/assets/icons.svg +1 -1
  9. package/src/assets/tokens/tokens.json +5 -0
  10. package/dist/mediacube-ui.common.js +0 -378
  11. package/src/elements/McAvatar/McAvatar.vue +0 -274
  12. package/src/elements/McBadge/McBadge.vue +0 -148
  13. package/src/elements/McButton/McButton.vue +0 -841
  14. package/src/elements/McChip/McChip.vue +0 -300
  15. package/src/elements/McCropper/McCropper.vue +0 -133
  16. package/src/elements/McDate/McDate.vue +0 -105
  17. package/src/elements/McDatePicker/McDatePicker.vue +0 -902
  18. package/src/elements/McField/McFieldCheckbox/McFieldCheckbox.vue +0 -332
  19. package/src/elements/McField/McFieldRadio/McFieldRadioButton/McFieldRadioButton.vue +0 -201
  20. package/src/elements/McField/McFieldRadio/McFieldRadioGroup/McFieldRadioGroup.vue +0 -194
  21. package/src/elements/McField/McFieldSelect/McFieldSelect.vue +0 -1087
  22. package/src/elements/McField/McFieldText/McFieldText.vue +0 -969
  23. package/src/elements/McField/McFieldToggle/McFieldToggle.vue +0 -268
  24. package/src/elements/McInfinityLoadingIndicator/McInfinityLoadingIndicator.vue +0 -97
  25. package/src/elements/McNotification/McNotification.vue +0 -209
  26. package/src/elements/McProgress/McProgress.vue +0 -218
  27. package/src/elements/McRangeSlider/McRangeSlider.vue +0 -195
  28. package/src/elements/McSeparator/McSeparator.vue +0 -143
  29. package/src/elements/McSlideUpDown/McSlideUpDown.vue +0 -157
  30. package/src/elements/McSvgIcon/McSvgIcon.vue +0 -127
  31. package/src/elements/McTabs/McTab/McTab.vue +0 -187
  32. package/src/elements/McTabs/McTabs/McTabs.vue +0 -531
  33. package/src/elements/McTitle/McTitle.vue +0 -365
  34. package/src/elements/McTooltip/McTooltip.vue +0 -334
  35. package/src/helpers/consts.js +0 -3
  36. package/src/helpers/delayedAction.js +0 -26
  37. package/src/helpers/storybookFunctions.js +0 -20
  38. package/src/helpers/storybookVariables.js +0 -24
  39. package/src/mixins/equalFieldHeight.js +0 -59
  40. package/src/mixins/fieldErrors.js +0 -28
  41. package/src/patterns/McAccordion/McAccordion.vue +0 -53
  42. package/src/patterns/McCells/McCell/McCell.vue +0 -101
  43. package/src/patterns/McChat/McChat.vue +0 -305
  44. package/src/patterns/McChat/McChatComment/McChatComment.vue +0 -265
  45. package/src/patterns/McChat/McChatForm/McChatForm.vue +0 -147
  46. package/src/patterns/McCollapse/McCollapse.vue +0 -280
  47. package/src/patterns/McDrawer/McDrawer.vue +0 -146
  48. package/src/patterns/McDropdown/McDropdown.vue +0 -247
  49. package/src/patterns/McDropdown/McDropdownPanel/McDropdownPanel.vue +0 -40
  50. package/src/patterns/McFakeScroll/McFakeScroll.vue +0 -277
  51. package/src/patterns/McFilter/McFilter.vue +0 -847
  52. package/src/patterns/McFilter/McFilterChip/McFilterChip.vue +0 -83
  53. package/src/patterns/McFilter/McFilterTags/McFilterTags.vue +0 -374
  54. package/src/patterns/McFilter/McFilterTypeDate/McFilterTypeDate.vue +0 -70
  55. package/src/patterns/McFilter/McFilterTypeRange/McFilterTypeRange.vue +0 -132
  56. package/src/patterns/McFilter/McFilterTypeRelation/McFilterTypeRelation.vue +0 -221
  57. package/src/patterns/McFilter/McFilterTypeSimple/McFilterTypeSimple.vue +0 -161
  58. package/src/patterns/McFilter/McFilterTypeText/McFilterTypeText.vue +0 -62
  59. package/src/patterns/McGrid/McGridCol/McGridCol.vue +0 -165
  60. package/src/patterns/McGrid/McGridRow/McGridRow.vue +0 -158
  61. package/src/patterns/McModal/McModal.vue +0 -680
  62. package/src/patterns/McOverlay/McOverlay.vue +0 -78
  63. package/src/patterns/McPreview/McPreview.vue +0 -118
  64. package/src/patterns/McSideBar/McSideBar/McSideBar.vue +0 -387
  65. package/src/patterns/McSideBar/McSideBarBottom/McSideBarBottom.vue +0 -125
  66. package/src/patterns/McSideBar/McSideBarButton/McSideBarButton.vue +0 -252
  67. package/src/patterns/McSideBar/McSideBarCenter/McSideBarCenter.vue +0 -367
  68. package/src/patterns/McSideBar/McSideBarTop/McSideBarTop.vue +0 -238
  69. package/src/patterns/McStack/McStack.vue +0 -158
  70. package/src/patterns/McTable/McTable/McTable.vue +0 -854
  71. package/src/patterns/McTable/McTableCol/McTableCol.vue +0 -296
  72. package/src/patterns/McTableCard/McTableCard.vue +0 -135
  73. package/src/patterns/McTableCard/McTableCardHeader/McTableCardHeader.vue +0 -74
  74. package/src/patterns/McTopBar/McTopBar.vue +0 -153
  75. package/src/patterns/McWrapScroll/McWrapScroll.vue +0 -291
  76. package/src/styles/_functions.scss +0 -187
  77. package/src/styles/_mixins.scss +0 -612
  78. package/src/styles/_spacing.scss +0 -33
  79. package/src/styles/_variables.scss +0 -23
  80. package/src/styles/global.scss +0 -308
  81. package/src/styles/main.scss +0 -4
  82. package/src/styles/table.scss +0 -10
  83. package/src/styles/toast.scss +0 -55
  84. package/src/templates/layouts/McContentFixed/McContentFixed.vue +0 -60
  85. package/src/templates/layouts/McMain/McMain.vue +0 -115
  86. package/src/templates/layouts/McRoot/McRoot.vue +0 -45
  87. package/src/tokens/animations.scss +0 -9
  88. package/src/tokens/border-radius.scss +0 -26
  89. package/src/tokens/box-shadows.scss +0 -28
  90. package/src/tokens/colors.scss +0 -82
  91. package/src/tokens/durations.scss +0 -7
  92. package/src/tokens/easings.scss +0 -6
  93. package/src/tokens/font-families.scss +0 -8
  94. package/src/tokens/font-sizes.scss +0 -23
  95. package/src/tokens/font-weights.scss +0 -9
  96. package/src/tokens/gradients.scss +0 -18
  97. package/src/tokens/letter-spacings.scss +0 -6
  98. package/src/tokens/line-heights.scss +0 -22
  99. package/src/tokens/media-queries.scss +0 -32
  100. package/src/tokens/opacities.scss +0 -8
  101. package/src/tokens/sizes.scss +0 -47
  102. package/src/tokens/spacings.scss +0 -38
  103. package/src/tokens/z-indexes.scss +0 -14
  104. package/src/utils/dayjs.js +0 -19
  105. package/src/utils/filters.js +0 -11
  106. package/src/utils/getTokens.js +0 -41
  107. package/src/utils/load-icons.js +0 -3
  108. package/src/utils/treeSearch.js +0 -30
  109. package/src/utils/webFontLoader.js +0 -12
@@ -1,847 +0,0 @@
1
- <template>
2
- <div class="mc-filter">
3
- <div class="mc-filter__header">
4
- <mc-tooltip :content="placeholders.main_tooltip" placement="top" size="s">
5
- <mc-button
6
- :variation="visibilityToggleVariation"
7
- :disabled="disabledOpen"
8
- :bg-flat="isOpen"
9
- size="m-compact"
10
- @click="isOpen = !isOpen"
11
- >
12
- <mc-svg-icon slot="icon-prepend" name="filter_list" />
13
- </mc-button>
14
- </mc-tooltip>
15
- <div v-if="currentPresets.length" class="mc-filter__presets">
16
- <div ref="dragArea" class="mc-filter__presets-inner" @mousedown="onMouseDown">
17
- <mc-button
18
- v-for="preset in currentPresets"
19
- :key="preset.name"
20
- :variation="getPresetButtonVariation(preset)"
21
- :tooltip="preset.tooltip"
22
- secondary-color="purple"
23
- @mouseup="() => handlePresetMouseUp(preset)"
24
- >
25
- {{ preset.visibleName }}
26
- </mc-button>
27
- </div>
28
- </div>
29
- </div>
30
- <component :is="usePortal ? 'portal' : 'div'" to="filterTarget">
31
- <div v-if="isOpen" class="mc-filter__body">
32
- <div class="mc-filter__body-top">
33
- <div class="mc-filter__body-top-left">
34
- <mc-field-select
35
- v-model="selectedOptionFilter"
36
- :title="placeholders.value"
37
- :options="regularFilters"
38
- :placeholder="placeholders.choose"
39
- :hide-selected="false"
40
- class="mc-filter__main-select"
41
- name="filter_value_name"
42
- />
43
- <template v-if="currentFilter">
44
- <component
45
- :is="computedComponentTypeName"
46
- :value="currentCondition"
47
- :filter="currentFilter"
48
- :placeholders="placeholders"
49
- :current-values="!activeTag ? currentValues : {}"
50
- :use-timezone="useTimezone"
51
- @input="handleConditionChange"
52
- />
53
- <mc-button v-if="hasButtonAdd" variation="purple-outline" @click.native="handleStoreTag">
54
- {{ placeholders.actions[activeTag ? 'save' : 'add'] }}
55
- </mc-button>
56
- </template>
57
- </div>
58
- <div v-if="false" class="mc-filter__body-top-right">
59
- <mc-cell>
60
- <mc-title slot="title">{{ placeholders.fast_filters }}</mc-title>
61
- </mc-cell>
62
- </div>
63
- </div>
64
- <mc-filter-tags
65
- :value="currentValuesName"
66
- :filters="filters"
67
- :placeholders="placeholders"
68
- :active-tag="activeTag"
69
- :use-timezone="useTimezone"
70
- @tag-change="onTagsChange"
71
- @tag-click="onTagClick"
72
- @clear="allTagsClear"
73
- />
74
- <section class="mc-filter__body-fast-tags-wrapper">
75
- <mc-tooltip
76
- v-for="(tag, i) in fastFilters"
77
- :key="i"
78
- :content="tag.description || ''"
79
- placement="top"
80
- size="s"
81
- >
82
- <mc-chip
83
- variation="gray-outline"
84
- text-color="black"
85
- size="s"
86
- @click.native="handlerSetFastFilter(tag)"
87
- >
88
- {{ tag.name }}
89
- </mc-chip>
90
- </mc-tooltip>
91
- </section>
92
- <div class="mc-filter__body-bottom">
93
- <div class="mc-filter__body-bottom-left">
94
- <mc-button
95
- :disabled="buttonConfirmIsDisable"
96
- :loading="buttonConfirmIsLoading"
97
- size="s"
98
- @click.native="handleConfirm"
99
- >
100
- {{ placeholders.actions.confirm }}
101
- </mc-button>
102
- <mc-button
103
- v-if="activePreset"
104
- variation="red-outline"
105
- size="s"
106
- @click.native="() => handleDeletePreset(activePreset)"
107
- >
108
- {{ placeholders.actions.delete_preset }}
109
- <mc-svg-icon slot="icon-append" name="delete" size="250" color="red" />
110
- </mc-button>
111
- </div>
112
- <div class="mc-filter__body-bottom-right">
113
- <mc-title class="mc-filter__preset-input-title">
114
- {{ placeholders.create_preset }}
115
- <mc-tooltip
116
- slot="icon-append"
117
- :content="placeholders.enter_preset_tooltip"
118
- placement="top"
119
- size="s"
120
- >
121
- <mc-svg-icon name="help" size="250" color="outline-gray" />
122
- </mc-tooltip>
123
- </mc-title>
124
- <mc-field-text
125
- v-model="newPresetName"
126
- :placeholder="placeholders.enter_preset_name"
127
- class="mc-filter__preset-input"
128
- name="preset_name"
129
- />
130
- <mc-button
131
- :disabled="buttonCreateIsDisable"
132
- variation="purple-outline"
133
- size="s"
134
- @click.native="handleCreatePreset"
135
- >
136
- {{ placeholders.actions.create }}
137
- </mc-button>
138
- </div>
139
- </div>
140
- </div>
141
- </component>
142
- </div>
143
- </template>
144
-
145
- <script>
146
- import _isEmpty from 'lodash/isEmpty'
147
- import _isEqual from 'lodash/isEqual'
148
- import _uniq from 'lodash/uniq'
149
- import _cloneDeep from 'lodash/cloneDeep'
150
- import McSvgIcon from '../../elements/McSvgIcon/McSvgIcon'
151
- import McButton from '../../elements/McButton/McButton'
152
- import McTitle from '../../elements/McTitle/McTitle'
153
- import McFieldSelect from '../../elements/McField/McFieldSelect/McFieldSelect'
154
- import McFieldText from '../../elements/McField/McFieldText/McFieldText'
155
- import McCell from '../../patterns/McCells/McCell/McCell'
156
- import McTooltip from '../../elements/McTooltip/McTooltip'
157
- import McFilterTypeRelation from './McFilterTypeRelation/McFilterTypeRelation'
158
- import McFilterTypeText from './McFilterTypeText/McFilterTypeText'
159
- import McFilterTypeRange from './McFilterTypeRange/McFilterTypeRange'
160
- import McFilterTypeDate from './McFilterTypeDate/McFilterTypeDate'
161
- import McFilterTypeSimple from './McFilterTypeSimple/McFilterTypeSimple'
162
- import McFilterTags from './McFilterTags/McFilterTags'
163
- import McChip from '../../elements/McChip/McChip'
164
-
165
- export default {
166
- name: 'McFilter',
167
- components: {
168
- McFilterTags,
169
- McFilterTypeRelation,
170
- McFilterTypeText,
171
- McFilterTypeRange,
172
- McFilterTypeDate,
173
- McFilterTypeSimple,
174
- McSvgIcon,
175
- McButton,
176
- McTitle,
177
- McFieldSelect,
178
- McFieldText,
179
- McCell,
180
- McTooltip,
181
- McChip,
182
- },
183
- props: {
184
- /**
185
- * Имя фильтра
186
- * (для записи данных в стор)
187
- */
188
- name: {
189
- type: String,
190
- required: true,
191
- },
192
- /**
193
- * Значение фильтра
194
- */
195
- value: {
196
- type: Object,
197
- required: true,
198
- },
199
- /**
200
- * Типы фильтров
201
- *
202
- * [{
203
- name: Filter title,
204
- value: [String] - Filter value(key),
205
- type: [String] - Filter type(relation / date / text / fast / labels / simple),
206
- options: [Array] - Filter options,
207
- getAjaxOne: [Function] - Method for get selected options when filter initialize,
208
- getAjaxOptions: [Function] - Method for get options by API,
209
- [relation]: [String] - Filter relation, only for fast filter,
210
- [default]: [String, Number, Boolean] - Only for fast filter type. Fast filter haven't options, we set default value
211
- [description]: [String] - Only for fast filter type. Description of fast filter
212
- }, ...]
213
- */
214
- filters: {
215
- type: Array,
216
- required: true,
217
- },
218
- /**
219
- * Лоадинг кнопки применить фильтр
220
- */
221
- buttonConfirmIsLoading: {
222
- type: Boolean,
223
- default: false,
224
- },
225
- /**
226
- * Использовать ли портал (для рендеринга вне компонента)
227
- * Если да то необходим пакет portal-vue и <portal-target name="filterTarget" /> для рендеринга
228
- */
229
- usePortal: {
230
- type: Boolean,
231
- default: true,
232
- },
233
- /**
234
- * Доступен ли фильтр для открытия
235
- */
236
- disabledOpen: {
237
- type: Boolean,
238
- default: false,
239
- },
240
- useTimezone: {
241
- type: Boolean,
242
- default: true,
243
- },
244
- /**
245
- * Переводы локализаций
246
- */
247
- placeholders: {
248
- type: Object,
249
- default() {
250
- return {
251
- main_tooltip: '',
252
- value: 'Value',
253
- condition: 'Condition',
254
- create_preset: 'Create new preset',
255
- fast_filters: 'Fast filters',
256
- added_filters: 'Added filters',
257
- enter_preset_name: 'Enter preset name',
258
- enter_preset_tooltip: 'Сохранение выбранных параметров фильтра в пользовательский пресет',
259
- from: 'From',
260
- to: 'To',
261
- enter: 'Enter',
262
- choose: 'Choose',
263
- actions: {
264
- add: 'Add',
265
- save: 'Save',
266
- clear: 'Clear',
267
- create: 'Create',
268
- delete_preset: 'Delete preset',
269
- is: 'This',
270
- is_not: 'Is not',
271
- empty: 'Empty',
272
- confirm: 'Confirm',
273
- },
274
- calendar: {
275
- week: 'Week',
276
- month: 'Month',
277
- quarter: 'Quarter',
278
- year: 'Year',
279
- confirm: 'Confirm',
280
- },
281
- messages: {
282
- same_filter: 'Уже есть фильтр с таким параметром',
283
- same_preset_name: 'Уже есть фильтр с таким именем',
284
- accidentally_cleared: 'Случайно очистили?',
285
- accidentally_deleted: 'Случайно удалили?',
286
- more_than: 'Значение "от" не может быть больше значения "до"',
287
- },
288
- }
289
- },
290
- },
291
- },
292
- data() {
293
- return {
294
- isOpen: false,
295
- currentValues: {},
296
- currentValuesName: {},
297
- temporaryValues: {},
298
- temporaryValuesName: {},
299
- selectedOptionFilter: null,
300
- currentCondition: null,
301
- currentConditionName: null,
302
- buttonConfirmIsDisable: false,
303
- newPresetName: '',
304
- preset_max_size: 40,
305
- dragOptions: {
306
- scrollPos: 0,
307
- startClientPos: 0,
308
- distance: 0,
309
- isDrag: false,
310
- mouseIsDown: false,
311
- },
312
- presets: {},
313
- activePreset: null,
314
- temporaryActivePreset: null,
315
- activeTag: null,
316
- }
317
- },
318
- computed: {
319
- fastFilters() {
320
- const selected = (this.currentValues && Object.keys(this.currentValues)) || []
321
- return this.filters.filter(f => f.type === 'fast' && !selected.includes(f.value))
322
- },
323
- regularFilters() {
324
- return this.filters.filter(f => f.type !== 'fast')
325
- },
326
- visibilityToggleVariation() {
327
- return this.isOpen || !this.buttonConfirmIsDisable ? 'purple-invert' : 'black-flat'
328
- },
329
- currentFilter() {
330
- return this.filters.find(f => f.value === this.selectedOptionFilter)
331
- },
332
- computedComponentTypeName() {
333
- if (this.currentFilter && this.currentFilter.type === 'fast') return null
334
- return `mc-filter-type-${this.currentFilter.type}`
335
- },
336
- hasButtonAdd() {
337
- return !_isEmpty(this.currentCondition)
338
- },
339
- buttonCreateIsDisable() {
340
- return !(this.newPresetName.trim() && Object.keys(this.currentValues)?.length)
341
- },
342
- currentPresets() {
343
- return (
344
- this.presets[this.name]?.map(preset => {
345
- const hasLongName = preset?.name?.length > this.preset_max_size
346
- return {
347
- ...preset,
348
- visibleName: hasLongName ? `${preset.name.slice(0, this.preset_max_size)}...` : preset.name,
349
- tooltip: hasLongName ? preset?.name : null,
350
- }
351
- }) || []
352
- )
353
- },
354
- },
355
- watch: {
356
- value: {
357
- handler(val) {
358
- this.currentValues = { ...val.filter }
359
- if (val.filter_name) {
360
- try {
361
- this.currentValuesName = JSON.parse(decodeURI(atob(val.filter_name)))
362
- } catch (e) {
363
- console.error(`Can't parse filters`)
364
- }
365
- }
366
- this.buttonConfirmIsDisable = _isEmpty(val.filter) || _isEmpty(val.filter_name)
367
- },
368
- immediate: true,
369
- deep: true,
370
- },
371
- currentFilter: {
372
- handler() {
373
- this.handleConditionChange()
374
- },
375
- deep: true,
376
- },
377
- currentValues(newVal, oldVal) {
378
- if (_isEmpty(oldVal) && !_isEmpty(newVal)) {
379
- this.buttonConfirmIsDisable = false
380
- }
381
- if (_isEmpty(this.value.filter) && _isEmpty(newVal)) {
382
- this.buttonConfirmIsDisable = true
383
- }
384
- if (!_isEqual(this.activePreset?.filter, newVal)) {
385
- this.activePreset = null
386
- }
387
- },
388
- },
389
- mounted() {
390
- this.updatePresets()
391
- document.documentElement.addEventListener('mousemove', this.onMouseMove)
392
- document.documentElement.addEventListener('mouseup', this.onMouseUp)
393
- window.addEventListener('storage', this.updatePresets)
394
- },
395
- beforeDestroy() {
396
- document.documentElement.removeEventListener('mousemove', this.onMouseMove)
397
- document.documentElement.removeEventListener('mouseup', this.onMouseUp)
398
- window.removeEventListener('storage', this.updatePresets)
399
- },
400
- methods: {
401
- updatePresets() {
402
- this.presets = {
403
- [this.name]: [],
404
- ...JSON.parse(window.localStorage.mcFilterPresets || '{}'),
405
- }
406
- },
407
- handlerSetFastFilter(tag) {
408
- const filterValue = tag.relation ? { [tag.relation]: tag.default } : tag.default
409
- this.selectedOptionFilter = tag.value
410
- this.handleConditionChange(filterValue, tag.name)
411
- this.handleStoreTag()
412
- },
413
- onMouseDown(e) {
414
- this.dragOptions.startClientPos = e.clientX
415
- this.dragOptions.mouseIsDown = true
416
- this.dragOptions.scrollPos = this.$refs.dragArea.scrollLeft
417
- },
418
- onMouseMove(e) {
419
- if (!this.dragOptions.mouseIsDown) return
420
-
421
- this.dragOptions.distance = e.clientX - this.dragOptions.startClientPos
422
- if (Math.abs(this.dragOptions.distance) > 2 && !this.dragOptions.isDrag) {
423
- this.dragOptions.isDrag = true
424
- }
425
- if (this.dragOptions.isDrag) {
426
- this.$refs.dragArea.scrollTo({
427
- left: this.dragOptions.scrollPos - this.dragOptions.distance,
428
- })
429
- }
430
- if (Math.abs(this.scrollPos)) {
431
- this.dragOptions.scrollPos = 0
432
- }
433
- },
434
- onMouseUp() {
435
- if (this.dragOptions.isDrag) {
436
- this.dragOptions.isDrag = false
437
- }
438
- this.dragOptions.mouseIsDown = false
439
- },
440
- handlePresetMouseUp(preset) {
441
- if (this.dragOptions.isDrag) return
442
- if (this.activePreset && this.activePreset.name === preset.name) {
443
- this.activePreset = null
444
- this.currentValues = {}
445
- this.currentValuesName = {}
446
- } else {
447
- this.activePreset = preset
448
- this.currentValues = _cloneDeep(preset.filter)
449
- this.currentValuesName = _cloneDeep(preset.filter_name)
450
- }
451
- if (!this.isOpen) {
452
- this.handleConfirm()
453
- }
454
- },
455
- handleConditionChange(val = null, valName = null) {
456
- this.currentCondition = val
457
- this.currentConditionName = valName || val
458
- },
459
- handleStoreTag() {
460
- this.activeTag ? this.editTag() : this.addTag()
461
- },
462
- editTag() {
463
- switch (this.currentFilter.type) {
464
- case 'relation': {
465
- this.editRelationValue()
466
- break
467
- }
468
- default: {
469
- this.addSimpleValue()
470
- break
471
- }
472
- }
473
- this.activeTag = null
474
- },
475
- addTag() {
476
- switch (this.currentFilter.type) {
477
- case 'relation': {
478
- this.addRelationValue()
479
- break
480
- }
481
- default: {
482
- this.addSimpleValue()
483
- break
484
- }
485
- }
486
- this.activeTag = null
487
- },
488
- editRelationValue() {
489
- const tagRelationValue = this.activeTag.relationKey === 'exists' ? [0] : [this.activeTag.value]
490
- const tagRelation = {
491
- [this.activeTag.category]: {
492
- [this.activeTag.relationKey]: tagRelationValue,
493
- },
494
- }
495
- const selectedRelation = {
496
- [this.selectedOptionFilter]: _cloneDeep(this.currentCondition),
497
- }
498
- if (_isEqual(selectedRelation, tagRelation)) {
499
- /**
500
- * Событие по возникшей ошибке
501
- */
502
- this.$emit('error', this.placeholders.messages.same_filter)
503
- return
504
- }
505
- const { category, categoryName } = this.getCategoriesWithNewRelation()
506
- if (this.activeTag.relationKey === 'exists') {
507
- delete category[this.activeTag.relationKey]
508
- delete categoryName[this.activeTag.relationKey]
509
- } else {
510
- const numerableValues = category[this.activeTag.relationKey]
511
- const index = numerableValues.indexOf(this.activeTag.value)
512
- if (index !== -1) {
513
- category[this.activeTag.relationKey].splice(index, 1)
514
- _isEmpty(category[this.activeTag.relationKey]) && delete category[this.activeTag.relationKey]
515
-
516
- delete categoryName[this.activeTag.relationKey][this.activeTag.value]
517
- _isEmpty(categoryName[this.activeTag.relationKey]) &&
518
- delete categoryName[this.activeTag.relationKey]
519
- }
520
- }
521
-
522
- this.setFilterValues(category, categoryName)
523
- },
524
- addRelationValue() {
525
- const { category, categoryName } = this.getCategoriesWithNewRelation()
526
- this.setFilterValues(category, categoryName)
527
- },
528
- getCategoriesWithNewRelation() {
529
- const relationKeys = Object.keys(this.currentCondition)
530
- const values = _cloneDeep(this.currentValues)
531
- const valuesName = _cloneDeep(this.currentValuesName)
532
- const selectedCategory = values[this.selectedOptionFilter]
533
- const selectedCategoryName = valuesName[this.selectedOptionFilter]
534
-
535
- selectedCategory &&
536
- relationKeys.forEach(k => {
537
- if (k === 'exists') {
538
- selectedCategory[k] = [0]
539
- selectedCategoryName[k] = [0]
540
- } else {
541
- if (k in selectedCategory) {
542
- selectedCategory[k] = _uniq([...selectedCategory[k], ...this.currentCondition[k]])
543
- selectedCategoryName[k] = {
544
- ...selectedCategoryName[k],
545
- ...this.currentConditionName[k],
546
- }
547
- } else {
548
- selectedCategory[k] = this.currentCondition[k]
549
- selectedCategoryName[k] = this.currentConditionName[k]
550
- }
551
- }
552
- })
553
- return { category: selectedCategory, categoryName: selectedCategoryName }
554
- },
555
- setFilterValues(val, valName) {
556
- const newVal = {
557
- ...this.currentValues,
558
- [this.selectedOptionFilter]: val || this.currentCondition,
559
- }
560
- if (_isEqual(this.currentValues, newVal)) {
561
- /**
562
- * Событие по возникшей ошибке
563
- */
564
- this.$emit('error', this.placeholders.messages.same_filter)
565
- return
566
- }
567
- this.currentValues = newVal
568
- this.currentValuesName = {
569
- ...this.currentValuesName,
570
- [this.selectedOptionFilter]: valName || this.currentConditionName,
571
- }
572
-
573
- this.setEmptyCondition()
574
- },
575
- setEmptyCondition() {
576
- switch (this.currentFilter?.type) {
577
- case 'relation':
578
- case 'date':
579
- this.handleConditionChange()
580
- break
581
- case 'text':
582
- this.handleConditionChange('')
583
- break
584
- case 'range':
585
- this.handleConditionChange({})
586
- break
587
- default:
588
- break
589
- }
590
- },
591
- addSimpleValue() {
592
- if (this.currentFilter.type === 'range' && Object.keys(this.currentCondition).length === 2) {
593
- if (this.currentCondition.more > this.currentCondition.less) {
594
- /**
595
- * Событие по возникшей ошибке
596
- */
597
- this.$emit('error', this.placeholders.messages.more_than)
598
- return
599
- }
600
- }
601
- this.setFilterValues(this.currentCondition, this.currentCondition)
602
- },
603
- onTagsChange(val) {
604
- this.activeTag = null
605
- if (_isEmpty(val)) {
606
- this.currentValues = {}
607
- this.currentValuesName = {}
608
- return
609
- }
610
- this.currentValuesName = _cloneDeep(val)
611
- this.setRelationsToArrayFormat(val)
612
- },
613
- allTagsClear() {
614
- this.temporaryValues = _cloneDeep(this.currentValues)
615
- this.temporaryValuesName = _cloneDeep(this.currentValuesName)
616
- this.currentValues = {}
617
- this.currentValuesName = {}
618
- /**
619
- * Событие по очистке выбранных фильтров из поля
620
- */
621
- this.$emit('clear', this.placeholders.messages.accidentally_cleared)
622
- },
623
- clearTemporaryValues() {
624
- this.temporaryValues = {}
625
- this.temporaryValuesName = {}
626
- },
627
- revertClearedValues() {
628
- this.currentValues = _cloneDeep(this.temporaryValues)
629
- this.currentValuesName = _cloneDeep(this.temporaryValuesName)
630
- },
631
- setRelationsToArrayFormat(obj) {
632
- const newObj = _cloneDeep(obj)
633
- const relationKeys = ['is', 'is_not']
634
- for (let [categoryKey, categoryVal] of Object.entries(obj)) {
635
- if (categoryVal.constructor === Object) {
636
- for (let [key, val] of Object.entries(categoryVal)) {
637
- if (relationKeys.includes(key) && val.constructor === Object) {
638
- newObj[categoryKey][key] = [...Object.keys(val)]
639
- }
640
- }
641
- }
642
- }
643
- this.currentValues = newObj
644
- },
645
- onTagClick(tag) {
646
- this.activeTag = _isEqual(this.activeTag, tag) ? null : tag
647
- if (!this.activeTag) {
648
- this.setEmptyCondition()
649
- return
650
- }
651
- let condition = null
652
- let conditionName = null
653
- if (tag.relationKey) {
654
- condition = {
655
- [tag.relationKey]: tag.relationKey === 'exists' ? [0] : [String(tag.value)],
656
- }
657
- conditionName = {
658
- [tag.relationKey]: tag.relationKey === 'exists' ? [0] : { [tag.value]: tag.title },
659
- }
660
- } else {
661
- condition = tag.value?.constructor === Object ? tag.value : String(tag.value)
662
- conditionName = tag.value
663
- }
664
-
665
- this.selectedOptionFilter = tag.category
666
- this.$nextTick(() => {
667
- this.currentCondition = condition
668
- this.currentConditionName = conditionName
669
- })
670
- },
671
- handleConfirm() {
672
- const encodedData = btoa(encodeURI(JSON.stringify(this.currentValuesName)))
673
- /**
674
- * Событие по изменению значения фильтра
675
- */
676
- this.$emit('input', {
677
- filter: this.currentValues,
678
- filter_name: encodedData,
679
- })
680
- this.$emit('confirm')
681
- if (_isEmpty(this.currentValues)) {
682
- this.buttonConfirmIsDisable = true
683
- }
684
- },
685
- handleDeletePreset(preset) {
686
- const filteredPresets = this.presets[this.name].filter(p => p.name !== preset.name)
687
- this.presets[this.name] = [...filteredPresets]
688
- this.temporaryActivePreset = _cloneDeep(this.activePreset)
689
- this.activePreset = null
690
- this.currentValues = {}
691
- this.currentValuesName = {}
692
- /**
693
- * Событие по удалению пресета
694
- */
695
- this.$emit('delete-preset', this.placeholders.messages.accidentally_deleted)
696
- },
697
- savePresetsToLocalStorage() {
698
- window.localStorage.mcFilterPresets = JSON.stringify({ ...this.presets })
699
- },
700
- getPresetsFromLocalStorage() {
701
- this.activePreset = _cloneDeep(this.temporaryActivePreset)
702
- this.currentValues = _cloneDeep(this.activePreset.filter)
703
- this.currentValuesName = _cloneDeep(this.activePreset.filter_name)
704
- this.temporaryActivePreset = null
705
- this.presets = JSON.parse(window.localStorage.mcFilterPresets || '{}')
706
- },
707
- handleCreatePreset() {
708
- if (
709
- this.presets[this.name] &&
710
- this.presets[this.name].find(p => p.name?.trim() === this.newPresetName?.trim())
711
- ) {
712
- this.$emit('error', this.placeholders.messages.same_preset_name)
713
- return
714
- }
715
- const preset = {
716
- name: this.newPresetName?.trim(),
717
- filter: _cloneDeep(this.currentValues),
718
- filter_name: _cloneDeep(this.currentValuesName),
719
- }
720
- if ('mcFilterPresets' in window.localStorage) {
721
- const presets = JSON.parse(window.localStorage.mcFilterPresets)
722
- if (this.name in presets) {
723
- this.presets[this.name] = [preset, ...this.presets[this.name]]
724
- } else {
725
- this.presets[this.name] = [preset]
726
- }
727
- } else {
728
- this.presets[this.name] = [preset]
729
- }
730
- window.localStorage.mcFilterPresets = JSON.stringify({ ...this.presets })
731
- this.newPresetName = ''
732
- this.activePreset = { ...preset }
733
- },
734
- getPresetButtonVariation(preset) {
735
- return this.activePreset && this.activePreset.name === preset.name ? 'purple-invert' : 'gray-outline'
736
- },
737
- },
738
- }
739
- </script>
740
-
741
- <style lang="scss">
742
- @import '../../styles/mixins';
743
- @import '../../tokens/spacings';
744
- @import '../../tokens/colors';
745
- @import '../../tokens/sizes';
746
- .mc-filter {
747
- $block-name: &;
748
- flex-grow: 1;
749
- min-width: 0;
750
- &__header {
751
- display: flex;
752
- @include child-indent-right($space-100);
753
- }
754
-
755
- &__presets {
756
- position: relative;
757
- flex-grow: 1;
758
- min-width: 0;
759
- &::after {
760
- @include pseudo();
761
- @include position(null, 0 0 0 null);
762
- width: $size-1000;
763
- background: linear-gradient(90deg, hsla(0, 0%, 100%, 0) 0, $color-white);
764
- pointer-events: none;
765
- }
766
-
767
- &-inner {
768
- display: flex;
769
- flex-wrap: nowrap;
770
- overflow-x: auto;
771
- @include child-indent-right($space-100);
772
- @include hide-scrollbar();
773
- &::after {
774
- @include pseudo(block, static);
775
- min-width: $space-300;
776
- }
777
- }
778
- }
779
-
780
- &__body {
781
- padding: $space-200 $space-200 $space-300 $space-200;
782
- background-color: $color-hover-gray;
783
- @include child-indent-bottom($space-200);
784
- &-top {
785
- display: flex;
786
- @include child-indent-right($space-400);
787
-
788
- &-left,
789
- &-right {
790
- @include child-indent-right($space-100);
791
- }
792
- &-left {
793
- display: flex;
794
- align-items: flex-end;
795
- }
796
- }
797
- &-bottom {
798
- display: flex;
799
- align-items: center;
800
- justify-content: space-between;
801
- @include child-indent-right($space-400);
802
-
803
- &-left {
804
- > *:not(:first-child) {
805
- margin-inline-start: $space-200;
806
- }
807
- }
808
- &-right {
809
- display: flex;
810
- align-items: center;
811
- justify-content: flex-end;
812
- @include child-indent-right($space-100);
813
- }
814
- .mc-button {
815
- &--disabled {
816
- opacity: 1;
817
- background-color: fade-out($color-dark-gray, 0.8);
818
- color: $color-dark-gray;
819
- border-color: fade-out($color-dark-gray, 1);
820
- .mc-button__background {
821
- display: none;
822
- }
823
- }
824
- }
825
- }
826
- &-fast-tags-wrapper {
827
- margin: -($space-50);
828
- & > .mc-tooltip-target {
829
- .mc-chip {
830
- cursor: pointer;
831
- margin: calc(#{$space-100} / 2) calc(#{$space-50} / 2);
832
- &:hover {
833
- background-color: $color-outline-gray;
834
- }
835
- }
836
- }
837
- }
838
- }
839
- &__main-select,
840
- &__preset-input {
841
- width: 270px;
842
- }
843
- &__preset-input-title {
844
- width: auto;
845
- }
846
- }
847
- </style>