bfg-common 1.2.197 → 1.2.198

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 (107) hide show
  1. package/assets/localization/local_be.json +9 -2
  2. package/assets/localization/local_en.json +9 -2
  3. package/assets/localization/local_hy.json +9 -2
  4. package/assets/localization/local_kk.json +9 -2
  5. package/assets/localization/local_ru.json +9 -2
  6. package/assets/localization/local_zh.json +9 -2
  7. package/components/atoms/table/dataGrid/DataGrid.vue +1490 -1490
  8. package/components/atoms/table/simpleTable/SimpleTable.vue +5 -2
  9. package/components/atoms/wizard/Wizard.vue +4 -4
  10. package/components/atoms/wizard/models/interfaces.ts +4 -3
  11. package/components/atoms/wizard/utils/utils.ts +106 -27
  12. package/components/common/diagramMain/DiagramMain.vue +11 -47
  13. package/components/common/diagramMain/modals/config/index.ts +0 -6
  14. package/components/common/diagramMain/modals/config/vmKernelAdapter.ts +2 -2
  15. package/components/common/diagramMain/modals/editSettings/tabs/NetworkProperties.vue +1 -1
  16. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +1 -1
  17. package/components/common/diagramMain/modals/migrateVmkernelAdapter/MigrateVmkernelAdapter.vue +531 -0
  18. package/components/common/diagramMain/modals/migrateVmkernelAdapter/config/steps.ts +114 -0
  19. package/components/common/diagramMain/modals/migrateVmkernelAdapter/steps/ConnectionSettings.vue +161 -0
  20. package/components/common/diagramMain/modals/{steps → migrateVmkernelAdapter/steps}/SelectVmkernelAdapter.vue +24 -86
  21. package/components/common/diagramMain/modals/{steps → migrateVmkernelAdapter/steps}/VmkernelAdapterReadyComplete.vue +7 -11
  22. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/common.ts +47 -0
  23. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/connectionSettings.ts +146 -0
  24. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/selectVmkernelAdapter.ts +54 -0
  25. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/validations.ts +19 -0
  26. package/components/common/diagramMain/models/enums.ts +6 -7
  27. package/components/common/diagramMain/models/interfaces.ts +28 -29
  28. package/components/common/diagramMain/models/types.ts +0 -1
  29. package/components/common/monitor/advanced/Advanced.vue +10 -3
  30. package/components/common/monitor/advanced/tools/Tools.vue +15 -7
  31. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModal.vue +21 -9
  32. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/Counters.vue +7 -3
  33. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/Table.vue +3 -3
  34. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/config/utils.ts +5 -5
  35. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/Timespan.vue +7 -3
  36. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/Object.vue +24 -3
  37. package/components/common/monitor/advanced/tools/chartOptionsModal/models/types.ts +2 -2
  38. package/components/common/monitor/advanced/tools/config/advancedToolbar.ts +14 -7
  39. package/components/common/monitor/overview/filters/Filters.vue +5 -4
  40. package/components/common/monitor/overview/filters/config/filterOptions.ts +3 -2
  41. package/components/common/tools/viewSettings/ViewSettings.vue +71 -0
  42. package/components/common/tools/viewSettings/models/interfaces.ts +9 -0
  43. package/components/common/vm/actions/add/Add.vue +785 -525
  44. package/components/common/vm/actions/add/utils.ts +105 -0
  45. package/components/common/vm/actions/addOld/Add.vue +690 -0
  46. package/components/common/vm/actions/addOld/FolderTreeView.vue +83 -0
  47. package/components/common/vm/actions/addOld/utils.ts +118 -0
  48. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/Cpu.vue +394 -394
  49. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +1 -1
  50. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDevice.vue +1 -1
  51. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newUsbController/NewUsbController.vue +1 -1
  52. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/Other.vue +1 -1
  53. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCard.vue +1 -1
  54. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/BootOptions.vue +1 -1
  55. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptions.vue +1 -1
  56. package/components/common/vm/actions/common/select/name/Name.vue +10 -5
  57. package/components/common/vm/actions/common/select/name/NameOld.vue +215 -0
  58. package/components/common/vm/actions/common/select/storage/Storage.vue +6 -4
  59. package/components/common/vm/actions/common/select/storage/StorageOld.vue +194 -0
  60. package/components/common/wizards/network/add/Add.vue +874 -0
  61. package/components/common/{addNetworking → wizards/network/add}/config/index.ts +2 -16
  62. package/components/common/{addNetworking → wizards/network/add}/config/initialData.ts +4 -19
  63. package/components/common/{addNetworking → wizards/network/add}/config/portPropertiesStep.ts +1 -1
  64. package/components/common/{addNetworking → wizards/network/add}/config/selectSwitch.ts +1 -1
  65. package/components/common/{addNetworking → wizards/network/add}/config/sendData.ts +1 -1
  66. package/components/common/{addNetworking/config/addNetworkingSteps.ts → wizards/network/add/config/steps.ts} +107 -60
  67. package/components/common/{addNetworking → wizards/network/add}/modals/SelectNetwork.vue +2 -2
  68. package/components/common/{addNetworking → wizards/network/add}/modals/SelectStandardSwitch.vue +2 -2
  69. package/components/common/{addNetworking → wizards/network/add}/modals/SelectSwitch.vue +2 -2
  70. package/components/common/wizards/network/add/models/enums.ts +17 -0
  71. package/components/common/{addNetworking → wizards/network/add}/models/interfaces.ts +30 -37
  72. package/components/common/wizards/network/add/models/types.ts +2 -0
  73. package/components/common/wizards/network/add/steps/ConnectionSettings.vue +148 -0
  74. package/components/common/{addNetworking → wizards/network/add}/steps/CreateStandardSwitch.vue +0 -7
  75. package/components/common/wizards/network/add/steps/IpFourSettings.vue +245 -0
  76. package/components/common/{addNetworking → wizards/network/add}/steps/PhysicalAdapter.vue +1 -12
  77. package/components/common/{addNetworking → wizards/network/add}/steps/PortProperties.vue +57 -180
  78. package/components/common/{addNetworking → wizards/network/add}/steps/ReadyComplete.vue +1 -10
  79. package/components/common/{addNetworking → wizards/network/add}/steps/SelectConnectionType.vue +3 -15
  80. package/components/common/{addNetworking → wizards/network/add}/steps/SelectedTargetDevice.vue +106 -212
  81. package/components/common/wizards/network/add/utils/index.ts +4 -0
  82. package/components/common/wizards/network/add/validations/common.ts +58 -0
  83. package/components/common/wizards/network/add/validations/connectionSettings.ts +75 -0
  84. package/components/common/wizards/network/add/validations/createStandardSwitch.ts +58 -0
  85. package/components/common/wizards/network/add/validations/ipFourSettings.ts +188 -0
  86. package/components/common/wizards/network/add/validations/networkValidation.ts +73 -0
  87. package/components/common/wizards/network/add/validations/portProperties.ts +87 -0
  88. package/components/common/wizards/network/add/validations/targetDevice.ts +113 -0
  89. package/components/common/wizards/network/add/validations/validations.ts +43 -0
  90. package/models/composables/useMyFetch/interfaces.ts +25 -25
  91. package/package.json +1 -1
  92. package/components/common/addNetworking/AddNetworking.vue +0 -1123
  93. package/components/common/addNetworking/Wizard.vue +0 -286
  94. package/components/common/addNetworking/config/temporaryData.ts +0 -8
  95. package/components/common/addNetworking/config/validation.ts +0 -23
  96. package/components/common/addNetworking/models/enums.ts +0 -7
  97. package/components/common/addNetworking/models/types.ts +0 -13
  98. package/components/common/addNetworking/steps/ConnectionSettings.vue +0 -269
  99. package/components/common/addNetworking/steps/Header.vue +0 -53
  100. package/components/common/addNetworking/steps/IpFourSettings.vue +0 -361
  101. package/components/common/addNetworking/utils/index.ts +0 -212
  102. package/components/common/diagramMain/modals/MigrateVmkernelAdapter.vue +0 -603
  103. package/components/common/diagramMain/modals/config/migrateVmkernelAdapterSteps.ts +0 -81
  104. package/components/common/diagramMain/modals/config/validation.ts +0 -3
  105. package/components/common/diagramMain/modals/steps/ConnectionSettings.vue +0 -221
  106. package/components/common/diagramMain/modals/steps/Header.vue +0 -60
  107. /package/components/common/{addNetworking → wizards/network/add}/mappers/mappers.ts +0 -0
@@ -1,1490 +1,1490 @@
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
- :class="[
15
- 'datagrid',
16
- {
17
- 'datagrid-opened-info': isShowHiddenInfo,
18
- },
19
- ]"
20
- >
21
- <div :id="tableWrapperId" class="datagrid-table-wrapper">
22
- <div class="datagrid-table">
23
- <div class="datagrid-header">
24
- <div class="datagrid-row">
25
- <div class="datagrid-row-master datagrid-row-flex">
26
- <div v-if="props.type" class="datagrid-row-sticky">
27
- <div
28
- :id="expandableCaret"
29
- class="datagrid-column datagrid-expandable-caret datagrid-fixed-column flex-align-center flex-justify-center"
30
- >
31
- <template v-if="props.type === 'checkbox'">
32
- <div
33
- class="clr-checkbox-wrapper flex-align-center flex-justify-center w-100"
34
- >
35
- <input
36
- :id="`${props.testId}-${inputId}-all`"
37
- v-model="selectedAll"
38
- type="checkbox"
39
- class="checkbox-btn"
40
- :value="-1"
41
- @change="changeAll"
42
- />
43
- <label
44
- :for="`${props.testId}-${inputId}-all`"
45
- class="clr-control-label"
46
- />
47
- </div>
48
- <div class="datagrid-column-separator"></div>
49
- </template>
50
- </div>
51
- <div
52
- v-if="$slots.toggleBlock"
53
- class="datagrid-toggle-block datagrid-column datagrid-fixed-width"
54
- >
55
- <div class="datagrid-column-flex">
56
- <div class="datagrid-column-separator">
57
- <span class="clr-sr-only" />
58
- <div class="datagrid-column-resize-tracker" />
59
- </div>
60
- </div>
61
- </div>
62
- </div>
63
- <div class="datagrid-row-scrollable">
64
- <div
65
- v-for="(item, key) in headItemsPresent"
66
- :key="key"
67
- :style="{
68
- width: columnsWidth[key][0],
69
- minWidth: columnsWidth[key][1],
70
- }"
71
- class="datagrid-column datagrid-fixed-width"
72
- >
73
- <div class="datagrid-column-flex">
74
- <button
75
- :id="`${props.testId}-sort-column-${key}`"
76
- :class="[
77
- 'datagrid-column-title',
78
- {
79
- 'default text-decoration-none':
80
- !item.sortColumn,
81
- },
82
- ]"
83
- @click="sortTable(item.sortColumn)"
84
- >
85
- <slot :key="key" name="th" :item="item">
86
- <span
87
- :title="item.text"
88
- :style="{
89
- width:
90
- columnsWidth[key][0]?.slice(0, -2) -
91
- (item.hasFilter ? 65 : 40) +
92
- 'px',
93
- }"
94
- class="title-column"
95
- >
96
- {{ item.text }}
97
- </span>
98
- </slot>
99
- <span
100
- v-if="item.sortColumn"
101
- class="sort-arrow-wrap"
102
- >
103
- <atoms-the-icon
104
- v-show="sortInfo[0] === item.sortColumn"
105
- :class="['sort-arrow', { down: sortInfo[1] }]"
106
- name="sort-arrow"
107
- />
108
- </span>
109
- </button>
110
- <button
111
- v-if="item.hasFilter"
112
- :id="`${props.testId}-filter-icon-${key}`"
113
- class="datagrid-filter-toggle clr-anchor clr-smart-open-close"
114
- @click="filterShow[key] = !filterShow[key]"
115
- >
116
- <atoms-the-icon
117
- v-if="filterTerm[key]"
118
- class="filter-icon"
119
- name="filter-solid"
120
- style="fill: #0079b8"
121
- />
122
- <atoms-the-icon
123
- v-else
124
- class="filter-icon"
125
- name="filter"
126
- />
127
- </button>
128
- <atoms-popup-simple-popup
129
- v-model="filterShow[key]"
130
- :test-id="`${props.testId}-filter`"
131
- top="100%"
132
- right="0"
133
- >
134
- <input
135
- :id="`${props.testId}-filter-input-${key}`"
136
- v-model="filterTerm[key]"
137
- type="text"
138
- @input="filtering"
139
- />
140
- </atoms-popup-simple-popup>
141
- <div
142
- v-show="
143
- !isShowHiddenInfo ||
144
- (isShowHiddenInfo && key === 0)
145
- "
146
- :class="[
147
- 'datagrid-column-separator',
148
- {
149
- 'double-arrow-separator':
150
- key === 0 && props.withInfo,
151
- },
152
- ]"
153
- @mousedown="setGrab(key, $event)"
154
- >
155
- <button
156
- :id="`${props.testId}-resize-tracker-${key}`"
157
- class="datagrid-column-handle drag-handle draggable"
158
- />
159
- <span class="clr-sr-only" />
160
- <div class="datagrid-column-resize-tracker" />
161
- </div>
162
- </div>
163
- </div>
164
- </div>
165
- </div>
166
- </div>
167
- </div>
168
-
169
- <template v-if="bodyItemsPresent.length">
170
- <div
171
- v-for="(item, key) in bodyItemsPresent"
172
- :key="item.id"
173
- :class="[
174
- 'datagrid-body-row datagrid-row animation',
175
- {
176
- 'datagrid-selected active':
177
- !props.withInfo && checkIsSelectedRow(item[0].id),
178
- 'datagrid-selected-info':
179
- props.withInfo &&
180
- isShowHiddenInfo &&
181
- checkIsSelectedRow(item[0].id),
182
- },
183
- ]"
184
- :[props.rowAttributeIdName]="item[0].dataId"
185
- >
186
- <div>
187
- <div
188
- class="datagrid-row-master datagrid-row-flex"
189
- @click.prevent.stop="selectRowById(item[0].id)"
190
- >
191
- <div
192
- v-if="props.type"
193
- class="datagrid-row-sticky"
194
- @click.stop
195
- >
196
- <div
197
- :id="expandableCaret"
198
- :class="[
199
- 'datagrid-expandable-caret flex-justify-center datagrid-cell',
200
- {
201
- 'datagrid-fixed-column': !props.withInfo,
202
- 'datagrid-fixed-column-without-separator':
203
- props.withInfo,
204
- },
205
- ]"
206
- >
207
- <slot :key="key" name="type" :item="item">
208
- <div
209
- :class="`clr-${props.type}-wrapper flex-justify-center flex-align-center`"
210
- >
211
- <input
212
- :id="`${props.testId}-${inputId}-${item[0].id}`"
213
- v-model="selectedRowLocal"
214
- :key="item[0].id"
215
- :type="props.type"
216
- :class="`${props.type}-btn`"
217
- :value="item[0].id"
218
- name="selected-store"
219
- @change="changeSelectedRow($event, item[0].id)"
220
- />
221
- <label
222
- :for="`${props.testId}-${inputId}-${item[0].id}`"
223
- class="clr-control-label"
224
- />
225
- </div>
226
- </slot>
227
- </div>
228
- <div
229
- v-if="$slots.toggleBlock"
230
- class="datagrid-cell datagrid-fixed-width"
231
- >
232
- <div class="flex-align-center">
233
- <button
234
- :id="`${props.testId}-toggle-icon-${key}`"
235
- class="datagrid-expandable-caret-button reset-btn"
236
- @click="toggle(key)"
237
- >
238
- <atoms-the-icon
239
- :class="[
240
- 'datagrid-expandable-caret-icon',
241
- { toggle: toggedItems[key] },
242
- ]"
243
- name="angle"
244
- />
245
- </button>
246
- </div>
247
- </div>
248
- </div>
249
- <div class="datagrid-row-scrollable">
250
- <div class="datagrid-scrolling-cells">
251
- <div
252
- v-for="(item2, key2) in item"
253
- v-show="
254
- !isShowHiddenInfo ||
255
- item2.key === 'col1' ||
256
- item2.key === 'icon'
257
- "
258
- :key="key2"
259
- :style="{
260
- width: columnsWidth[key2][0],
261
- minWidth: columnsWidth[key2][1],
262
- }"
263
- :class="[
264
- 'datagrid-cell datagrid-fixed-width',
265
- {
266
- 'hidden-text-triangle':
267
- isShowHiddenInfo &&
268
- item2.data?.name === 'hidden-text-triangle',
269
- },
270
- ]"
271
- >
272
- <div
273
- :class="[
274
- 'flex-align-center h-100',
275
- {
276
- 'double-arrow-width':
277
- item2.data?.name === 'doubleArrows',
278
- },
279
- ]"
280
- >
281
- <div
282
- v-if="item2.data?.name === 'doubleArrows'"
283
- :id="`show-info-${item[1].text}`"
284
- :class="[
285
- 'double-arrow-wrap',
286
- {
287
- 'arrow-selected':
288
- isShowHiddenInfo &&
289
- item2.id === selectedRow,
290
- },
291
- ]"
292
- @click.prevent.stop="
293
- doubleArrowClick(item2, item)
294
- "
295
- >
296
- <atoms-the-icon
297
- v-if="item2.data?.name === 'doubleArrows'"
298
- name="doubleArrows"
299
- :class="[
300
- 'double-arrow',
301
- {
302
- 'arrow-selected':
303
- isShowHiddenInfo &&
304
- item2.id === selectedRow,
305
- },
306
- ]"
307
- />
308
- </div>
309
- <span
310
- v-if="item2.text && item2.data?.iconClassName"
311
- class="vertical-divider"
312
- />
313
- <slot :name="item2.key" :item="item2">
314
- <span class="text-ellipsis" :title="item2.text"
315
- >{{ item2.text }}
316
- </span>
317
- </slot>
318
- </div>
319
- </div>
320
- </div>
321
- <div
322
- v-show="toggedItems[key]"
323
- class="datagrid-row-flex datagrid-row-detail datagrid-container"
324
- >
325
- <slot name="toggleBlock" />
326
- </div>
327
- </div>
328
- </div>
329
- </div>
330
- </div>
331
- </template>
332
- <template v-else>
333
- <div class="datagrid-placeholder-container">
334
- <div class="datagrid-placeholder datagrid-empty">
335
- <div class="datagrid-placeholder-image"></div>
336
-
337
- <span>No items found</span>
338
- </div>
339
- </div>
340
- </template>
341
- </div>
342
- </div>
343
- </div>
344
-
345
- <div
346
- v-if="!hideFooter"
347
- :class="[
348
- 'datagrid-footer',
349
- {
350
- 'datagrid-footer-opened-info': isShowHiddenInfo,
351
- },
352
- ]"
353
- >
354
- <div
355
- v-if="props.type === 'checkbox' && props.selectedRow?.length"
356
- class="clr-form-control-disabled"
357
- >
358
- <div class="clr-checkbox-wrapper">
359
- <input
360
- :id="`${props.testId}-check-all`"
361
- type="checkbox"
362
- checked
363
- />
364
- <label class="clr-control-label">
365
- {{ props.selectedRow?.length }}
366
- </label>
367
- </div>
368
- </div>
369
- <div class="datagrid-footer-description flex-align-center">
370
- <atoms-table-data-grid-column-switch
371
- v-if="columnKeysLocal"
372
- v-model:column-keys="columnKeysLocal"
373
- :test-id="`${props.testId}-footer-description`"
374
- class="switch-icon"
375
- />
376
-
377
- <div v-if="$slots.action" class="datagrid-footer__action">
378
- <slot name="action" />
379
- </div>
380
- </div>
381
-
382
- <atoms-table-data-grid-pagination
383
- test-id="props.testId"
384
- :page-size="props.pageSize"
385
- :page="props.page"
386
- :options="mergeOptions"
387
- :total-items="props.totalItems"
388
- :total-pages="props.totalPages"
389
- :hide-pagination="props.hidePagination"
390
- :hide-page-size="props.hidePageSize"
391
- :show-page-info="props.showPageInfo"
392
- :page-items-count="props.bodyItems.length"
393
- :is-show-hidden-info="isShowHiddenInfo"
394
- @change-page-size="changePageSize"
395
- @change-page="changePage"
396
- />
397
- </div>
398
-
399
- <atoms-loader v-show="props.loading" class="datagrid-spinner" />
400
- </div>
401
- </div>
402
- <div
403
- v-if="isShowInfo"
404
- id="hidden-features"
405
- :class="[
406
- 'hidden-features',
407
- {
408
- 'show-hidden-info': isShowHiddenInfo,
409
- },
410
- ]"
411
- >
412
- <div class="header">
413
- <slot name="hiddenInfoHeader" :item="showedInfoCol" />
414
- <button
415
- :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"
416
- class="signpost-action close"
417
- @click="isShowHiddenInfo = false"
418
- >
419
- <atoms-the-icon class="close-icon" name="close" />
420
- </button>
421
- </div>
422
- <slot name="hiddenInfoBody" />
423
- </div>
424
- </div>
425
- </template>
426
-
427
- <script setup lang="ts">
428
- import { UI_I_HTMLSelectElement } from '~/models/interfaces'
429
- import { itemsPerPage } from '~/components/atoms/table/dataGrid/config/itemsPerPage'
430
- import {
431
- UI_I_HeadItem,
432
- UI_I_BodyItem,
433
- UI_I_ColumnKey,
434
- } from '~/components/atoms/table/dataGrid/models/interfaces'
435
- import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
436
- import {
437
- UI_T_ColumnKeys,
438
- UI_T_DataGridType,
439
- UI_T_SelectedRow,
440
- } from '~/components/atoms/table/dataGrid/models/types'
441
-
442
- const props = withDefaults(
443
- defineProps<{
444
- headItems: UI_I_HeadItem[]
445
- bodyItems: UI_I_BodyItem[][]
446
- pageSize: number
447
- page: number
448
- totalItems: number
449
- totalPages: number
450
- loading?: boolean
451
- columnKeys?: UI_I_ColumnKey[]
452
- selectedRow?: UI_T_SelectedRow
453
- type?: UI_T_DataGridType
454
- itemsPerPage?: UI_I_OptionItem[]
455
- offSelectByRow?: boolean
456
- hidePageSize?: boolean
457
- showPageInfo?: boolean
458
- serverOff?: boolean
459
- fillWidth?: boolean
460
- hideFooter?: boolean
461
- hidePagination?: boolean
462
- testId?: string
463
- withInfo?: boolean
464
- rowAttributeIdName?: string
465
- }>(),
466
- {
467
- columnKeys: undefined,
468
- selectedRow: undefined,
469
- type: undefined,
470
- itemsPerPage: undefined,
471
- fillWidth: true,
472
- testId: 'ui-data-grid',
473
- withInfo: false,
474
- rowAttributeIdName: 'data-id',
475
- }
476
- )
477
-
478
- const emits = defineEmits<{
479
- (event: 'update:column-keys', value: UI_T_ColumnKeys): void
480
- (event: 'update:selected-row', value: UI_T_SelectedRow): void
481
- (event: 'update:page-size', value: number): void
482
- (event: 'update:page', value: number): void
483
- (event: 'filtering', value: string[][]): void
484
- (event: 'sorting', value: [string, boolean]): void
485
- (event: 'change', value: any): void
486
- (event: 'row-detail', value: number): void
487
- }>()
488
-
489
- const mergeOptions = computed<UI_I_OptionItem[]>(
490
- () => props.itemsPerPage || itemsPerPage
491
- )
492
-
493
- const inputId = ref<string>(`radio-input-${useUniqueId()}`)
494
-
495
- const columnKeysLocal = computed<UI_T_ColumnKeys>({
496
- get() {
497
- return props.columnKeys
498
- },
499
- set(newValue) {
500
- emits('update:column-keys', newValue)
501
- },
502
- })
503
-
504
- const selectedAll = ref<boolean>(false)
505
- const changeAll = (e: UI_I_HTMLSelectElement): void => {
506
- const newSelectedRow: (number | string)[] = []
507
- if (e.target.checked) {
508
- bodyItemsPresent.value.forEach((row) => {
509
- newSelectedRow.push(row[0].id)
510
- })
511
- }
512
-
513
- emits('update:selected-row', newSelectedRow)
514
- }
515
-
516
- const selectedRowLocal = ref<UI_T_SelectedRow>([])
517
- const isShowHiddenInfo = ref<boolean>(false)
518
- const tableWrapperId = `table-wrapper-${useUniqueId()}`
519
- let memoryWidth = '0'
520
-
521
- const showedInfoRow = ref<UI_I_BodyItem | null>(null)
522
- const showedInfoCol = ref<UI_I_BodyItem[] | null>(null)
523
-
524
- const isShowInfo = computed(
525
- () =>
526
- showedInfoRow.value &&
527
- showedInfoRow.value.id === props.selectedRow &&
528
- !showedInfoRow.value.data?.text &&
529
- isShowHiddenInfo.value
530
- )
531
-
532
- const setShowedInfoData = (
533
- item: UI_I_BodyItem | null,
534
- items: UI_I_BodyItem[] | null,
535
- reset: boolean = false
536
- ): void => {
537
- showedInfoRow.value = item
538
- showedInfoCol.value = items
539
-
540
- reset && (isShowHiddenInfo.value = false)
541
- item && selectRowById(item.id)
542
- reset && (isShowHiddenInfo.value = true)
543
- }
544
-
545
- const doubleArrowClick = (
546
- item: UI_I_BodyItem,
547
- items: UI_I_BodyItem[]
548
- ): void => {
549
- if (!isShowHiddenInfo.value) {
550
- setShowedInfoData(item, items)
551
- } else {
552
- if (showedInfoRow.value?.id !== item.id) {
553
- setShowedInfoData(item, items, true)
554
-
555
- return
556
- } else {
557
- setShowedInfoData(null, null)
558
- }
559
- }
560
-
561
- isShowHiddenInfo.value = !isShowHiddenInfo.value
562
- }
563
-
564
- watch(
565
- () => props.selectedRow,
566
- (newValue) => {
567
- if (newValue === undefined) return
568
-
569
- if (Array.isArray(newValue) && !newValue.length) selectedAll.value = false
570
-
571
- selectedRowLocal.value = newValue
572
- },
573
- { immediate: true }
574
- )
575
- const selectRowById = (id: number | string): void => {
576
- if (props.offSelectByRow || isShowHiddenInfo.value) return
577
-
578
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
579
- const has = selectedRowLocal.value.includes(id)
580
- if (has) {
581
- selectedRowLocal.value = selectedRowLocal.value.filter(
582
- (rowId: string | number) => rowId !== id
583
- )
584
- } else {
585
- selectedRowLocal.value.push(id)
586
- }
587
-
588
- emits('change', selectedRowLocal.value)
589
- emits('update:selected-row', selectedRowLocal.value)
590
-
591
- changeSelectedAll(!has)
592
- return
593
- }
594
-
595
- emits('change', id)
596
- emits('update:selected-row', id)
597
- }
598
- const changeSelectedRow = (
599
- e: UI_I_HTMLSelectElement,
600
- id: number | string
601
- ): void => {
602
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
603
- const newSelectedRow = [...selectedRowLocal.value]
604
- emits('change', newSelectedRow)
605
- emits('update:selected-row', newSelectedRow)
606
-
607
- changeSelectedAll(e.target.checked)
608
- return
609
- }
610
-
611
- emits('change', id)
612
- emits('update:selected-row', id)
613
- }
614
- const changeSelectedAll = (checked: boolean): void => {
615
- if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
616
- const newSelectedRow = [...selectedRowLocal.value]
617
-
618
- if (!checked) {
619
- selectedAll.value = false
620
- } else if (newSelectedRow.length === bodyItemsPresent.value.length) {
621
- selectedAll.value = true
622
- }
623
- }
624
- }
625
-
626
- const checkIsSelectedRow = (id: number | string): boolean => {
627
- if (props.type === 'checkbox' && Array.isArray(props.selectedRow)) {
628
- return props.selectedRow.includes(id)
629
- }
630
- return props.selectedRow === id
631
- }
632
-
633
- // Sorting
634
- const sortInfo = ref<[string, boolean]>(['', true])
635
- const sortedColumnIndex = computed<number>(() => {
636
- let index = -1
637
- headItemsPresent.value.forEach((item, key) => {
638
- if (item.sortColumn === sortInfo.value[0]) index = key
639
- })
640
-
641
- return index
642
- })
643
- const sortTable = (sortName: string): void => {
644
- if (!sortName) return
645
-
646
- emits('update:selected-row', selectedRowLocal.value)
647
-
648
- if (sortInfo.value[0] === sortName) {
649
- sortInfo.value[1] = !sortInfo.value[1]
650
-
651
- emits('sorting', sortInfo.value)
652
- return
653
- }
654
- sortInfo.value[0] = sortName
655
- sortInfo.value[1] = true
656
-
657
- emits('sorting', sortInfo.value)
658
- }
659
-
660
- // Filtering
661
- const filterShow = ref<boolean[]>([])
662
- const filterTerm = ref<string[]>([])
663
- const filtering = (): void => {
664
- const filter: string[][] = []
665
- headItemsPresent.value.forEach((item, key) => {
666
- if (filterTerm.value[key]) filter.push([item.key, filterTerm.value[key]])
667
- })
668
-
669
- emits('filtering', filter)
670
- }
671
-
672
- // Pagination
673
- const changePageSize = (value: number): void => {
674
- emits('update:page-size', value)
675
- }
676
- const changePage = (value: number): void => {
677
- emits('update:page', value)
678
- }
679
-
680
- const headItemsPresent = computed<UI_I_HeadItem[]>(() => {
681
- if (!columnKeysLocal.value) {
682
- return props.headItems
683
- }
684
-
685
- return props.headItems.filter((item, key) => {
686
- return columnKeysLocal.value?.find(
687
- (item2, key2) => item2.key === item.key && key === key2
688
- )?.show
689
- })
690
- })
691
-
692
- const bodyItemsPresent = computed<UI_I_BodyItem[][]>(() => {
693
- let items: UI_I_BodyItem[][] = props.bodyItems
694
-
695
- // Filtering by column
696
- if (columnKeysLocal.value) {
697
- items = items.map((arr) => {
698
- arr = arr.filter((item, key) => {
699
- return columnKeysLocal.value?.find(
700
- (item2, key2) => item2.key === item.key && key === key2
701
- )?.show
702
- })
703
- return arr
704
- })
705
- }
706
-
707
- if (props.serverOff) {
708
- // Sorting
709
- if (sortInfo.value[0] !== '') {
710
- items = useDeepCopy(items).sort(
711
- (a: UI_I_BodyItem[], b: UI_I_BodyItem[]) => {
712
- const first = a[sortedColumnIndex.value].text.toString().toLowerCase()
713
- const second = b[sortedColumnIndex.value].text
714
- .toString()
715
- .toLowerCase()
716
-
717
- if (sortInfo.value[1]) {
718
- return first > second ? 1 : first < second ? -1 : 0
719
- } else {
720
- return first < second ? 1 : first > second ? -1 : 0
721
- }
722
- }
723
- )
724
- }
725
- // Filtering
726
- const hasFilter = headItemsPresent.value.some(
727
- (_, key) => filterTerm.value[key]
728
- )
729
- if (hasFilter) {
730
- items = items.filter((row) => {
731
- // 0 - начальное значение
732
- // 1 - найден элемент
733
- // -1 - ненайден элемент
734
- let hasItem = 0
735
- headItemsPresent.value.forEach((item, key) => {
736
- if (!filterTerm.value[key]) return
737
- const term = filterTerm.value[key].toLowerCase()
738
-
739
- row.forEach((col) => {
740
- if (
741
- col.key === item.key &&
742
- typeof col.text === 'string' &&
743
- hasItem != -1
744
- ) {
745
- hasItem = col.text.toLowerCase().includes(term) ? 1 : -1
746
- }
747
- })
748
- })
749
-
750
- return hasItem === 1
751
- })
752
- }
753
- }
754
-
755
- return items
756
- })
757
-
758
- const toggedItems = ref<boolean[]>([])
759
-
760
- const toggle = (key: number): void => {
761
- toggedItems.value[key] = !toggedItems.value[key]
762
- if (!toggedItems.value[key]) return
763
- emits('row-detail', key)
764
- }
765
-
766
- const outerWrapper = `datagrid-outer-wrapper${useUniqueId()}`
767
- const expandableCaret = `datagrid-expandable-caret${useUniqueId()}`
768
-
769
- // Resize
770
- let helper = false
771
- let setColumnWidth = (): void => {
772
- if (!helper) {
773
- columnsWidth.value = []
774
- headItemsPresent.value.forEach((item) => {
775
- columnsWidth.value.push([
776
- item.width, // width
777
- item.width, // min-width
778
- ])
779
- })
780
-
781
- helper = true
782
- setTimeout(() => setColumnWidth(), 0)
783
- return
784
- }
785
- // Не продолжаем, чтобы ширина калонок была так как заданно в headItemsPresent
786
- if (!props.fillWidth) return
787
-
788
- const dataGridWidth = document.getElementById(outerWrapper)?.clientWidth || 0
789
- const leftColumnWidth =
790
- document.getElementById(expandableCaret)?.clientWidth || 0
791
- const bordersWidth = 2
792
- const columnWidth =
793
- (dataGridWidth - leftColumnWidth - bordersWidth) /
794
- headItemsPresent.value.length
795
-
796
- headItemsPresent.value.forEach((item) => {
797
- columnsWidth.value.push([
798
- `${columnWidth}px`, // width
799
- item.width, // min-width
800
- ])
801
- })
802
- }
803
- setColumnWidth = useThrottle(setColumnWidth)
804
-
805
- const columnsWidth = ref<[string, string][]>([])
806
- watch(
807
- bodyItemsPresent,
808
- (newValue: UI_I_BodyItem[][]) => {
809
- newValue.forEach(() => {
810
- toggedItems.value.push(false)
811
- })
812
- setColumnWidth()
813
- },
814
- {
815
- immediate: true,
816
- deep: true,
817
- }
818
- )
819
-
820
- watch(
821
- headItemsPresent,
822
- (newValue: UI_I_HeadItem[]) => {
823
- filterShow.value = newValue.map(() => false)
824
- filterTerm.value = newValue.map(() => '')
825
- },
826
- {
827
- immediate: true,
828
- deep: true,
829
- }
830
- )
831
-
832
- const grabColumn = ref<number>(-1)
833
- const grabStartX = ref<number>(0)
834
- const setGrab = (key: number, e: MouseEvent): void => {
835
- if (props.withInfo && key === 0) return
836
-
837
- if (!isShowHiddenInfo.value) {
838
- grabColumn.value = key
839
- const currentWidth = parseInt(columnsWidth.value[grabColumn.value][0])
840
- grabStartX.value = e.clientX - currentWidth
841
- }
842
- }
843
-
844
- const isDrag = ref<boolean>(false)
845
-
846
- const mouseup = (): void => {
847
- if (grabColumn.value === -1) {
848
- return
849
- }
850
-
851
- grabColumn.value = -1
852
- isDrag.value = false
853
- }
854
-
855
- let resizeObserve: ResizeObserver
856
- let mousemove = (e: MouseEvent): void => {
857
- if (grabColumn.value === -1) return
858
-
859
- e.preventDefault()
860
- isDrag.value = true
861
- resizeObserve.disconnect()
862
-
863
- const minWidth = parseInt(columnsWidth.value[grabColumn.value][1])
864
- const changeX = Math.max(e.clientX - grabStartX.value, minWidth)
865
-
866
- columnsWidth.value[grabColumn.value] = [`${changeX}px`, `${minWidth}px`]
867
- }
868
- mousemove = useThrottle(mousemove)
869
-
870
- const setResizeObserve = (): void => {
871
- const el = document.getElementById(outerWrapper)
872
-
873
- if (!el) {
874
- setTimeout(setResizeObserve, 0)
875
- return
876
- }
877
-
878
- resizeObserve = new ResizeObserver(setColumnWidth)
879
- resizeObserve.observe(el)
880
- }
881
-
882
- let resizeObserveWithInfo: ResizeObserver
883
-
884
- const setColumnWidthWithInfo = (ent: ResizeObserverEntry[]): void => {
885
- if (isShowHiddenInfo.value) {
886
- memoryWidth = columnsWidth.value[1][0]
887
- columnsWidth.value[1][0] = `${ent[0].contentBoxSize[0].inlineSize - 86}px`
888
- } else {
889
- columnsWidth.value[1][0] = memoryWidth
890
- }
891
- }
892
-
893
- const setResizeObserveWithInfo = (): void => {
894
- const el = document.querySelector('.datagrid')
895
-
896
- if (!el) {
897
- setTimeout(setResizeObserveWithInfo, 0)
898
- return
899
- }
900
-
901
- resizeObserveWithInfo = new ResizeObserver(setColumnWidthWithInfo)
902
- resizeObserveWithInfo.observe(el)
903
- }
904
-
905
- onMounted(() => {
906
- window.addEventListener('mousemove', mousemove)
907
- window.addEventListener('mouseup', mouseup)
908
-
909
- if (props.withInfo) {
910
- setResizeObserveWithInfo()
911
- }
912
-
913
- setResizeObserve()
914
- })
915
- onUnmounted(() => {
916
- window.removeEventListener('mouseup', mouseup)
917
- window.removeEventListener('mousemove', mousemove)
918
- })
919
- </script>
920
-
921
- <style scoped lang="scss">
922
- @import '~/assets/scss/common/mixins';
923
- .datagrid-outer-wrapper {
924
- @include flex($dir: row);
925
- padding-top: 12px;
926
- flex-grow: 1;
927
- overflow: auto;
928
-
929
- &.datagrid-outer-wrapper-opened-info {
930
- width: 35%;
931
- min-width: 195px;
932
- }
933
-
934
- & * {
935
- box-sizing: border-box;
936
- }
937
-
938
- & svg {
939
- fill: var(--table-color);
940
- }
941
-
942
- .datagrid-inner-wrapper {
943
- @include flex($dir: column);
944
- flex-grow: 1;
945
- overflow: auto;
946
-
947
- .datagrid {
948
- overflow: auto;
949
- flex: 1 1 auto;
950
- border-radius: 0.125rem 0.125rem 0 0;
951
- background-color: var(--block-view-bg-color);
952
- border-color: var(--global-border-color);
953
-
954
- &.datagrid-opened-info {
955
- border-radius: 0.125rem 0 0 0;
956
- overflow-x: hidden;
957
- }
958
-
959
- .datagrid-table-wrapper {
960
- min-width: max-content;
961
- display: flex;
962
- flex: 1 1 auto;
963
- min-height: 100%;
964
-
965
- .datagrid-table {
966
- @include flex($dir: column);
967
- flex: 1 1 auto;
968
- align-content: flex-start;
969
- position: relative;
970
-
971
- .datagrid-header {
972
- position: sticky;
973
- top: 0;
974
- z-index: 501;
975
- width: auto;
976
-
977
- .datagrid-row-scrollable {
978
- flex-direction: row;
979
-
980
- .datagrid-column-separator {
981
- user-select: none;
982
-
983
- &::after {
984
- cursor: col-resize;
985
- }
986
- &.double-arrow-separator .datagrid-column-handle {
987
- cursor: unset;
988
- }
989
- &.double-arrow-separator::after {
990
- cursor: unset;
991
- }
992
- }
993
- }
994
-
995
- .datagrid-row {
996
- color: var(--table-color);
997
- background-color: var(--block-view-bg-color);
998
-
999
- &.datagrid-selected {
1000
- background-color: var(--row-selected-bg-color);
1001
- border-bottom: 1px solid var(--global-border-color);
1002
-
1003
- & :deep(*) {
1004
- color: var(--table-active-color);
1005
- }
1006
- }
1007
-
1008
- .datagrid-column {
1009
- background-color: var(--block-view-bg-color);
1010
- border-bottom: 1px solid var(--global-border-color);
1011
- padding: 6px 12px 5px;
1012
- position: relative;
1013
- //flex: 1 1 auto;
1014
-
1015
- &:last-child {
1016
- flex: 1 1 auto;
1017
- }
1018
-
1019
- &.datagrid-toggle-block {
1020
- width: 38px;
1021
- min-width: 38px;
1022
-
1023
- .datagrid-column-separator {
1024
- cursor: default;
1025
-
1026
- &::after {
1027
- cursor: default;
1028
- }
1029
- }
1030
- }
1031
- }
1032
-
1033
- .datagrid-column-title {
1034
- align-self: auto;
1035
- color: var(--table-color);
1036
- background-color: var(--block-view-bg-color);
1037
- border-bottom-color: var(--global-border-color);
1038
- font-size: 11px;
1039
- @include flex($align: center);
1040
- display: flex;
1041
- flex-direction: row;
1042
- justify-content: flex-start;
1043
- align-items: center;
1044
- //line-height: 24px;
1045
- line-height: normal;
1046
-
1047
- .title-column {
1048
- font-weight: bold;
1049
- font-size: 11px;
1050
- overflow: hidden;
1051
- text-wrap: none;
1052
- text-overflow: ellipsis;
1053
- }
1054
-
1055
- .sort-arrow-wrap {
1056
- margin-left: auto;
1057
- height: 14px;
1058
- width: 14px;
1059
- min-height: 14px;
1060
- min-width: 14px;
1061
- vertical-align: middle;
1062
-
1063
- .sort-arrow {
1064
- &.down {
1065
- transform: rotate(180deg);
1066
- }
1067
- }
1068
- }
1069
- .title-icon {
1070
- width: 24px;
1071
- height: 24px;
1072
- }
1073
- }
1074
-
1075
- .datagrid-filter-toggle {
1076
- background: unset;
1077
- margin-top: -4px;
1078
- align-self: center;
1079
-
1080
- .filter-icon {
1081
- width: 16px;
1082
- height: 16px;
1083
- }
1084
- }
1085
- }
1086
- }
1087
-
1088
- .datagrid-placeholder-container {
1089
- .datagrid-placeholder.datagrid-empty {
1090
- background: var(--block-view-bg-color);
1091
- }
1092
- span {
1093
- font-size: 16px;
1094
- color: var(--global-font-color4);
1095
- }
1096
- }
1097
-
1098
- .datagrid-row {
1099
- width: 100%;
1100
- min-width: max-content;
1101
- border-top: none;
1102
- color: var(--table-color);
1103
- background-color: var(--block-view-bg-color);
1104
- border-bottom: 1px solid var(--global-border-color);
1105
-
1106
- &.datagrid-selected {
1107
- & :deep(*) {
1108
- color: var(--table-active-color);
1109
- }
1110
-
1111
- .datagrid-cell {
1112
- background-color: var(--row-selected-bg-color);
1113
- border-bottom: 1px solid var(--global-border-color);
1114
- position: relative;
1115
- line-height: 1rem;
1116
- }
1117
-
1118
- .datagrid-row-detail {
1119
- background-color: var(--row-selected-bg-color);
1120
- border-bottom: 1px solid var(--global-border-color);
1121
- }
1122
- }
1123
-
1124
- .datagrid-cell {
1125
- min-width: 38px;
1126
- min-height: 28px;
1127
- padding: 2px 12px 3px 12px;
1128
- position: relative;
1129
-
1130
- &:has(.double-arrow-wrap) {
1131
- padding-left: 4px;
1132
- }
1133
-
1134
- &:has(.double-arrow-wrap)::after {
1135
- content: '';
1136
- width: 0.5px;
1137
- height: calc(100% - 6px);
1138
- position: absolute;
1139
- right: 2px;
1140
- top: 3px;
1141
- background-color: var(--global-border-color);
1142
- }
1143
-
1144
- &:last-child {
1145
- flex: 1 1 auto;
1146
- }
1147
-
1148
- button {
1149
- height: 0.9rem;
1150
- width: 0.9rem;
1151
-
1152
- .arrow-icon {
1153
- width: 16px;
1154
- height: 16px;
1155
- transform: rotate(90deg);
1156
- }
1157
- }
1158
-
1159
- .datagrid-cell-icon {
1160
- display: inline-block;
1161
- width: 16px;
1162
- height: 16px;
1163
- }
1164
-
1165
- .datagrid-expandable-caret-button {
1166
- cursor: pointer;
1167
- width: 100%;
1168
-
1169
- .datagrid-expandable-caret-icon {
1170
- width: 16px;
1171
- height: 16px;
1172
- transform: rotate(90deg);
1173
- fill: var(--table-caret-color);
1174
-
1175
- &.toggle {
1176
- transform: rotate(180deg);
1177
- }
1178
- }
1179
- }
1180
- }
1181
-
1182
- &.datagrid-selected-info {
1183
- width: 100%;
1184
- min-width: max-content;
1185
- border-top: none;
1186
- color: var(--table-color);
1187
- background-color: var(--block-view-bg-color);
1188
-
1189
- .datagrid-cell {
1190
- position: relative;
1191
-
1192
- &.hidden-text-triangle::after {
1193
- content: '';
1194
- position: absolute;
1195
- transform: rotate(225deg);
1196
- border-bottom: 15px solid transparent;
1197
- border-right: 15px solid var(--global-bg-color);
1198
- bottom: 26%;
1199
- right: -16px;
1200
- z-index: 1000;
1201
- }
1202
-
1203
- &.hidden-text-triangle::before {
1204
- content: '';
1205
- transform: rotate(-135deg);
1206
- position: absolute;
1207
- border-bottom: 16px solid transparent;
1208
- border-right: 16px solid var(--global-border-color);
1209
- bottom: 23%;
1210
- right: -17px;
1211
- z-index: 999;
1212
- }
1213
- }
1214
- }
1215
- }
1216
-
1217
- .datagrid-row-sticky {
1218
- @include flex($w: nowrap);
1219
- position: sticky;
1220
- left: 0;
1221
- z-index: 500;
1222
- background-color: var(--block-view-bg-color);
1223
-
1224
- .datagrid-column {
1225
- color: var(--table-color);
1226
- background-color: var(--block-view-bg-color);
1227
- border-bottom-color: var(--global-border-color);
1228
- text-align: left;
1229
- display: flex;
1230
- flex: 1 1 auto;
1231
- vertical-align: top;
1232
- border: none;
1233
-
1234
- &.datagrid-expandable-caret {
1235
- .datagrid-column-separator {
1236
- display: block;
1237
-
1238
- &::after {
1239
- top: 0;
1240
- height: 18px;
1241
- }
1242
- }
1243
-
1244
- .radio-btn {
1245
- width: 16px;
1246
- height: 16px;
1247
- }
1248
- }
1249
-
1250
- .datagrid-column-separator {
1251
- position: relative;
1252
- //left: 0.6rem;
1253
- flex: 0 0 auto;
1254
- width: 0.05rem;
1255
- order: 100;
1256
- margin-left: auto;
1257
- height: 100%;
1258
- }
1259
- }
1260
-
1261
- .datagrid-fixed-column-without-separator {
1262
- background-color: var(--block-view-bg-color);
1263
-
1264
- &::after {
1265
- background-color: transparent;
1266
- }
1267
- }
1268
-
1269
- .datagrid-fixed-column {
1270
- background-color: var(--block-view-bg-color);
1271
-
1272
- &::after {
1273
- content: '';
1274
- width: 0.05rem;
1275
- height: calc(100% - 0.5rem);
1276
- position: absolute;
1277
- right: 0;
1278
- top: 0.25rem;
1279
- background-color: var(--global-border-color);
1280
- }
1281
- }
1282
- }
1283
-
1284
- .datagrid-row-scrollable {
1285
- @include flex($ff: row nowrap);
1286
- flex: 1 1 auto;
1287
-
1288
- .datagrid-scrolling-cells {
1289
- @include flex($ff: row nowrap);
1290
- flex: 1 1 auto;
1291
- }
1292
- }
1293
- .datagrid-body-row {
1294
- .datagrid-row-scrollable {
1295
- @include flex($ff: column nowrap);
1296
-
1297
- .datagrid-row-detail {
1298
- flex: 1;
1299
- }
1300
- }
1301
-
1302
- &:not(.datagrid-selected):hover {
1303
- border-bottom: 1px solid var(--table-hover-row-border-color);
1304
- background-color: var(--table-hover-row-background-color);
1305
- color: var(--table-hover-row-color);
1306
-
1307
- .datagrid-fixed-column {
1308
- background-color: var(--table-hover-row-background-color);
1309
- }
1310
- .datagrid-cell {
1311
- background-color: var(--table-hover-row-background-color);
1312
- }
1313
- }
1314
- }
1315
- }
1316
- }
1317
- }
1318
-
1319
- .datagrid-footer {
1320
- flex: 0 0 auto;
1321
- @include flex($ff: row nowrap, $just: space-between, $align: stretch);
1322
- font-size: 0.55rem;
1323
- background-color: var(--block-view-bg-color);
1324
- border: 0.05rem solid var(--global-border-color);
1325
- border-top: none;
1326
- border-radius: 0 0 0.15rem 0.15rem;
1327
- padding: 0 0.6rem;
1328
- height: 28px;
1329
-
1330
- &.datagrid-footer-opened-info {
1331
- border-radius: 0 0 0 0.15rem;
1332
- flex-direction: row-reverse;
1333
- }
1334
-
1335
- .clr-form-control-disabled {
1336
- opacity: 1;
1337
-
1338
- .clr-checkbox-wrapper {
1339
- label {
1340
- color: #8c8c8c;
1341
- margin-right: 9px;
1342
- padding-left: 22px;
1343
-
1344
- &:before {
1345
- position: absolute;
1346
- top: 4px;
1347
- left: 0;
1348
- content: '';
1349
- display: inline-block;
1350
- height: 16px;
1351
- width: 16px;
1352
- border: none;
1353
- border-radius: 3px;
1354
- background-color: var(--table-checkbox-color);
1355
- }
1356
-
1357
- &:after {
1358
- position: absolute;
1359
- content: '';
1360
- display: inline-block;
1361
- height: 5px;
1362
- width: 8px;
1363
- border-left: 2px solid #fff;
1364
- border-bottom: 2px solid #fff;
1365
- top: 4px;
1366
- left: 4px;
1367
- transform: translateY(4px) rotate(-45deg);
1368
- }
1369
- }
1370
- }
1371
- }
1372
- }
1373
-
1374
- .datagrid-spinner {
1375
- top: 0.6rem;
1376
- height: calc(100% - 0.6rem);
1377
- }
1378
-
1379
- .datagrid-footer-description {
1380
- flex: 1 1 auto;
1381
-
1382
- :deep(svg) {
1383
- fill: var(--table-switch-color);
1384
- }
1385
- }
1386
-
1387
- .clr-radio-wrapper,
1388
- .clr-checkbox-wrapper {
1389
- height: 18px;
1390
- }
1391
-
1392
- .clr-radio-wrapper label,
1393
- .clr-checkbox-wrapper label {
1394
- padding-left: 16px;
1395
- }
1396
- }
1397
- }
1398
- //.vertical-divider {
1399
- // width: 1px;
1400
- // height: 22px;
1401
- // background: #bbb;
1402
- // margin: 2px 2px 0 -5px;
1403
- //}
1404
-
1405
- .hidden-features {
1406
- padding: 9px 14px;
1407
- background-color: var(--global-bg-color);
1408
- color: var(--global-font-color2);
1409
- border: 1px solid var(--global-border-color);
1410
- border-left: none;
1411
- overflow-y: auto;
1412
- overflow-x: hidden;
1413
- width: 65%;
1414
-
1415
- .header {
1416
- display: flex;
1417
- align-items: center;
1418
- justify-content: space-between;
1419
- background-color: inherit;
1420
-
1421
- h3 {
1422
- font-size: 1rem;
1423
- color: var(--global-font-color2) !important;
1424
- line-height: 1.7rem;
1425
- }
1426
- button {
1427
- line-height: 24px;
1428
-
1429
- .close-icon {
1430
- margin-left: 10px;
1431
- width: 24px;
1432
- height: 24px;
1433
- }
1434
- }
1435
- }
1436
- }
1437
- .double-arrow-width {
1438
- width: 25px;
1439
- }
1440
- .double-arrow-wrap {
1441
- width: 30px;
1442
- height: 20px;
1443
- padding-top: 1px;
1444
- padding-left: 5px;
1445
- cursor: pointer;
1446
- background-color: transparent;
1447
-
1448
- .double-arrow {
1449
- background-color: transparent;
1450
- transform: rotate(90deg);
1451
- width: 16px;
1452
- height: 16px;
1453
- }
1454
-
1455
- .double-arrow.arrow-selected {
1456
- transform: rotate(-90deg) !important;
1457
- background-color: #0079b8;
1458
- }
1459
- }
1460
- .double-arrow-wrap.arrow-selected {
1461
- background-color: #0079b8;
1462
- border-radius: 3px;
1463
- }
1464
- </style>
1465
-
1466
- <style>
1467
- :root {
1468
- --table-color: #565656;
1469
- --table-active-color: #fff;
1470
- --table-checkbox-color: #454545;
1471
- --table-caret-color: #454545;
1472
- --table-switch-color: #575757;
1473
- --table-hover-row-border-color: #666;
1474
- --table-hover-row-background-color: #e8e8e8;
1475
- --table-hover-row-color: #454545;
1476
- --table-spinner-bg-color: #ffffff99;
1477
- }
1478
-
1479
- :root.dark-theme {
1480
- --table-color: #fff;
1481
- --table-active-color: #565656;
1482
- --table-checkbox-color: #49aeda;
1483
- --table-caret-color: #ffffff;
1484
- --table-switch-color: #b3b3b3;
1485
- --table-hover-row-border-color: #fff;
1486
- --table-hover-row-background-color: #324f61;
1487
- --table-hover-row-color: #e9ecef;
1488
- --table-spinner-bg-color: rgba(0, 0, 0, 0.5);
1489
- }
1490
- </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
+ :class="[
15
+ 'datagrid',
16
+ {
17
+ 'datagrid-opened-info': isShowHiddenInfo,
18
+ },
19
+ ]"
20
+ >
21
+ <div :id="tableWrapperId" class="datagrid-table-wrapper">
22
+ <div class="datagrid-table">
23
+ <div class="datagrid-header">
24
+ <div class="datagrid-row">
25
+ <div class="datagrid-row-master datagrid-row-flex">
26
+ <div v-if="props.type" class="datagrid-row-sticky">
27
+ <div
28
+ :id="expandableCaret"
29
+ class="datagrid-column datagrid-expandable-caret datagrid-fixed-column flex-align-center flex-justify-center"
30
+ >
31
+ <template v-if="props.type === 'checkbox'">
32
+ <div
33
+ class="clr-checkbox-wrapper flex-align-center flex-justify-center w-100"
34
+ >
35
+ <input
36
+ :id="`${props.testId}-${inputId}-all`"
37
+ v-model="selectedAll"
38
+ type="checkbox"
39
+ class="checkbox-btn"
40
+ :value="-1"
41
+ @change="changeAll"
42
+ />
43
+ <label
44
+ :for="`${props.testId}-${inputId}-all`"
45
+ class="clr-control-label"
46
+ />
47
+ </div>
48
+ <div class="datagrid-column-separator"></div>
49
+ </template>
50
+ </div>
51
+ <div
52
+ v-if="$slots.toggleBlock"
53
+ class="datagrid-toggle-block datagrid-column datagrid-fixed-width"
54
+ >
55
+ <div class="datagrid-column-flex">
56
+ <div class="datagrid-column-separator">
57
+ <span class="clr-sr-only" />
58
+ <div class="datagrid-column-resize-tracker" />
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ <div class="datagrid-row-scrollable">
64
+ <div
65
+ v-for="(item, key) in headItemsPresent"
66
+ :key="key"
67
+ :style="{
68
+ width: columnsWidth[key][0],
69
+ minWidth: columnsWidth[key][1],
70
+ }"
71
+ class="datagrid-column datagrid-fixed-width"
72
+ >
73
+ <div class="datagrid-column-flex">
74
+ <button
75
+ :id="`${props.testId}-sort-column-${key}`"
76
+ :class="[
77
+ 'datagrid-column-title',
78
+ {
79
+ 'default text-decoration-none':
80
+ !item.sortColumn,
81
+ },
82
+ ]"
83
+ @click="sortTable(item.sortColumn)"
84
+ >
85
+ <slot :key="key" name="th" :item="item">
86
+ <span
87
+ :title="item.text"
88
+ :style="{
89
+ width:
90
+ columnsWidth[key][0]?.slice(0, -2) -
91
+ (item.hasFilter ? 65 : 40) +
92
+ 'px',
93
+ }"
94
+ class="title-column"
95
+ >
96
+ {{ item.text }}
97
+ </span>
98
+ </slot>
99
+ <span
100
+ v-if="item.sortColumn"
101
+ class="sort-arrow-wrap"
102
+ >
103
+ <atoms-the-icon
104
+ v-show="sortInfo[0] === item.sortColumn"
105
+ :class="['sort-arrow', { down: sortInfo[1] }]"
106
+ name="sort-arrow"
107
+ />
108
+ </span>
109
+ </button>
110
+ <button
111
+ v-if="item.hasFilter"
112
+ :id="`${props.testId}-filter-icon-${key}`"
113
+ class="datagrid-filter-toggle clr-anchor clr-smart-open-close"
114
+ @click="filterShow[key] = !filterShow[key]"
115
+ >
116
+ <atoms-the-icon
117
+ v-if="filterTerm[key]"
118
+ class="filter-icon"
119
+ name="filter-solid"
120
+ style="fill: #0079b8"
121
+ />
122
+ <atoms-the-icon
123
+ v-else
124
+ class="filter-icon"
125
+ name="filter"
126
+ />
127
+ </button>
128
+ <atoms-popup-simple-popup
129
+ v-model="filterShow[key]"
130
+ :test-id="`${props.testId}-filter`"
131
+ top="100%"
132
+ right="0"
133
+ >
134
+ <input
135
+ :id="`${props.testId}-filter-input-${key}`"
136
+ v-model="filterTerm[key]"
137
+ type="text"
138
+ @input="filtering"
139
+ />
140
+ </atoms-popup-simple-popup>
141
+ <div
142
+ v-show="
143
+ !isShowHiddenInfo ||
144
+ (isShowHiddenInfo && key === 0)
145
+ "
146
+ :class="[
147
+ 'datagrid-column-separator',
148
+ {
149
+ 'double-arrow-separator':
150
+ key === 0 && props.withInfo,
151
+ },
152
+ ]"
153
+ @mousedown="setGrab(key, $event)"
154
+ >
155
+ <button
156
+ :id="`${props.testId}-resize-tracker-${key}`"
157
+ class="datagrid-column-handle drag-handle draggable"
158
+ />
159
+ <span class="clr-sr-only" />
160
+ <div class="datagrid-column-resize-tracker" />
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <template v-if="bodyItemsPresent.length">
170
+ <div
171
+ v-for="(item, key) in bodyItemsPresent"
172
+ :key="item.id"
173
+ :class="[
174
+ 'datagrid-body-row datagrid-row animation',
175
+ {
176
+ 'datagrid-selected active':
177
+ !props.withInfo && checkIsSelectedRow(item[0].id),
178
+ 'datagrid-selected-info':
179
+ props.withInfo &&
180
+ isShowHiddenInfo &&
181
+ checkIsSelectedRow(item[0].id),
182
+ },
183
+ ]"
184
+ :[props.rowAttributeIdName]="item[0].dataId"
185
+ >
186
+ <div>
187
+ <div
188
+ class="datagrid-row-master datagrid-row-flex"
189
+ @click.prevent.stop="selectRowById(item[0].id)"
190
+ >
191
+ <div
192
+ v-if="props.type"
193
+ class="datagrid-row-sticky"
194
+ @click.stop
195
+ >
196
+ <div
197
+ :id="expandableCaret"
198
+ :class="[
199
+ 'datagrid-expandable-caret flex-justify-center datagrid-cell',
200
+ {
201
+ 'datagrid-fixed-column': !props.withInfo,
202
+ 'datagrid-fixed-column-without-separator':
203
+ props.withInfo,
204
+ },
205
+ ]"
206
+ >
207
+ <slot :key="key" name="type" :item="item">
208
+ <div
209
+ :class="`clr-${props.type}-wrapper flex-justify-center flex-align-center`"
210
+ >
211
+ <input
212
+ :id="`${props.testId}-${inputId}-${item[0].id}`"
213
+ v-model="selectedRowLocal"
214
+ :key="item[0].id"
215
+ :type="props.type"
216
+ :class="`${props.type}-btn`"
217
+ :value="item[0].id"
218
+ name="selected-store"
219
+ @change="changeSelectedRow($event, item[0].id)"
220
+ />
221
+ <label
222
+ :for="`${props.testId}-${inputId}-${item[0].id}`"
223
+ class="clr-control-label"
224
+ />
225
+ </div>
226
+ </slot>
227
+ </div>
228
+ <div
229
+ v-if="$slots.toggleBlock"
230
+ class="datagrid-cell datagrid-fixed-width"
231
+ >
232
+ <div class="flex-align-center">
233
+ <button
234
+ :id="`${props.testId}-toggle-icon-${key}`"
235
+ class="datagrid-expandable-caret-button reset-btn"
236
+ @click="toggle(key)"
237
+ >
238
+ <atoms-the-icon
239
+ :class="[
240
+ 'datagrid-expandable-caret-icon',
241
+ { toggle: toggedItems[key] },
242
+ ]"
243
+ name="angle"
244
+ />
245
+ </button>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ <div class="datagrid-row-scrollable">
250
+ <div class="datagrid-scrolling-cells">
251
+ <div
252
+ v-for="(item2, key2) in item"
253
+ v-show="
254
+ !isShowHiddenInfo ||
255
+ item2.key === 'col1' ||
256
+ item2.key === 'icon'
257
+ "
258
+ :key="key2"
259
+ :style="{
260
+ width: columnsWidth[key2][0],
261
+ minWidth: columnsWidth[key2][1],
262
+ }"
263
+ :class="[
264
+ 'datagrid-cell datagrid-fixed-width',
265
+ {
266
+ 'hidden-text-triangle':
267
+ isShowHiddenInfo &&
268
+ item2.data?.name === 'hidden-text-triangle',
269
+ },
270
+ ]"
271
+ >
272
+ <div
273
+ :class="[
274
+ 'flex-align-center h-100',
275
+ {
276
+ 'double-arrow-width':
277
+ item2.data?.name === 'doubleArrows',
278
+ },
279
+ ]"
280
+ >
281
+ <div
282
+ v-if="item2.data?.name === 'doubleArrows'"
283
+ :id="`show-info-${item[1].text}`"
284
+ :class="[
285
+ 'double-arrow-wrap',
286
+ {
287
+ 'arrow-selected':
288
+ isShowHiddenInfo &&
289
+ item2.id === selectedRow,
290
+ },
291
+ ]"
292
+ @click.prevent.stop="
293
+ doubleArrowClick(item2, item)
294
+ "
295
+ >
296
+ <atoms-the-icon
297
+ v-if="item2.data?.name === 'doubleArrows'"
298
+ name="doubleArrows"
299
+ :class="[
300
+ 'double-arrow',
301
+ {
302
+ 'arrow-selected':
303
+ isShowHiddenInfo &&
304
+ item2.id === selectedRow,
305
+ },
306
+ ]"
307
+ />
308
+ </div>
309
+ <span
310
+ v-if="item2.text && item2.data?.iconClassName"
311
+ class="vertical-divider"
312
+ />
313
+ <slot :name="item2.key" :item="item2">
314
+ <span class="text-ellipsis" :title="item2.text"
315
+ >{{ item2.text }}
316
+ </span>
317
+ </slot>
318
+ </div>
319
+ </div>
320
+ </div>
321
+ <div
322
+ v-show="toggedItems[key]"
323
+ class="datagrid-row-flex datagrid-row-detail datagrid-container"
324
+ >
325
+ <slot name="toggleBlock" />
326
+ </div>
327
+ </div>
328
+ </div>
329
+ </div>
330
+ </div>
331
+ </template>
332
+ <template v-else>
333
+ <div class="datagrid-placeholder-container">
334
+ <div class="datagrid-placeholder datagrid-empty">
335
+ <div class="datagrid-placeholder-image"></div>
336
+
337
+ <span>No items found</span>
338
+ </div>
339
+ </div>
340
+ </template>
341
+ </div>
342
+ </div>
343
+ </div>
344
+
345
+ <div
346
+ v-if="!hideFooter"
347
+ :class="[
348
+ 'datagrid-footer',
349
+ {
350
+ 'datagrid-footer-opened-info': isShowHiddenInfo,
351
+ },
352
+ ]"
353
+ >
354
+ <div
355
+ v-if="props.type === 'checkbox' && props.selectedRow?.length"
356
+ class="clr-form-control-disabled"
357
+ >
358
+ <div class="clr-checkbox-wrapper">
359
+ <input
360
+ :id="`${props.testId}-check-all`"
361
+ type="checkbox"
362
+ checked
363
+ />
364
+ <label class="clr-control-label">
365
+ {{ props.selectedRow?.length }}
366
+ </label>
367
+ </div>
368
+ </div>
369
+ <div class="datagrid-footer-description flex-align-center">
370
+ <atoms-table-data-grid-column-switch
371
+ v-if="columnKeysLocal"
372
+ v-model:column-keys="columnKeysLocal"
373
+ :test-id="`${props.testId}-footer-description`"
374
+ class="switch-icon"
375
+ />
376
+
377
+ <div v-if="$slots.action" class="datagrid-footer__action">
378
+ <slot name="action" />
379
+ </div>
380
+ </div>
381
+
382
+ <atoms-table-data-grid-pagination
383
+ test-id="props.testId"
384
+ :page-size="props.pageSize"
385
+ :page="props.page"
386
+ :options="mergeOptions"
387
+ :total-items="props.totalItems"
388
+ :total-pages="props.totalPages"
389
+ :hide-pagination="props.hidePagination"
390
+ :hide-page-size="props.hidePageSize"
391
+ :show-page-info="props.showPageInfo"
392
+ :page-items-count="props.bodyItems.length"
393
+ :is-show-hidden-info="isShowHiddenInfo"
394
+ @change-page-size="changePageSize"
395
+ @change-page="changePage"
396
+ />
397
+ </div>
398
+
399
+ <atoms-loader v-show="props.loading" class="datagrid-spinner" />
400
+ </div>
401
+ </div>
402
+ <div
403
+ v-if="isShowInfo"
404
+ id="hidden-features"
405
+ :class="[
406
+ 'hidden-features',
407
+ {
408
+ 'show-hidden-info': isShowHiddenInfo,
409
+ },
410
+ ]"
411
+ >
412
+ <div class="header">
413
+ <slot name="hiddenInfoHeader" :item="showedInfoCol" />
414
+ <button
415
+ :id="`${props.testId}-hidden-info-toggle-icon-${showedInfoRow?.key}-${showedInfoRow?.data.name}`"
416
+ class="signpost-action close"
417
+ @click="isShowHiddenInfo = false"
418
+ >
419
+ <atoms-the-icon class="close-icon" name="close" />
420
+ </button>
421
+ </div>
422
+ <slot name="hiddenInfoBody" />
423
+ </div>
424
+ </div>
425
+ </template>
426
+
427
+ <script setup lang="ts">
428
+ import { UI_I_HTMLSelectElement } from '~/models/interfaces'
429
+ import { itemsPerPage } from '~/components/atoms/table/dataGrid/config/itemsPerPage'
430
+ import {
431
+ UI_I_HeadItem,
432
+ UI_I_BodyItem,
433
+ UI_I_ColumnKey,
434
+ } from '~/components/atoms/table/dataGrid/models/interfaces'
435
+ import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
436
+ import {
437
+ UI_T_ColumnKeys,
438
+ UI_T_DataGridType,
439
+ UI_T_SelectedRow,
440
+ } from '~/components/atoms/table/dataGrid/models/types'
441
+
442
+ const props = withDefaults(
443
+ defineProps<{
444
+ headItems: UI_I_HeadItem[]
445
+ bodyItems: UI_I_BodyItem[][]
446
+ pageSize: number
447
+ page: number
448
+ totalItems: number
449
+ totalPages: number
450
+ loading?: boolean
451
+ columnKeys?: UI_I_ColumnKey[]
452
+ selectedRow?: UI_T_SelectedRow
453
+ type?: UI_T_DataGridType
454
+ itemsPerPage?: UI_I_OptionItem[]
455
+ offSelectByRow?: boolean
456
+ hidePageSize?: boolean
457
+ showPageInfo?: boolean
458
+ serverOff?: boolean
459
+ fillWidth?: boolean
460
+ hideFooter?: boolean
461
+ hidePagination?: boolean
462
+ testId?: string
463
+ withInfo?: boolean
464
+ rowAttributeIdName?: string
465
+ }>(),
466
+ {
467
+ columnKeys: undefined,
468
+ selectedRow: undefined,
469
+ type: undefined,
470
+ itemsPerPage: undefined,
471
+ fillWidth: true,
472
+ testId: 'ui-data-grid',
473
+ withInfo: false,
474
+ rowAttributeIdName: 'data-id',
475
+ }
476
+ )
477
+
478
+ const emits = defineEmits<{
479
+ (event: 'update:column-keys', value: UI_T_ColumnKeys): void
480
+ (event: 'update:selected-row', value: UI_T_SelectedRow): void
481
+ (event: 'update:page-size', value: number): void
482
+ (event: 'update:page', value: number): void
483
+ (event: 'filtering', value: string[][]): void
484
+ (event: 'sorting', value: [string, boolean]): void
485
+ (event: 'change', value: any): void
486
+ (event: 'row-detail', value: number): void
487
+ }>()
488
+
489
+ const mergeOptions = computed<UI_I_OptionItem[]>(
490
+ () => props.itemsPerPage || itemsPerPage
491
+ )
492
+
493
+ const inputId = ref<string>(`radio-input-${useUniqueId()}`)
494
+
495
+ const columnKeysLocal = computed<UI_T_ColumnKeys>({
496
+ get() {
497
+ return props.columnKeys
498
+ },
499
+ set(newValue) {
500
+ emits('update:column-keys', newValue)
501
+ },
502
+ })
503
+
504
+ const selectedAll = ref<boolean>(false)
505
+ const changeAll = (e: UI_I_HTMLSelectElement): void => {
506
+ const newSelectedRow: (number | string)[] = []
507
+ if (e.target.checked) {
508
+ bodyItemsPresent.value.forEach((row) => {
509
+ newSelectedRow.push(row[0].id)
510
+ })
511
+ }
512
+
513
+ emits('update:selected-row', newSelectedRow)
514
+ }
515
+
516
+ const selectedRowLocal = ref<UI_T_SelectedRow>([])
517
+ const isShowHiddenInfo = ref<boolean>(false)
518
+ const tableWrapperId = `table-wrapper-${useUniqueId()}`
519
+ let memoryWidth = '0'
520
+
521
+ const showedInfoRow = ref<UI_I_BodyItem | null>(null)
522
+ const showedInfoCol = ref<UI_I_BodyItem[] | null>(null)
523
+
524
+ const isShowInfo = computed(
525
+ () =>
526
+ showedInfoRow.value &&
527
+ showedInfoRow.value.id === props.selectedRow &&
528
+ !showedInfoRow.value.data?.text &&
529
+ isShowHiddenInfo.value
530
+ )
531
+
532
+ const setShowedInfoData = (
533
+ item: UI_I_BodyItem | null,
534
+ items: UI_I_BodyItem[] | null,
535
+ reset: boolean = false
536
+ ): void => {
537
+ showedInfoRow.value = item
538
+ showedInfoCol.value = items
539
+
540
+ reset && (isShowHiddenInfo.value = false)
541
+ item && selectRowById(item.id)
542
+ reset && (isShowHiddenInfo.value = true)
543
+ }
544
+
545
+ const doubleArrowClick = (
546
+ item: UI_I_BodyItem,
547
+ items: UI_I_BodyItem[]
548
+ ): void => {
549
+ if (!isShowHiddenInfo.value) {
550
+ setShowedInfoData(item, items)
551
+ } else {
552
+ if (showedInfoRow.value?.id !== item.id) {
553
+ setShowedInfoData(item, items, true)
554
+
555
+ return
556
+ } else {
557
+ setShowedInfoData(null, null)
558
+ }
559
+ }
560
+
561
+ isShowHiddenInfo.value = !isShowHiddenInfo.value
562
+ }
563
+
564
+ watch(
565
+ () => props.selectedRow,
566
+ (newValue) => {
567
+ if (newValue === undefined) return
568
+
569
+ if (Array.isArray(newValue) && !newValue.length) selectedAll.value = false
570
+
571
+ selectedRowLocal.value = newValue
572
+ },
573
+ { immediate: true }
574
+ )
575
+ const selectRowById = (id: number | string): void => {
576
+ if (props.offSelectByRow || isShowHiddenInfo.value) return
577
+
578
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
579
+ const has = selectedRowLocal.value.includes(id)
580
+ if (has) {
581
+ selectedRowLocal.value = selectedRowLocal.value.filter(
582
+ (rowId: string | number) => rowId !== id
583
+ )
584
+ } else {
585
+ selectedRowLocal.value.push(id)
586
+ }
587
+
588
+ emits('change', selectedRowLocal.value)
589
+ emits('update:selected-row', selectedRowLocal.value)
590
+
591
+ changeSelectedAll(!has)
592
+ return
593
+ }
594
+
595
+ emits('change', id)
596
+ emits('update:selected-row', id)
597
+ }
598
+ const changeSelectedRow = (
599
+ e: UI_I_HTMLSelectElement,
600
+ id: number | string
601
+ ): void => {
602
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
603
+ const newSelectedRow = [...selectedRowLocal.value]
604
+ emits('change', newSelectedRow)
605
+ emits('update:selected-row', newSelectedRow)
606
+
607
+ changeSelectedAll(e.target.checked)
608
+ return
609
+ }
610
+
611
+ emits('change', id)
612
+ emits('update:selected-row', id)
613
+ }
614
+ const changeSelectedAll = (checked: boolean): void => {
615
+ if (props.type === 'checkbox' && Array.isArray(selectedRowLocal.value)) {
616
+ const newSelectedRow = [...selectedRowLocal.value]
617
+
618
+ if (!checked) {
619
+ selectedAll.value = false
620
+ } else if (newSelectedRow.length === bodyItemsPresent.value.length) {
621
+ selectedAll.value = true
622
+ }
623
+ }
624
+ }
625
+
626
+ const checkIsSelectedRow = (id: number | string): boolean => {
627
+ if (props.type === 'checkbox' && Array.isArray(props.selectedRow)) {
628
+ return props.selectedRow.includes(id)
629
+ }
630
+ return props.selectedRow === id
631
+ }
632
+
633
+ // Sorting
634
+ const sortInfo = ref<[string, boolean]>(['', true])
635
+ const sortedColumnIndex = computed<number>(() => {
636
+ let index = -1
637
+ headItemsPresent.value.forEach((item, key) => {
638
+ if (item.sortColumn === sortInfo.value[0]) index = key
639
+ })
640
+
641
+ return index
642
+ })
643
+ const sortTable = (sortName: string): void => {
644
+ if (!sortName) return
645
+
646
+ emits('update:selected-row', selectedRowLocal.value)
647
+
648
+ if (sortInfo.value[0] === sortName) {
649
+ sortInfo.value[1] = !sortInfo.value[1]
650
+
651
+ emits('sorting', sortInfo.value)
652
+ return
653
+ }
654
+ sortInfo.value[0] = sortName
655
+ sortInfo.value[1] = true
656
+
657
+ emits('sorting', sortInfo.value)
658
+ }
659
+
660
+ // Filtering
661
+ const filterShow = ref<boolean[]>([])
662
+ const filterTerm = ref<string[]>([])
663
+ const filtering = (): void => {
664
+ const filter: string[][] = []
665
+ headItemsPresent.value.forEach((item, key) => {
666
+ if (filterTerm.value[key]) filter.push([item.key, filterTerm.value[key]])
667
+ })
668
+
669
+ emits('filtering', filter)
670
+ }
671
+
672
+ // Pagination
673
+ const changePageSize = (value: number): void => {
674
+ emits('update:page-size', value)
675
+ }
676
+ const changePage = (value: number): void => {
677
+ emits('update:page', value)
678
+ }
679
+
680
+ const headItemsPresent = computed<UI_I_HeadItem[]>(() => {
681
+ if (!columnKeysLocal.value) {
682
+ return props.headItems
683
+ }
684
+
685
+ return props.headItems.filter((item, key) => {
686
+ return columnKeysLocal.value?.find(
687
+ (item2, key2) => item2.key === item.key && key === key2
688
+ )?.show
689
+ })
690
+ })
691
+
692
+ const bodyItemsPresent = computed<UI_I_BodyItem[][]>(() => {
693
+ let items: UI_I_BodyItem[][] = props.bodyItems
694
+
695
+ // Filtering by column
696
+ if (columnKeysLocal.value) {
697
+ items = items.map((arr) => {
698
+ arr = arr.filter((item, key) => {
699
+ return columnKeysLocal.value?.find(
700
+ (item2, key2) => item2.key === item.key && key === key2
701
+ )?.show
702
+ })
703
+ return arr
704
+ })
705
+ }
706
+
707
+ if (props.serverOff) {
708
+ // Sorting
709
+ if (sortInfo.value[0] !== '') {
710
+ items = useDeepCopy(items).sort(
711
+ (a: UI_I_BodyItem[], b: UI_I_BodyItem[]) => {
712
+ const first = a[sortedColumnIndex.value].text.toString().toLowerCase()
713
+ const second = b[sortedColumnIndex.value].text
714
+ .toString()
715
+ .toLowerCase()
716
+
717
+ if (sortInfo.value[1]) {
718
+ return first > second ? 1 : first < second ? -1 : 0
719
+ } else {
720
+ return first < second ? 1 : first > second ? -1 : 0
721
+ }
722
+ }
723
+ )
724
+ }
725
+ // Filtering
726
+ const hasFilter = headItemsPresent.value.some(
727
+ (_, key) => filterTerm.value[key]
728
+ )
729
+ if (hasFilter) {
730
+ items = items.filter((row) => {
731
+ // 0 - начальное значение
732
+ // 1 - найден элемент
733
+ // -1 - ненайден элемент
734
+ let hasItem = 0
735
+ headItemsPresent.value.forEach((item, key) => {
736
+ if (!filterTerm.value[key]) return
737
+ const term = filterTerm.value[key].toLowerCase()
738
+
739
+ row.forEach((col) => {
740
+ if (
741
+ col.key === item.key &&
742
+ typeof col.text === 'string' &&
743
+ hasItem != -1
744
+ ) {
745
+ hasItem = col.text.toLowerCase().includes(term) ? 1 : -1
746
+ }
747
+ })
748
+ })
749
+
750
+ return hasItem === 1
751
+ })
752
+ }
753
+ }
754
+
755
+ return items
756
+ })
757
+
758
+ const toggedItems = ref<boolean[]>([])
759
+
760
+ const toggle = (key: number): void => {
761
+ toggedItems.value[key] = !toggedItems.value[key]
762
+ if (!toggedItems.value[key]) return
763
+ emits('row-detail', key)
764
+ }
765
+
766
+ const outerWrapper = `datagrid-outer-wrapper${useUniqueId()}`
767
+ const expandableCaret = `datagrid-expandable-caret${useUniqueId()}`
768
+
769
+ // Resize
770
+ let helper = false
771
+ let setColumnWidth = (): void => {
772
+ if (!helper) {
773
+ columnsWidth.value = []
774
+ headItemsPresent.value.forEach((item) => {
775
+ columnsWidth.value.push([
776
+ item.width, // width
777
+ item.width, // min-width
778
+ ])
779
+ })
780
+
781
+ helper = true
782
+ setTimeout(() => setColumnWidth(), 0)
783
+ return
784
+ }
785
+ // Не продолжаем, чтобы ширина калонок была так как заданно в headItemsPresent
786
+ if (!props.fillWidth) return
787
+
788
+ const dataGridWidth = document.getElementById(outerWrapper)?.clientWidth || 0
789
+ const leftColumnWidth =
790
+ document.getElementById(expandableCaret)?.clientWidth || 0
791
+ const bordersWidth = 2
792
+ const columnWidth =
793
+ (dataGridWidth - leftColumnWidth - bordersWidth) /
794
+ headItemsPresent.value.length
795
+
796
+ headItemsPresent.value.forEach((item) => {
797
+ columnsWidth.value.push([
798
+ `${columnWidth}px`, // width
799
+ item.width, // min-width
800
+ ])
801
+ })
802
+ }
803
+ setColumnWidth = useThrottle(setColumnWidth)
804
+
805
+ const columnsWidth = ref<[string, string][]>([])
806
+ watch(
807
+ bodyItemsPresent,
808
+ (newValue: UI_I_BodyItem[][]) => {
809
+ newValue.forEach(() => {
810
+ toggedItems.value.push(false)
811
+ })
812
+ setColumnWidth()
813
+ },
814
+ {
815
+ immediate: true,
816
+ deep: true,
817
+ }
818
+ )
819
+
820
+ watch(
821
+ headItemsPresent,
822
+ (newValue: UI_I_HeadItem[]) => {
823
+ filterShow.value = newValue.map(() => false)
824
+ filterTerm.value = newValue.map(() => '')
825
+ },
826
+ {
827
+ immediate: true,
828
+ deep: true,
829
+ }
830
+ )
831
+
832
+ const grabColumn = ref<number>(-1)
833
+ const grabStartX = ref<number>(0)
834
+ const setGrab = (key: number, e: MouseEvent): void => {
835
+ if (props.withInfo && key === 0) return
836
+
837
+ if (!isShowHiddenInfo.value) {
838
+ grabColumn.value = key
839
+ const currentWidth = parseInt(columnsWidth.value[grabColumn.value][0])
840
+ grabStartX.value = e.clientX - currentWidth
841
+ }
842
+ }
843
+
844
+ const isDrag = ref<boolean>(false)
845
+
846
+ const mouseup = (): void => {
847
+ if (grabColumn.value === -1) {
848
+ return
849
+ }
850
+
851
+ grabColumn.value = -1
852
+ isDrag.value = false
853
+ }
854
+
855
+ let resizeObserve: ResizeObserver
856
+ let mousemove = (e: MouseEvent): void => {
857
+ if (grabColumn.value === -1) return
858
+
859
+ e.preventDefault()
860
+ isDrag.value = true
861
+ resizeObserve.disconnect()
862
+
863
+ const minWidth = parseInt(columnsWidth.value[grabColumn.value][1])
864
+ const changeX = Math.max(e.clientX - grabStartX.value, minWidth)
865
+
866
+ columnsWidth.value[grabColumn.value] = [`${changeX}px`, `${minWidth}px`]
867
+ }
868
+ mousemove = useThrottle(mousemove)
869
+
870
+ const setResizeObserve = (): void => {
871
+ const el = document.getElementById(outerWrapper)
872
+
873
+ if (!el) {
874
+ setTimeout(setResizeObserve, 0)
875
+ return
876
+ }
877
+
878
+ resizeObserve = new ResizeObserver(setColumnWidth)
879
+ resizeObserve.observe(el)
880
+ }
881
+
882
+ let resizeObserveWithInfo: ResizeObserver
883
+
884
+ const setColumnWidthWithInfo = (ent: ResizeObserverEntry[]): void => {
885
+ if (isShowHiddenInfo.value) {
886
+ memoryWidth = columnsWidth.value[1][0]
887
+ columnsWidth.value[1][0] = `${ent[0].contentBoxSize[0].inlineSize - 86}px`
888
+ } else {
889
+ columnsWidth.value[1][0] = memoryWidth
890
+ }
891
+ }
892
+
893
+ const setResizeObserveWithInfo = (): void => {
894
+ const el = document.querySelector('.datagrid')
895
+
896
+ if (!el) {
897
+ setTimeout(setResizeObserveWithInfo, 0)
898
+ return
899
+ }
900
+
901
+ resizeObserveWithInfo = new ResizeObserver(setColumnWidthWithInfo)
902
+ resizeObserveWithInfo.observe(el)
903
+ }
904
+
905
+ onMounted(() => {
906
+ window.addEventListener('mousemove', mousemove)
907
+ window.addEventListener('mouseup', mouseup)
908
+
909
+ if (props.withInfo) {
910
+ setResizeObserveWithInfo()
911
+ }
912
+
913
+ setResizeObserve()
914
+ })
915
+ onUnmounted(() => {
916
+ window.removeEventListener('mouseup', mouseup)
917
+ window.removeEventListener('mousemove', mousemove)
918
+ })
919
+ </script>
920
+
921
+ <style scoped lang="scss">
922
+ @import '~/assets/scss/common/mixins';
923
+ .datagrid-outer-wrapper {
924
+ @include flex($dir: row);
925
+ padding-top: 12px;
926
+ flex-grow: 1;
927
+ overflow: auto;
928
+
929
+ &.datagrid-outer-wrapper-opened-info {
930
+ width: 35%;
931
+ min-width: 195px;
932
+ }
933
+
934
+ & * {
935
+ box-sizing: border-box;
936
+ }
937
+
938
+ & svg {
939
+ fill: var(--table-color);
940
+ }
941
+
942
+ .datagrid-inner-wrapper {
943
+ @include flex($dir: column);
944
+ flex-grow: 1;
945
+ overflow: auto;
946
+
947
+ .datagrid {
948
+ overflow: auto;
949
+ flex: 1 1 auto;
950
+ border-radius: 0.125rem 0.125rem 0 0;
951
+ background-color: var(--block-view-bg-color);
952
+ border-color: var(--global-border-color);
953
+
954
+ &.datagrid-opened-info {
955
+ border-radius: 0.125rem 0 0 0;
956
+ overflow-x: hidden;
957
+ }
958
+
959
+ .datagrid-table-wrapper {
960
+ min-width: max-content;
961
+ display: flex;
962
+ flex: 1 1 auto;
963
+ min-height: 100%;
964
+
965
+ .datagrid-table {
966
+ @include flex($dir: column);
967
+ flex: 1 1 auto;
968
+ align-content: flex-start;
969
+ position: relative;
970
+
971
+ .datagrid-header {
972
+ position: sticky;
973
+ top: 0;
974
+ z-index: 501;
975
+ width: auto;
976
+
977
+ .datagrid-row-scrollable {
978
+ flex-direction: row;
979
+
980
+ .datagrid-column-separator {
981
+ user-select: none;
982
+
983
+ &::after {
984
+ cursor: col-resize;
985
+ }
986
+ &.double-arrow-separator .datagrid-column-handle {
987
+ cursor: unset;
988
+ }
989
+ &.double-arrow-separator::after {
990
+ cursor: unset;
991
+ }
992
+ }
993
+ }
994
+
995
+ .datagrid-row {
996
+ color: var(--table-color);
997
+ background-color: var(--block-view-bg-color);
998
+
999
+ &.datagrid-selected {
1000
+ background-color: var(--row-selected-bg-color);
1001
+ border-bottom: 1px solid var(--global-border-color);
1002
+
1003
+ & :deep(*) {
1004
+ color: var(--table-active-color);
1005
+ }
1006
+ }
1007
+
1008
+ .datagrid-column {
1009
+ background-color: var(--block-view-bg-color);
1010
+ border-bottom: 1px solid var(--global-border-color);
1011
+ padding: 6px 12px 5px;
1012
+ position: relative;
1013
+ //flex: 1 1 auto;
1014
+
1015
+ &:last-child {
1016
+ flex: 1 1 auto;
1017
+ }
1018
+
1019
+ &.datagrid-toggle-block {
1020
+ width: 38px;
1021
+ min-width: 38px;
1022
+
1023
+ .datagrid-column-separator {
1024
+ cursor: default;
1025
+
1026
+ &::after {
1027
+ cursor: default;
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+
1033
+ .datagrid-column-title {
1034
+ align-self: auto;
1035
+ color: var(--table-color);
1036
+ background-color: var(--block-view-bg-color);
1037
+ border-bottom-color: var(--global-border-color);
1038
+ font-size: 11px;
1039
+ @include flex($align: center);
1040
+ display: flex;
1041
+ flex-direction: row;
1042
+ justify-content: flex-start;
1043
+ align-items: center;
1044
+ //line-height: 24px;
1045
+ line-height: normal;
1046
+
1047
+ .title-column {
1048
+ font-weight: bold;
1049
+ font-size: 11px;
1050
+ overflow: hidden;
1051
+ text-wrap: none;
1052
+ text-overflow: ellipsis;
1053
+ }
1054
+
1055
+ .sort-arrow-wrap {
1056
+ margin-left: auto;
1057
+ height: 14px;
1058
+ width: 14px;
1059
+ min-height: 14px;
1060
+ min-width: 14px;
1061
+ vertical-align: middle;
1062
+
1063
+ .sort-arrow {
1064
+ &.down {
1065
+ transform: rotate(180deg);
1066
+ }
1067
+ }
1068
+ }
1069
+ .title-icon {
1070
+ width: 24px;
1071
+ height: 24px;
1072
+ }
1073
+ }
1074
+
1075
+ .datagrid-filter-toggle {
1076
+ background: unset;
1077
+ margin-top: -4px;
1078
+ align-self: center;
1079
+
1080
+ .filter-icon {
1081
+ width: 16px;
1082
+ height: 16px;
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
+ .datagrid-placeholder-container {
1089
+ .datagrid-placeholder.datagrid-empty {
1090
+ background: var(--block-view-bg-color);
1091
+ }
1092
+ span {
1093
+ font-size: 16px;
1094
+ color: var(--global-font-color4);
1095
+ }
1096
+ }
1097
+
1098
+ .datagrid-row {
1099
+ width: 100%;
1100
+ min-width: max-content;
1101
+ border-top: none;
1102
+ color: var(--table-color);
1103
+ background-color: var(--block-view-bg-color);
1104
+ border-bottom: 1px solid var(--global-border-color);
1105
+
1106
+ &.datagrid-selected {
1107
+ & :deep(*) {
1108
+ color: var(--table-active-color);
1109
+ }
1110
+
1111
+ .datagrid-cell {
1112
+ background-color: var(--row-selected-bg-color);
1113
+ border-bottom: 1px solid var(--global-border-color);
1114
+ position: relative;
1115
+ line-height: 1rem;
1116
+ }
1117
+
1118
+ .datagrid-row-detail {
1119
+ background-color: var(--row-selected-bg-color);
1120
+ border-bottom: 1px solid var(--global-border-color);
1121
+ }
1122
+ }
1123
+
1124
+ .datagrid-cell {
1125
+ min-width: 38px;
1126
+ min-height: 28px;
1127
+ padding: 2px 12px 3px 12px;
1128
+ position: relative;
1129
+
1130
+ &:has(.double-arrow-wrap) {
1131
+ padding-left: 4px;
1132
+ }
1133
+
1134
+ &:has(.double-arrow-wrap)::after {
1135
+ content: '';
1136
+ width: 0.5px;
1137
+ height: calc(100% - 6px);
1138
+ position: absolute;
1139
+ right: 2px;
1140
+ top: 3px;
1141
+ background-color: var(--global-border-color);
1142
+ }
1143
+
1144
+ &:last-child {
1145
+ flex: 1 1 auto;
1146
+ }
1147
+
1148
+ button {
1149
+ height: 0.9rem;
1150
+ width: 0.9rem;
1151
+
1152
+ .arrow-icon {
1153
+ width: 16px;
1154
+ height: 16px;
1155
+ transform: rotate(90deg);
1156
+ }
1157
+ }
1158
+
1159
+ .datagrid-cell-icon {
1160
+ display: inline-block;
1161
+ width: 16px;
1162
+ height: 16px;
1163
+ }
1164
+
1165
+ .datagrid-expandable-caret-button {
1166
+ cursor: pointer;
1167
+ width: 100%;
1168
+
1169
+ .datagrid-expandable-caret-icon {
1170
+ width: 16px;
1171
+ height: 16px;
1172
+ transform: rotate(90deg);
1173
+ fill: var(--table-caret-color);
1174
+
1175
+ &.toggle {
1176
+ transform: rotate(180deg);
1177
+ }
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ &.datagrid-selected-info {
1183
+ width: 100%;
1184
+ min-width: max-content;
1185
+ border-top: none;
1186
+ color: var(--table-color);
1187
+ background-color: var(--block-view-bg-color);
1188
+
1189
+ .datagrid-cell {
1190
+ position: relative;
1191
+
1192
+ &.hidden-text-triangle::after {
1193
+ content: '';
1194
+ position: absolute;
1195
+ transform: rotate(225deg);
1196
+ border-bottom: 15px solid transparent;
1197
+ border-right: 15px solid var(--global-bg-color);
1198
+ bottom: 26%;
1199
+ right: -16px;
1200
+ z-index: 1000;
1201
+ }
1202
+
1203
+ &.hidden-text-triangle::before {
1204
+ content: '';
1205
+ transform: rotate(-135deg);
1206
+ position: absolute;
1207
+ border-bottom: 16px solid transparent;
1208
+ border-right: 16px solid var(--global-border-color);
1209
+ bottom: 23%;
1210
+ right: -17px;
1211
+ z-index: 999;
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+
1217
+ .datagrid-row-sticky {
1218
+ @include flex($w: nowrap);
1219
+ position: sticky;
1220
+ left: 0;
1221
+ z-index: 500;
1222
+ background-color: var(--block-view-bg-color);
1223
+
1224
+ .datagrid-column {
1225
+ color: var(--table-color);
1226
+ background-color: var(--block-view-bg-color);
1227
+ border-bottom-color: var(--global-border-color);
1228
+ text-align: left;
1229
+ display: flex;
1230
+ flex: 1 1 auto;
1231
+ vertical-align: top;
1232
+ border: none;
1233
+
1234
+ &.datagrid-expandable-caret {
1235
+ .datagrid-column-separator {
1236
+ display: block;
1237
+
1238
+ &::after {
1239
+ top: 0;
1240
+ height: 18px;
1241
+ }
1242
+ }
1243
+
1244
+ .radio-btn {
1245
+ width: 16px;
1246
+ height: 16px;
1247
+ }
1248
+ }
1249
+
1250
+ .datagrid-column-separator {
1251
+ position: relative;
1252
+ //left: 0.6rem;
1253
+ flex: 0 0 auto;
1254
+ width: 0.05rem;
1255
+ order: 100;
1256
+ margin-left: auto;
1257
+ height: 100%;
1258
+ }
1259
+ }
1260
+
1261
+ .datagrid-fixed-column-without-separator {
1262
+ background-color: var(--block-view-bg-color);
1263
+
1264
+ &::after {
1265
+ background-color: transparent;
1266
+ }
1267
+ }
1268
+
1269
+ .datagrid-fixed-column {
1270
+ background-color: var(--block-view-bg-color);
1271
+
1272
+ &::after {
1273
+ content: '';
1274
+ width: 0.05rem;
1275
+ height: calc(100% - 0.5rem);
1276
+ position: absolute;
1277
+ right: 0;
1278
+ top: 0.25rem;
1279
+ background-color: var(--global-border-color);
1280
+ }
1281
+ }
1282
+ }
1283
+
1284
+ .datagrid-row-scrollable {
1285
+ @include flex($ff: row nowrap);
1286
+ flex: 1 1 auto;
1287
+
1288
+ .datagrid-scrolling-cells {
1289
+ @include flex($ff: row nowrap);
1290
+ flex: 1 1 auto;
1291
+ }
1292
+ }
1293
+ .datagrid-body-row {
1294
+ .datagrid-row-scrollable {
1295
+ @include flex($ff: column nowrap);
1296
+
1297
+ .datagrid-row-detail {
1298
+ flex: 1;
1299
+ }
1300
+ }
1301
+
1302
+ &:not(.datagrid-selected):hover {
1303
+ border-bottom: 1px solid var(--table-hover-row-border-color);
1304
+ background-color: var(--table-hover-row-background-color);
1305
+ color: var(--table-hover-row-color);
1306
+
1307
+ .datagrid-fixed-column {
1308
+ background-color: var(--table-hover-row-background-color);
1309
+ }
1310
+ .datagrid-cell {
1311
+ background-color: var(--table-hover-row-background-color);
1312
+ }
1313
+ }
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+
1319
+ .datagrid-footer {
1320
+ flex: 0 0 auto;
1321
+ @include flex($ff: row nowrap, $just: space-between, $align: stretch);
1322
+ font-size: 0.55rem;
1323
+ background-color: var(--block-view-bg-color);
1324
+ border: 0.05rem solid var(--global-border-color);
1325
+ border-top: none;
1326
+ border-radius: 0 0 0.15rem 0.15rem;
1327
+ padding: 0 0.6rem;
1328
+ height: 28px;
1329
+
1330
+ &.datagrid-footer-opened-info {
1331
+ border-radius: 0 0 0 0.15rem;
1332
+ flex-direction: row-reverse;
1333
+ }
1334
+
1335
+ .clr-form-control-disabled {
1336
+ opacity: 1;
1337
+
1338
+ .clr-checkbox-wrapper {
1339
+ label {
1340
+ color: #8c8c8c;
1341
+ margin-right: 9px;
1342
+ padding-left: 22px;
1343
+
1344
+ &:before {
1345
+ position: absolute;
1346
+ top: 4px;
1347
+ left: 0;
1348
+ content: '';
1349
+ display: inline-block;
1350
+ height: 16px;
1351
+ width: 16px;
1352
+ border: none;
1353
+ border-radius: 3px;
1354
+ background-color: var(--table-checkbox-color);
1355
+ }
1356
+
1357
+ &:after {
1358
+ position: absolute;
1359
+ content: '';
1360
+ display: inline-block;
1361
+ height: 5px;
1362
+ width: 8px;
1363
+ border-left: 2px solid #fff;
1364
+ border-bottom: 2px solid #fff;
1365
+ top: 4px;
1366
+ left: 4px;
1367
+ transform: translateY(4px) rotate(-45deg);
1368
+ }
1369
+ }
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ .datagrid-spinner {
1375
+ top: 0.6rem;
1376
+ height: calc(100% - 0.6rem);
1377
+ }
1378
+
1379
+ .datagrid-footer-description {
1380
+ flex: 1 1 auto;
1381
+
1382
+ :deep(svg) {
1383
+ fill: var(--table-switch-color);
1384
+ }
1385
+ }
1386
+
1387
+ .clr-radio-wrapper,
1388
+ .clr-checkbox-wrapper {
1389
+ height: 18px;
1390
+ }
1391
+
1392
+ .clr-radio-wrapper label,
1393
+ .clr-checkbox-wrapper label {
1394
+ padding-left: 16px;
1395
+ }
1396
+ }
1397
+ }
1398
+ //.vertical-divider {
1399
+ // width: 1px;
1400
+ // height: 22px;
1401
+ // background: #bbb;
1402
+ // margin: 2px 2px 0 -5px;
1403
+ //}
1404
+
1405
+ .hidden-features {
1406
+ padding: 9px 14px;
1407
+ background-color: var(--global-bg-color);
1408
+ color: var(--global-font-color2);
1409
+ border: 1px solid var(--global-border-color);
1410
+ border-left: none;
1411
+ overflow-y: auto;
1412
+ overflow-x: hidden;
1413
+ width: 65%;
1414
+
1415
+ .header {
1416
+ display: flex;
1417
+ align-items: center;
1418
+ justify-content: space-between;
1419
+ background-color: inherit;
1420
+
1421
+ h3 {
1422
+ font-size: 1rem;
1423
+ color: var(--global-font-color2) !important;
1424
+ line-height: 1.7rem;
1425
+ }
1426
+ button {
1427
+ line-height: 24px;
1428
+
1429
+ .close-icon {
1430
+ margin-left: 10px;
1431
+ width: 24px;
1432
+ height: 24px;
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1437
+ .double-arrow-width {
1438
+ width: 25px;
1439
+ }
1440
+ .double-arrow-wrap {
1441
+ width: 30px;
1442
+ height: 20px;
1443
+ padding-top: 1px;
1444
+ padding-left: 5px;
1445
+ cursor: pointer;
1446
+ background-color: transparent;
1447
+
1448
+ .double-arrow {
1449
+ background-color: transparent;
1450
+ transform: rotate(90deg);
1451
+ width: 16px;
1452
+ height: 16px;
1453
+ }
1454
+
1455
+ .double-arrow.arrow-selected {
1456
+ transform: rotate(-90deg) !important;
1457
+ background-color: #0079b8;
1458
+ }
1459
+ }
1460
+ .double-arrow-wrap.arrow-selected {
1461
+ background-color: #0079b8;
1462
+ border-radius: 3px;
1463
+ }
1464
+ </style>
1465
+
1466
+ <style>
1467
+ :root {
1468
+ --table-color: #565656;
1469
+ --table-active-color: #fff;
1470
+ --table-checkbox-color: #454545;
1471
+ --table-caret-color: #454545;
1472
+ --table-switch-color: #575757;
1473
+ --table-hover-row-border-color: #666;
1474
+ --table-hover-row-background-color: #e8e8e8;
1475
+ --table-hover-row-color: #454545;
1476
+ --table-spinner-bg-color: #ffffff99;
1477
+ }
1478
+
1479
+ :root.dark-theme {
1480
+ --table-color: #fff;
1481
+ --table-active-color: #565656;
1482
+ --table-checkbox-color: #49aeda;
1483
+ --table-caret-color: #ffffff;
1484
+ --table-switch-color: #b3b3b3;
1485
+ --table-hover-row-border-color: #fff;
1486
+ --table-hover-row-background-color: #324f61;
1487
+ --table-hover-row-color: #e9ecef;
1488
+ --table-spinner-bg-color: rgba(0, 0, 0, 0.5);
1489
+ }
1490
+ </style>