bfg-common 1.4.657 → 1.4.658

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