bfg-common 1.4.877 → 1.4.879

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