bfg-common 1.2.59 → 1.2.61

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