bfg-common 1.4.652 → 1.4.653

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