bfg-common 1.5.474 → 1.5.475

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