bfg-common 1.4.884 → 1.4.901

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 (200) hide show
  1. package/assets/localization/local_en.json +6 -6
  2. package/assets/scss/common/normalize.scss +361 -361
  3. package/components/atoms/TheIcon3.vue +50 -50
  4. package/components/atoms/autocomplete/Autocomplete.vue +301 -301
  5. package/components/atoms/collapse/CollapseNav.vue +165 -165
  6. package/components/atoms/collapse/CollapseNavItem.vue +3 -1
  7. package/components/atoms/collapse/lib/models/interfaces.ts +1 -0
  8. package/components/atoms/dropdown/dropdown/Dropdown.vue +168 -168
  9. package/components/atoms/modal/bySteps/BySteps.vue +253 -253
  10. package/components/atoms/perPage/PerPage.vue +58 -53
  11. package/components/atoms/stack/StackBlock.vue +185 -185
  12. package/components/atoms/table/dataGrid/DataGrid.vue +1704 -1704
  13. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +222 -222
  14. package/components/atoms/table/dataGrid/lib/config/settingsTable.ts +94 -94
  15. package/components/atoms/table/dataGrid/lib/utils/export.ts +16 -16
  16. package/components/atoms/tabs/Tabs.vue +1 -0
  17. package/components/atoms/tabs/VerticalTabs.vue +105 -105
  18. package/components/common/accordion/Recursion.vue +222 -221
  19. package/components/common/accordion/lib/models/interfaces.ts +1 -0
  20. package/components/common/browse/BrowseNew.vue +237 -237
  21. package/components/common/browse/BrowseOld.vue +217 -217
  22. package/components/common/browse/blocks/contents/Files.vue +37 -37
  23. package/components/common/browse/blocks/contents/FilesOld.vue +72 -72
  24. package/components/common/browse/blocks/contents/filesNew/FilesNew.vue +96 -96
  25. package/components/common/browse/blocks/contents/filesNew/Skeleton.vue +18 -18
  26. package/components/common/chartOptionsModal/counters/timespan/form/Form.vue +92 -102
  27. package/components/common/chartOptionsModal/counters/timespan/form/FormNew.vue +18 -39
  28. package/components/common/context/Context.vue +111 -111
  29. package/components/common/context/lib/models/interfaces.ts +31 -30
  30. package/components/common/context/recursion/Recursion.vue +87 -87
  31. package/components/common/context/recursion/RecursionNew.vue +238 -237
  32. package/components/common/context/recursion/RecursionOld.vue +228 -227
  33. package/components/common/details/DetailsItem.vue +109 -109
  34. package/components/common/diagramMain/DiagramMain.vue +897 -893
  35. package/components/common/diagramMain/Header.vue +214 -211
  36. package/components/common/diagramMain/lib/models/interfaces.ts +1 -0
  37. package/components/common/diagramMain/modals/lib/config/diagramConfig.ts +1 -0
  38. package/components/common/graph/Graph.vue +104 -104
  39. package/components/common/graph/GraphNew.vue +2 -4
  40. package/components/common/layout/theHeader/helpMenu/About.vue +82 -82
  41. package/components/common/layout/theHeader/helpMenu/aboutNew/AboutNew.vue +103 -103
  42. package/components/common/layout/theHeader/userMenu/modals/preferences/view/ViewOld.vue +112 -112
  43. package/components/common/mainNavigationPanel/MainNavigationPanelNew.vue +335 -335
  44. package/components/common/mainNavigationPanel/MainNavigationPanelOld.vue +310 -310
  45. package/components/common/modals/unsavedChanges/UnsavedChanges.vue +56 -56
  46. package/components/common/monitor/advanced/Advanced.vue +0 -2
  47. package/components/common/monitor/advanced/AdvancedNew.vue +16 -28
  48. package/components/common/monitor/advanced/graphView/GraphView.vue +1 -0
  49. package/components/common/monitor/advanced/graphView/GraphViewNew.vue +4 -5
  50. package/components/common/monitor/advanced/table/tableNew/TableNew.vue +1 -8
  51. package/components/common/monitor/advanced/table/tableNew/lib/config/options.ts +2 -2
  52. package/components/common/monitor/advanced/tools/Tools.vue +121 -123
  53. package/components/common/monitor/advanced/tools/ToolsNew.vue +0 -9
  54. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModal.vue +0 -34
  55. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModalNew.vue +5 -17
  56. package/components/common/monitor/advanced/tools/chartOptionsModal/NotificationNew.vue +0 -2
  57. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/ActionsNew.vue +12 -38
  58. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/lib/utils/optionsActions.ts +1 -1
  59. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/Counters.vue +66 -76
  60. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/CountersNew.vue +2 -43
  61. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/lib/config/utils.ts +1040 -1040
  62. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/tableNew/TableNew.vue +0 -2
  63. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/Timespan.vue +0 -10
  64. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/TimespanNew.vue +14 -43
  65. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/objectNew/ObjectNew.vue +0 -6
  66. package/components/common/monitor/advanced/tools/chartOptionsModal/metrics/Metrics.vue +1 -1
  67. package/components/common/monitor/advanced/tools/chartOptionsModal/metrics/metricsNew/MetricsNew.vue +101 -0
  68. package/components/common/monitor/advanced/tools/chartOptionsModal/metrics/metricsNew/lib/utils/constructAccordion.ts +32 -0
  69. package/components/common/monitor/overview/OverviewNew.vue +142 -142
  70. package/components/common/monitor/overview/OverviewOld.vue +139 -139
  71. package/components/common/monitor/overview/filters/Filters.vue +166 -166
  72. package/components/common/monitor/overview/filters/FiltersNew.vue +172 -172
  73. package/components/common/monitor/overview/filters/FiltersOld.vue +151 -151
  74. package/components/common/monitor/overview/filters/customIntervalModal/CustomIntervalModal.vue +175 -175
  75. package/components/common/monitor/overview/filters/customIntervalModal/CustomIntervalModalOld.vue +161 -161
  76. package/components/common/pages/home/StatusContent.vue +49 -49
  77. package/components/common/pages/home/headline/Headline.vue +45 -45
  78. package/components/common/pages/home/headline/HeadlineOld.vue +42 -42
  79. package/components/common/pages/home/lib/models/interfaces.ts +48 -48
  80. package/components/common/pages/home/widgets/Widgets.vue +49 -49
  81. package/components/common/pages/home/widgets/WidgetsNew.vue +86 -86
  82. package/components/common/pages/home/widgets/WidgetsOld.vue +34 -34
  83. package/components/common/pages/home/widgets/hosts/Hosts.vue +27 -27
  84. package/components/common/pages/home/widgets/hosts/lib/config/items.ts +23 -23
  85. package/components/common/pages/home/widgets/vms/Vms.vue +26 -26
  86. package/components/common/pages/home/widgets/vms/VmsOld.vue +35 -35
  87. package/components/common/pages/home/widgets/vms/lib/config/items.ts +19 -19
  88. package/components/common/pages/packages/Packages.vue +208 -208
  89. package/components/common/pages/shortcuts/block/BlockNew.vue +96 -96
  90. package/components/common/pages/shortcuts/block/BlockOld.vue +68 -68
  91. package/components/common/portlets/customAttributes/Portlet.vue +667 -667
  92. package/components/common/portlets/tag/Portlet.vue +433 -433
  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/tools/Actions.vue +179 -175
  101. package/components/common/tools/lib/models/interfaces.ts +2 -1
  102. package/components/common/vm/actions/add/Add.vue +622 -622
  103. package/components/common/vm/actions/clone/Clone.vue +639 -639
  104. package/components/common/vm/actions/clone/lib/config/steps.ts +129 -129
  105. package/components/common/vm/actions/clone/toTemplate/ToTemplate.vue +634 -634
  106. package/components/common/vm/actions/clone/toTemplate/lib/config/steps.ts +116 -116
  107. package/components/common/vm/actions/common/customizeHardware/CustomizeHardware.vue +275 -275
  108. package/components/common/vm/actions/common/customizeHardware/CustomizeHardwareNew.vue +274 -274
  109. package/components/common/vm/actions/common/customizeHardware/CustomizeHardwareOld.vue +177 -177
  110. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardware.vue +698 -698
  111. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardwareNew.vue +410 -410
  112. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardwareOld.vue +319 -319
  113. package/components/common/vm/actions/common/customizeHardware/virtualHardware/browseView/BrowseView.vue +219 -219
  114. package/components/common/vm/actions/common/customizeHardware/virtualHardware/bus/Bus.vue +99 -99
  115. package/components/common/vm/actions/common/customizeHardware/virtualHardware/bus/BusNew.vue +117 -117
  116. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDrive.vue +232 -232
  117. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveNew.vue +164 -164
  118. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveOld.vue +168 -168
  119. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/Media.vue +25 -25
  120. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/MediaNew.vue +70 -70
  121. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/MediaOld.vue +50 -50
  122. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/Cpu.vue +338 -338
  123. package/components/common/vm/actions/common/customizeHardware/virtualHardware/limit/Limit.vue +220 -220
  124. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +368 -368
  125. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDiskNew.vue +232 -232
  126. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDiskOld.vue +250 -250
  127. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/mode/ModeOld.vue +56 -56
  128. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/sharing/SharingNew.vue +44 -44
  129. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +286 -286
  130. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetworkNew.vue +124 -124
  131. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/LocationOld.vue +134 -134
  132. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/new/New.vue +63 -63
  133. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/new/table/lib/config/config.ts +95 -95
  134. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddress.vue +119 -119
  135. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddressNew.vue +69 -69
  136. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddressOld.vue +83 -83
  137. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDevice.vue +205 -205
  138. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/directPathIo/DirectPathIoNew.vue +66 -66
  139. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/directPathIo/DirectPathIoOld.vue +62 -62
  140. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIo.vue +31 -31
  141. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIoNew.vue +84 -84
  142. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIoOld.vue +76 -76
  143. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/Note.vue +15 -15
  144. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/NoteNew.vue +42 -42
  145. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/NoteOld.vue +30 -30
  146. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/nvidiaGrid/NvidiaGrid.vue +41 -41
  147. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/nvidiaGrid/NvidiaGridNew.vue +81 -81
  148. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/nvidiaGrid/NvidiaGridOld.vue +84 -84
  149. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newUsbController/NewUsbControllerNew.vue +56 -56
  150. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/Other.vue +16 -16
  151. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/OtherNew.vue +30 -30
  152. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCardNew.vue +104 -104
  153. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCardOld.vue +112 -112
  154. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/totalVideoMemory/TotalVideoMemoryNew.vue +54 -54
  155. package/components/common/vm/actions/common/customizeHardware/vmoptions/Vmoptions.vue +145 -145
  156. package/components/common/vm/actions/common/customizeHardware/vmoptions/VmoptionsNew.vue +102 -102
  157. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/BootOptionsNew.vue +75 -75
  158. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/delay/Delay.vue +26 -26
  159. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/Firmware.vue +57 -57
  160. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/FirmwareNew.vue +42 -42
  161. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/menu/MenuNew.vue +25 -25
  162. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +171 -171
  163. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/OrderNew.vue +50 -50
  164. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptionsNew.vue +141 -141
  165. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/New.vue +140 -140
  166. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/copyPaste/CopyPasteNew.vue +30 -30
  167. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/fileTransfer/FileTransferNew.vue +30 -30
  168. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/folderSharing/FolderSharingNew.vue +30 -30
  169. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +32 -32
  170. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/KeymapNew.vue +39 -39
  171. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/Password.vue +103 -103
  172. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/PasswordNew.vue +102 -102
  173. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/PasswordOld.vue +94 -94
  174. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirection.vue +28 -28
  175. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirectionNew.vue +38 -38
  176. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirectionOld.vue +44 -44
  177. package/components/common/vm/actions/common/select/storage/Storage.vue +130 -130
  178. package/components/common/vm/actions/common/select/storage/StorageOld.vue +129 -129
  179. package/components/common/vm/actions/editSettings/new/Skeleton.vue +88 -88
  180. package/components/common/wizards/datastore/add/lib/config/steps.ts +138 -138
  181. package/components/common/wizards/network/add/Add.vue +1 -0
  182. package/components/common/wizards/network/add/steps/SelectConnectionType.vue +105 -99
  183. package/components/common/wizards/vm/migrate/Migrate.vue +302 -302
  184. package/components/common/wizards/vm/migrate/lib/config/constructDataReady.ts +220 -220
  185. package/components/common/wizards/vm/migrate/select/network/Network.vue +103 -103
  186. package/components/common/wizards/vm/migrate/select/network/table/network/Network.vue +150 -150
  187. package/components/common/wizards/vm/migrate/select/network/table/network/lib/config/advancedTable.ts +91 -91
  188. package/components/common/wizards/vm/migrate/select/priority/Priority.vue +43 -43
  189. package/composables/productNameLocal.ts +30 -30
  190. package/composables/useAppVersion.ts +21 -21
  191. package/package.json +2 -2
  192. package/plugins/date.ts +233 -233
  193. package/plugins/directives.ts +24 -24
  194. package/plugins/recursion.ts +311 -311
  195. package/public/spice-console/lib/images/bitmap.js +203 -203
  196. package/public/spice-console/network/spicechannel.js +383 -383
  197. package/store/main/mutations.ts +7 -7
  198. package/store/main/state.ts +7 -7
  199. package/store/tasks/mappers/recentTasks.ts +64 -64
  200. package/components/common/monitor/advanced/tools/chartOptionsModal/metrics/MetricsNew.vue +0 -143
@@ -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>