bfg-common 1.4.657 → 1.4.659

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 (138) 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/scss/common/icons/icons-4.scss +6 -0
  6. package/components/atoms/TheIcon3.vue +50 -50
  7. package/components/atoms/modal/bySteps/BySteps.vue +253 -253
  8. package/components/atoms/stack/StackBlock.vue +185 -185
  9. package/components/atoms/table/dataGrid/DataGrid.vue +1633 -1633
  10. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +222 -222
  11. package/components/common/browse/BrowseNew.vue +237 -237
  12. package/components/common/browse/BrowseOld.vue +217 -217
  13. package/components/common/browse/blocks/contents/Files.vue +37 -37
  14. package/components/common/browse/blocks/contents/FilesOld.vue +72 -72
  15. package/components/common/browse/blocks/contents/filesNew/FilesNew.vue +96 -96
  16. package/components/common/browse/blocks/contents/filesNew/Skeleton.vue +18 -18
  17. package/components/common/browse/blocks/lib/models/types.ts +1 -1
  18. package/components/common/browse/lib/models/interfaces.ts +5 -5
  19. package/components/common/context/lib/models/interfaces.ts +30 -30
  20. package/components/common/context/recursion/Recursion.vue +86 -86
  21. package/components/common/context/recursion/RecursionNew.vue +199 -199
  22. package/components/common/context/recursion/RecursionOld.vue +213 -213
  23. package/components/common/diagramMain/Header.vue +211 -211
  24. package/components/common/diagramMain/adapter/AdapterItems.vue +61 -61
  25. package/components/common/diagramMain/lib/config/initial.ts +50 -50
  26. package/components/common/diagramMain/lib/models/types.ts +21 -21
  27. package/components/common/diagramMain/lib/utils/utils.ts +331 -331
  28. package/components/common/diagramMain/modals/ManagePhysicalAdaptersModal.vue +330 -330
  29. package/components/common/diagramMain/modals/editSettings/ConfirmTeamingSettingsModal.vue +40 -40
  30. package/components/common/diagramMain/modals/editSettings/EditSettings.vue +497 -497
  31. package/components/common/diagramMain/modals/editSettings/EditSettingsModal.vue +812 -812
  32. package/components/common/diagramMain/modals/editSettings/tabs/NetworkProperties.vue +214 -214
  33. package/components/common/diagramMain/modals/editSettings/tabs/Security.vue +189 -189
  34. package/components/common/diagramMain/modals/editSettings/tabs/SwitchProperties.vue +163 -163
  35. package/components/common/diagramMain/modals/editSettings/tabs/TeamingFailover.vue +175 -175
  36. package/components/common/diagramMain/modals/editSettings/tabs/TrafficShaping.vue +398 -398
  37. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +346 -346
  38. package/components/common/diagramMain/modals/editSettings/tabs/port/PortProperties.vue +205 -205
  39. package/components/common/diagramMain/modals/lib/config/diagramConfig.ts +23 -23
  40. package/components/common/diagramMain/modals/lib/config/initial.ts +180 -180
  41. package/components/common/diagramMain/modals/lib/config/vmKernelAdapter.ts +90 -90
  42. package/components/common/diagramMain/modals/lib/mappers/mappers.ts +87 -87
  43. package/components/common/diagramMain/modals/lib/utils/index.ts +24 -24
  44. package/components/common/diagramMain/modals/migrateVmkernelAdapter/MigrateVmkernelAdapter.vue +537 -537
  45. package/components/common/diagramMain/modals/migrateVmkernelAdapter/lib/config/steps.ts +114 -114
  46. package/components/common/diagramMain/modals/migrateVmkernelAdapter/steps/ConnectionSettings.vue +169 -169
  47. package/components/common/diagramMain/modals/migrateVmkernelAdapter/steps/SelectVmkernelAdapter.vue +159 -159
  48. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/common.ts +14 -14
  49. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/connectionSettings.ts +137 -137
  50. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/selectVmkernelAdapter.ts +52 -52
  51. package/components/common/diagramMain/modals/migrateVmkernelAdapter/validations/validations.ts +19 -19
  52. package/components/common/diagramMain/port/Ports.vue +47 -47
  53. package/components/common/layout/theHeader/helpMenu/About.vue +85 -85
  54. package/components/common/layout/theHeader/helpMenu/aboutNew/AboutNew.vue +105 -105
  55. package/components/common/mainNavigationPanel/MainNavigationPanel.vue +152 -152
  56. package/components/common/modals/confirmByInput/ConfirmByInput.vue +206 -206
  57. package/components/common/modals/unsavedChanges/UnsavedChanges.vue +56 -56
  58. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/Actions.vue +1 -1
  59. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/actions/Actions.vue +1 -1
  60. package/components/common/spiceConsole/Drawer.vue +370 -370
  61. package/components/common/spiceConsole/lib/models/interfaces.ts +5 -5
  62. package/components/common/split/vertical/Vertical.vue +160 -160
  63. package/components/common/vm/actions/add/Add.vue +617 -617
  64. package/components/common/vm/actions/clone/lib/config/steps.ts +129 -129
  65. package/components/common/vm/actions/common/customizeHardware/CustomizeHardware.vue +267 -267
  66. package/components/common/vm/actions/common/customizeHardware/CustomizeHardwareNew.vue +269 -269
  67. package/components/common/vm/actions/common/customizeHardware/virtualHardware/browseView/BrowseView.vue +219 -219
  68. package/components/common/vm/actions/common/customizeHardware/virtualHardware/bus/BusNew.vue +118 -118
  69. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveNew.vue +161 -161
  70. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveOld.vue +165 -165
  71. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/Media.vue +25 -25
  72. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/MediaNew.vue +55 -55
  73. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/Cpu.vue +338 -338
  74. package/components/common/vm/actions/common/customizeHardware/virtualHardware/lib/config/dropdownItems.ts +147 -147
  75. package/components/common/vm/actions/common/customizeHardware/virtualHardware/limit/Limit.vue +220 -220
  76. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/mode/ModeOld.vue +55 -55
  77. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/sharing/SharingNew.vue +44 -44
  78. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +281 -281
  79. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetworkNew.vue +124 -124
  80. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/LocationOld.vue +134 -134
  81. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/new/New.vue +63 -63
  82. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/new/table/lib/config/config.ts +95 -95
  83. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddress.vue +119 -119
  84. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddressNew.vue +69 -69
  85. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddressOld.vue +83 -83
  86. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDeviceNew.vue +85 -85
  87. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDeviceOld.vue +91 -91
  88. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/directPathIo/DirectPathIoNew.vue +35 -35
  89. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIoNew.vue +48 -48
  90. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/Note.vue +15 -15
  91. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/NoteNew.vue +42 -42
  92. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/NoteOld.vue +30 -30
  93. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/nvidiaGrid/NvidiaGridNew.vue +30 -30
  94. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/typeSelection/TypeSelectionNew.vue +46 -46
  95. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newUsbController/NewUsbControllerNew.vue +56 -56
  96. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/Other.vue +16 -16
  97. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/OtherNew.vue +30 -30
  98. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCardNew.vue +107 -107
  99. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCardOld.vue +115 -115
  100. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/totalVideoMemory/TotalVideoMemoryNew.vue +54 -54
  101. package/components/common/vm/actions/common/customizeHardware/vmoptions/Vmoptions.vue +145 -145
  102. package/components/common/vm/actions/common/customizeHardware/vmoptions/VmoptionsNew.vue +102 -102
  103. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/BootOptionsNew.vue +75 -75
  104. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/delay/Delay.vue +26 -26
  105. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/Firmware.vue +57 -57
  106. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/FirmwareNew.vue +42 -42
  107. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/menu/MenuNew.vue +25 -25
  108. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +171 -171
  109. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/OrderNew.vue +50 -50
  110. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptionsNew.vue +141 -141
  111. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/New.vue +140 -140
  112. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/copyPaste/CopyPasteNew.vue +30 -30
  113. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/fileTransfer/FileTransferNew.vue +30 -30
  114. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/folderSharing/FolderSharingNew.vue +30 -30
  115. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +32 -32
  116. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/KeymapNew.vue +39 -39
  117. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/Password.vue +103 -103
  118. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/PasswordNew.vue +102 -102
  119. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/PasswordOld.vue +94 -94
  120. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirection.vue +28 -28
  121. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirectionNew.vue +38 -38
  122. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirectionOld.vue +44 -44
  123. package/components/common/vm/actions/common/select/storage/Storage.vue +130 -130
  124. package/components/common/vm/actions/common/select/storage/StorageOld.vue +129 -129
  125. package/components/common/vm/actions/editSettings/EditSettings.vue +232 -232
  126. package/components/common/vm/actions/editSettings/EditSettingsOld.vue +183 -183
  127. package/components/common/vm/actions/editSettings/new/New.vue +177 -177
  128. package/components/common/vm/actions/editSettings/new/Skeleton.vue +88 -88
  129. package/components/common/wizards/network/add/lib/config/steps.ts +464 -464
  130. package/composables/productNameLocal.ts +30 -30
  131. package/package.json +1 -1
  132. package/plugins/date.ts +233 -233
  133. package/plugins/recursion.ts +311 -311
  134. package/public/spice-console/lib/images/bitmap.js +203 -203
  135. package/public/spice-console/network/spicechannel.js +383 -383
  136. package/store/main/mutations.ts +7 -7
  137. package/store/main/state.ts +7 -7
  138. package/store/tasks/mappers/recentTasks.ts +64 -64
@@ -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>