bfg-common 1.5.92 → 1.5.94

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 (112) hide show
  1. package/assets/scss/common/normalize.scss +347 -347
  2. package/components/atoms/alert/Notification.vue +169 -169
  3. package/components/atoms/autocomplete/Autocomplete.vue +361 -362
  4. package/components/atoms/collapse/CollapseNav.vue +169 -169
  5. package/components/atoms/comboDropdownMenu/ComboDropdownMenu.vue +357 -357
  6. package/components/atoms/combobox/Combobox.vue +154 -154
  7. package/components/atoms/datepicker/Datepicker.vue +639 -639
  8. package/components/atoms/dropdown/Portlet.vue +113 -113
  9. package/components/atoms/dropdown/dropdown/Dropdown.vue +168 -168
  10. package/components/atoms/dropdown/tree/Tree.vue +137 -137
  11. package/components/atoms/list/SelectList.vue +63 -63
  12. package/components/atoms/list/dragDropList/DragDropList.vue +148 -148
  13. package/components/atoms/modal/Modal.vue +250 -250
  14. package/components/atoms/modal/bySteps/BySteps.vue +253 -253
  15. package/components/atoms/notificationBar/NotificationBar.vue +178 -178
  16. package/components/atoms/popover/Popover.vue +58 -58
  17. package/components/atoms/popover/lib/models/interfaces.ts +4 -4
  18. package/components/atoms/select/TheSelect.vue +187 -187
  19. package/components/atoms/stack/StackBlock.vue +185 -185
  20. package/components/atoms/stack/StackContent.vue +63 -63
  21. package/components/atoms/step/lib/models/verticalStepItem.ts +5 -5
  22. package/components/atoms/switch/Switch.vue +111 -111
  23. package/components/atoms/table/compact/Compact.vue +529 -529
  24. package/components/atoms/table/dataGrid/DataGrid.vue +1716 -1713
  25. package/components/atoms/table/dataGrid/DataGridPage.vue +195 -195
  26. package/components/atoms/table/info/Info.vue +2 -2
  27. package/components/atoms/table/simpleEvent/SimpleEvent.vue +98 -98
  28. package/components/atoms/table/simpleInfo/SimpleInfo.vue +73 -73
  29. package/components/atoms/tabs/Tabs.vue +217 -217
  30. package/components/atoms/wizard/Wizard.vue +341 -341
  31. package/components/common/accordion/Recursion.vue +222 -222
  32. package/components/common/adapterManager/AddAdapterModal.vue +561 -561
  33. package/components/common/adapterManager/ui/actions/AddAdapterButton.vue +30 -30
  34. package/components/common/adapterManager/ui/table/Table.vue +162 -162
  35. package/components/common/browse/BrowseNew.vue +237 -237
  36. package/components/common/browse/BrowseOld.vue +217 -217
  37. package/components/common/browse/blocks/TitleNew.vue +145 -145
  38. package/components/common/browse/blocks/TitleOld.vue +91 -91
  39. package/components/common/browse/blocks/contents/FilesOld.vue +72 -72
  40. package/components/common/chartOptionsModal/counters/timespan/form/FormNew.vue +262 -262
  41. package/components/common/context/Context.vue +111 -111
  42. package/components/common/context/recursion/RecursionOld.vue +228 -228
  43. package/components/common/details/DetailsItem.vue +109 -109
  44. package/components/common/feedback/Buttons.vue +229 -229
  45. package/components/common/feedback/Feedback.vue +270 -270
  46. package/components/common/feedback/Message.vue +519 -519
  47. package/components/common/graph/graphNew/GraphNew.vue +194 -194
  48. package/components/common/graph/lib/utils/renderGraph.ts +389 -389
  49. package/components/common/layout/theHeader/feedback/new/New.vue +227 -227
  50. package/components/common/layout/theHeader/feedback/new/additionalDetails/AdditionalDetails.vue +606 -606
  51. package/components/common/layout/theHeader/feedback/new/additionalDetails/Headline.vue +98 -98
  52. package/components/common/layout/theHeader/feedback/new/description/Description.vue +59 -59
  53. package/components/common/layout/theHeader/feedback/new/email/Email.vue +43 -43
  54. package/components/common/layout/theHeader/feedback/new/subtitle/Subtitle.vue +103 -103
  55. package/components/common/layout/theHeader/helpMenu/aboutNew/AboutNew.vue +112 -112
  56. package/components/common/layout/theHeader/helpMenu/aboutOld/AboutOld.vue +80 -80
  57. package/components/common/layout/theHeader/helpMenu/helpMenuOld/HelpMenuOld.vue +1 -1
  58. package/components/common/layout/theHeader/modals/Reconnect.vue +2 -2
  59. package/components/common/layout/theHeader/modals/RedirectLogin.vue +3 -3
  60. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePassword.vue +1 -1
  61. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePasswordNew.vue +8 -8
  62. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePasswordOld.vue +3 -3
  63. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesNew.vue +1 -1
  64. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesOld.vue +1 -1
  65. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguage.vue +1 -1
  66. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguageNew.vue +1 -1
  67. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguageOld.vue +2 -5
  68. package/components/common/layout/theHeader/userMenu/modals/preferences/defaultConsole/DefaultConsoleOld.vue +1 -1
  69. package/components/common/layout/theHeader/userMenu/modals/preferences/inventory/InventoryNew.vue +1 -1
  70. package/components/common/layout/theHeader/userMenu/userMenuNew/UserMenuNew.vue +2 -2
  71. package/components/common/layout/theHeader/userMenu/userMenuNew/lib/config/dropMenu.ts +1 -1
  72. package/components/common/layout/theHeader/userMenu/userMenuOld/UserMenuOld.vue +1 -1
  73. package/components/common/mainNavigationPanel/MainNavigationPanelOld.vue +2 -2
  74. package/components/common/modals/Rename.vue +2 -2
  75. package/components/common/modals/confirmByInput/ConfirmByInput.vue +2 -3
  76. package/components/common/modals/confirmByInput/ConfirmByInputOld.vue +3 -3
  77. package/components/common/modals/confirmation/ConfirmationOld.vue +1 -1
  78. package/components/common/modals/unsavedChanges/UnsavedChanges.vue +1 -1
  79. package/components/common/monitor/advanced/Advanced.vue +1 -1
  80. package/components/common/monitor/advanced/AdvancedNew.vue +1 -1
  81. package/components/common/monitor/advanced/AdvancedOld.vue +1 -1
  82. package/components/common/monitor/advanced/graphView/GraphViewNew.vue +1 -1
  83. package/components/common/monitor/advanced/graphView/GraphViewOld.vue +1 -1
  84. package/components/common/monitor/advanced/table/Table.vue +1 -1
  85. package/components/common/monitor/advanced/table/tableNew/TableNew.vue +2 -2
  86. package/components/common/monitor/advanced/table/tableOld/lib/config/performanceDatatable.ts +2 -2
  87. package/components/common/monitor/advanced/tools/ToolsOld.vue +2 -2
  88. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModalOld.vue +1 -1
  89. package/components/common/monitor/advanced/tools/chartOptionsModal/NotificationOld.vue +1 -1
  90. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/ActionsOld.vue +1 -1
  91. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/saveOptionsModal/SaveOptionsModal.vue +1 -1
  92. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/CountersNew.vue +1 -1
  93. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/tableOld/lib/config/tableConfig.ts +2 -2
  94. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/lib/config/objectTable.ts +10 -3
  95. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/objectNew/ObjectNew.vue +1 -1
  96. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/objectOld/ObjectOld.vue +2 -2
  97. package/components/common/monitor/advanced/tools/lib/utils/countCores.ts +1 -1
  98. package/components/common/monitor/lib/models/interfaces.ts +1 -1
  99. package/components/common/monitor/overview/filters/customIntervalModal/CustomIntervalModalOld.vue +3 -3
  100. package/components/common/monitor/overview/filters/customIntervalModal/customIntervalModalNew/CustomIntervalModalNew.vue +4 -3
  101. package/components/common/monitor/resourceAllocation/lib/models/interfaces.ts +8 -8
  102. package/components/common/monitor/resourceAllocation/resourceAllocation.vue +2 -2
  103. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/ChartOptionsModal.vue +1 -1
  104. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/Notification.vue +1 -1
  105. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/actions/SaveOptionsModal.vue +1 -1
  106. package/components/common/pages/hardwareHealth/tableView/lib/config/alertWarningTable.ts +1 -1
  107. package/components/common/pages/hardwareHealth/tableView/lib/config/historyTestimonyTable.ts +5 -5
  108. package/components/common/wizards/vm/migrate/Migrate.vue +39 -2
  109. package/components/common/wizards/vm/migrate/vmOrigin/VmOrigin.vue +92 -0
  110. package/components/common/wizards/vm/migrate/vmOrigin/lib/models/interfaces.ts +19 -0
  111. package/components/common/wizards/vm/migrate/vmOrigin/lib/utils/constructItems.ts +62 -0
  112. package/package.json +1 -1
@@ -1,1713 +1,1716 @@
1
- <template>
2
- <div class="relative flex">
3
- <div
4
- :id="outerWrapper"
5
- :class="[
6
- 'datagrid-outer-wrapper',
7
- {
8
- 'datagrid-outer-wrapper-opened-info': isShowHiddenInfo,
9
- },
10
- ]"
11
- >
12
- <div class="datagrid-inner-wrapper">
13
- <div
14
- v-if="props.isMainFilter"
15
- class="main-filter-content flex-justify-end"
16
- >
17
- <atoms-the-icon class="filter-icon" name="filter" />
18
- <input
19
- :id="`${props.testId}-main-filter-input`"
20
- v-model.trim="mainFilter"
21
- :data-id="`${props.testId}-main-filter-input`"
22
- :placeholder="props.mainFilterPlaceholder"
23
- type="text"
24
- @input="emits('main-filter', mainFilter)"
25
- />
26
- </div>
27
- <div
28
- :class="[
29
- 'datagrid',
30
- {
31
- 'datagrid-opened-info': isShowHiddenInfo,
32
- },
33
- ]"
34
- >
35
- <div :id="tableWrapperId" class="datagrid-table-wrapper">
36
- <div class="datagrid-table" :data-id="props.testId">
37
- <div class="datagrid-header">
38
- <div class="datagrid-row">
39
- <div class="datagrid-row-master datagrid-row-flex">
40
- <div
41
- v-if="props.type || $slots.toggleBlock"
42
- class="datagrid-row-sticky"
43
- >
44
- <div
45
- v-if="props.type"
46
- :id="expandableCaret"
47
- class="datagrid-column datagrid-expandable-caret datagrid-fixed-column flex-align-center flex-justify-center"
48
- >
49
- <template v-if="props.type === 'checkbox'">
50
- <div
51
- class="clr-checkbox-wrapper flex-align-center flex-justify-center w-100"
52
- >
53
- <input
54
- :id="`${props.testId}-${inputId}-all`"
55
- v-model="selectedAll"
56
- :data-id="`${props.testId}-filter-all`"
57
- :value="-1"
58
- type="checkbox"
59
- class="checkbox-btn"
60
- @change="changeAll"
61
- />
62
- <label
63
- :for="`${props.testId}-${inputId}-all`"
64
- class="clr-control-label"
65
- />
66
- </div>
67
- <div class="datagrid-column-separator"></div>
68
- </template>
69
- </div>
70
- <div
71
- v-if="$slots.toggleBlock"
72
- class="datagrid-toggle-block datagrid-column datagrid-fixed-width"
73
- >
74
- <div class="datagrid-column-flex">
75
- <div class="datagrid-column-separator">
76
- <span class="clr-sr-only" />
77
- <div class="datagrid-column-resize-tracker" />
78
- </div>
79
- </div>
80
- </div>
81
- </div>
82
- <div class="datagrid-row-scrollable">
83
- <div
84
- v-for="(item, key) in headItemsPresent"
85
- :key="key"
86
- :style="{
87
- width: columnsWidth[key][0],
88
- minWidth: columnsWidth[key][1],
89
- }"
90
- class="datagrid-column datagrid-fixed-width"
91
- >
92
- <div class="datagrid-column-flex">
93
- <button
94
- :id="`${props.testId}-sort-column-${key}`"
95
- :data-id="`${item.testId}-sort-column`"
96
- :class="[
97
- 'datagrid-column-title',
98
- {
99
- 'default text-decoration-none':
100
- !item.sortColumn,
101
- },
102
- ]"
103
- @click="sortTable(item.sortColumn)"
104
- >
105
- <slot :key="key" name="th" :item="item">
106
- <span
107
- :title="item.text"
108
- :style="{
109
- width:
110
- columnsWidth[key][0]?.slice(0, -2) -
111
- (item.hasFilter ? 65 : 40) +
112
- 'px',
113
- }"
114
- class="title-column"
115
- >
116
- {{ item.text }}
117
- </span>
118
- </slot>
119
- <span
120
- v-if="item.sortColumn"
121
- class="sort-arrow-wrap"
122
- >
123
- <atoms-the-icon
124
- v-show="sortInfo[0] === item.sortColumn"
125
- :class="['sort-arrow', { down: sortInfo[1] }]"
126
- name="sort-arrow"
127
- />
128
- </span>
129
- </button>
130
- <button
131
- v-if="item.hasFilter"
132
- :id="`${props.testId}-filter-icon-${key}`"
133
- :data-id="`${item.testId}-filter-icon`"
134
- class="datagrid-filter-toggle clr-anchor clr-smart-open-close"
135
- @click="filterShow[key] = !filterShow[key]"
136
- >
137
- <atoms-the-icon
138
- v-if="filterTerm[key]"
139
- class="filter-icon"
140
- name="filter-solid"
141
- style="fill: #0079b8"
142
- />
143
- <atoms-the-icon
144
- v-else
145
- class="filter-icon"
146
- name="filter"
147
- />
148
- </button>
149
- <atoms-popup-simple-popup
150
- v-model="filterShow[key]"
151
- :test-id="`${props.testId}-filter`"
152
- :left="key === 0 ? '0' : ''"
153
- :right="key !== 0 ? '0' : ''"
154
- top="100%"
155
- >
156
- <input
157
- :id="`${props.testId}-filter-input-${key}`"
158
- v-model="filterTerm[key]"
159
- :data-id="`${item.testId}-filter-input`"
160
- type="text"
161
- @input="filtering"
162
- />
163
- </atoms-popup-simple-popup>
164
- <div
165
- v-show="
166
- !isShowHiddenInfo ||
167
- (isShowHiddenInfo && key === 0)
168
- "
169
- :class="[
170
- 'datagrid-column-separator',
171
- {
172
- 'double-arrow-separator':
173
- key === 0 && props.withInfo,
174
- },
175
- ]"
176
- @mousedown="setGrab(key, $event)"
177
- >
178
- <button
179
- :id="`${props.testId}-resize-tracker-${key}`"
180
- class="datagrid-column-handle drag-handle draggable"
181
- />
182
- <span class="clr-sr-only" />
183
- <div class="datagrid-column-resize-tracker" />
184
- </div>
185
- </div>
186
- </div>
187
- </div>
188
- </div>
189
- </div>
190
- </div>
191
-
192
- <template v-if="bodyItemsPresent.length">
193
- <div
194
- v-for="(item, key) in bodyItemsPresent"
195
- :key="item.id"
196
- :class="[
197
- 'datagrid-body-row datagrid-row animation',
198
- {
199
- 'datagrid-selected active': checkIsSelectedRow(
200
- item[0].id
201
- ),
202
- 'datagrid-selected-info':
203
- props.withInfo &&
204
- isShowHiddenInfo &&
205
- checkIsSelectedRow(item[0].id),
206
- },
207
- ]"
208
- :[props.rowAttributeIdName]="item[0].dataId"
209
- >
210
- <div>
211
- <div
212
- :data-id="`${item[0].testId}-select-row`"
213
- class="datagrid-row-master datagrid-row-flex"
214
- @click.stop="selectRowById(item[0])"
215
- >
216
- <div
217
- v-if="props.type || $slots.toggleBlock"
218
- class="datagrid-row-sticky"
219
- @click.stop
220
- >
221
- <div
222
- :id="expandableCaret"
223
- :class="[
224
- 'datagrid-expandable-caret flex-justify-center datagrid-cell',
225
- {
226
- 'datagrid-fixed-column': !props.withInfo,
227
- 'datagrid-fixed-column-without-separator':
228
- props.withInfo,
229
- },
230
- ]"
231
- >
232
- <!--TODO refactoring (duplicate)-->
233
- <div
234
- v-if="$slots.toggleBlock && !props.type"
235
- class="datagrid-cell datagrid-fixed-width"
236
- >
237
- <div
238
- v-if="item[0]?.isShowToggleIcon ?? true"
239
- class="flex-align-center"
240
- >
241
- <button
242
- :id="`${props.testId}-toggle-icon-${key}`"
243
- :data-id="`${item[0].testId}-toggle-button`"
244
- class="datagrid-expandable-caret-button reset-btn"
245
- @click="toggle(key)"
246
- >
247
- <atoms-the-icon
248
- :class="[
249
- 'datagrid-expandable-caret-icon',
250
- { toggle: toggedItems[key] },
251
- ]"
252
- name="angle"
253
- />
254
- </button>
255
- </div>
256
- </div>
257
- <slot
258
- v-if="props.type"
259
- :key="key"
260
- :item="item"
261
- name="type"
262
- >
263
- <div
264
- :class="
265
- item[0]?.disabled && 'clr-form-control-disabled'
266
- "
267
- >
268
- <div
269
- :class="`clr-${props.type}-wrapper flex-justify-center flex-align-center`"
270
- >
271
- <input
272
- :id="`${props.testId}-${inputId}-${item[0].id}`"
273
- :key="item[0].id"
274
- v-model="selectedRowLocal"
275
- :data-id="`${item[0].testId}-row-selection-input`"
276
- :type="props.type"
277
- :class="`${props.type}-btn`"
278
- :value="item[0].id"
279
- :disabled="item[0]?.disabled || false"
280
- name="selected-store"
281
- @change="
282
- changeSelectedRow($event, item[0].id)
283
- "
284
- />
285
- <label
286
- :for="`${props.testId}-${inputId}-${item[0].id}`"
287
- class="clr-control-label"
288
- />
289
- </div>
290
- </div>
291
- </slot>
292
- </div>
293
- <!--TODO refactoring (duplicate)-->
294
- <div
295
- v-if="$slots.toggleBlock && props.type"
296
- class="datagrid-cell datagrid-fixed-width"
297
- >
298
- <div class="flex-align-center">
299
- <button
300
- :id="`${props.testId}-toggle-icon-${key}`"
301
- :data-id="`${item[0].testId}-toggle-row-button`"
302
- class="datagrid-expandable-caret-button reset-btn"
303
- @click="toggle(key)"
304
- >
305
- <atoms-the-icon
306
- :class="[
307
- 'datagrid-expandable-caret-icon',
308
- { toggle: toggedItems[key] },
309
- ]"
310
- name="angle"
311
- />
312
- </button>
313
- </div>
314
- </div>
315
- </div>
316
- <div class="datagrid-row-scrollable">
317
- <div class="datagrid-scrolling-cells">
318
- <div
319
- v-for="(item2, key2) in item"
320
- v-show="
321
- !isShowHiddenInfo ||
322
- item2.key === 'col1' ||
323
- item2.key === 'icon'
324
- "
325
- :key="key2"
326
- :style="{
327
- width: columnsWidth[key2][0],
328
- minWidth: columnsWidth[key2][1],
329
- }"
330
- :class="[
331
- 'datagrid-cell datagrid-fixed-width',
332
- {
333
- 'hidden-text-triangle':
334
- isShowHiddenInfo &&
335
- item2.data?.name === 'hidden-text-triangle',
336
- },
337
- ]"
338
- >
339
- <div
340
- :class="[
341
- 'flex-align-center h-100',
342
- {
343
- 'double-arrow-width':
344
- item2.data?.name === 'doubleArrows',
345
- },
346
- ]"
347
- >
348
- <div
349
- v-if="item2.data?.name === 'doubleArrows'"
350
- :id="`show-info-${item[0].data.id}`"
351
- :data-id="`${item[0].testId}-double-arrow`"
352
- :class="[
353
- 'double-arrow-wrap',
354
- {
355
- 'arrow-selected':
356
- isShowHiddenInfo &&
357
- item2.id === props.selectedRow,
358
- },
359
- ]"
360
- @click.prevent.stop="
361
- doubleArrowClick(item2, item)
362
- "
363
- >
364
- <atoms-the-icon
365
- v-if="item2.data?.name === 'doubleArrows'"
366
- name="doubleArrows"
367
- :class="[
368
- 'double-arrow',
369
- {
370
- 'arrow-selected':
371
- isShowHiddenInfo &&
372
- item2.id === props.selectedRow,
373
- },
374
- ]"
375
- />
376
- </div>
377
- <span
378
- v-if="item2.text && item2.data?.iconClassName"
379
- class="vertical-divider"
380
- />
381
- <slot :name="item2.key" :item="item2">
382
- <span class="text-ellipsis" :title="item2.text"
383
- >{{ item2.text }}
384
- </span>
385
- </slot>
386
- </div>
387
- </div>
388
- </div>
389
- <div
390
- v-show="toggedItems[key]"
391
- class="datagrid-row-flex datagrid-row-detail datagrid-container"
392
- >
393
- <slot name="toggleBlock" :item="item" />
394
- </div>
395
- </div>
396
- </div>
397
- </div>
398
- </div>
399
- </template>
400
- <template v-else>
401
- <div class="datagrid-placeholder-container">
402
- <div class="datagrid-placeholder datagrid-empty">
403
- <div class="datagrid-placeholder-image"></div>
404
-
405
- <span>No items found</span>
406
- </div>
407
- </div>
408
- </template>
409
- </div>
410
- </div>
411
- </div>
412
-
413
- <div
414
- v-if="!hideFooter"
415
- :class="[
416
- 'datagrid-footer',
417
- {
418
- 'datagrid-footer-opened-info': isShowHiddenInfo,
419
- },
420
- ]"
421
- >
422
- <div
423
- v-if="props.type === 'checkbox' && props.selectedRow?.length"
424
- class="clr-form-control-disabled"
425
- >
426
- <div class="clr-checkbox-wrapper">
427
- <input
428
- :id="`${props.testId}-check-all`"
429
- :data-id="`${props.testId}-check-all`"
430
- type="checkbox"
431
- checked
432
- />
433
- <label class="clr-control-label">
434
- {{ props.selectedRow?.length }}
435
- </label>
436
- </div>
437
- </div>
438
- <div class="datagrid-footer-description flex-align-center">
439
- <atoms-table-data-grid-column-switch
440
- v-if="columnKeysLocal"
441
- v-model:column-keys="columnKeysLocal"
442
- :test-id="`${props.testId}-footer-description`"
443
- class="switch-icon"
444
- />
445
-
446
- <template v-if="props.isShowExport && bodyItemsPresent.length">
447
- <common-select-button-dropdown
448
- v-if="props.selectedRow?.length"
449
- :heading="localization.common.export"
450
- :items="exportItems"
451
- :test-id="`${props.testId}-export-btn`"
452
- class="properties__actions"
453
- is-top
454
- @click="onExport"
455
- />
456
- <button
457
- v-else
458
- :data-id="`${props.testId}-export-button`"
459
- class="export-link dropdown-toggle btn btn-sm btn-link"
460
- @click="onExportAll"
461
- >
462
- {{ localization.common.export }}
463
- </button>
464
- </template>
465
-
466
- <div v-if="$slots.action" class="datagrid-footer__action">
467
- <slot name="action" />
468
- </div>
469
- </div>
470
-
471
- <atoms-table-data-grid-pagination
472
- :test-id="props.testId"
473
- :page-size="props.pageSize"
474
- :page="props.page"
475
- :options="mergeOptions"
476
- :total-items="props.totalItems"
477
- :total-pages="props.totalPages"
478
- :hide-pagination="props.hidePagination"
479
- :hide-page-size="props.hidePageSize"
480
- :show-page-info="props.showPageInfo"
481
- :page-items-count="props.bodyItems.length"
482
- :is-show-hidden-info="isShowHiddenInfo"
483
- @change-page-size="changePageSize"
484
- @change-page="changePage"
485
- />
486
- </div>
487
-
488
- <atoms-loader
489
- v-show="props.loading"
490
- :test-id="`${props.testId}-spinner`"
491
- class="datagrid-spinner"
492
- />
493
- </div>
494
- </div>
495
- <div
496
- v-if="isShowInfo"
497
- id="hidden-features"
498
- :class="[
499
- 'hidden-features',
500
- {
501
- 'show-hidden-info': isShowHiddenInfo,
502
- },
503
- ]"
504
- >
505
- <!-- <div class="header">-->
506
- <!-- <slot name="hiddenInfoHeader" :item="showedInfoCol" />-->
507
- <!-- <button-->
508
- <!-- :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"-->
509
- <!-- :data-id="`${props.testId}-hidden-info-toggle-icon`"-->
510
- <!-- class="signpost-action close"-->
511
- <!-- @click="isShowHiddenInfo = false"-->
512
- <!-- >-->
513
- <!-- <atoms-the-icon class="close-icon" name="close" />-->
514
- <!-- </button>-->
515
- <!-- </div>-->
516
- <!-- <slot name="hiddenInfoBody" />-->
517
- <button
518
- :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"
519
- :data-id="`${props.testId}-hidden-info-toggle-icon`"
520
- class="signpost-action close"
521
- @click="isShowHiddenInfo = false"
522
- >
523
- <atoms-the-icon class="close-icon" name="close" />
524
- </button>
525
- <slot name="hiddenInfo" :item="showedInfoCol" />
526
- </div>
527
- </div>
528
- </template>
529
-
530
- <script setup lang="ts">
531
- import { isRtl } from 'bfg-uikit/lib/config/trl'
532
- import type {
533
- UI_I_HTMLSelectElement,
534
- UI_I_Localization,
535
- } from '~/lib/models/interfaces'
536
- import type {
537
- UI_I_HeadItem,
538
- UI_I_BodyItem,
539
- UI_I_ColumnKey,
540
- } from '~/components/atoms/table/dataGrid/lib/models/interfaces'
541
- import type {
542
- UI_T_ColumnKeys,
543
- UI_T_DataGridType,
544
- UI_T_SelectedRow,
545
- } from '~/components/atoms/table/dataGrid/lib/models/types'
546
- import type { UI_I_OptionItem } from '~/components/atoms/lib/models/interfaces'
547
- import type { UI_I_DropdownButtonItem } from '~/components/common/select/button/lib/models/interfaces'
548
- import { itemsPerPage } from '~/components/atoms/table/dataGrid/lib/config/itemsPerPage'
549
- import { exportItemsFunc } from '~/components/atoms/table/dataGrid/lib/config/settingsTable'
550
- import { generateCsvAndDownload } from '~/components/atoms/table/dataGrid/lib/utils/export'
551
-
552
- const props = withDefaults(
553
- defineProps<{
554
- headItems: UI_I_HeadItem[]
555
- bodyItems: UI_I_BodyItem[][]
556
- pageSize: number
557
- page: number
558
- totalItems: number
559
- totalPages: number
560
- loading?: boolean
561
- columnKeys?: UI_I_ColumnKey[]
562
- selectedRow?: UI_T_SelectedRow
563
- type?: UI_T_DataGridType
564
- itemsPerPage?: UI_I_OptionItem[]
565
- offSelectByRow?: boolean
566
- hidePageSize?: boolean
567
- showPageInfo?: boolean
568
- serverOff?: boolean
569
- fillWidth?: boolean
570
- hideFooter?: boolean
571
- hidePagination?: boolean
572
- testId?: string
573
- withInfo?: boolean
574
- rowAttributeIdName?: string
575
- isMainFilter?: boolean
576
- mainFilterPlaceholder?: string
577
- isShowExport?: boolean
578
- }>(),
579
- {
580
- columnKeys: undefined,
581
- selectedRow: undefined,
582
- type: undefined,
583
- itemsPerPage: undefined,
584
- fillWidth: true,
585
- testId: 'ui-data-grid',
586
- withInfo: false,
587
- rowAttributeIdName: 'data-id',
588
- isShowExport: false,
589
- }
590
- )
591
-
592
- const emits = defineEmits<{
593
- (event: 'update:column-keys', value: UI_T_ColumnKeys): void
594
- (event: 'update:selected-row', value: UI_T_SelectedRow): void
595
- (event: 'update:page-size', value: number): void
596
- (event: 'update:page', value: number): void
597
- (event: 'main-filter', value: string): void
598
- (event: 'filtering', value: string[][]): void
599
- (event: 'sorting', value: [string, boolean]): void
600
- (event: 'change', value: any): void
601
- (event: 'row-detail', value: number): void
602
- }>()
603
-
604
- const localization = computed<UI_I_Localization>(() => useLocal())
605
-
606
- const mainFilter = ref<string>('')
607
-
608
- const mergeOptions = computed<UI_I_OptionItem[]>(
609
- () => props.itemsPerPage || itemsPerPage
610
- )
611
-
612
- const inputId = ref<string>(`radio-input-${useUniqueId()}`)
613
-
614
- const columnKeysLocal = computed<UI_T_ColumnKeys>({
615
- get() {
616
- return props.columnKeys
617
- },
618
- set(newValue) {
619
- emits('update:column-keys', newValue)
620
- },
621
- })
622
-
623
- const selectedAll = ref<boolean>(false)
624
- const changeAll = (event: UI_I_HTMLSelectElement): void => {
625
- const newSelectedRow: (number | string)[] = []
626
- if (event.target.checked) {
627
- bodyItemsPresent.value.forEach((row) => {
628
- if (row[0]?.disabled) return
629
-
630
- newSelectedRow.push(row[0].id)
631
- })
632
- }
633
-
634
- emits('update:selected-row', newSelectedRow)
635
- }
636
-
637
- const selectedRowLocal = ref<UI_T_SelectedRow>([])
638
- const isShowHiddenInfo = ref<boolean>(false)
639
- const tableWrapperId = `table-wrapper-${useUniqueId()}`
640
- let memoryWidth = '0'
641
-
642
- const showedInfoRow = ref<UI_I_BodyItem | null>(null)
643
- const showedInfoCol = ref<UI_I_BodyItem[] | null>(null)
644
-
645
- const isShowInfo = computed<boolean>(
646
- () =>
647
- showedInfoRow.value &&
648
- showedInfoRow.value.id === props.selectedRow &&
649
- !showedInfoRow.value.data?.text &&
650
- isShowHiddenInfo.value
651
- )
652
-
653
- const setShowedInfoData = (
654
- item: UI_I_BodyItem | null,
655
- items: UI_I_BodyItem[] | null,
656
- reset: boolean = false
657
- ): void => {
658
- showedInfoRow.value = item
659
- showedInfoCol.value = items
660
-
661
- reset && (isShowHiddenInfo.value = false)
662
- item && selectRowById(item)
663
- reset && (isShowHiddenInfo.value = true)
664
- }
665
-
666
- const doubleArrowClick = (
667
- item: UI_I_BodyItem,
668
- items: UI_I_BodyItem[]
669
- ): void => {
670
- if (!isShowHiddenInfo.value) {
671
- setShowedInfoData(item, items)
672
- } else {
673
- if (showedInfoRow.value?.id !== item.id) {
674
- setShowedInfoData(item, items, true)
675
-
676
- return
677
- } else {
678
- setShowedInfoData(null, null)
679
- }
680
- }
681
-
682
- isShowHiddenInfo.value = !isShowHiddenInfo.value
683
- }
684
-
685
- watch(
686
- () => props.selectedRow,
687
- (newValue) => {
688
- if (newValue === undefined) return
689
-
690
- if (Array.isArray(newValue) && !newValue.length) selectedAll.value = false
691
-
692
- selectedRowLocal.value = newValue
693
- },
694
- { immediate: true }
695
- )
696
- const selectRowById = (item: UI_I_BodyItem): void => {
697
- const { id, disabled } = item
698
-
699
- if (props.offSelectByRow || isShowHiddenInfo.value || disabled) return
700
-
701
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
702
- const has = selectedRowLocal.value.includes(id)
703
- if (has) {
704
- selectedRowLocal.value = selectedRowLocal.value.filter(
705
- (rowId: string | number) => rowId !== id
706
- )
707
- } else {
708
- selectedRowLocal.value.push(id)
709
- }
710
-
711
- emits('change', selectedRowLocal.value)
712
- emits('update:selected-row', selectedRowLocal.value)
713
-
714
- changeSelectedAll(!has)
715
- return
716
- }
717
-
718
- emits('change', id)
719
- emits('update:selected-row', id)
720
- }
721
- const changeSelectedRow = (
722
- event: UI_I_HTMLSelectElement,
723
- id: number | string
724
- ): void => {
725
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
726
- const newSelectedRow = [...selectedRowLocal.value]
727
- emits('change', newSelectedRow)
728
- emits('update:selected-row', newSelectedRow)
729
-
730
- changeSelectedAll(event.target.checked)
731
- return
732
- }
733
-
734
- emits('change', id)
735
- emits('update:selected-row', id)
736
- }
737
- const changeSelectedAll = (checked: boolean): void => {
738
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
739
- const newSelectedRow = [...selectedRowLocal.value]
740
-
741
- if (!checked) {
742
- selectedAll.value = false
743
- } else if (newSelectedRow.length === bodyItemsPresent.value.length) {
744
- selectedAll.value = true
745
- }
746
- }
747
- }
748
-
749
- const checkIsSelectedRow = (id: number | string): boolean => {
750
- if (props.type === 'checkbox' && Array.isArray(props.selectedRow)) {
751
- return props.selectedRow.includes(id)
752
- }
753
- return props.selectedRow === id
754
- }
755
-
756
- // Sorting
757
- const sortInfo = ref<[string, boolean]>(['', true])
758
- const sortedColumnIndex = computed<number>(() => {
759
- let index = -1
760
- headItemsPresent.value.forEach((item, key) => {
761
- if (item.sortColumn === sortInfo.value[0]) index = key
762
- })
763
-
764
- return index
765
- })
766
- const sortTable = (sortName: string): void => {
767
- if (!sortName) return
768
-
769
- emits('update:selected-row', selectedRowLocal.value)
770
-
771
- if (sortInfo.value[0] === sortName) {
772
- sortInfo.value[1] = !sortInfo.value[1]
773
-
774
- emits('sorting', sortInfo.value)
775
- return
776
- }
777
- sortInfo.value[0] = sortName
778
- sortInfo.value[1] = true
779
-
780
- emits('sorting', sortInfo.value)
781
- }
782
-
783
- // Filtering
784
- const filterShow = ref<boolean[]>([])
785
- const filterTerm = ref<string[]>([])
786
- const filtering = (): void => {
787
- const filter: string[][] = []
788
- headItemsPresent.value.forEach((item, key) => {
789
- if (filterTerm.value[key]) filter.push([item.key, filterTerm.value[key]])
790
- })
791
-
792
- emits('filtering', filter)
793
- }
794
-
795
- // Pagination
796
- const changePageSize = (value: number): void => {
797
- emits('update:page-size', value)
798
- }
799
- const changePage = (value: number): void => {
800
- emits('update:selected-row', props.type === 'radio' ? null : [])
801
- emits('update:page', value)
802
- }
803
-
804
- const headItemsPresent = computed<UI_I_HeadItem[]>(() => {
805
- if (!columnKeysLocal.value) {
806
- return props.headItems
807
- }
808
-
809
- return props.headItems.filter((item, key) => {
810
- return columnKeysLocal.value?.find(
811
- (item2, key2) => item2.key === item.key && key === key2
812
- )?.show
813
- })
814
- })
815
-
816
- const bodyItemsPresent = computed<UI_I_BodyItem[][]>(() => {
817
- let items: UI_I_BodyItem[][] = props.bodyItems.map((row) => {
818
- return row.map((item) => {
819
- return {
820
- ...item,
821
- // Если текст пустой нужно поставить '--' для экспорта
822
- text: item.text !== '' ? item.text : '--',
823
- }
824
- })
825
- })
826
-
827
- // Filtering by column
828
- if (columnKeysLocal.value) {
829
- items = items.map((arr) => {
830
- arr = arr.filter((item, key) => {
831
- return columnKeysLocal.value?.find(
832
- (item2, key2) => item2.key === item.key && key === key2
833
- )?.show
834
- })
835
- return arr
836
- })
837
- }
838
-
839
- if (props.serverOff) {
840
- // Sorting
841
- if (sortInfo.value[0] !== '') {
842
- items = useDeepCopy(items).sort(
843
- (a: UI_I_BodyItem[], b: UI_I_BodyItem[]) => {
844
- let first = a[sortedColumnIndex.value].text.toString().toLowerCase()
845
- let second = b[sortedColumnIndex.value].text.toString().toLowerCase()
846
-
847
- const sortValueA = a[sortedColumnIndex.value]?.data?.sortValue
848
- const sortValueB = b[sortedColumnIndex.value]?.data?.sortValue
849
- if (sortValueA || sortValueA === 0) {
850
- first = sortValueA
851
- }
852
- if (sortValueB || sortValueB === 0) {
853
- second = sortValueB
854
- }
855
-
856
- if (sortInfo.value[1]) {
857
- return first > second ? 1 : first < second ? -1 : 0
858
- } else {
859
- return first < second ? 1 : first > second ? -1 : 0
860
- }
861
- }
862
- )
863
- }
864
- // Filtering
865
- const hasFilter = headItemsPresent.value.some(
866
- (_, key) => filterTerm.value[key]
867
- )
868
- if (hasFilter) {
869
- items = items.filter((row) => {
870
- // 0 - начальное значение
871
- // 1 - найден элемент
872
- // -1 - ненайден элемент
873
- let hasItem = 0
874
- headItemsPresent.value.forEach((item, key) => {
875
- if (!filterTerm.value[key]) return
876
- const term = filterTerm.value[key].toLowerCase()
877
-
878
- row.forEach((col) => {
879
- if (
880
- col.key === item.key &&
881
- typeof col.text === 'string' &&
882
- hasItem != -1
883
- ) {
884
- hasItem = col.text.toLowerCase().includes(term) ? 1 : -1
885
- }
886
- })
887
- })
888
-
889
- return hasItem === 1
890
- })
891
- }
892
- }
893
-
894
- return items
895
- })
896
-
897
- const toggedItems = ref<boolean[]>([])
898
-
899
- const toggle = (key: number): void => {
900
- toggedItems.value[key] = !toggedItems.value[key]
901
- if (!toggedItems.value[key]) return
902
- emits('row-detail', key)
903
- }
904
-
905
- const outerWrapper = `datagrid-outer-wrapper${useUniqueId()}`
906
- const expandableCaret = `datagrid-expandable-caret${useUniqueId()}`
907
-
908
- // Resize
909
- let helper = false
910
- let setColumnWidth = (): void => {
911
- if (!helper) {
912
- columnsWidth.value = []
913
- headItemsPresent.value.forEach((item) => {
914
- columnsWidth.value.push([
915
- item.width, // width
916
- item.width, // min-width
917
- ])
918
- })
919
-
920
- helper = true
921
- setTimeout(() => setColumnWidth(), 0)
922
- return
923
- }
924
- // Не продолжаем, чтобы ширина калонок была так как заданно в headItemsPresent
925
- if (!props.fillWidth) return
926
-
927
- // PC-672
928
- // const dataGridWidth = document.getElementById(outerWrapper)?.clientWidth || 0
929
- // const leftColumnWidth =
930
- // document.getElementById(expandableCaret)?.clientWidth || 0
931
- // const bordersWidth = 2
932
- // const columnWidth =
933
- // (dataGridWidth - leftColumnWidth - bordersWidth) /
934
- // headItemsPresent.value.length
935
-
936
- headItemsPresent.value.forEach((item) => {
937
- columnsWidth.value.push([
938
- // `${columnWidth}px`, // width
939
- item.width, // width
940
- item.width, // min-width
941
- ])
942
- })
943
- }
944
- setColumnWidth = useThrottle(setColumnWidth)
945
-
946
- const columnsWidth = ref<[string, string][]>([])
947
- watch(
948
- bodyItemsPresent,
949
- (newValue: UI_I_BodyItem[][]) => {
950
- newValue.forEach(() => {
951
- toggedItems.value.push(false)
952
- })
953
- setColumnWidth()
954
- },
955
- {
956
- immediate: true,
957
- deep: true,
958
- }
959
- )
960
-
961
- watch(
962
- headItemsPresent,
963
- (newValue: UI_I_HeadItem[]) => {
964
- filterShow.value = newValue.map(() => false)
965
- filterTerm.value = newValue.map(() => '')
966
- },
967
- {
968
- immediate: true,
969
- deep: true,
970
- }
971
- )
972
-
973
- const grabColumn = ref<number>(-1)
974
- const grabStartX = ref<number>(0)
975
- const setGrab = (key: number, event: MouseEvent): void => {
976
- if (props.withInfo && key === 0) return
977
-
978
- if (!isShowHiddenInfo.value) {
979
- grabColumn.value = key
980
- const currentWidth = parseInt(columnsWidth.value[grabColumn.value][0])
981
- grabStartX.value = event.clientX - currentWidth
982
- if (isRtl.value) {
983
- grabStartX.value = event.clientX + currentWidth
984
- }
985
- }
986
- }
987
-
988
- const isDrag = ref<boolean>(false)
989
-
990
- const mouseup = (): void => {
991
- if (grabColumn.value === -1) {
992
- return
993
- }
994
-
995
- grabColumn.value = -1
996
- isDrag.value = false
997
- }
998
-
999
- let resizeObserve: ResizeObserver
1000
- let mousemove = (event: MouseEvent): void => {
1001
- if (grabColumn.value === -1) return
1002
-
1003
- event.preventDefault()
1004
- isDrag.value = true
1005
- resizeObserve.disconnect()
1006
-
1007
- const minWidth = parseInt(columnsWidth.value[grabColumn.value][1])
1008
- let changeX = Math.max(event.clientX - grabStartX.value, minWidth)
1009
- if (isRtl.value) {
1010
- changeX = Math.max(grabStartX.value - event.clientX, minWidth)
1011
- }
1012
-
1013
- columnsWidth.value[grabColumn.value] = [`${changeX}px`, `${minWidth}px`]
1014
- }
1015
- mousemove = useThrottle(mousemove)
1016
-
1017
- const setResizeObserve = (): void => {
1018
- const element = document.getElementById(outerWrapper)
1019
-
1020
- if (!element) {
1021
- setTimeout(setResizeObserve, 0)
1022
- return
1023
- }
1024
-
1025
- resizeObserve = new ResizeObserver(setColumnWidth)
1026
- resizeObserve.observe(element)
1027
- }
1028
-
1029
- let resizeObserveWithInfo: ResizeObserver
1030
-
1031
- const setColumnWidthWithInfo = (ent: ResizeObserverEntry[]): void => {
1032
- if (isShowHiddenInfo.value) {
1033
- memoryWidth = columnsWidth.value[1][0]
1034
- columnsWidth.value[1][0] = `${ent[0].contentBoxSize[0].inlineSize - 86}px`
1035
- } else {
1036
- columnsWidth.value[1][0] = memoryWidth
1037
- }
1038
- }
1039
-
1040
- const setResizeObserveWithInfo = (): void => {
1041
- const element = document.querySelector('.datagrid')
1042
-
1043
- if (!element) {
1044
- setTimeout(setResizeObserveWithInfo, 0)
1045
- return
1046
- }
1047
-
1048
- resizeObserveWithInfo = new ResizeObserver(setColumnWidthWithInfo)
1049
- resizeObserveWithInfo.observe(element)
1050
- }
1051
-
1052
- // Export
1053
- const exportItems = computed<UI_I_DropdownButtonItem[]>(() =>
1054
- exportItemsFunc(
1055
- localization.value,
1056
- bodyItemsPresent.value.length || 0,
1057
- props.selectedRow?.length || 0,
1058
- props.testId || ''
1059
- )
1060
- )
1061
- const onExport = (type: '0' | '1'): void => {
1062
- switch (type) {
1063
- case '0':
1064
- onExportAll()
1065
- break
1066
- case '1':
1067
- exportSelected()
1068
- }
1069
- }
1070
- const onExportAll = (): void => {
1071
- const rows = document.querySelectorAll(
1072
- `#${tableWrapperId} .datagrid-row-scrollable`
1073
- ) as NodeListOf<HTMLElement>
1074
- generateCsvAndDownload(Array.from(rows))
1075
- }
1076
- const exportSelected = (): void => {
1077
- const header = document.querySelectorAll(
1078
- `#${tableWrapperId} .datagrid-row-scrollable`
1079
- )[0] as HTMLElement
1080
- const rows = document.querySelectorAll(
1081
- `#${tableWrapperId} .datagrid-selected`
1082
- ) as NodeListOf<HTMLElement>
1083
- generateCsvAndDownload([header, ...Array.from(rows)])
1084
- }
1085
-
1086
- onMounted(() => {
1087
- window.addEventListener('mousemove', mousemove)
1088
- window.addEventListener('mouseup', mouseup)
1089
-
1090
- if (props.withInfo) {
1091
- setResizeObserveWithInfo()
1092
- }
1093
-
1094
- setResizeObserve()
1095
- })
1096
- onUnmounted(() => {
1097
- window.removeEventListener('mouseup', mouseup)
1098
- window.removeEventListener('mousemove', mousemove)
1099
- })
1100
- </script>
1101
-
1102
- <style scoped lang="scss">
1103
- @import '~/assets/scss/common/mixins';
1104
- .datagrid-outer-wrapper {
1105
- @include flex($dir: row);
1106
- //padding-top: 12px;
1107
- flex-grow: 1;
1108
- overflow: auto;
1109
-
1110
- &.datagrid-outer-wrapper-opened-info {
1111
- width: 35%;
1112
- min-width: 195px;
1113
- }
1114
-
1115
- & * {
1116
- box-sizing: border-box;
1117
- }
1118
-
1119
- & svg {
1120
- fill: var(--table-color);
1121
- }
1122
-
1123
- .datagrid-inner-wrapper {
1124
- @include flex($dir: column);
1125
- flex-grow: 1;
1126
- overflow: auto;
1127
-
1128
- .main-filter-content {
1129
- align-items: center;
1130
-
1131
- .filter-icon {
1132
- width: 16px;
1133
- height: 16px;
1134
- margin-right: 10px;
1135
- }
1136
- }
1137
- .datagrid {
1138
- overflow: auto;
1139
- flex: 1 1 auto;
1140
- border-radius: 0.125rem 0.125rem 0 0;
1141
- background-color: var(--block-view-bg-color);
1142
- border-color: var(--global-border-color);
1143
- margin-top: 0;
1144
-
1145
- &.datagrid-opened-info {
1146
- border-radius: 0.125rem 0 0 0;
1147
- overflow-x: hidden;
1148
- }
1149
-
1150
- .datagrid-table-wrapper {
1151
- min-width: max-content;
1152
- display: flex;
1153
- flex: 1 1 auto;
1154
- min-height: 100%;
1155
-
1156
- .datagrid-table {
1157
- @include flex($dir: column);
1158
- flex: 1 1 auto;
1159
- align-content: flex-start;
1160
- position: relative;
1161
-
1162
- .datagrid-header {
1163
- position: sticky;
1164
- top: 0;
1165
- z-index: calc(var(--z-sticky) + 1);
1166
- width: auto;
1167
-
1168
- .datagrid-row-scrollable {
1169
- flex-direction: row;
1170
-
1171
- .datagrid-column-separator {
1172
- user-select: none;
1173
-
1174
- &::after {
1175
- cursor: col-resize;
1176
- }
1177
- &.double-arrow-separator .datagrid-column-handle {
1178
- cursor: unset;
1179
- }
1180
- &.double-arrow-separator::after {
1181
- cursor: unset;
1182
- }
1183
- }
1184
- }
1185
-
1186
- .datagrid-row {
1187
- color: var(--table-color);
1188
- background-color: var(--block-view-bg-color);
1189
-
1190
- &.datagrid-selected {
1191
- background-color: var(--row-selected-bg-color);
1192
- border-bottom: 1px solid var(--global-border-color);
1193
-
1194
- & :deep(*) {
1195
- color: var(--table-active-color);
1196
- }
1197
- }
1198
-
1199
- .datagrid-column {
1200
- background-color: var(--block-view-bg-color);
1201
- border-bottom: 1px solid var(--global-border-color);
1202
- padding: 6px 12px 5px;
1203
- position: relative;
1204
- //flex: 1 1 auto;
1205
-
1206
- &:last-child {
1207
- flex: 1 1 auto;
1208
- }
1209
-
1210
- &.datagrid-toggle-block {
1211
- width: 38px;
1212
- min-width: 38px;
1213
-
1214
- &::after {
1215
- content: '';
1216
- width: 0.05rem;
1217
- height: calc(100% - 0.5rem);
1218
- position: absolute;
1219
- right: 0;
1220
- top: 0.25rem;
1221
- background-color: var(--global-border-color);
1222
- }
1223
-
1224
- .datagrid-column-separator {
1225
- cursor: default;
1226
-
1227
- &::after {
1228
- cursor: default;
1229
- }
1230
- }
1231
- }
1232
- }
1233
-
1234
- .datagrid-column-title {
1235
- align-self: auto;
1236
- color: var(--table-color);
1237
- background-color: var(--block-view-bg-color);
1238
- border-bottom-color: var(--global-border-color);
1239
- font-size: 11px;
1240
- @include flex($align: center);
1241
- display: flex;
1242
- flex-direction: row;
1243
- justify-content: flex-start;
1244
- align-items: center;
1245
- //line-height: 24px;
1246
- line-height: normal;
1247
-
1248
- .title-column {
1249
- font-weight: bold;
1250
- font-size: 11px;
1251
- overflow: hidden;
1252
- text-wrap: none;
1253
- text-overflow: ellipsis;
1254
- }
1255
-
1256
- .sort-arrow-wrap {
1257
- margin-left: auto;
1258
- height: 14px;
1259
- width: 14px;
1260
- min-height: 14px;
1261
- min-width: 14px;
1262
- vertical-align: middle;
1263
-
1264
- .sort-arrow {
1265
- &.down {
1266
- transform: rotate(180deg);
1267
- }
1268
- }
1269
- }
1270
- .title-icon {
1271
- width: 24px;
1272
- height: 24px;
1273
- }
1274
- }
1275
-
1276
- .datagrid-filter-toggle {
1277
- background: unset;
1278
- margin-top: -4px;
1279
- align-self: center;
1280
-
1281
- .filter-icon {
1282
- width: 16px;
1283
- height: 16px;
1284
- }
1285
- }
1286
- }
1287
- }
1288
-
1289
- .datagrid-placeholder-container {
1290
- .datagrid-placeholder.datagrid-empty {
1291
- background: var(--block-view-bg-color);
1292
- }
1293
- span {
1294
- font-size: 16px;
1295
- color: var(--global-font-color4);
1296
- }
1297
- }
1298
-
1299
- .datagrid-row {
1300
- width: 100%;
1301
- min-width: max-content;
1302
- border-top: none;
1303
- color: var(--table-color);
1304
- background-color: var(--block-view-bg-color);
1305
- border-bottom: 1px solid var(--global-border-color);
1306
-
1307
- &.datagrid-selected {
1308
- & :deep(*) {
1309
- color: var(--table-active-color);
1310
- }
1311
-
1312
- .datagrid-cell {
1313
- background-color: var(--row-selected-bg-color);
1314
- border-bottom: 1px solid var(--global-border-color);
1315
- position: relative;
1316
- line-height: 1rem;
1317
- }
1318
-
1319
- .datagrid-row-detail {
1320
- background-color: var(--row-selected-bg-color);
1321
- border-bottom: 1px solid var(--global-border-color);
1322
- }
1323
- }
1324
-
1325
- .datagrid-cell {
1326
- min-width: 38px;
1327
- min-height: 28px;
1328
- padding: 2px 12px 3px 12px;
1329
- position: relative;
1330
-
1331
- &:has(.double-arrow-wrap) {
1332
- padding-left: 4px;
1333
- }
1334
-
1335
- &:has(.double-arrow-wrap)::after {
1336
- content: '';
1337
- width: 0.5px;
1338
- height: calc(100% - 6px);
1339
- position: absolute;
1340
- right: 2px;
1341
- top: 3px;
1342
- background-color: var(--global-border-color);
1343
- }
1344
-
1345
- &:last-child {
1346
- flex: 1 1 auto;
1347
- }
1348
-
1349
- button {
1350
- height: 0.9rem;
1351
- width: 0.9rem;
1352
-
1353
- .arrow-icon {
1354
- width: 16px;
1355
- height: 16px;
1356
- transform: rotate(90deg);
1357
- }
1358
- }
1359
-
1360
- .datagrid-cell-icon {
1361
- display: inline-block;
1362
- width: 16px;
1363
- height: 16px;
1364
- }
1365
-
1366
- .datagrid-expandable-caret-button {
1367
- cursor: pointer;
1368
- width: 100%;
1369
-
1370
- .datagrid-expandable-caret-icon {
1371
- width: 16px;
1372
- height: 16px;
1373
- transform: rotate(90deg);
1374
- fill: var(--table-caret-color);
1375
-
1376
- &.toggle {
1377
- transform: rotate(180deg);
1378
- }
1379
- }
1380
- }
1381
- }
1382
-
1383
- &.datagrid-selected-info {
1384
- width: 100%;
1385
- min-width: max-content;
1386
- border-top: none;
1387
- color: var(--table-color);
1388
- background-color: var(--block-view-bg-color);
1389
-
1390
- .datagrid-cell {
1391
- position: relative;
1392
-
1393
- &.hidden-text-triangle::after {
1394
- content: '';
1395
- position: absolute;
1396
- transform: rotate(225deg);
1397
- border-bottom: 15px solid transparent;
1398
- border-right: 15px solid var(--global-bg-color);
1399
- bottom: 26%;
1400
- right: -16px;
1401
- z-index: calc(var(--z-sticky) + 1);
1402
- }
1403
-
1404
- &.hidden-text-triangle::before {
1405
- content: '';
1406
- transform: rotate(-135deg);
1407
- position: absolute;
1408
- border-bottom: 16px solid transparent;
1409
- border-right: 16px solid var(--global-border-color);
1410
- bottom: 23%;
1411
- right: -17px;
1412
- z-index: calc(var(--z-sticky) + 1);
1413
- }
1414
- }
1415
- }
1416
- }
1417
-
1418
- .datagrid-row-sticky {
1419
- @include flex($w: nowrap);
1420
- position: sticky;
1421
- left: 0;
1422
- z-index: var(--z-sticky);
1423
- background-color: var(--block-view-bg-color);
1424
-
1425
- .datagrid-column {
1426
- color: var(--table-color);
1427
- background-color: var(--block-view-bg-color);
1428
- border-bottom-color: var(--global-border-color);
1429
- text-align: left;
1430
- display: flex;
1431
- flex: 1 1 auto;
1432
- vertical-align: top;
1433
- border: none;
1434
-
1435
- &.datagrid-expandable-caret {
1436
- .datagrid-column-separator {
1437
- display: block;
1438
-
1439
- &::after {
1440
- top: 0;
1441
- height: 18px;
1442
- }
1443
- }
1444
-
1445
- .radio-btn {
1446
- width: 16px;
1447
- height: 16px;
1448
- }
1449
- }
1450
-
1451
- .datagrid-column-separator {
1452
- position: relative;
1453
- //left: 0.6rem;
1454
- flex: 0 0 auto;
1455
- width: 0.05rem;
1456
- order: 100;
1457
- margin-left: auto;
1458
- height: 100%;
1459
- }
1460
- }
1461
-
1462
- .datagrid-fixed-column-without-separator {
1463
- background-color: var(--block-view-bg-color);
1464
-
1465
- &::after {
1466
- background-color: transparent;
1467
- }
1468
- }
1469
-
1470
- .datagrid-fixed-column {
1471
- background-color: var(--block-view-bg-color);
1472
-
1473
- //&::after {
1474
- // content: '';
1475
- // width: 0.05rem;
1476
- // height: calc(100% - 0.5rem);
1477
- // position: absolute;
1478
- // right: 0;
1479
- // top: 0.25rem;
1480
- // background-color: var(--global-border-color);
1481
- //}
1482
-
1483
- .clr-form-control-disabled {
1484
- .clr-checkbox-wrapper {
1485
- label {
1486
- cursor: not-allowed;
1487
- }
1488
- }
1489
- }
1490
- }
1491
-
1492
- .datagrid-fixed-width {
1493
- &::after {
1494
- content: '';
1495
- width: 0.05rem;
1496
- height: calc(100% - 0.5rem);
1497
- position: absolute;
1498
- right: 0;
1499
- top: 0.25rem;
1500
- background-color: var(--global-border-color);
1501
- }
1502
- }
1503
- }
1504
-
1505
- .datagrid-row-scrollable {
1506
- @include flex($ff: row nowrap);
1507
- flex: 1 1 auto;
1508
-
1509
- .datagrid-scrolling-cells {
1510
- @include flex($ff: row nowrap);
1511
- flex: 1 1 auto;
1512
- }
1513
- }
1514
- .datagrid-body-row {
1515
- .datagrid-row-scrollable {
1516
- @include flex($ff: column nowrap);
1517
-
1518
- .datagrid-row-detail {
1519
- flex: 1;
1520
- }
1521
- }
1522
-
1523
- &:not(.datagrid-selected):hover {
1524
- border-bottom: 1px solid var(--table-hover-row-border-color);
1525
- background-color: var(--table-hover-row-background-color);
1526
- color: var(--table-hover-row-color);
1527
-
1528
- .datagrid-fixed-column {
1529
- background-color: var(--table-hover-row-background-color);
1530
- }
1531
- .datagrid-cell {
1532
- background-color: var(--table-hover-row-background-color);
1533
- }
1534
- }
1535
- }
1536
- }
1537
- }
1538
- }
1539
-
1540
- .datagrid-footer {
1541
- flex: 0 0 auto;
1542
- @include flex($ff: row nowrap, $just: space-between, $align: stretch);
1543
- font-size: 0.55rem;
1544
- background-color: var(--block-view-bg-color);
1545
- border: 0.05rem solid var(--global-border-color);
1546
- border-top: none;
1547
- border-radius: 0 0 0.15rem 0.15rem;
1548
- padding: 0 0.6rem;
1549
- height: 28px;
1550
-
1551
- &.datagrid-footer-opened-info {
1552
- border-radius: 0 0 0 0.15rem;
1553
- flex-direction: row-reverse;
1554
- }
1555
-
1556
- .clr-form-control-disabled {
1557
- opacity: 1;
1558
-
1559
- .clr-checkbox-wrapper {
1560
- label {
1561
- color: #8c8c8c;
1562
- margin-right: 9px;
1563
- padding-left: 22px;
1564
- &:before {
1565
- position: absolute;
1566
- top: 4px;
1567
- left: 0;
1568
- content: '';
1569
- display: inline-block;
1570
- height: 16px;
1571
- width: 16px;
1572
- border: none;
1573
- border-radius: 3px;
1574
- background-color: var(--table-checkbox-color);
1575
- }
1576
-
1577
- &:after {
1578
- position: absolute;
1579
- content: '';
1580
- display: inline-block;
1581
- height: 5px;
1582
- width: 8px;
1583
- border-left: 2px solid #fff;
1584
- border-bottom: 2px solid #fff;
1585
- top: 4px;
1586
- left: 4px;
1587
- transform: translateY(4px) rotate(-45deg);
1588
- }
1589
- }
1590
- }
1591
- }
1592
- }
1593
-
1594
- .datagrid-spinner {
1595
- top: 0.6rem;
1596
- height: calc(100% - 0.6rem);
1597
- }
1598
-
1599
- .datagrid-footer-description {
1600
- flex: 1 1 auto;
1601
-
1602
- :deep(svg) {
1603
- fill: var(--table-switch-color);
1604
- }
1605
- }
1606
-
1607
- .clr-radio-wrapper,
1608
- .clr-checkbox-wrapper {
1609
- height: 18px;
1610
- }
1611
-
1612
- .clr-radio-wrapper label,
1613
- .clr-checkbox-wrapper label {
1614
- padding-left: 16px;
1615
- }
1616
- }
1617
- }
1618
- //.vertical-divider {
1619
- // width: 1px;
1620
- // height: 22px;
1621
- // background: #bbb;
1622
- // margin: 2px 2px 0 -5px;
1623
- //}
1624
-
1625
- .hidden-features {
1626
- padding: 9px 14px;
1627
- background-color: var(--global-bg-color);
1628
- color: var(--global-font-color2);
1629
- border: 1px solid var(--global-border-color);
1630
- border-left: none;
1631
- overflow-y: auto;
1632
- overflow-x: hidden;
1633
- width: 65%;
1634
-
1635
- //.header {
1636
- // display: flex;
1637
- // align-items: center;
1638
- // justify-content: space-between;
1639
- // background-color: inherit;
1640
- //
1641
- // h3 {
1642
- // font-size: 1rem;
1643
- // color: var(--global-font-color2) !important;
1644
- // line-height: 1.7rem;
1645
- // }
1646
- button {
1647
- position: absolute;
1648
- top: 24px;
1649
- right: 24px;
1650
- line-height: 24px;
1651
-
1652
- .close-icon {
1653
- //margin-left: 10px;
1654
- width: 24px;
1655
- height: 24px;
1656
- }
1657
- }
1658
- //}
1659
- }
1660
- .double-arrow-width {
1661
- width: 25px;
1662
- }
1663
- .double-arrow-wrap {
1664
- width: 30px;
1665
- height: 20px;
1666
- padding-top: 1px;
1667
- padding-left: 5px;
1668
- cursor: pointer;
1669
- background-color: transparent;
1670
-
1671
- .double-arrow {
1672
- background-color: transparent;
1673
- transform: rotate(90deg);
1674
- width: 16px;
1675
- height: 16px;
1676
- }
1677
-
1678
- .double-arrow.arrow-selected {
1679
- transform: rotate(-90deg) !important;
1680
- background-color: #0079b8;
1681
- }
1682
- }
1683
- .double-arrow-wrap.arrow-selected {
1684
- background-color: #0079b8;
1685
- border-radius: 3px;
1686
- }
1687
- </style>
1688
-
1689
- <style>
1690
- :root {
1691
- --table-color: #565656;
1692
- --table-active-color: #fff;
1693
- --table-checkbox-color: #454545;
1694
- --table-caret-color: #454545;
1695
- --table-switch-color: #575757;
1696
- --table-hover-row-border-color: #666;
1697
- --table-hover-row-background-color: #e8e8e8;
1698
- --table-hover-row-color: #454545;
1699
- --table-spinner-bg-color: #ffffff99;
1700
- }
1701
-
1702
- :root.dark-theme {
1703
- --table-color: #fff;
1704
- --table-active-color: #565656;
1705
- --table-checkbox-color: #49aeda;
1706
- --table-caret-color: #ffffff;
1707
- --table-switch-color: #b3b3b3;
1708
- --table-hover-row-border-color: #fff;
1709
- --table-hover-row-background-color: #324f61;
1710
- --table-hover-row-color: #e9ecef;
1711
- --table-spinner-bg-color: rgba(0, 0, 0, 0.5);
1712
- }
1713
- </style>
1
+ <template>
2
+ <div class="relative" style="display: flex">
3
+ <div
4
+ :id="outerWrapper"
5
+ :class="[
6
+ 'datagrid-outer-wrapper',
7
+ {
8
+ 'datagrid-outer-wrapper-opened-info': isShowHiddenInfo,
9
+ },
10
+ ]"
11
+ >
12
+ <div class="datagrid-inner-wrapper">
13
+ <div
14
+ v-if="props.isMainFilter"
15
+ class="main-filter-content flex-justify-end"
16
+ >
17
+ <atoms-the-icon class="filter-icon" name="filter" />
18
+ <input
19
+ :id="`${props.testId}-main-filter-input`"
20
+ v-model.trim="mainFilter"
21
+ :data-id="`${props.testId}-main-filter-input`"
22
+ :placeholder="props.mainFilterPlaceholder"
23
+ type="text"
24
+ @input="emits('main-filter', mainFilter)"
25
+ />
26
+ </div>
27
+ <div
28
+ :class="[
29
+ 'datagrid',
30
+ {
31
+ 'datagrid-opened-info': isShowHiddenInfo,
32
+ },
33
+ ]"
34
+ >
35
+ <div :id="tableWrapperId" class="datagrid-table-wrapper">
36
+ <div class="datagrid-table" :data-id="props.testId">
37
+ <div class="datagrid-header">
38
+ <div class="datagrid-row">
39
+ <div class="datagrid-row-master datagrid-row-flex">
40
+ <div
41
+ v-if="props.type || $slots.toggleBlock"
42
+ class="datagrid-row-sticky"
43
+ >
44
+ <div
45
+ v-if="props.type"
46
+ :id="expandableCaret"
47
+ class="datagrid-column datagrid-expandable-caret datagrid-fixed-column flex-align-center flex-justify-center"
48
+ >
49
+ <template v-if="props.type === 'checkbox'">
50
+ <div
51
+ class="clr-checkbox-wrapper flex-align-center flex-justify-center w-100"
52
+ >
53
+ <input
54
+ :id="`${props.testId}-${inputId}-all`"
55
+ v-model="selectedAll"
56
+ :data-id="`${props.testId}-filter-all`"
57
+ :value="-1"
58
+ type="checkbox"
59
+ class="checkbox-btn"
60
+ @change="changeAll"
61
+ />
62
+ <label
63
+ :for="`${props.testId}-${inputId}-all`"
64
+ class="clr-control-label"
65
+ />
66
+ </div>
67
+ <div class="datagrid-column-separator"></div>
68
+ </template>
69
+ </div>
70
+ <div
71
+ v-if="$slots.toggleBlock"
72
+ class="datagrid-toggle-block datagrid-column datagrid-fixed-width"
73
+ >
74
+ <div class="datagrid-column-flex">
75
+ <div class="datagrid-column-separator">
76
+ <span class="clr-sr-only" />
77
+ <div class="datagrid-column-resize-tracker" />
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ <div class="datagrid-row-scrollable">
83
+ <div
84
+ v-for="(item, key) in headItemsPresent"
85
+ :key="key"
86
+ :style="{
87
+ width: columnsWidth[key][0],
88
+ minWidth: columnsWidth[key][1],
89
+ }"
90
+ class="datagrid-column datagrid-fixed-width"
91
+ >
92
+ <div class="datagrid-column-flex">
93
+ <button
94
+ :id="`${props.testId}-sort-column-${key}`"
95
+ :data-id="`${item.testId}-sort-column`"
96
+ :class="[
97
+ 'datagrid-column-title',
98
+ {
99
+ 'default text-decoration-none':
100
+ !item.sortColumn,
101
+ },
102
+ ]"
103
+ @click="sortTable(item.sortColumn)"
104
+ >
105
+ <slot :key="key" name="th" :item="item">
106
+ <span
107
+ :title="item.text"
108
+ :style="{
109
+ width:
110
+ columnsWidth[key][0]?.slice(0, -2) -
111
+ (item.hasFilter ? 65 : 40) +
112
+ 'px',
113
+ }"
114
+ class="title-column"
115
+ >
116
+ {{ item.text }}
117
+ </span>
118
+ </slot>
119
+ <span
120
+ v-if="item.sortColumn"
121
+ class="sort-arrow-wrap"
122
+ >
123
+ <atoms-the-icon
124
+ v-show="sortInfo[0] === item.sortColumn"
125
+ :class="['sort-arrow', { down: sortInfo[1] }]"
126
+ name="sort-arrow"
127
+ />
128
+ </span>
129
+ </button>
130
+ <button
131
+ v-if="item.hasFilter"
132
+ :id="`${props.testId}-filter-icon-${key}`"
133
+ :data-id="`${item.testId}-filter-icon`"
134
+ class="datagrid-filter-toggle clr-anchor clr-smart-open-close"
135
+ @click="filterShow[key] = !filterShow[key]"
136
+ >
137
+ <atoms-the-icon
138
+ v-if="filterTerm[key]"
139
+ class="filter-icon"
140
+ name="filter-solid"
141
+ style="fill: #0079b8"
142
+ />
143
+ <atoms-the-icon
144
+ v-else
145
+ class="filter-icon"
146
+ name="filter"
147
+ />
148
+ </button>
149
+ <atoms-popup-simple-popup
150
+ v-model="filterShow[key]"
151
+ :test-id="`${props.testId}-filter`"
152
+ :left="key === 0 ? '0' : ''"
153
+ :right="key !== 0 ? '0' : ''"
154
+ top="100%"
155
+ >
156
+ <input
157
+ :id="`${props.testId}-filter-input-${key}`"
158
+ v-model="filterTerm[key]"
159
+ :data-id="`${item.testId}-filter-input`"
160
+ type="text"
161
+ @input="filtering"
162
+ />
163
+ </atoms-popup-simple-popup>
164
+ <div
165
+ v-show="
166
+ !isShowHiddenInfo ||
167
+ (isShowHiddenInfo && key === 0)
168
+ "
169
+ :class="[
170
+ 'datagrid-column-separator',
171
+ {
172
+ 'double-arrow-separator':
173
+ key === 0 && props.withInfo,
174
+ },
175
+ ]"
176
+ @mousedown="setGrab(key, $event)"
177
+ >
178
+ <button
179
+ :id="`${props.testId}-resize-tracker-${key}`"
180
+ class="datagrid-column-handle drag-handle draggable"
181
+ />
182
+ <span class="clr-sr-only" />
183
+ <div class="datagrid-column-resize-tracker" />
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+ <template v-if="bodyItemsPresent.length">
193
+ <div
194
+ v-for="(item, key) in bodyItemsPresent"
195
+ :key="item.id"
196
+ :class="[
197
+ 'datagrid-body-row datagrid-row animation',
198
+ {
199
+ 'datagrid-selected active': checkIsSelectedRow(
200
+ item[0].id
201
+ ),
202
+ 'datagrid-selected-info':
203
+ props.withInfo &&
204
+ isShowHiddenInfo &&
205
+ checkIsSelectedRow(item[0].id),
206
+ },
207
+ ]"
208
+ :[props.rowAttributeIdName]="item[0].dataId"
209
+ >
210
+ <div>
211
+ <div
212
+ :data-id="`${item[0].testId}-select-row`"
213
+ class="datagrid-row-master datagrid-row-flex"
214
+ @click.stop="selectRowById(item[0])"
215
+ >
216
+ <div
217
+ v-if="props.type || $slots.toggleBlock"
218
+ class="datagrid-row-sticky"
219
+ @click.stop
220
+ >
221
+ <div
222
+ :id="expandableCaret"
223
+ :class="[
224
+ 'datagrid-expandable-caret flex-justify-center datagrid-cell',
225
+ {
226
+ 'datagrid-fixed-column': !props.withInfo,
227
+ 'datagrid-fixed-column-without-separator':
228
+ props.withInfo,
229
+ },
230
+ ]"
231
+ >
232
+ <!--TODO refactoring (duplicate)-->
233
+ <div
234
+ v-if="$slots.toggleBlock && !props.type"
235
+ class="datagrid-cell datagrid-fixed-width"
236
+ >
237
+ <div
238
+ v-if="item[0]?.isShowToggleIcon ?? true"
239
+ class="flex-align-center"
240
+ >
241
+ <button
242
+ :id="`${props.testId}-toggle-icon-${key}`"
243
+ :data-id="`${item[0].testId}-toggle-button`"
244
+ class="datagrid-expandable-caret-button reset-btn"
245
+ @click="toggle(key)"
246
+ >
247
+ <atoms-the-icon
248
+ :class="[
249
+ 'datagrid-expandable-caret-icon',
250
+ { toggle: toggedItems[key] },
251
+ ]"
252
+ name="angle"
253
+ />
254
+ </button>
255
+ </div>
256
+ </div>
257
+ <slot
258
+ v-if="props.type"
259
+ :key="key"
260
+ :item="item"
261
+ name="type"
262
+ >
263
+ <div
264
+ :class="
265
+ item[0]?.disabled && 'clr-form-control-disabled'
266
+ "
267
+ >
268
+ <div
269
+ :class="`clr-${props.type}-wrapper flex-justify-center flex-align-center`"
270
+ >
271
+ <input
272
+ :id="`${props.testId}-${inputId}-${item[0].id}`"
273
+ :key="item[0].id"
274
+ v-model="selectedRowLocal"
275
+ :data-id="`${item[0].testId}-row-selection-input`"
276
+ :type="props.type"
277
+ :class="`${props.type}-btn`"
278
+ :value="item[0].id"
279
+ :disabled="item[0]?.disabled || false"
280
+ name="selected-store"
281
+ @change="
282
+ changeSelectedRow($event, item[0].id)
283
+ "
284
+ />
285
+ <label
286
+ :for="`${props.testId}-${inputId}-${item[0].id}`"
287
+ class="clr-control-label"
288
+ />
289
+ </div>
290
+ </div>
291
+ </slot>
292
+ </div>
293
+ <!--TODO refactoring (duplicate)-->
294
+ <div
295
+ v-if="$slots.toggleBlock && props.type"
296
+ class="datagrid-cell datagrid-fixed-width"
297
+ >
298
+ <div class="flex-align-center">
299
+ <button
300
+ :id="`${props.testId}-toggle-icon-${key}`"
301
+ :data-id="`${item[0].testId}-toggle-row-button`"
302
+ class="datagrid-expandable-caret-button reset-btn"
303
+ @click="toggle(key)"
304
+ >
305
+ <atoms-the-icon
306
+ :class="[
307
+ 'datagrid-expandable-caret-icon',
308
+ { toggle: toggedItems[key] },
309
+ ]"
310
+ name="angle"
311
+ />
312
+ </button>
313
+ </div>
314
+ </div>
315
+ </div>
316
+ <div
317
+ :data-id="`${item[0].testId}-select-row-scrollable`"
318
+ class="datagrid-row-scrollable"
319
+ >
320
+ <div class="datagrid-scrolling-cells">
321
+ <div
322
+ v-for="(item2, key2) in item"
323
+ v-show="
324
+ !isShowHiddenInfo ||
325
+ item2.key === 'col1' ||
326
+ item2.key === 'icon'
327
+ "
328
+ :key="key2"
329
+ :style="{
330
+ width: columnsWidth[key2][0],
331
+ minWidth: columnsWidth[key2][1],
332
+ }"
333
+ :class="[
334
+ 'datagrid-cell datagrid-fixed-width',
335
+ {
336
+ 'hidden-text-triangle':
337
+ isShowHiddenInfo &&
338
+ item2.data?.name === 'hidden-text-triangle',
339
+ },
340
+ ]"
341
+ >
342
+ <div
343
+ :class="[
344
+ 'flex-align-center h-100',
345
+ {
346
+ 'double-arrow-width':
347
+ item2.data?.name === 'doubleArrows',
348
+ },
349
+ ]"
350
+ >
351
+ <div
352
+ v-if="item2.data?.name === 'doubleArrows'"
353
+ :id="`show-info-${item[0].data.id}`"
354
+ :data-id="`${item[0].testId}-double-arrow`"
355
+ :class="[
356
+ 'double-arrow-wrap',
357
+ {
358
+ 'arrow-selected':
359
+ isShowHiddenInfo &&
360
+ item2.id === props.selectedRow,
361
+ },
362
+ ]"
363
+ @click.prevent.stop="
364
+ doubleArrowClick(item2, item)
365
+ "
366
+ >
367
+ <atoms-the-icon
368
+ v-if="item2.data?.name === 'doubleArrows'"
369
+ name="doubleArrows"
370
+ :class="[
371
+ 'double-arrow',
372
+ {
373
+ 'arrow-selected':
374
+ isShowHiddenInfo &&
375
+ item2.id === props.selectedRow,
376
+ },
377
+ ]"
378
+ />
379
+ </div>
380
+ <span
381
+ v-if="item2.text && item2.data?.iconClassName"
382
+ class="vertical-divider"
383
+ />
384
+ <slot :name="item2.key" :item="item2">
385
+ <span class="text-ellipsis" :title="item2.text"
386
+ >{{ item2.text }}
387
+ </span>
388
+ </slot>
389
+ </div>
390
+ </div>
391
+ </div>
392
+ <div
393
+ v-show="toggedItems[key]"
394
+ class="datagrid-row-flex datagrid-row-detail datagrid-container"
395
+ >
396
+ <slot name="toggleBlock" :item="item" />
397
+ </div>
398
+ </div>
399
+ </div>
400
+ </div>
401
+ </div>
402
+ </template>
403
+ <template v-else>
404
+ <div class="datagrid-placeholder-container">
405
+ <div class="datagrid-placeholder datagrid-empty">
406
+ <div class="datagrid-placeholder-image"></div>
407
+
408
+ <span>No items found</span>
409
+ </div>
410
+ </div>
411
+ </template>
412
+ </div>
413
+ </div>
414
+ </div>
415
+
416
+ <div
417
+ v-if="!hideFooter"
418
+ :class="[
419
+ 'datagrid-footer',
420
+ {
421
+ 'datagrid-footer-opened-info': isShowHiddenInfo,
422
+ },
423
+ ]"
424
+ >
425
+ <div
426
+ v-if="props.type === 'checkbox' && props.selectedRow?.length"
427
+ class="clr-form-control-disabled"
428
+ >
429
+ <div class="clr-checkbox-wrapper">
430
+ <input
431
+ :id="`${props.testId}-check-all`"
432
+ :data-id="`${props.testId}-check-all`"
433
+ type="checkbox"
434
+ checked
435
+ />
436
+ <label class="clr-control-label">
437
+ {{ props.selectedRow?.length }}
438
+ </label>
439
+ </div>
440
+ </div>
441
+ <div class="datagrid-footer-description flex-align-center">
442
+ <atoms-table-data-grid-column-switch
443
+ v-if="columnKeysLocal"
444
+ v-model:column-keys="columnKeysLocal"
445
+ :test-id="`${props.testId}-footer-description`"
446
+ class="switch-icon"
447
+ />
448
+
449
+ <template v-if="props.isShowExport && bodyItemsPresent.length">
450
+ <common-select-button-dropdown
451
+ v-if="props.selectedRow?.length"
452
+ :heading="localization.common.export"
453
+ :items="exportItems"
454
+ :test-id="`${props.testId}-export-btn`"
455
+ class="properties__actions"
456
+ is-top
457
+ @click="onExport"
458
+ />
459
+ <button
460
+ v-else
461
+ :data-id="`${props.testId}-export-button`"
462
+ class="export-link dropdown-toggle btn btn-sm btn-link"
463
+ @click="onExportAll"
464
+ >
465
+ {{ localization.common.export }}
466
+ </button>
467
+ </template>
468
+
469
+ <div v-if="$slots.action" class="datagrid-footer__action">
470
+ <slot name="action" />
471
+ </div>
472
+ </div>
473
+
474
+ <atoms-table-data-grid-pagination
475
+ :test-id="props.testId"
476
+ :page-size="props.pageSize"
477
+ :page="props.page"
478
+ :options="mergeOptions"
479
+ :total-items="props.totalItems"
480
+ :total-pages="props.totalPages"
481
+ :hide-pagination="props.hidePagination"
482
+ :hide-page-size="props.hidePageSize"
483
+ :show-page-info="props.showPageInfo"
484
+ :page-items-count="props.bodyItems.length"
485
+ :is-show-hidden-info="isShowHiddenInfo"
486
+ @change-page-size="changePageSize"
487
+ @change-page="changePage"
488
+ />
489
+ </div>
490
+
491
+ <atoms-loader
492
+ v-show="props.loading"
493
+ :test-id="`${props.testId}-spinner`"
494
+ class="datagrid-spinner"
495
+ />
496
+ </div>
497
+ </div>
498
+ <div
499
+ v-if="isShowInfo"
500
+ id="hidden-features"
501
+ :class="[
502
+ 'hidden-features',
503
+ {
504
+ 'show-hidden-info': isShowHiddenInfo,
505
+ },
506
+ ]"
507
+ >
508
+ <!-- <div class="header">-->
509
+ <!-- <slot name="hiddenInfoHeader" :item="showedInfoCol" />-->
510
+ <!-- <button-->
511
+ <!-- :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"-->
512
+ <!-- :data-id="`${props.testId}-hidden-info-toggle-icon`"-->
513
+ <!-- class="signpost-action close"-->
514
+ <!-- @click="isShowHiddenInfo = false"-->
515
+ <!-- >-->
516
+ <!-- <atoms-the-icon class="close-icon" name="close" />-->
517
+ <!-- </button>-->
518
+ <!-- </div>-->
519
+ <!-- <slot name="hiddenInfoBody" />-->
520
+ <button
521
+ :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"
522
+ :data-id="`${props.testId}-hidden-info-toggle-icon`"
523
+ class="signpost-action close"
524
+ @click="isShowHiddenInfo = false"
525
+ >
526
+ <atoms-the-icon class="close-icon" name="close" />
527
+ </button>
528
+ <slot name="hiddenInfo" :item="showedInfoCol" />
529
+ </div>
530
+ </div>
531
+ </template>
532
+
533
+ <script setup lang="ts">
534
+ import { isRtl } from 'bfg-uikit/lib/config/trl'
535
+ import type {
536
+ UI_I_HTMLSelectElement,
537
+ UI_I_Localization,
538
+ } from '~/lib/models/interfaces'
539
+ import type {
540
+ UI_I_HeadItem,
541
+ UI_I_BodyItem,
542
+ UI_I_ColumnKey,
543
+ } from '~/components/atoms/table/dataGrid/lib/models/interfaces'
544
+ import type {
545
+ UI_T_ColumnKeys,
546
+ UI_T_DataGridType,
547
+ UI_T_SelectedRow,
548
+ } from '~/components/atoms/table/dataGrid/lib/models/types'
549
+ import type { UI_I_OptionItem } from '~/components/atoms/lib/models/interfaces'
550
+ import type { UI_I_DropdownButtonItem } from '~/components/common/select/button/lib/models/interfaces'
551
+ import { itemsPerPage } from '~/components/atoms/table/dataGrid/lib/config/itemsPerPage'
552
+ import { exportItemsFunc } from '~/components/atoms/table/dataGrid/lib/config/settingsTable'
553
+ import { generateCsvAndDownload } from '~/components/atoms/table/dataGrid/lib/utils/export'
554
+
555
+ const props = withDefaults(
556
+ defineProps<{
557
+ headItems: UI_I_HeadItem[]
558
+ bodyItems: UI_I_BodyItem[][]
559
+ pageSize: number
560
+ page: number
561
+ totalItems: number
562
+ totalPages: number
563
+ loading?: boolean
564
+ columnKeys?: UI_I_ColumnKey[]
565
+ selectedRow?: UI_T_SelectedRow
566
+ type?: UI_T_DataGridType
567
+ itemsPerPage?: UI_I_OptionItem[]
568
+ offSelectByRow?: boolean
569
+ hidePageSize?: boolean
570
+ showPageInfo?: boolean
571
+ serverOff?: boolean
572
+ fillWidth?: boolean
573
+ hideFooter?: boolean
574
+ hidePagination?: boolean
575
+ testId?: string
576
+ withInfo?: boolean
577
+ rowAttributeIdName?: string
578
+ isMainFilter?: boolean
579
+ mainFilterPlaceholder?: string
580
+ isShowExport?: boolean
581
+ }>(),
582
+ {
583
+ columnKeys: undefined,
584
+ selectedRow: undefined,
585
+ type: undefined,
586
+ itemsPerPage: undefined,
587
+ fillWidth: true,
588
+ testId: 'ui-data-grid',
589
+ withInfo: false,
590
+ rowAttributeIdName: 'data-id',
591
+ isShowExport: false,
592
+ }
593
+ )
594
+
595
+ const emits = defineEmits<{
596
+ (event: 'update:column-keys', value: UI_T_ColumnKeys): void
597
+ (event: 'update:selected-row', value: UI_T_SelectedRow): void
598
+ (event: 'update:page-size', value: number): void
599
+ (event: 'update:page', value: number): void
600
+ (event: 'main-filter', value: string): void
601
+ (event: 'filtering', value: string[][]): void
602
+ (event: 'sorting', value: [string, boolean]): void
603
+ (event: 'change', value: any): void
604
+ (event: 'row-detail', value: number): void
605
+ }>()
606
+
607
+ const localization = computed<UI_I_Localization>(() => useLocal())
608
+
609
+ const mainFilter = ref<string>('')
610
+
611
+ const mergeOptions = computed<UI_I_OptionItem[]>(
612
+ () => props.itemsPerPage || itemsPerPage
613
+ )
614
+
615
+ const inputId = ref<string>(`radio-input-${useUniqueId()}`)
616
+
617
+ const columnKeysLocal = computed<UI_T_ColumnKeys>({
618
+ get() {
619
+ return props.columnKeys
620
+ },
621
+ set(newValue) {
622
+ emits('update:column-keys', newValue)
623
+ },
624
+ })
625
+
626
+ const selectedAll = ref<boolean>(false)
627
+ const changeAll = (event: UI_I_HTMLSelectElement): void => {
628
+ const newSelectedRow: (number | string)[] = []
629
+ if (event.target.checked) {
630
+ bodyItemsPresent.value.forEach((row) => {
631
+ if (row[0]?.disabled) return
632
+
633
+ newSelectedRow.push(row[0].id)
634
+ })
635
+ }
636
+
637
+ emits('update:selected-row', newSelectedRow)
638
+ }
639
+
640
+ const selectedRowLocal = ref<UI_T_SelectedRow>([])
641
+ const isShowHiddenInfo = ref<boolean>(false)
642
+ const tableWrapperId = `table-wrapper-${useUniqueId()}`
643
+ let memoryWidth = '0'
644
+
645
+ const showedInfoRow = ref<UI_I_BodyItem | null>(null)
646
+ const showedInfoCol = ref<UI_I_BodyItem[] | null>(null)
647
+
648
+ const isShowInfo = computed<boolean>(
649
+ () =>
650
+ showedInfoRow.value &&
651
+ showedInfoRow.value.id === props.selectedRow &&
652
+ !showedInfoRow.value.data?.text &&
653
+ isShowHiddenInfo.value
654
+ )
655
+
656
+ const setShowedInfoData = (
657
+ item: UI_I_BodyItem | null,
658
+ items: UI_I_BodyItem[] | null,
659
+ reset: boolean = false
660
+ ): void => {
661
+ showedInfoRow.value = item
662
+ showedInfoCol.value = items
663
+
664
+ reset && (isShowHiddenInfo.value = false)
665
+ item && selectRowById(item)
666
+ reset && (isShowHiddenInfo.value = true)
667
+ }
668
+
669
+ const doubleArrowClick = (
670
+ item: UI_I_BodyItem,
671
+ items: UI_I_BodyItem[]
672
+ ): void => {
673
+ if (!isShowHiddenInfo.value) {
674
+ setShowedInfoData(item, items)
675
+ } else {
676
+ if (showedInfoRow.value?.id !== item.id) {
677
+ setShowedInfoData(item, items, true)
678
+
679
+ return
680
+ } else {
681
+ setShowedInfoData(null, null)
682
+ }
683
+ }
684
+
685
+ isShowHiddenInfo.value = !isShowHiddenInfo.value
686
+ }
687
+
688
+ watch(
689
+ () => props.selectedRow,
690
+ (newValue) => {
691
+ if (newValue === undefined) return
692
+
693
+ if (Array.isArray(newValue) && !newValue.length) selectedAll.value = false
694
+
695
+ selectedRowLocal.value = newValue
696
+ },
697
+ { immediate: true }
698
+ )
699
+ const selectRowById = (item: UI_I_BodyItem): void => {
700
+ const { id, disabled } = item
701
+
702
+ if (props.offSelectByRow || isShowHiddenInfo.value || disabled) return
703
+
704
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
705
+ const has = selectedRowLocal.value.includes(id)
706
+ if (has) {
707
+ selectedRowLocal.value = selectedRowLocal.value.filter(
708
+ (rowId: string | number) => rowId !== id
709
+ )
710
+ } else {
711
+ selectedRowLocal.value.push(id)
712
+ }
713
+
714
+ emits('change', selectedRowLocal.value)
715
+ emits('update:selected-row', selectedRowLocal.value)
716
+
717
+ changeSelectedAll(!has)
718
+ return
719
+ }
720
+
721
+ emits('change', id)
722
+ emits('update:selected-row', id)
723
+ }
724
+ const changeSelectedRow = (
725
+ event: UI_I_HTMLSelectElement,
726
+ id: number | string
727
+ ): void => {
728
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
729
+ const newSelectedRow = [...selectedRowLocal.value]
730
+ emits('change', newSelectedRow)
731
+ emits('update:selected-row', newSelectedRow)
732
+
733
+ changeSelectedAll(event.target.checked)
734
+ return
735
+ }
736
+
737
+ emits('change', id)
738
+ emits('update:selected-row', id)
739
+ }
740
+ const changeSelectedAll = (checked: boolean): void => {
741
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
742
+ const newSelectedRow = [...selectedRowLocal.value]
743
+
744
+ if (!checked) {
745
+ selectedAll.value = false
746
+ } else if (newSelectedRow.length === bodyItemsPresent.value.length) {
747
+ selectedAll.value = true
748
+ }
749
+ }
750
+ }
751
+
752
+ const checkIsSelectedRow = (id: number | string): boolean => {
753
+ if (props.type === 'checkbox' && Array.isArray(props.selectedRow)) {
754
+ return props.selectedRow.includes(id)
755
+ }
756
+ return props.selectedRow === id
757
+ }
758
+
759
+ // Sorting
760
+ const sortInfo = ref<[string, boolean]>(['', true])
761
+ const sortedColumnIndex = computed<number>(() => {
762
+ let index = -1
763
+ headItemsPresent.value.forEach((item, key) => {
764
+ if (item.sortColumn === sortInfo.value[0]) index = key
765
+ })
766
+
767
+ return index
768
+ })
769
+ const sortTable = (sortName: string): void => {
770
+ if (!sortName) return
771
+
772
+ emits('update:selected-row', selectedRowLocal.value)
773
+
774
+ if (sortInfo.value[0] === sortName) {
775
+ sortInfo.value[1] = !sortInfo.value[1]
776
+
777
+ emits('sorting', sortInfo.value)
778
+ return
779
+ }
780
+ sortInfo.value[0] = sortName
781
+ sortInfo.value[1] = true
782
+
783
+ emits('sorting', sortInfo.value)
784
+ }
785
+
786
+ // Filtering
787
+ const filterShow = ref<boolean[]>([])
788
+ const filterTerm = ref<string[]>([])
789
+ const filtering = (): void => {
790
+ const filter: string[][] = []
791
+ headItemsPresent.value.forEach((item, key) => {
792
+ if (filterTerm.value[key]) filter.push([item.key, filterTerm.value[key]])
793
+ })
794
+
795
+ emits('filtering', filter)
796
+ }
797
+
798
+ // Pagination
799
+ const changePageSize = (value: number): void => {
800
+ emits('update:page-size', value)
801
+ }
802
+ const changePage = (value: number): void => {
803
+ emits('update:selected-row', props.type === 'radio' ? null : [])
804
+ emits('update:page', value)
805
+ }
806
+
807
+ const headItemsPresent = computed<UI_I_HeadItem[]>(() => {
808
+ if (!columnKeysLocal.value) {
809
+ return props.headItems
810
+ }
811
+
812
+ return props.headItems.filter((item, key) => {
813
+ return columnKeysLocal.value?.find(
814
+ (item2, key2) => item2.key === item.key && key === key2
815
+ )?.show
816
+ })
817
+ })
818
+
819
+ const bodyItemsPresent = computed<UI_I_BodyItem[][]>(() => {
820
+ let items: UI_I_BodyItem[][] = props.bodyItems.map((row) => {
821
+ return row.map((item) => {
822
+ return {
823
+ ...item,
824
+ // Если текст пустой нужно поставить '--' для экспорта
825
+ text: item.text !== '' ? item.text : '--',
826
+ }
827
+ })
828
+ })
829
+
830
+ // Filtering by column
831
+ if (columnKeysLocal.value) {
832
+ items = items.map((arr) => {
833
+ arr = arr.filter((item, key) => {
834
+ return columnKeysLocal.value?.find(
835
+ (item2, key2) => item2.key === item.key && key === key2
836
+ )?.show
837
+ })
838
+ return arr
839
+ })
840
+ }
841
+
842
+ if (props.serverOff) {
843
+ // Sorting
844
+ if (sortInfo.value[0] !== '') {
845
+ items = useDeepCopy(items).sort(
846
+ (a: UI_I_BodyItem[], b: UI_I_BodyItem[]) => {
847
+ let first = a[sortedColumnIndex.value].text.toString().toLowerCase()
848
+ let second = b[sortedColumnIndex.value].text.toString().toLowerCase()
849
+
850
+ const sortValueA = a[sortedColumnIndex.value]?.data?.sortValue
851
+ const sortValueB = b[sortedColumnIndex.value]?.data?.sortValue
852
+ if (sortValueA || sortValueA === 0) {
853
+ first = sortValueA
854
+ }
855
+ if (sortValueB || sortValueB === 0) {
856
+ second = sortValueB
857
+ }
858
+
859
+ if (sortInfo.value[1]) {
860
+ return first > second ? 1 : first < second ? -1 : 0
861
+ } else {
862
+ return first < second ? 1 : first > second ? -1 : 0
863
+ }
864
+ }
865
+ )
866
+ }
867
+ // Filtering
868
+ const hasFilter = headItemsPresent.value.some(
869
+ (_, key) => filterTerm.value[key]
870
+ )
871
+ if (hasFilter) {
872
+ items = items.filter((row) => {
873
+ // 0 - начальное значение
874
+ // 1 - найден элемент
875
+ // -1 - ненайден элемент
876
+ let hasItem = 0
877
+ headItemsPresent.value.forEach((item, key) => {
878
+ if (!filterTerm.value[key]) return
879
+ const term = filterTerm.value[key].toLowerCase()
880
+
881
+ row.forEach((col) => {
882
+ if (
883
+ col.key === item.key &&
884
+ typeof col.text === 'string' &&
885
+ hasItem != -1
886
+ ) {
887
+ hasItem = col.text.toLowerCase().includes(term) ? 1 : -1
888
+ }
889
+ })
890
+ })
891
+
892
+ return hasItem === 1
893
+ })
894
+ }
895
+ }
896
+
897
+ return items
898
+ })
899
+
900
+ const toggedItems = ref<boolean[]>([])
901
+
902
+ const toggle = (key: number): void => {
903
+ toggedItems.value[key] = !toggedItems.value[key]
904
+ if (!toggedItems.value[key]) return
905
+ emits('row-detail', key)
906
+ }
907
+
908
+ const outerWrapper = `datagrid-outer-wrapper${useUniqueId()}`
909
+ const expandableCaret = `datagrid-expandable-caret${useUniqueId()}`
910
+
911
+ // Resize
912
+ let helper = false
913
+ let setColumnWidth = (): void => {
914
+ if (!helper) {
915
+ columnsWidth.value = []
916
+ headItemsPresent.value.forEach((item) => {
917
+ columnsWidth.value.push([
918
+ item.width, // width
919
+ item.width, // min-width
920
+ ])
921
+ })
922
+
923
+ helper = true
924
+ setTimeout(() => setColumnWidth(), 0)
925
+ return
926
+ }
927
+ // Не продолжаем, чтобы ширина калонок была так как заданно в headItemsPresent
928
+ if (!props.fillWidth) return
929
+
930
+ // PC-672
931
+ // const dataGridWidth = document.getElementById(outerWrapper)?.clientWidth || 0
932
+ // const leftColumnWidth =
933
+ // document.getElementById(expandableCaret)?.clientWidth || 0
934
+ // const bordersWidth = 2
935
+ // const columnWidth =
936
+ // (dataGridWidth - leftColumnWidth - bordersWidth) /
937
+ // headItemsPresent.value.length
938
+
939
+ headItemsPresent.value.forEach((item) => {
940
+ columnsWidth.value.push([
941
+ // `${columnWidth}px`, // width
942
+ item.width, // width
943
+ item.width, // min-width
944
+ ])
945
+ })
946
+ }
947
+ setColumnWidth = useThrottle(setColumnWidth)
948
+
949
+ const columnsWidth = ref<[string, string][]>([])
950
+ watch(
951
+ bodyItemsPresent,
952
+ (newValue: UI_I_BodyItem[][]) => {
953
+ newValue.forEach(() => {
954
+ toggedItems.value.push(false)
955
+ })
956
+ setColumnWidth()
957
+ },
958
+ {
959
+ immediate: true,
960
+ deep: true,
961
+ }
962
+ )
963
+
964
+ watch(
965
+ headItemsPresent,
966
+ (newValue: UI_I_HeadItem[]) => {
967
+ filterShow.value = newValue.map(() => false)
968
+ filterTerm.value = newValue.map(() => '')
969
+ },
970
+ {
971
+ immediate: true,
972
+ deep: true,
973
+ }
974
+ )
975
+
976
+ const grabColumn = ref<number>(-1)
977
+ const grabStartX = ref<number>(0)
978
+ const setGrab = (key: number, event: MouseEvent): void => {
979
+ if (props.withInfo && key === 0) return
980
+
981
+ if (!isShowHiddenInfo.value) {
982
+ grabColumn.value = key
983
+ const currentWidth = parseInt(columnsWidth.value[grabColumn.value][0])
984
+ grabStartX.value = event.clientX - currentWidth
985
+ if (isRtl.value) {
986
+ grabStartX.value = event.clientX + currentWidth
987
+ }
988
+ }
989
+ }
990
+
991
+ const isDrag = ref<boolean>(false)
992
+
993
+ const mouseup = (): void => {
994
+ if (grabColumn.value === -1) {
995
+ return
996
+ }
997
+
998
+ grabColumn.value = -1
999
+ isDrag.value = false
1000
+ }
1001
+
1002
+ let resizeObserve: ResizeObserver
1003
+ let mousemove = (event: MouseEvent): void => {
1004
+ if (grabColumn.value === -1) return
1005
+
1006
+ event.preventDefault()
1007
+ isDrag.value = true
1008
+ resizeObserve.disconnect()
1009
+
1010
+ const minWidth = parseInt(columnsWidth.value[grabColumn.value][1])
1011
+ let changeX = Math.max(event.clientX - grabStartX.value, minWidth)
1012
+ if (isRtl.value) {
1013
+ changeX = Math.max(grabStartX.value - event.clientX, minWidth)
1014
+ }
1015
+
1016
+ columnsWidth.value[grabColumn.value] = [`${changeX}px`, `${minWidth}px`]
1017
+ }
1018
+ mousemove = useThrottle(mousemove)
1019
+
1020
+ const setResizeObserve = (): void => {
1021
+ const element = document.getElementById(outerWrapper)
1022
+
1023
+ if (!element) {
1024
+ setTimeout(setResizeObserve, 0)
1025
+ return
1026
+ }
1027
+
1028
+ resizeObserve = new ResizeObserver(setColumnWidth)
1029
+ resizeObserve.observe(element)
1030
+ }
1031
+
1032
+ let resizeObserveWithInfo: ResizeObserver
1033
+
1034
+ const setColumnWidthWithInfo = (ent: ResizeObserverEntry[]): void => {
1035
+ if (isShowHiddenInfo.value) {
1036
+ memoryWidth = columnsWidth.value[1][0]
1037
+ columnsWidth.value[1][0] = `${ent[0].contentBoxSize[0].inlineSize - 86}px`
1038
+ } else {
1039
+ columnsWidth.value[1][0] = memoryWidth
1040
+ }
1041
+ }
1042
+
1043
+ const setResizeObserveWithInfo = (): void => {
1044
+ const element = document.querySelector('.datagrid')
1045
+
1046
+ if (!element) {
1047
+ setTimeout(setResizeObserveWithInfo, 0)
1048
+ return
1049
+ }
1050
+
1051
+ resizeObserveWithInfo = new ResizeObserver(setColumnWidthWithInfo)
1052
+ resizeObserveWithInfo.observe(element)
1053
+ }
1054
+
1055
+ // Export
1056
+ const exportItems = computed<UI_I_DropdownButtonItem[]>(() =>
1057
+ exportItemsFunc(
1058
+ localization.value,
1059
+ bodyItemsPresent.value.length || 0,
1060
+ props.selectedRow?.length || 0,
1061
+ props.testId || ''
1062
+ )
1063
+ )
1064
+ const onExport = (type: '0' | '1'): void => {
1065
+ switch (type) {
1066
+ case '0':
1067
+ onExportAll()
1068
+ break
1069
+ case '1':
1070
+ exportSelected()
1071
+ }
1072
+ }
1073
+ const onExportAll = (): void => {
1074
+ const rows = document.querySelectorAll(
1075
+ `#${tableWrapperId} .datagrid-row-scrollable`
1076
+ ) as NodeListOf<HTMLElement>
1077
+ generateCsvAndDownload(Array.from(rows))
1078
+ }
1079
+ const exportSelected = (): void => {
1080
+ const header = document.querySelectorAll(
1081
+ `#${tableWrapperId} .datagrid-row-scrollable`
1082
+ )[0] as HTMLElement
1083
+ const rows = document.querySelectorAll(
1084
+ `#${tableWrapperId} .datagrid-selected`
1085
+ ) as NodeListOf<HTMLElement>
1086
+ generateCsvAndDownload([header, ...Array.from(rows)])
1087
+ }
1088
+
1089
+ onMounted(() => {
1090
+ window.addEventListener('mousemove', mousemove)
1091
+ window.addEventListener('mouseup', mouseup)
1092
+
1093
+ if (props.withInfo) {
1094
+ setResizeObserveWithInfo()
1095
+ }
1096
+
1097
+ setResizeObserve()
1098
+ })
1099
+ onUnmounted(() => {
1100
+ window.removeEventListener('mouseup', mouseup)
1101
+ window.removeEventListener('mousemove', mousemove)
1102
+ })
1103
+ </script>
1104
+
1105
+ <style scoped lang="scss">
1106
+ @import '~/assets/scss/common/mixins';
1107
+ .datagrid-outer-wrapper {
1108
+ @include flex($dir: row);
1109
+ //padding-top: 12px;
1110
+ flex-grow: 1;
1111
+ overflow: auto;
1112
+
1113
+ &.datagrid-outer-wrapper-opened-info {
1114
+ width: 35%;
1115
+ min-width: 195px;
1116
+ }
1117
+
1118
+ & * {
1119
+ box-sizing: border-box;
1120
+ }
1121
+
1122
+ & svg {
1123
+ fill: var(--table-color);
1124
+ }
1125
+
1126
+ .datagrid-inner-wrapper {
1127
+ @include flex($dir: column);
1128
+ flex-grow: 1;
1129
+ overflow: auto;
1130
+
1131
+ .main-filter-content {
1132
+ align-items: center;
1133
+
1134
+ .filter-icon {
1135
+ width: 16px;
1136
+ height: 16px;
1137
+ margin-right: 10px;
1138
+ }
1139
+ }
1140
+ .datagrid {
1141
+ overflow: auto;
1142
+ flex: 1 1 auto;
1143
+ border-radius: 0.125rem 0.125rem 0 0;
1144
+ background-color: var(--block-view-bg-color);
1145
+ border-color: var(--global-border-color);
1146
+ margin-top: 0;
1147
+
1148
+ &.datagrid-opened-info {
1149
+ border-radius: 0.125rem 0 0 0;
1150
+ overflow-x: hidden;
1151
+ }
1152
+
1153
+ .datagrid-table-wrapper {
1154
+ min-width: max-content;
1155
+ display: flex;
1156
+ flex: 1 1 auto;
1157
+ min-height: 100%;
1158
+
1159
+ .datagrid-table {
1160
+ @include flex($dir: column);
1161
+ flex: 1 1 auto;
1162
+ align-content: flex-start;
1163
+ position: relative;
1164
+
1165
+ .datagrid-header {
1166
+ position: sticky;
1167
+ top: 0;
1168
+ z-index: calc(var(--z-sticky) + 1);
1169
+ width: auto;
1170
+
1171
+ .datagrid-row-scrollable {
1172
+ flex-direction: row;
1173
+
1174
+ .datagrid-column-separator {
1175
+ user-select: none;
1176
+
1177
+ &::after {
1178
+ cursor: col-resize;
1179
+ }
1180
+ &.double-arrow-separator .datagrid-column-handle {
1181
+ cursor: unset;
1182
+ }
1183
+ &.double-arrow-separator::after {
1184
+ cursor: unset;
1185
+ }
1186
+ }
1187
+ }
1188
+
1189
+ .datagrid-row {
1190
+ color: var(--table-color);
1191
+ background-color: var(--block-view-bg-color);
1192
+
1193
+ &.datagrid-selected {
1194
+ background-color: var(--row-selected-bg-color);
1195
+ border-bottom: 1px solid var(--global-border-color);
1196
+
1197
+ & :deep(*) {
1198
+ color: var(--table-active-color);
1199
+ }
1200
+ }
1201
+
1202
+ .datagrid-column {
1203
+ background-color: var(--block-view-bg-color);
1204
+ border-bottom: 1px solid var(--global-border-color);
1205
+ padding: 6px 12px 5px;
1206
+ position: relative;
1207
+ //flex: 1 1 auto;
1208
+
1209
+ &:last-child {
1210
+ flex: 1 1 auto;
1211
+ }
1212
+
1213
+ &.datagrid-toggle-block {
1214
+ width: 38px;
1215
+ min-width: 38px;
1216
+
1217
+ &::after {
1218
+ content: '';
1219
+ width: 0.05rem;
1220
+ height: calc(100% - 0.5rem);
1221
+ position: absolute;
1222
+ right: 0;
1223
+ top: 0.25rem;
1224
+ background-color: var(--global-border-color);
1225
+ }
1226
+
1227
+ .datagrid-column-separator {
1228
+ cursor: default;
1229
+
1230
+ &::after {
1231
+ cursor: default;
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+
1237
+ .datagrid-column-title {
1238
+ align-self: auto;
1239
+ color: var(--table-color);
1240
+ background-color: var(--block-view-bg-color);
1241
+ border-bottom-color: var(--global-border-color);
1242
+ font-size: 11px;
1243
+ @include flex($align: center);
1244
+ display: flex;
1245
+ flex-direction: row;
1246
+ justify-content: flex-start;
1247
+ align-items: center;
1248
+ //line-height: 24px;
1249
+ line-height: normal;
1250
+
1251
+ .title-column {
1252
+ font-weight: bold;
1253
+ font-size: 11px;
1254
+ overflow: hidden;
1255
+ text-wrap: none;
1256
+ text-overflow: ellipsis;
1257
+ }
1258
+
1259
+ .sort-arrow-wrap {
1260
+ margin-left: auto;
1261
+ height: 14px;
1262
+ width: 14px;
1263
+ min-height: 14px;
1264
+ min-width: 14px;
1265
+ vertical-align: middle;
1266
+
1267
+ .sort-arrow {
1268
+ &.down {
1269
+ transform: rotate(180deg);
1270
+ }
1271
+ }
1272
+ }
1273
+ .title-icon {
1274
+ width: 24px;
1275
+ height: 24px;
1276
+ }
1277
+ }
1278
+
1279
+ .datagrid-filter-toggle {
1280
+ background: unset;
1281
+ margin-top: -4px;
1282
+ align-self: center;
1283
+
1284
+ .filter-icon {
1285
+ width: 16px;
1286
+ height: 16px;
1287
+ }
1288
+ }
1289
+ }
1290
+ }
1291
+
1292
+ .datagrid-placeholder-container {
1293
+ .datagrid-placeholder.datagrid-empty {
1294
+ background: var(--block-view-bg-color);
1295
+ }
1296
+ span {
1297
+ font-size: 16px;
1298
+ color: var(--global-font-color4);
1299
+ }
1300
+ }
1301
+
1302
+ .datagrid-row {
1303
+ width: 100%;
1304
+ min-width: max-content;
1305
+ border-top: none;
1306
+ color: var(--table-color);
1307
+ background-color: var(--block-view-bg-color);
1308
+ border-bottom: 1px solid var(--global-border-color);
1309
+
1310
+ &.datagrid-selected {
1311
+ & :deep(*) {
1312
+ color: var(--table-active-color);
1313
+ }
1314
+
1315
+ .datagrid-cell {
1316
+ background-color: var(--row-selected-bg-color);
1317
+ border-bottom: 1px solid var(--global-border-color);
1318
+ position: relative;
1319
+ line-height: 1rem;
1320
+ }
1321
+
1322
+ .datagrid-row-detail {
1323
+ background-color: var(--row-selected-bg-color);
1324
+ border-bottom: 1px solid var(--global-border-color);
1325
+ }
1326
+ }
1327
+
1328
+ .datagrid-cell {
1329
+ min-width: 38px;
1330
+ min-height: 28px;
1331
+ padding: 2px 12px 3px 12px;
1332
+ position: relative;
1333
+
1334
+ &:has(.double-arrow-wrap) {
1335
+ padding-left: 4px;
1336
+ }
1337
+
1338
+ &:has(.double-arrow-wrap)::after {
1339
+ content: '';
1340
+ width: 0.5px;
1341
+ height: calc(100% - 6px);
1342
+ position: absolute;
1343
+ right: 2px;
1344
+ top: 3px;
1345
+ background-color: var(--global-border-color);
1346
+ }
1347
+
1348
+ &:last-child {
1349
+ flex: 1 1 auto;
1350
+ }
1351
+
1352
+ button {
1353
+ height: 0.9rem;
1354
+ width: 0.9rem;
1355
+
1356
+ .arrow-icon {
1357
+ width: 16px;
1358
+ height: 16px;
1359
+ transform: rotate(90deg);
1360
+ }
1361
+ }
1362
+
1363
+ .datagrid-cell-icon {
1364
+ display: inline-block;
1365
+ width: 16px;
1366
+ height: 16px;
1367
+ }
1368
+
1369
+ .datagrid-expandable-caret-button {
1370
+ cursor: pointer;
1371
+ width: 100%;
1372
+
1373
+ .datagrid-expandable-caret-icon {
1374
+ width: 16px;
1375
+ height: 16px;
1376
+ transform: rotate(90deg);
1377
+ fill: var(--table-caret-color);
1378
+
1379
+ &.toggle {
1380
+ transform: rotate(180deg);
1381
+ }
1382
+ }
1383
+ }
1384
+ }
1385
+
1386
+ &.datagrid-selected-info {
1387
+ width: 100%;
1388
+ min-width: max-content;
1389
+ border-top: none;
1390
+ color: var(--table-color);
1391
+ background-color: var(--block-view-bg-color);
1392
+
1393
+ .datagrid-cell {
1394
+ position: relative;
1395
+
1396
+ &.hidden-text-triangle::after {
1397
+ content: '';
1398
+ position: absolute;
1399
+ transform: rotate(225deg);
1400
+ border-bottom: 15px solid transparent;
1401
+ border-right: 15px solid var(--global-bg-color);
1402
+ bottom: 26%;
1403
+ right: -16px;
1404
+ z-index: calc(var(--z-sticky) + 1);
1405
+ }
1406
+
1407
+ &.hidden-text-triangle::before {
1408
+ content: '';
1409
+ transform: rotate(-135deg);
1410
+ position: absolute;
1411
+ border-bottom: 16px solid transparent;
1412
+ border-right: 16px solid var(--global-border-color);
1413
+ bottom: 23%;
1414
+ right: -17px;
1415
+ z-index: calc(var(--z-sticky) + 1);
1416
+ }
1417
+ }
1418
+ }
1419
+ }
1420
+
1421
+ .datagrid-row-sticky {
1422
+ @include flex($w: nowrap);
1423
+ position: sticky;
1424
+ left: 0;
1425
+ z-index: var(--z-sticky);
1426
+ background-color: var(--block-view-bg-color);
1427
+
1428
+ .datagrid-column {
1429
+ color: var(--table-color);
1430
+ background-color: var(--block-view-bg-color);
1431
+ border-bottom-color: var(--global-border-color);
1432
+ text-align: left;
1433
+ display: flex;
1434
+ flex: 1 1 auto;
1435
+ vertical-align: top;
1436
+ border: none;
1437
+
1438
+ &.datagrid-expandable-caret {
1439
+ .datagrid-column-separator {
1440
+ display: block;
1441
+
1442
+ &::after {
1443
+ top: 0;
1444
+ height: 18px;
1445
+ }
1446
+ }
1447
+
1448
+ .radio-btn {
1449
+ width: 16px;
1450
+ height: 16px;
1451
+ }
1452
+ }
1453
+
1454
+ .datagrid-column-separator {
1455
+ position: relative;
1456
+ //left: 0.6rem;
1457
+ flex: 0 0 auto;
1458
+ width: 0.05rem;
1459
+ order: 100;
1460
+ margin-left: auto;
1461
+ height: 100%;
1462
+ }
1463
+ }
1464
+
1465
+ .datagrid-fixed-column-without-separator {
1466
+ background-color: var(--block-view-bg-color);
1467
+
1468
+ &::after {
1469
+ background-color: transparent;
1470
+ }
1471
+ }
1472
+
1473
+ .datagrid-fixed-column {
1474
+ background-color: var(--block-view-bg-color);
1475
+
1476
+ //&::after {
1477
+ // content: '';
1478
+ // width: 0.05rem;
1479
+ // height: calc(100% - 0.5rem);
1480
+ // position: absolute;
1481
+ // right: 0;
1482
+ // top: 0.25rem;
1483
+ // background-color: var(--global-border-color);
1484
+ //}
1485
+
1486
+ .clr-form-control-disabled {
1487
+ .clr-checkbox-wrapper {
1488
+ label {
1489
+ cursor: not-allowed;
1490
+ }
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ .datagrid-fixed-width {
1496
+ &::after {
1497
+ content: '';
1498
+ width: 0.05rem;
1499
+ height: calc(100% - 0.5rem);
1500
+ position: absolute;
1501
+ right: 0;
1502
+ top: 0.25rem;
1503
+ background-color: var(--global-border-color);
1504
+ }
1505
+ }
1506
+ }
1507
+
1508
+ .datagrid-row-scrollable {
1509
+ @include flex($ff: row nowrap);
1510
+ flex: 1 1 auto;
1511
+
1512
+ .datagrid-scrolling-cells {
1513
+ @include flex($ff: row nowrap);
1514
+ flex: 1 1 auto;
1515
+ }
1516
+ }
1517
+ .datagrid-body-row {
1518
+ .datagrid-row-scrollable {
1519
+ @include flex($ff: column nowrap);
1520
+
1521
+ .datagrid-row-detail {
1522
+ flex: 1;
1523
+ }
1524
+ }
1525
+
1526
+ &:not(.datagrid-selected):hover {
1527
+ border-bottom: 1px solid var(--table-hover-row-border-color);
1528
+ background-color: var(--table-hover-row-background-color);
1529
+ color: var(--table-hover-row-color);
1530
+
1531
+ .datagrid-fixed-column {
1532
+ background-color: var(--table-hover-row-background-color);
1533
+ }
1534
+ .datagrid-cell {
1535
+ background-color: var(--table-hover-row-background-color);
1536
+ }
1537
+ }
1538
+ }
1539
+ }
1540
+ }
1541
+ }
1542
+
1543
+ .datagrid-footer {
1544
+ flex: 0 0 auto;
1545
+ @include flex($ff: row nowrap, $just: space-between, $align: stretch);
1546
+ font-size: 0.55rem;
1547
+ background-color: var(--block-view-bg-color);
1548
+ border: 0.05rem solid var(--global-border-color);
1549
+ border-top: none;
1550
+ border-radius: 0 0 0.15rem 0.15rem;
1551
+ padding: 0 0.6rem;
1552
+ height: 28px;
1553
+
1554
+ &.datagrid-footer-opened-info {
1555
+ border-radius: 0 0 0 0.15rem;
1556
+ flex-direction: row-reverse;
1557
+ }
1558
+
1559
+ .clr-form-control-disabled {
1560
+ opacity: 1;
1561
+
1562
+ .clr-checkbox-wrapper {
1563
+ label {
1564
+ color: #8c8c8c;
1565
+ margin-right: 9px;
1566
+ padding-left: 22px;
1567
+ &:before {
1568
+ position: absolute;
1569
+ top: 4px;
1570
+ left: 0;
1571
+ content: '';
1572
+ display: inline-block;
1573
+ height: 16px;
1574
+ width: 16px;
1575
+ border: none;
1576
+ border-radius: 3px;
1577
+ background-color: var(--table-checkbox-color);
1578
+ }
1579
+
1580
+ &:after {
1581
+ position: absolute;
1582
+ content: '';
1583
+ display: inline-block;
1584
+ height: 5px;
1585
+ width: 8px;
1586
+ border-left: 2px solid #fff;
1587
+ border-bottom: 2px solid #fff;
1588
+ top: 4px;
1589
+ left: 4px;
1590
+ transform: translateY(4px) rotate(-45deg);
1591
+ }
1592
+ }
1593
+ }
1594
+ }
1595
+ }
1596
+
1597
+ .datagrid-spinner {
1598
+ top: 0.6rem;
1599
+ height: calc(100% - 0.6rem);
1600
+ }
1601
+
1602
+ .datagrid-footer-description {
1603
+ flex: 1 1 auto;
1604
+
1605
+ :deep(svg) {
1606
+ fill: var(--table-switch-color);
1607
+ }
1608
+ }
1609
+
1610
+ .clr-radio-wrapper,
1611
+ .clr-checkbox-wrapper {
1612
+ height: 18px;
1613
+ }
1614
+
1615
+ .clr-radio-wrapper label,
1616
+ .clr-checkbox-wrapper label {
1617
+ padding-left: 16px;
1618
+ }
1619
+ }
1620
+ }
1621
+ //.vertical-divider {
1622
+ // width: 1px;
1623
+ // height: 22px;
1624
+ // background: #bbb;
1625
+ // margin: 2px 2px 0 -5px;
1626
+ //}
1627
+
1628
+ .hidden-features {
1629
+ padding: 9px 14px;
1630
+ background-color: var(--global-bg-color);
1631
+ color: var(--global-font-color2);
1632
+ border: 1px solid var(--global-border-color);
1633
+ border-left: none;
1634
+ overflow-y: auto;
1635
+ overflow-x: hidden;
1636
+ width: 65%;
1637
+
1638
+ //.header {
1639
+ // display: flex;
1640
+ // align-items: center;
1641
+ // justify-content: space-between;
1642
+ // background-color: inherit;
1643
+ //
1644
+ // h3 {
1645
+ // font-size: 1rem;
1646
+ // color: var(--global-font-color2) !important;
1647
+ // line-height: 1.7rem;
1648
+ // }
1649
+ button {
1650
+ position: absolute;
1651
+ top: 24px;
1652
+ right: 24px;
1653
+ line-height: 24px;
1654
+
1655
+ .close-icon {
1656
+ //margin-left: 10px;
1657
+ width: 24px;
1658
+ height: 24px;
1659
+ }
1660
+ }
1661
+ //}
1662
+ }
1663
+ .double-arrow-width {
1664
+ width: 25px;
1665
+ }
1666
+ .double-arrow-wrap {
1667
+ width: 30px;
1668
+ height: 20px;
1669
+ padding-top: 1px;
1670
+ padding-left: 5px;
1671
+ cursor: pointer;
1672
+ background-color: transparent;
1673
+
1674
+ .double-arrow {
1675
+ background-color: transparent;
1676
+ transform: rotate(90deg);
1677
+ width: 16px;
1678
+ height: 16px;
1679
+ }
1680
+
1681
+ .double-arrow.arrow-selected {
1682
+ transform: rotate(-90deg) !important;
1683
+ background-color: #0079b8;
1684
+ }
1685
+ }
1686
+ .double-arrow-wrap.arrow-selected {
1687
+ background-color: #0079b8;
1688
+ border-radius: 3px;
1689
+ }
1690
+ </style>
1691
+
1692
+ <style>
1693
+ :root {
1694
+ --table-color: #565656;
1695
+ --table-active-color: #fff;
1696
+ --table-checkbox-color: #454545;
1697
+ --table-caret-color: #454545;
1698
+ --table-switch-color: #575757;
1699
+ --table-hover-row-border-color: #666;
1700
+ --table-hover-row-background-color: #e8e8e8;
1701
+ --table-hover-row-color: #454545;
1702
+ --table-spinner-bg-color: #ffffff99;
1703
+ }
1704
+
1705
+ :root.dark-theme {
1706
+ --table-color: #fff;
1707
+ --table-active-color: #565656;
1708
+ --table-checkbox-color: #49aeda;
1709
+ --table-caret-color: #ffffff;
1710
+ --table-switch-color: #b3b3b3;
1711
+ --table-hover-row-border-color: #fff;
1712
+ --table-hover-row-background-color: #324f61;
1713
+ --table-hover-row-color: #e9ecef;
1714
+ --table-spinner-bg-color: rgba(0, 0, 0, 0.5);
1715
+ }
1716
+ </style>