dashboard-shell-shell 1.0.10000011122 → 3.0.5-test.1

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 (695) hide show
  1. package/assets/data/aws-regions.json +3 -0
  2. package/assets/icons/demo.css:Zone.Identifier +0 -0
  3. package/assets/icons/demo_index.html:Zone.Identifier +0 -0
  4. package/assets/icons/iconfont.css:Zone.Identifier +0 -0
  5. package/assets/icons/iconfont.js:Zone.Identifier +0 -0
  6. package/assets/icons/iconfont.json:Zone.Identifier +0 -0
  7. package/assets/icons/iconfont.ttf:Zone.Identifier +0 -0
  8. package/assets/icons/iconfont.woff2:Zone.Identifier +0 -0
  9. package/assets/icons/iconfont.woff:Zone.Identifier +0 -0
  10. package/assets/images/action.svg +6 -0
  11. package/assets/images/icons/document.svg +3 -0
  12. package/assets/images/key.svg +17 -0
  13. package/assets/images/pl/logo.png +0 -0
  14. package/assets/images/providers/sks.svg +1 -0
  15. package/assets/images/vendor/cognito.svg +1 -0
  16. package/assets/styles/app.scss +3 -0
  17. package/assets/styles/base/_basic.scss +10 -0
  18. package/assets/styles/base/_functions.scss +0 -0
  19. package/assets/styles/base/_mixins.scss +1 -1
  20. package/assets/styles/base/_spacing.scss +29 -0
  21. package/assets/styles/base/_variables.scss +16 -10
  22. package/assets/styles/global/_button.scss +17 -10
  23. package/assets/styles/global/_form.scss +2 -2
  24. package/assets/styles/global/_labeled-input.scss +7 -3
  25. package/assets/styles/global/_layout.scss +1 -1
  26. package/assets/styles/global/_select.scss +6 -7
  27. package/assets/styles/global/_table.scss +3 -2
  28. package/assets/styles/global/_tooltip.scss +8 -1
  29. package/assets/styles/themes/_dark.scss +32 -0
  30. package/assets/styles/themes/_light.scss +85 -4
  31. package/assets/styles/vendor/vue-select.scss +2 -1
  32. package/assets/translations/en-us.yaml +822 -107
  33. package/assets/translations/zh-hans.yaml +64 -31
  34. package/chart/__tests__/S3.test.ts +2 -1
  35. package/chart/monitoring/index.vue +1 -1
  36. package/cloud-credential/gcp.vue +9 -1
  37. package/components/ActionDropdown.vue +1 -0
  38. package/components/ActionMenuShell.vue +2 -3
  39. package/components/AppModal.vue +9 -28
  40. package/components/AsyncButton.vue +2 -0
  41. package/components/BrandImage.vue +1 -0
  42. package/components/Certificates.vue +5 -0
  43. package/components/ClusterIconMenu.vue +1 -1
  44. package/components/CodeMirror.vue +4 -3
  45. package/components/CommunityLinks.vue +3 -58
  46. package/components/ConfigMapSettings/Settings.vue +377 -0
  47. package/components/ConfigMapSettings/index.vue +354 -0
  48. package/components/CruResource.vue +104 -17
  49. package/components/CruResourceFooter.vue +1 -1
  50. package/components/DetailText.vue +61 -11
  51. package/components/Drawer/Chrome.vue +115 -0
  52. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  53. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  54. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  55. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  56. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +106 -0
  57. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  58. package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
  59. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  60. package/components/Drawer/ResourceDetailDrawer/index.vue +123 -0
  61. package/components/ExplorerProjectsNamespaces.vue +30 -33
  62. package/components/FilterPanel.vue +156 -0
  63. package/components/FixedBanner.vue +19 -5
  64. package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
  65. package/components/GlobalRoleBindings.vue +112 -48
  66. package/components/GrowlManager.vue +16 -15
  67. package/components/IconOrSvg.vue +19 -35
  68. package/components/IndentedPanel.vue +4 -10
  69. package/components/KeyValueView.vue +1 -1
  70. package/components/LandingPagePreference.vue +2 -0
  71. package/components/Loading.vue +1 -1
  72. package/components/LocaleSelector.vue +10 -2
  73. package/components/PaginatedResourceTable.vue +53 -1
  74. package/components/ProgressBarMulti.vue +1 -0
  75. package/components/PromptModal.vue +38 -7
  76. package/components/PromptRemove.vue +8 -4
  77. package/components/PromptRestore.vue +22 -44
  78. package/components/RelatedResources.vue +4 -12
  79. package/components/Resource/Detail/Additional.vue +46 -0
  80. package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
  81. package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
  82. package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
  83. package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
  84. package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
  85. package/components/Resource/Detail/Card/Scaler.vue +89 -0
  86. package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
  87. package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
  88. package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
  89. package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
  90. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
  91. package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
  92. package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
  93. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
  94. package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
  95. package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
  96. package/components/Resource/Detail/Card/index.vue +56 -0
  97. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
  98. package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
  99. package/components/Resource/Detail/Metadata/Annotations/index.vue +31 -0
  100. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  101. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
  102. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +72 -0
  103. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
  104. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +140 -0
  105. package/components/Resource/Detail/Metadata/KeyValue.vue +140 -0
  106. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
  107. package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
  108. package/components/Resource/Detail/Metadata/Labels/index.vue +31 -0
  109. package/components/Resource/Detail/Metadata/Rectangle.vue +34 -0
  110. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
  111. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
  112. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  113. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
  114. package/components/Resource/Detail/Metadata/composables.ts +81 -0
  115. package/components/Resource/Detail/Metadata/index.vue +88 -0
  116. package/components/Resource/Detail/Page.vue +37 -0
  117. package/components/Resource/Detail/PercentageBar.vue +40 -0
  118. package/components/Resource/Detail/ResourceRow.vue +138 -0
  119. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  120. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  121. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  122. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  123. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  124. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  125. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  126. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  127. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  128. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  129. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  130. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  131. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  132. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  133. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  134. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  135. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  136. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  137. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  138. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  139. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  140. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  141. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  142. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  143. package/components/Resource/Detail/SpacedRow.vue +14 -0
  144. package/components/Resource/Detail/StatusBar.vue +59 -0
  145. package/components/Resource/Detail/StatusRow.vue +61 -0
  146. package/components/Resource/Detail/TitleBar/Title.vue +14 -0
  147. package/components/Resource/Detail/TitleBar/Top.vue +14 -0
  148. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
  149. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
  150. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  151. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
  152. package/components/Resource/Detail/TitleBar/composables.ts +46 -0
  153. package/components/Resource/Detail/TitleBar/index.vue +204 -0
  154. package/components/Resource/Detail/Top/index.vue +34 -0
  155. package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
  156. package/components/Resource/Detail/composables.ts +45 -0
  157. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  158. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  159. package/components/ResourceDetail/Masthead/index.vue +65 -0
  160. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  161. package/components/{rancherResourceDetail/Masthead.vue → ResourceDetail/Masthead/legacy.vue} +36 -16
  162. package/components/ResourceDetail/__tests__/index.test.ts +135 -0
  163. package/components/ResourceDetail/index.vue +75 -560
  164. package/components/{rancherResourceDetail/index.vue → ResourceDetail/legacy.vue} +28 -55
  165. package/components/ResourceList/Masthead.vue +188 -85
  166. package/components/ResourceList/ResourceLoadingIndicator.vue +5 -2
  167. package/components/ResourceList/index.vue +3 -2
  168. package/components/ResourceTable.vue +65 -16
  169. package/components/ResourceYaml.vue +15 -2
  170. package/components/RichTranslation.vue +106 -0
  171. package/components/SideNav.vue +66 -29
  172. package/components/SlideInPanelManager.vue +116 -14
  173. package/components/SortableTable/THead.vue +6 -0
  174. package/components/SortableTable/index.vue +490 -389
  175. package/components/SortableTable/paging.js +15 -16
  176. package/components/SortableTable/selection.js +22 -10
  177. package/components/StateDot/index.vue +28 -0
  178. package/components/StatusBadge.vue +6 -4
  179. package/components/SubtleLink.vue +25 -0
  180. package/components/Tabbed/Tab.vue +1 -1
  181. package/components/Tabbed/index.vue +65 -69
  182. package/components/Wizard.vue +16 -3
  183. package/components/YamlEditor.vue +1 -2
  184. package/components/__tests__/AsyncButton.test.ts +39 -0
  185. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  186. package/components/__tests__/CruResource.test.ts +63 -0
  187. package/components/__tests__/FilterPanel.test.ts +81 -0
  188. package/components/__tests__/GrowlManager.test.ts +0 -25
  189. package/components/__tests__/PromptModal.test.ts +146 -0
  190. package/components/__tests__/PromptRestore.test.ts +1 -65
  191. package/components/__tests__/RichTranslation.test.ts +115 -0
  192. package/components/auth/AuthBanner.vue +15 -14
  193. package/components/auth/Principal.vue +2 -2
  194. package/components/auth/RoleDetailEdit.vue +101 -8
  195. package/components/auth/SelectPrincipal.vue +1 -0
  196. package/components/auth/login/ldap.vue +2 -2
  197. package/components/auth/login/oidc.vue +6 -1
  198. package/components/fleet/FleetApplications.vue +174 -0
  199. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  200. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  201. package/components/fleet/FleetClusters.vue +25 -6
  202. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  203. package/components/fleet/FleetHelmOps.vue +123 -0
  204. package/components/fleet/FleetIntro.vue +58 -28
  205. package/components/fleet/FleetNoWorkspaces.vue +5 -1
  206. package/components/fleet/FleetOCIStorageSecret.vue +171 -0
  207. package/components/fleet/FleetRepos.vue +37 -80
  208. package/components/fleet/FleetResources.vue +69 -27
  209. package/components/fleet/FleetSummary.vue +26 -51
  210. package/components/fleet/FleetValuesFrom.vue +295 -0
  211. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  212. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  213. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
  214. package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
  215. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  216. package/components/fleet/dashboard/Empty.vue +73 -0
  217. package/components/fleet/dashboard/ResourceCard.vue +184 -0
  218. package/components/fleet/dashboard/ResourceCardSummary.vue +195 -0
  219. package/components/fleet/dashboard/ResourceDetails.vue +194 -0
  220. package/components/fleet/dashboard/ResourcePanel.vue +384 -0
  221. package/components/form/ArrayList.vue +144 -116
  222. package/components/form/BannerSettings.vue +130 -61
  223. package/components/form/ChangePassword.vue +7 -5
  224. package/components/form/ColorInput.vue +67 -14
  225. package/components/form/FileImageSelector.vue +1 -1
  226. package/components/form/Footer.vue +11 -5
  227. package/components/form/InputWithSelect.vue +2 -0
  228. package/components/form/KeyValue.vue +118 -53
  229. package/components/form/LabeledSelect.vue +219 -201
  230. package/components/form/Labels.vue +91 -21
  231. package/components/form/MatchExpressions.vue +56 -9
  232. package/components/form/Members/ClusterPermissionsEditor.vue +1 -2
  233. package/components/form/Members/MembershipEditor.vue +1 -1
  234. package/components/form/NameNsDescription.vue +31 -14
  235. package/components/form/Networking.vue +24 -19
  236. package/components/form/NotificationSettings.vue +15 -1
  237. package/components/form/Password.vue +6 -2
  238. package/components/form/ResourceLabeledSelect.vue +22 -8
  239. package/components/form/ResourceQuota/Namespace.vue +1 -1
  240. package/components/form/ResourceQuota/NamespaceRow.vue +13 -10
  241. package/components/form/ResourceQuota/ProjectRow.vue +0 -1
  242. package/components/form/ResourceSelector.vue +27 -23
  243. package/components/form/ResourceTabs/index.vue +7 -1
  244. package/components/form/SSHKnownHosts/index.vue +14 -11
  245. package/components/form/SecretSelector.vue +18 -2
  246. package/components/form/Select.vue +59 -28
  247. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  248. package/components/form/SimpleSecretSelector.vue +17 -4
  249. package/components/form/Taints.vue +21 -2
  250. package/components/form/UnitInput.vue +21 -0
  251. package/components/form/ValueFromResource.vue +31 -19
  252. package/components/form/__tests__/ArrayList.test.ts +32 -0
  253. package/components/form/__tests__/ColorInput.test.ts +35 -0
  254. package/components/form/__tests__/KeyValue.test.ts +36 -0
  255. package/components/form/__tests__/LabeledSelect.test.ts +79 -2
  256. package/components/form/__tests__/Labels.test.ts +360 -0
  257. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  258. package/components/form/__tests__/Networking.test.ts +116 -0
  259. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -2
  260. package/components/form/__tests__/Select.test.ts +37 -1
  261. package/components/form/__tests__/UnitInput.test.ts +23 -1
  262. package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
  263. package/components/formatter/ClusterLink.vue +5 -8
  264. package/components/formatter/Description.vue +30 -0
  265. package/components/formatter/FleetApplicationClustersReady.vue +77 -0
  266. package/components/formatter/FleetApplicationSource.vue +79 -0
  267. package/components/formatter/FleetSummaryGraph.vue +7 -0
  268. package/components/formatter/PodImages.vue +1 -1
  269. package/components/formatter/WorkloadHealthScale.vue +1 -1
  270. package/components/formatter/__tests__/ClusterLink.test.ts +2 -32
  271. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  272. package/components/google/AccountAccess.vue +209 -0
  273. package/components/google/types/gcp.d.ts +136 -0
  274. package/components/google/types/index.d.ts +101 -0
  275. package/components/google/util/__mocks__/gcp.ts +465 -0
  276. package/components/google/util/formatter.ts +82 -0
  277. package/components/google/util/gcp.ts +134 -0
  278. package/components/google/util/index.d.ts +11 -0
  279. package/components/nav/Favorite.vue +6 -2
  280. package/components/nav/Group.vue +74 -23
  281. package/components/nav/Header.vue +103 -52
  282. package/components/nav/HeaderPageActionMenu.vue +1 -0
  283. package/components/nav/NamespaceFilter.vue +141 -87
  284. package/components/nav/NotificationCenter/Notification.vue +484 -0
  285. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  286. package/components/nav/NotificationCenter/index.vue +148 -0
  287. package/components/nav/TopLevelMenu.helper.ts +55 -34
  288. package/components/nav/TopLevelMenu.vue +193 -119
  289. package/components/nav/Type.vue +52 -12
  290. package/components/nav/WindowManager/ContainerLogs.vue +87 -61
  291. package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
  292. package/components/nav/WindowManager/index.vue +3 -2
  293. package/components/templates/default.vue +0 -3
  294. package/components/templates/plain.vue +0 -3
  295. package/composables/drawer.ts +26 -0
  296. package/composables/focusTrap.ts +3 -3
  297. package/composables/resources.test.ts +63 -0
  298. package/composables/resources.ts +38 -0
  299. package/composables/useClickOutside.ts +1 -1
  300. package/composables/useI18n.ts +12 -11
  301. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  302. package/config/labels-annotations.js +22 -11
  303. package/config/pagination-table-headers.js +8 -1
  304. package/config/private-label.js +0 -1
  305. package/config/product/auth.js +33 -7
  306. package/config/product/{cis.js → compliance.js} +23 -26
  307. package/config/product/explorer.js +48 -16
  308. package/config/product/fleet.js +77 -17
  309. package/config/product/manager.js +1 -29
  310. package/config/product/settings.js +39 -18
  311. package/config/query-params.js +16 -1
  312. package/config/roles.ts +2 -1
  313. package/config/router/navigation-guards/authentication.js +51 -2
  314. package/config/router/navigation-guards/index.js +5 -67
  315. package/config/router/routes.js +65 -31
  316. package/config/secret.ts +15 -0
  317. package/config/settings.ts +61 -16
  318. package/config/store.js +2 -0
  319. package/config/system-namespaces.js +1 -1
  320. package/config/table-headers.js +91 -30
  321. package/config/types.js +18 -7
  322. package/config/version.js +1 -1
  323. package/core/plugin-helpers.ts +3 -2
  324. package/core/plugin.ts +32 -7
  325. package/core/types.ts +25 -7
  326. package/detail/catalog.cattle.io.app.vue +5 -1
  327. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  328. package/detail/fleet.cattle.io.bundle.vue +70 -6
  329. package/detail/fleet.cattle.io.cluster.vue +28 -15
  330. package/detail/fleet.cattle.io.gitrepo.vue +11 -2
  331. package/detail/fleet.cattle.io.helmop.vue +157 -0
  332. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  333. package/detail/management.cattle.io.oidcclient.vue +369 -0
  334. package/detail/namespace.vue +0 -3
  335. package/detail/node.vue +20 -16
  336. package/detail/pod.vue +2 -2
  337. package/detail/provisioning.cattle.io.cluster.vue +16 -50
  338. package/detail/service.vue +10 -2
  339. package/detail/workload/index.vue +48 -39
  340. package/dialog/AddCustomBadgeDialog.vue +0 -1
  341. package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
  342. package/dialog/AddonConfigConfirmationDialog.vue +1 -1
  343. package/dialog/AssignToDialog.vue +176 -0
  344. package/dialog/ChangePasswordDialog.vue +106 -0
  345. package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
  346. package/dialog/DisableAuthProviderDialog.vue +101 -0
  347. package/dialog/DrainNode.vue +1 -1
  348. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
  349. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +87 -66
  350. package/dialog/FeatureFlagListDialog.vue +288 -0
  351. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  352. package/dialog/GenericPrompt.vue +1 -1
  353. package/dialog/HelmOpForceUpdateDialog.vue +132 -0
  354. package/{components/Import.vue → dialog/ImportDialog.vue} +8 -13
  355. package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
  356. package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -62
  357. package/dialog/MoveNamespaceDialog.vue +157 -0
  358. package/dialog/OidcClientSecretDialog.vue +117 -0
  359. package/dialog/RedeployWorkloadDialog.vue +164 -0
  360. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  361. package/dialog/ScalePoolDownDialog.vue +1 -1
  362. package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
  363. package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
  364. package/dialog/WechatDialog.vue +57 -0
  365. package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +15 -34
  366. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  367. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +60 -68
  368. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  369. package/edit/__tests__/service.test.ts +2 -1
  370. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  371. package/edit/auth/ldap/config.vue +24 -0
  372. package/edit/auth/oidc.vue +159 -93
  373. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  374. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  375. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  376. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  377. package/edit/configmap.vue +8 -2
  378. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  379. package/edit/fleet.cattle.io.gitrepo.vue +70 -256
  380. package/edit/fleet.cattle.io.helmop.vue +786 -0
  381. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  382. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  383. package/edit/logging-flow/index.vue +1 -0
  384. package/edit/logging.banzaicloud.io.output/index.vue +2 -1
  385. package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
  386. package/edit/management.cattle.io.fleetworkspace.vue +44 -10
  387. package/edit/management.cattle.io.oidcclient.vue +162 -0
  388. package/edit/management.cattle.io.project.vue +4 -1
  389. package/edit/management.cattle.io.user.vue +17 -4
  390. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  391. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  392. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  393. package/edit/monitoring.coreos.com.receiver/auth.vue +3 -3
  394. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  395. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  396. package/edit/monitoring.coreos.com.route.vue +1 -0
  397. package/edit/namespace.vue +2 -4
  398. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  399. package/edit/networking.k8s.io.ingress/Certificate.vue +11 -3
  400. package/edit/networking.k8s.io.ingress/RulePath.vue +1 -1
  401. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +37 -0
  402. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  403. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -14
  404. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +57 -62
  405. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +10 -16
  406. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.test.ts +72 -41
  407. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +17 -1
  408. package/edit/networking.k8s.io.networkpolicy/index.vue +23 -31
  409. package/edit/node.vue +1 -0
  410. package/edit/persistentvolume/index.vue +4 -1
  411. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
  412. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +69 -2
  413. package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
  414. package/edit/provisioning.cattle.io.cluster/index.vue +21 -73
  415. package/edit/provisioning.cattle.io.cluster/rke2.vue +535 -428
  416. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
  417. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
  418. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  419. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
  420. package/edit/resources.cattle.io.restore.vue +1 -1
  421. package/edit/secret/basic.vue +1 -0
  422. package/edit/secret/index.vue +127 -15
  423. package/edit/service.vue +17 -29
  424. package/edit/serviceaccount.vue +4 -1
  425. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  426. package/edit/token.vue +1 -1
  427. package/edit/workload/index.vue +11 -15
  428. package/edit/workload/mixins/workload.js +0 -2
  429. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  430. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  431. package/list/fleet.cattle.io.helmop.vue +108 -0
  432. package/list/management.cattle.io.feature.vue +4 -288
  433. package/list/management.cattle.io.oidcclient.vue +108 -0
  434. package/list/management.cattle.io.setting.vue +22 -13
  435. package/list/management.cattle.io.user.vue +7 -3
  436. package/list/namespace.vue +6 -2
  437. package/list/node.vue +2 -0
  438. package/list/projectsecret.vue +345 -0
  439. package/list/provisioning.cattle.io.cluster.vue +6 -7
  440. package/list/secret.vue +109 -0
  441. package/list/workload.vue +6 -2
  442. package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
  443. package/machine-config/amazonec2.vue +3 -24
  444. package/machine-config/components/GCEImage.vue +374 -0
  445. package/machine-config/google.vue +617 -0
  446. package/machine-config/vmwarevsphere.vue +7 -17
  447. package/mixins/__tests__/brand.spec.ts +170 -0
  448. package/mixins/auth-config.js +8 -1
  449. package/mixins/brand.js +33 -17
  450. package/mixins/create-edit-view/impl.js +10 -1
  451. package/mixins/create-edit-view/index.js +5 -0
  452. package/mixins/preset.js +100 -0
  453. package/mixins/resource-fetch-api-pagination.js +73 -44
  454. package/mixins/resource-fetch.js +18 -8
  455. package/mixins/resource-table-watch.js +45 -0
  456. package/mixins/vue-select-overrides.js +1 -4
  457. package/models/__tests__/chart.test.ts +296 -0
  458. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  459. package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  460. package/models/__tests__/node.test.ts +7 -63
  461. package/models/__tests__/workload.test.ts +1 -0
  462. package/models/chart.js +157 -2
  463. package/models/cluster/node.js +2 -1
  464. package/models/cluster.js +32 -2
  465. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  466. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  467. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  468. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  469. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  470. package/models/fleet-application.js +297 -0
  471. package/models/fleet.cattle.io.bundle.js +9 -8
  472. package/models/fleet.cattle.io.cluster.js +21 -4
  473. package/models/fleet.cattle.io.gitrepo.js +46 -382
  474. package/models/fleet.cattle.io.helmop.js +202 -0
  475. package/models/management.cattle.io.authconfig.js +1 -0
  476. package/models/management.cattle.io.cluster.js +0 -20
  477. package/models/management.cattle.io.feature.js +7 -1
  478. package/models/management.cattle.io.fleetworkspace.js +14 -1
  479. package/models/management.cattle.io.node.js +7 -22
  480. package/models/management.cattle.io.nodepool.js +12 -0
  481. package/models/management.cattle.io.oidcclient.js +18 -0
  482. package/models/management.cattle.io.registration.js +3 -0
  483. package/models/management.cattle.io.setting.js +0 -1
  484. package/models/namespace.js +12 -1
  485. package/models/provisioning.cattle.io.cluster.js +60 -97
  486. package/models/secret.js +157 -2
  487. package/models/service.js +28 -9
  488. package/models/storage.k8s.io.storageclass.js +2 -2
  489. package/models/workload.js +91 -51
  490. package/package.json +6 -5
  491. package/pages/about.vue +17 -61
  492. package/pages/account/index.vue +9 -1
  493. package/pages/auth/login.vue +50 -30
  494. package/pages/auth/verify.vue +13 -1
  495. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +36 -0
  496. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
  497. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +57 -0
  498. package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
  499. package/pages/c/_cluster/apps/charts/index.vue +501 -468
  500. package/pages/c/_cluster/apps/charts/install.vue +0 -1
  501. package/pages/c/_cluster/auth/roles/index.vue +19 -1
  502. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  503. package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
  504. package/pages/c/_cluster/explorer/index.vue +14 -3
  505. package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
  506. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  507. package/pages/c/_cluster/fleet/__tests__/index.test.ts +720 -0
  508. package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
  509. package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
  510. package/pages/c/_cluster/fleet/application/create.vue +341 -0
  511. package/pages/c/_cluster/fleet/application/index.vue +139 -0
  512. package/pages/c/_cluster/fleet/graph/config.js +277 -0
  513. package/pages/c/_cluster/fleet/index.vue +866 -328
  514. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  515. package/pages/c/_cluster/longhorn/index.vue +5 -2
  516. package/pages/c/_cluster/settings/banners.vue +230 -103
  517. package/pages/c/_cluster/settings/brand.vue +349 -301
  518. package/pages/c/_cluster/settings/performance.vue +68 -64
  519. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  520. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  521. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
  522. package/pages/c/_cluster/uiplugins/index.vue +98 -55
  523. package/pages/explorer/resource/detail/configmap.vue +42 -0
  524. package/pages/explorer/resource/detail/projectsecret.vue +9 -0
  525. package/pages/explorer/resource/detail/secret.vue +63 -0
  526. package/pages/home.vue +61 -108
  527. package/pages/prefs.vue +25 -24
  528. package/pages/support/index.vue +4 -6
  529. package/pkg/tsconfig.json +9 -9
  530. package/pkg/vue.config.js +1 -1
  531. package/plugins/clean-html.js +2 -0
  532. package/plugins/dashboard-store/__tests__/actions.test.ts +4 -1
  533. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  534. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  535. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  536. package/plugins/dashboard-store/actions.js +212 -55
  537. package/plugins/dashboard-store/getters.js +112 -24
  538. package/plugins/dashboard-store/mutations.js +61 -12
  539. package/plugins/dashboard-store/normalize.js +29 -19
  540. package/plugins/dashboard-store/resource-class.js +132 -49
  541. package/plugins/steve/__tests__/getters.test.ts +19 -12
  542. package/plugins/steve/__tests__/steve-class.test.ts +1 -0
  543. package/plugins/steve/__tests__/subscribe.spec.ts +324 -1
  544. package/plugins/steve/actions.js +37 -24
  545. package/plugins/steve/getters.js +47 -12
  546. package/plugins/steve/resourceWatcher.js +10 -3
  547. package/plugins/steve/steve-class.js +5 -0
  548. package/plugins/steve/steve-pagination-utils.ts +225 -43
  549. package/plugins/steve/subscribe.js +418 -53
  550. package/plugins/steve/worker/web-worker.advanced.js +5 -1
  551. package/promptRemove/mixin/roleDeletionCheck.js +2 -2
  552. package/rancher-components/Banner/Banner.test.ts +51 -3
  553. package/rancher-components/Banner/Banner.vue +37 -6
  554. package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
  555. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -9
  556. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +51 -0
  557. package/rancher-components/Form/LabeledInput/LabeledInput.vue +21 -3
  558. package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
  559. package/rancher-components/Form/Radio/RadioButton.vue +21 -5
  560. package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
  561. package/rancher-components/Form/Radio/RadioGroup.vue +81 -38
  562. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +4 -0
  563. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +22 -1
  564. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  565. package/rancher-components/RcButton/RcButton.vue +1 -1
  566. package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
  567. package/rancher-components/RcDropdown/RcDropdown.vue +6 -0
  568. package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -55
  569. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +69 -0
  570. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +93 -0
  571. package/rancher-components/RcDropdown/RcDropdownMenu.vue +7 -8
  572. package/rancher-components/RcDropdown/index.ts +2 -0
  573. package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
  574. package/rancher-components/RcDropdown/useDropdownItem.ts +92 -0
  575. package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
  576. package/rancher-components/RcItemCard/RcItemCard.vue +430 -0
  577. package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
  578. package/rancher-components/RcItemCard/index.ts +2 -0
  579. package/rancher-components/StringList/StringList.vue +1 -1
  580. package/scripts/clean +0 -0
  581. package/scripts/extension/bundle +0 -0
  582. package/scripts/extension/helm/scripts/package +0 -0
  583. package/scripts/extension/helm/scripts/patch +0 -0
  584. package/scripts/extension/helm/scripts/version +0 -0
  585. package/scripts/extension/helmpatch +0 -0
  586. package/scripts/extension/parse-tag-name +0 -0
  587. package/scripts/extension/publish +1 -1
  588. package/scripts/publish-shell.sh +86 -60
  589. package/scripts/serve-pkgs +0 -0
  590. package/scripts/sync-shell-deps +0 -0
  591. package/scripts/typegen.sh +44 -28
  592. package/static/loading-indicator.html +1 -1
  593. package/store/action-menu.js +26 -56
  594. package/store/auth.js +3 -0
  595. package/store/catalog.js +85 -25
  596. package/store/features.js +0 -1
  597. package/store/growl.js +97 -8
  598. package/store/i18n.js +5 -5
  599. package/store/index.js +44 -14
  600. package/store/notifications.ts +426 -0
  601. package/store/prefs.js +11 -5
  602. package/store/slideInPanel.ts +6 -0
  603. package/store/type-map.js +34 -17
  604. package/store/type-map.utils.ts +49 -6
  605. package/store/uiplugins.ts +15 -1
  606. package/types/fleet.d.ts +60 -1
  607. package/types/kube/kube-api.ts +34 -0
  608. package/types/notifications/index.ts +74 -0
  609. package/types/resources/fleet.d.ts +43 -0
  610. package/types/resources/pod-security-admission.ts +36 -0
  611. package/types/resources/settings.d.ts +107 -0
  612. package/types/resources/userPreferences.d.ts +13 -0
  613. package/types/shell/index.d.ts +971 -745
  614. package/types/store/dashboard-store.types.ts +57 -4
  615. package/types/store/pagination.types.ts +41 -9
  616. package/types/store/subscribe.types.ts +50 -0
  617. package/utils/__mocks__/tabbable.js +13 -0
  618. package/utils/__tests__/back-off.test.ts +354 -0
  619. package/utils/__tests__/create-yaml.test.ts +235 -0
  620. package/utils/__tests__/fleet.test.ts +148 -0
  621. package/utils/__tests__/kontainer.test.ts +19 -0
  622. package/utils/__tests__/object.test.ts +54 -1
  623. package/utils/__tests__/string.test.ts +273 -1
  624. package/utils/__tests__/time.test.ts +31 -0
  625. package/utils/auth.js +41 -6
  626. package/utils/back-off.ts +176 -0
  627. package/utils/cluster.js +24 -20
  628. package/utils/create-yaml.js +103 -9
  629. package/utils/crypto/encryption.ts +103 -0
  630. package/utils/cspAdaptor.ts +51 -0
  631. package/utils/error.js +4 -5
  632. package/utils/fleet-types.ts +0 -0
  633. package/utils/fleet.ts +204 -74
  634. package/utils/grafana.js +1 -0
  635. package/utils/kontainer.ts +3 -5
  636. package/utils/object.js +36 -12
  637. package/utils/pagination-utils.ts +50 -3
  638. package/utils/pagination-wrapper.ts +132 -50
  639. package/utils/perf-setting.utils.ts +28 -0
  640. package/utils/release-notes.ts +48 -0
  641. package/utils/selector-typed.ts +210 -0
  642. package/utils/selector.js +29 -6
  643. package/utils/settings.ts +4 -1
  644. package/utils/string.js +24 -0
  645. package/utils/style.ts +39 -0
  646. package/utils/{time.js → time.ts} +25 -6
  647. package/utils/uiplugins.ts +41 -8
  648. package/utils/v-sphere.ts +5 -1
  649. package/utils/validators/formRules/__tests__/index.test.ts +76 -6
  650. package/utils/validators/formRules/index.ts +99 -4
  651. package/utils/window.js +11 -7
  652. package/vue.config.js +1 -6
  653. package/.DS_Store +0 -0
  654. package/components/AssignTo.vue +0 -199
  655. package/components/DisableAuthProviderModal.vue +0 -115
  656. package/components/MoveModal.vue +0 -167
  657. package/components/PromptChangePassword.vue +0 -123
  658. package/components/ResourceDetail/Masthead.vue +0 -842
  659. package/components/__tests__/ApplicationCard.test.ts +0 -27
  660. package/components/cards/ApplicationCard.vue +0 -145
  661. package/components/fleet/FleetBundleResources.vue +0 -86
  662. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
  663. package/components/formatter/RKETemplateName.vue +0 -37
  664. package/components/rancherResourceDetail/__tests__/Masthead.test.ts +0 -65
  665. package/components/rancherResourceList/Masthead-btn.vue +0 -225
  666. package/components/rancherResourceList/Masthead.vue +0 -375
  667. package/components/rancherResourceList/ResourceLoadingIndicator.vue +0 -140
  668. package/components/rancherResourceList/index.vue +0 -307
  669. package/components/rancherResourceList/resource-list.config.js +0 -7
  670. package/components/rancherResourceTable.vue +0 -783
  671. package/components/rancherSortableTable/THead.vue +0 -561
  672. package/components/rancherSortableTable/actions.js +0 -153
  673. package/components/rancherSortableTable/advanced-filtering.js +0 -272
  674. package/components/rancherSortableTable/debug.js +0 -117
  675. package/components/rancherSortableTable/filtering.js +0 -290
  676. package/components/rancherSortableTable/grouping.js +0 -48
  677. package/components/rancherSortableTable/index.vue +0 -2712
  678. package/components/rancherSortableTable/paging.js +0 -155
  679. package/components/rancherSortableTable/selection.js +0 -629
  680. package/components/rancherSortableTable/sortable-config.ts +0 -4
  681. package/components/rancherSortableTable/sorting.js +0 -129
  682. package/config/product/legacy.js +0 -62
  683. package/config/secret.js +0 -14
  684. package/dialog/SaveAsRKETemplateDialog.vue +0 -139
  685. package/models/etcdbackup.js +0 -45
  686. package/pages/auth copy/login.vue +0 -595
  687. package/pages/auth copy/logout.vue +0 -47
  688. package/pages/auth copy/setup.vue +0 -523
  689. package/pages/auth copy/verify.vue +0 -203
  690. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
  691. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  692. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  693. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  694. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
  695. package/types/cloud-shell/index.d.ts +0 -11014
@@ -1,2712 +0,0 @@
1
- <script>
2
- import { mapGetters, useStore } from 'vuex';
3
- import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from 'vue';
4
- import day from 'dayjs';
5
- import isEmpty from 'lodash/isEmpty';
6
- import { dasherize, ucFirst } from '@shell/utils/string';
7
- import { get, clone } from '@shell/utils/object';
8
- import { removeObject } from '@shell/utils/array';
9
- import { Checkbox } from '@components/Form/Checkbox';
10
- import AsyncButton, { ASYNC_BUTTON_STATES } from '@shell/components/AsyncButton';
11
- import Select from '@shell/components/form/Select';
12
- import ActionDropdown from '@shell/components/ActionDropdown';
13
- import throttle from 'lodash/throttle';
14
- import debounce from 'lodash/debounce';
15
- import THead from './THead';
16
- import filtering from './filtering';
17
- import selection from './selection';
18
- import sorting from './sorting';
19
- import paging from './paging';
20
- import grouping from './grouping';
21
- import actions from './actions';
22
- import AdvancedFiltering from './advanced-filtering';
23
- import LabeledSelect from '@shell/components/form/LabeledSelect';
24
- import { getParent } from '@shell/utils/dom';
25
- import { FORMATTERS } from '@shell/components/SortableTable/sortable-config';
26
- import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
27
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
28
- import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
29
- import ActionDropdownShell from '@shell/components/ActionDropdownShell.vue';
30
- import { harvesterhci2cloud, cloud2harvesterhci } from '@shell/utils/router'
31
-
32
- // Uncomment for table performance debugging
33
- // import tableDebug from './debug';
34
-
35
- // @TODO:
36
- // Fixed header/scrolling
37
-
38
- // Data Flow:
39
- // rows prop
40
- // --> sorting.js arrangedRows
41
- // --> filtering.js handleFiltering()
42
- // --> filtering.js filteredRows
43
- // --> paging.js pageRows
44
- // --> grouping.js groupedRows
45
- // --> index.vue displayRows
46
-
47
- export default {
48
- name: 'SortableTable',
49
-
50
- emits: [
51
- 'clickedActionButton',
52
- 'pagination-changed',
53
- 'group-value-change',
54
- 'selection',
55
- 'rowClick',
56
- 'enter',
57
- ],
58
-
59
- components: {
60
- THead,
61
- Checkbox,
62
- AsyncButton,
63
- Select,
64
- ActionDropdown,
65
- LabeledSelect,
66
- ButtonMultiAction,
67
- ActionMenu,
68
- ActionDropdownShell,
69
- },
70
- mixins: [
71
- filtering,
72
- sorting,
73
- paging,
74
- grouping,
75
- selection,
76
- actions,
77
- AdvancedFiltering,
78
- // For table performance debugging - uncomment and uncomment the corresponding import
79
- // tableDebug,
80
- ],
81
-
82
- props: {
83
- headers: {
84
- // {
85
- // name: Name for the column (goes in query param) and for defaultSortBy
86
- // label: Displayed column header
87
- // sort: string|array[string] Field name(s) to sort by, default: [name, keyField]
88
- // fields can be suffixed with ':desc' to flip the normal sort order
89
- // search: string|array[string] Field name(s) to search in, default: [name]
90
- // width: number
91
- // }
92
- type: Array,
93
- required: true
94
- },
95
-
96
- rows: {
97
- // The array of objects to show
98
- type: Array,
99
- required: true
100
- },
101
-
102
- keyField: {
103
- // Field that is unique for each row.
104
- type: String,
105
- default: '_key',
106
- },
107
-
108
- loading: {
109
- type: Boolean,
110
- required: false
111
- },
112
-
113
- /**
114
- * Alt Loading - True: Always show table rows and obscure them when `loading`. Intended for use with server-side pagination.
115
- *
116
- * Alt Loading - False: Hide the table rows when `loading`. Intended when all resources are provided up front.
117
- */
118
- altLoading: {
119
- type: Boolean,
120
- required: false
121
- },
122
-
123
- groupBy: {
124
- // Field to group rows by, row[groupBy] must be something that can be a map key
125
- type: String,
126
- default: null
127
- },
128
- groupRef: {
129
- // Object to provide as the reference for rendering the grouping row
130
- type: String,
131
- default: null,
132
- },
133
- groupSort: {
134
- // Field to order groups by, defaults to groupBy
135
- type: Array,
136
- default: null
137
- },
138
-
139
- defaultSortBy: {
140
- // Default field to sort by if none is specified
141
- // uses name on headers
142
- type: String,
143
- default: null
144
- },
145
-
146
- tableActions: {
147
- // Show bulk table actions
148
- type: Boolean,
149
- default: true
150
- },
151
-
152
- rowActions: {
153
- // Show action dropdown on the end of each row
154
- type: Boolean,
155
- default: true
156
- },
157
-
158
- mangleActionResources: {
159
- type: Function,
160
- default: null,
161
- },
162
-
163
- rowActionsWidth: {
164
- // How wide the action dropdown column should be
165
- type: Number,
166
- default: 40
167
- },
168
-
169
- search: {
170
- // Show search input to filter rows
171
- type: Boolean,
172
- default: true
173
- },
174
-
175
- extraSearchFields: {
176
- // Additional fields that aren't defined in the headers to search in on each row
177
- type: Array,
178
- default: null
179
- },
180
-
181
- subRows: {
182
- // If there are sub-rows, your main row must have <tr class="main-row"> to identify it
183
- type: Boolean,
184
- default: false,
185
- },
186
-
187
- subRowsDescription: {
188
- type: Boolean,
189
- default: true,
190
- },
191
-
192
- subExpandable: {
193
- type: Boolean,
194
- default: false,
195
- },
196
-
197
- subExpandColumn: {
198
- type: Boolean,
199
- default: false,
200
- },
201
-
202
- subSearch: {
203
- // A field containing an array of sub-items to also search in for each row
204
- type: String,
205
- default: null,
206
- },
207
-
208
- subFields: {
209
- // Search this list of fields within the items in "subSearch" of each row
210
- type: Array,
211
- default: null,
212
- },
213
-
214
- /**
215
- * Show the divider between the thead and tbody.
216
- */
217
- topDivider: {
218
- type: Boolean,
219
- default: true
220
- },
221
-
222
- /**
223
- * Show the dividers between rows
224
- */
225
- bodyDividers: {
226
- type: Boolean,
227
- default: false
228
- },
229
-
230
- overflowX: {
231
- type: Boolean,
232
- default: false
233
- },
234
- overflowY: {
235
- type: Boolean,
236
- default: false
237
- },
238
-
239
- /**
240
- * If pagination of the data is enabled or not
241
- */
242
- paging: {
243
- type: Boolean,
244
- default: false,
245
- },
246
-
247
- /**
248
- * What translation key to use for displaying the '1 - 10 of 100 Things' pagination info
249
- */
250
- pagingLabel: {
251
- type: String,
252
- default: 'sortableTable.paging.generic'
253
- },
254
-
255
- /**
256
- * Additional params to pass to the pagingLabel translation
257
- */
258
- pagingParams: {
259
- type: Object,
260
- default: null,
261
- },
262
-
263
- /**
264
- * Allows you to override the default preference of the number of
265
- * items to display per page. This is used by ./paging.js if you're
266
- * looking for a reference.
267
- */
268
- rowsPerPage: {
269
- type: Number,
270
- default: null, // Default comes from the user preference
271
- },
272
-
273
- /**
274
- * Allows you to override the default translation text of no rows view
275
- */
276
- noRowsKey: {
277
- type: String,
278
- default: 'sortableTable.noRows'
279
- },
280
-
281
- /**
282
- * Allows you to hide the no rows messaging.
283
- */
284
- showNoRows: {
285
- type: Boolean,
286
- default: true
287
- },
288
-
289
- /**
290
- * Allows you to override the default translation text of no search data view
291
- */
292
- noDataKey: {
293
- type: String,
294
- default: 'sortableTable.noData' // i18n-uses sortableTable.noData
295
- },
296
-
297
- /**
298
- * Allows you to override showing the THEAD section.
299
- */
300
- showHeaders: {
301
- type: Boolean,
302
- default: true
303
- },
304
-
305
- /**
306
- * Provide a unique key that will provide a new value given changes to the environment that
307
- * should kick off an update to table rows (for instance resource list generation or change of namespace)
308
- *
309
- * This does not have to update given internal facets like sort order or direction
310
- */
311
- sortGenerationFn: {
312
- type: Function,
313
- default: null,
314
- },
315
-
316
- /**
317
- * Can be used in place of sortGenerationFn
318
- */
319
- sortGeneration: {
320
- type: String,
321
- default: null
322
- },
323
-
324
- /**
325
- * The list will always be sorted by these regardless of what the user has selected
326
- */
327
- mandatorySort: {
328
- type: Array,
329
- default: null,
330
- },
331
-
332
- /**
333
- * Allows you to link to a custom detail page for data that
334
- * doesn't have a class model. For example, a receiver configuration
335
- * block within an AlertmanagerConfig resource.
336
- */
337
- getCustomDetailLink: {
338
- type: Function,
339
- default: null
340
- },
341
-
342
- /**
343
- * Inherited global identifier prefix for tests
344
- * Define a term based on the parent component to avoid conflicts on multiple components
345
- */
346
- componentTestid: {
347
- type: String,
348
- default: 'sortable-table'
349
- },
350
- /**
351
- * Allows for the usage of a query param to work for simple filtering (q)
352
- */
353
- useQueryParamsForSimpleFiltering: {
354
- type: Boolean,
355
- default: false
356
- },
357
- /**
358
- * Manaul force the update of live and delayed cells. Change this number to kick off the update
359
- */
360
- forceUpdateLiveAndDelayed: {
361
- type: Number,
362
- default: 0
363
- },
364
-
365
- /**
366
- * True if pagination is executed outside of the component
367
- */
368
- externalPaginationEnabled: {
369
- type: Boolean,
370
- default: false
371
- },
372
-
373
- /**
374
- * If `externalPaginationEnabled` is true this will be used as the current page
375
- */
376
- externalPaginationResult: {
377
- type: Object,
378
- default: null
379
- },
380
-
381
- manualRefreshButtonSize: {
382
- type: String,
383
- default: ''
384
- },
385
- isBanner: {
386
- // Show isBanner input to filter rows
387
- type: Boolean,
388
- default: false
389
- },
390
- marginTopValue: {
391
- type: Number,
392
- default: 0
393
- },
394
- isFilterLabel: {
395
- type: Boolean,
396
- default: false
397
- },
398
- searchPlaceholder: {
399
- // search框内的输入提示
400
- type: String,
401
- default: ''
402
- },
403
-
404
- },
405
-
406
- data() {
407
- let searchQuery = '';
408
- let eventualSearchQuery = '';
409
-
410
- // only allow for filter query param for simple filtering for now...
411
- if (!this.hasAdvancedFiltering && this.useQueryParamsForSimpleFiltering && this.$route.query?.q) {
412
- searchQuery = this.$route.query?.q;
413
- eventualSearchQuery = this.$route.query?.q;
414
- }
415
-
416
- const isLoading = this.loading || false;
417
-
418
- let isCreatable = false;
419
- const lastPath = this.$route.path.split('/'.pop());
420
-
421
- if (lastPath.includes('.')) {
422
- isCreatable = this.$store.getters['type-map/optionsFor'](lastPath).isCreatable;
423
- } else if (lastPath === 'namespace') {
424
- isCreatable = this.$store.getters['type-map/optionsFor'](this.$route.name).isCreatable;
425
- }
426
-
427
- return {
428
- refreshButtonPhase: isLoading ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION,
429
- expanded: {},
430
- searchQuery,
431
- eventualSearchQuery,
432
- isCreatable,
433
- subMatches: null,
434
- actionOfInterest: null,
435
- loadingDelay: false,
436
- debouncedPaginationChanged: null,
437
- /**
438
- * The is the bool the DOM uses to show loading state. it's proxied from `loading` to avoid blipping the indicator (see usages)
439
- */
440
- isLoading,
441
- isMuchSelected: false,
442
- inputPerPage: '10',
443
- inputPage: '', // 输入的要跳至的页码
444
- perPageOptions: [
445
- {
446
- label: '10条/页',
447
- value: '10',
448
- },
449
- {
450
- label: '25条/页',
451
- value: '25',
452
- },
453
- {
454
- label: '50条/页',
455
- value: '50',
456
- },
457
- {
458
- label: '100条/页',
459
- value: '100',
460
- }
461
- ]
462
- };
463
- },
464
-
465
- mounted() {
466
- this._loadingDelayTimer = setTimeout(() => {
467
- this.loadingDelay = true;
468
- }, 200);
469
-
470
- // Add scroll listener to the main element
471
- const $main = document.querySelector('main');
472
-
473
- this._onScroll = this.onScroll.bind(this);
474
- $main?.addEventListener('scroll', this._onScroll);
475
-
476
- const tables = document.querySelectorAll('.sort-table-div');
477
-
478
- tables.forEach((table) => {
479
- this._onTableScroll = this.onTableScroll.bind(this, table);
480
- table.addEventListener('scroll', this._onTableScroll.bind(this, table));
481
- });
482
-
483
- this.debouncedPaginationChanged();
484
- },
485
-
486
- beforeUnmount() {
487
- clearTimeout(this._scrollTimer);
488
- clearTimeout(this._loadingDelayTimer);
489
- clearTimeout(this._altLoadingDelayTimer);
490
- clearTimeout(this._liveColumnsTimer);
491
- clearTimeout(this._delayedColumnsTimer);
492
- clearTimeout(this.manualRefreshTimer);
493
-
494
- const $main = document.querySelector('main');
495
-
496
- $main?.removeEventListener('scroll', this._onScroll);
497
- // 移除所有表格容器的滚动事件监听器
498
- const tables = document.querySelectorAll('.sort-table-div');
499
-
500
- tables.forEach((table) => {
501
- table.removeEventListener('scroll', this._onTableScroll);
502
- });
503
- },
504
-
505
- watch: {
506
- eventualSearchQuery: debounce(function(q) {
507
- this.searchQuery = q;
508
-
509
- if (!this.hasAdvancedFiltering && this.useQueryParamsForSimpleFiltering) {
510
- const route = {
511
- name: this.$route.name,
512
- params: { ...this.$route.params },
513
- query: { ...this.$route.query, q }
514
- };
515
-
516
- if (!q && this.$route.query?.q) {
517
- route.query = {};
518
- }
519
-
520
- this.$router.replace(route);
521
- }
522
- }, 200),
523
-
524
- descending(neu, old) {
525
- this.watcherUpdateLiveAndDelayed(neu, old);
526
- },
527
-
528
- searchQuery(neu, old) {
529
- this.watcherUpdateLiveAndDelayed(neu, old);
530
- },
531
-
532
- sortFields(neu, old) {
533
- this.watcherUpdateLiveAndDelayed(neu, old);
534
- },
535
-
536
- groupBy(neu, old) {
537
- this.watcherUpdateLiveAndDelayed(neu, old);
538
- },
539
-
540
- namespaces(neu, old) {
541
- this.watcherUpdateLiveAndDelayed(neu, old);
542
- },
543
-
544
- page(neu, old) {
545
- this.watcherUpdateLiveAndDelayed(neu, old);
546
- },
547
-
548
- forceUpdateLiveAndDelayed(neu, old) {
549
- this.watcherUpdateLiveAndDelayed(neu, old);
550
- },
551
-
552
- selectedRowsText(neu, old) {
553
- if (neu) {
554
- this.isMuchSelected = true;
555
- } else {
556
- this.isMuchSelected = false;
557
- }
558
- },
559
-
560
- // Ensure we update live and delayed columns on first load
561
- initalLoad: {
562
- handler(neu) {
563
- if (neu) {
564
- this._didinit = true;
565
- this.$nextTick(() => this.updateLiveAndDelayed());
566
- }
567
- },
568
- immediate: true
569
- },
570
-
571
- // this is the flag that indicates that manual refresh data has been loaded
572
- // and we should update the deferred cols
573
- manualRefreshLoadingFinished: {
574
- handler(neu, old) {
575
- // this is merely to update the manual refresh button status
576
- this.refreshButtonPhase = !neu ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION;
577
- if (neu && neu !== old) {
578
- this.$nextTick(() => this.updateLiveAndDelayed());
579
- }
580
- },
581
- immediate: true
582
- },
583
-
584
- loading: {
585
- handler(neu, old) {
586
- // Always ensure the Refresh button phase aligns with loading state (to ensure external phase changes which can then reset the internal phase changed by click)
587
- this.refreshButtonPhase = neu ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION;
588
-
589
- if (this.altLoading) {
590
- // Delay setting the actual loading indicator. This should avoid flashing up the indicator if the API responds quickly
591
- if (neu) {
592
- this._altLoadingDelayTimer = setTimeout(() => {
593
- this.isLoading = true;
594
- }, 200); // this should be higher than the targeted quick response
595
- } else {
596
- clearTimeout(this._altLoadingDelayTimer);
597
- this.isLoading = false;
598
- }
599
- } else {
600
- this.isLoading = neu;
601
- }
602
- },
603
- immediate: true
604
- },
605
- },
606
- setup(_props, { emit }) {
607
- const table = ref(null);
608
-
609
- const handleEnterKey = (event) => {
610
- if (event.key === 'Enter' && !event.target?.classList?.contains('checkbox-custom')) {
611
- emit('enter', event);
612
- }
613
- };
614
-
615
-
616
- onBeforeUnmount(() => {
617
- table.value.removeEventListener('keyup', handleEnterKey);
618
- });
619
-
620
- const store = useStore();
621
- const { featureDropdownMenu } = useRuntimeFlag(store);
622
-
623
- onMounted(() => {
624
- table.value.addEventListener('keyup', handleEnterKey);
625
-
626
- console.log(featureDropdownMenu, ' featureDropdownMenu---------------------');
627
-
628
-
629
- });
630
-
631
- return {
632
- table,
633
- featureDropdownMenu,
634
- };
635
- },
636
-
637
- created() {
638
- this.debouncedRefreshTableData = debounce(this.refreshTableData, 500);
639
- this.debouncedPaginationChanged = debounce(this.paginationChanged, 50);
640
- },
641
-
642
- computed: {
643
- ...mapGetters({ isTooManyItemsToAutoUpdate: 'resource-fetch/isTooManyItemsToAutoUpdate' }),
644
- ...mapGetters({ isManualRefreshLoading: 'resource-fetch/manualRefreshIsLoading' }),
645
- namespaces() {
646
- return this.$store.getters['activeNamespaceCache'];
647
- },
648
-
649
- initalLoad() {
650
- return !!(!this.isLoading && !this._didinit && this.rows?.length);
651
- },
652
-
653
- manualRefreshLoadingFinished() {
654
- const res = !!(!this.isLoading && this._didinit && this.rows?.length && !this.isManualRefreshLoading);
655
-
656
- return res;
657
- },
658
-
659
- fullColspan() {
660
- let span = 0;
661
-
662
- for ( let i = 0 ; i < this.columns.length ; i++ ) {
663
- if (!this.columns[i].hide) {
664
- span++;
665
- }
666
- }
667
-
668
- if ( this.tableActions ) {
669
- span++;
670
- }
671
-
672
- if ( this.subExpandColumn ) {
673
- span++;
674
- }
675
-
676
- if ( this.rowActions ) {
677
- span++;
678
- }
679
-
680
- return span;
681
- },
682
-
683
- noResults() {
684
- return !!this.searchQuery && this.pagedRows.length === 0;
685
- },
686
-
687
- noRows() {
688
- return !this.noResults && (this.rows || []).length === 0;
689
- },
690
-
691
- showHeaderRow() {
692
- // All of these are used to show content in the header
693
- return this.search ||
694
- this.tableActions ||
695
- this.$slots['header-left'] ||
696
- this.$slots['header-middle'] ||
697
- this.$slots['header-right'] ||
698
- this.isTooManyItemsToAutoUpdate;
699
- },
700
-
701
- columns() {
702
- // Filter out any columns that are too heavy to show for large page sizes
703
- const out = this.headers.slice().filter((c) => !c.maxPageSize || (c.maxPageSize && c.maxPageSize >= this.perPage));
704
-
705
- if ( this.groupBy ) {
706
- const entry = out.find((x) => x.name === this.groupBy);
707
-
708
- if ( entry ) {
709
- removeObject(out, entry);
710
- }
711
- }
712
-
713
- // If all columns have a width, try to remove it from a column that can be variable (name)
714
- const missingWidth = out.find((x) => !x.width);
715
-
716
- if ( !missingWidth ) {
717
- const variable = out.find((x) => x.canBeVariable);
718
-
719
- if ( variable ) {
720
- const neu = clone(variable);
721
-
722
- delete neu.width;
723
-
724
- out.splice(out.indexOf(variable), 1, neu);
725
- }
726
- }
727
-
728
- // handle cols visibility and filtering if there is advanced filtering
729
- if (this.hasAdvancedFiltering) {
730
- const cols = this.handleColsVisibilyAndFiltering(out);
731
-
732
- return cols;
733
- }
734
-
735
- return out;
736
- },
737
-
738
- // For data-title properties on <td>s
739
- dt() {
740
- const out = {
741
- check: `Select: `,
742
- actions: `Actions: `,
743
- };
744
-
745
- this.columns.forEach((col) => {
746
- out[col.name] = `${ (col.label || col.name) }:`;
747
- });
748
-
749
- return out;
750
- },
751
-
752
- classObject() {
753
- return {
754
- 'top-divider': this.topDivider,
755
- 'body-dividers': this.bodyDividers,
756
- 'overflow-y': this.overflowY,
757
- 'overflow-x': this.overflowX,
758
- 'alt-loading': this.altLoading && this.isLoading
759
- };
760
- },
761
-
762
- // Do we have any live columns?
763
- hasLiveColumns() {
764
- const liveColumns = this.columns.find((c) => c.formatter?.startsWith('Live') || c.liveUpdates);
765
-
766
- return !!liveColumns;
767
- },
768
-
769
- hasDelayedColumns() {
770
- const delaeydColumns = this.columns.find((c) => c.delayLoading);
771
-
772
- return !!delaeydColumns;
773
- },
774
-
775
- columnFormmatterIDs() {
776
- const columnsIds = {};
777
-
778
- this.columns.forEach((c) => {
779
- if (c.formatter) {
780
- columnsIds[c.formatter] = dasherize(c.formatter);
781
- }
782
- });
783
-
784
- return columnsIds;
785
- },
786
-
787
- // Generate row and column data for easier rendering in the template
788
- // ensures we only call methods like `valueFor` once
789
- displayRows() {
790
- const rows = [];
791
- const columnFormmatterIDs = this.columnFormmatterIDs;
792
-
793
- this.groupedRows.forEach((grp) => {
794
- const group = {
795
- grp,
796
- key: grp.key,
797
- ref: grp.ref,
798
- rows: [],
799
- };
800
-
801
- rows.push(group);
802
-
803
- grp.rows.forEach((row) => {
804
- const rowData = {
805
- row,
806
- key: this.get(row, this.keyField),
807
- showSubRow: this.showSubRow(row, this.keyField),
808
- canRunBulkActionOfInterest: this.canRunBulkActionOfInterest(row),
809
- columns: []
810
- };
811
-
812
- group.rows.push(rowData);
813
-
814
- this.columns.forEach((c) => {
815
- const value = c.delayLoading ? undefined : this.valueFor(row, c, c.isLabel);
816
- let component;
817
- let formatted = value;
818
- let needRef = false;
819
-
820
- if (Array.isArray(value)) {
821
- formatted = value.join(', ');
822
- }
823
-
824
- if (c.formatter) {
825
- if (FORMATTERS[c.formatter]) {
826
- component = FORMATTERS[c.formatter];
827
- needRef = true;
828
- } else {
829
- // Check if we have a formatter from a plugin
830
- const pluginFormatter = this.$plugin?.getDynamic('formatters', c.formatter);
831
-
832
- if (pluginFormatter) {
833
- component = defineAsyncComponent(pluginFormatter);
834
- needRef = true;
835
- }
836
- }
837
- }
838
-
839
- rowData.columns.push({
840
- col: c,
841
- value,
842
- formatted,
843
- component,
844
- needRef,
845
- delayed: c.delayLoading,
846
- live: c.formatter?.startsWith('Live') || c.liveUpdates,
847
- label: this.labelFor(c),
848
- dasherize: columnFormmatterIDs[c.formatter] || '',
849
- });
850
- });
851
- });
852
- });
853
-
854
- return rows;
855
- },
856
- },
857
-
858
- methods: {
859
- // getTableList () {
860
- // const q = this.eventualSearchQuery;
861
-
862
- // this.searchQuery = q;
863
-
864
- // if (!this.hasAdvancedFiltering && this.useQueryParamsForSimpleFiltering) {
865
- // const route = {
866
- // name: this.$route.name,
867
- // params: { ...this.$route.params },
868
- // query: { ...this.$route.query, q }
869
- // };
870
-
871
- // if (!q && this.$route.query?.q) {
872
- // route.query = {};
873
- // }
874
-
875
- // this.$router.replace(route);
876
- // }
877
- // },
878
- onTableScroll(table, e) {
879
- // 记录最后滚动的距离
880
- let lastScrollTop = 0;
881
- let lastScrollLeft = 0;
882
-
883
- // 监听容器滚动
884
- table.addEventListener('scroll', (e) => {
885
- // 如果当前垂直滚动距离不等于上次
886
- if (e.target.scrollTop !== lastScrollTop) {
887
- // 更新最后距离
888
- lastScrollTop = e.target.scrollTop;
889
-
890
- // 移除左右阴影样式
891
- table.classList.remove('shadow-left');
892
- table.classList.remove('shadow-right');
893
-
894
- // 如果滚动到顶部,移除顶部阴影样式
895
- // if (lastScrollTop === 0) {
896
- // table.classList.remove('shadow-top');
897
- // }
898
- // // 否则添加顶部阴影样式
899
- // else {
900
- // table.classList.add('shadow-top');
901
- // }
902
-
903
- // 如果滚动到底部,移除底部阴影样式
904
- // if (lastScrollTop + table.clientHeight === table.scrollHeight) {
905
- // table.classList.remove('shadow-bottom');
906
- // }
907
- // // 否则添加底部阴影样式
908
- // else {
909
- // table.classList.add('shadow-bottom');
910
- // }
911
-
912
- // 阴影效果修正
913
- table.classList.remove('shadow-x');
914
- table.classList.add('shadow-y');
915
- }
916
-
917
- // 如果当前水平滚动距离不等于上次
918
- else if (e.target.scrollLeft !== lastScrollLeft) {
919
- // 更新最后距离
920
- lastScrollLeft = e.target.scrollLeft;
921
-
922
- // 移除上下阴影样式
923
- // table.classList.remove('shadow-top');
924
- // table.classList.remove('shadow-bottom');
925
-
926
- // 如果滚动到左边,移除左边阴影样式
927
- if (lastScrollLeft === 0) {
928
- table.classList.remove('shadow-left');
929
- }
930
- // 否则添加左边阴影样式
931
- else {
932
- table.classList.add('shadow-left');
933
- }
934
-
935
- // 如果滚动到右边,移除右边阴影样式
936
- if (lastScrollLeft + table.clientWidth === table.scrollWidth) {
937
- table.classList.remove('shadow-right');
938
- }
939
- // 否则添加右边阴影样式
940
- else {
941
- table.classList.add('shadow-right');
942
- }
943
-
944
- // 阴影效果修正
945
- table.classList.remove('shadow-y');
946
- table.classList.add('shadow-x');
947
- }
948
- });
949
- },
950
- changePerPage(value) {
951
- this.inputPerPage = value;
952
- this.setgetPerPage(value);
953
- },
954
- handleToPage() {
955
- this.setPage(parseInt(this.inputPage, 10));
956
- },
957
- refreshTableData() {
958
- this.$store.dispatch('resource-fetch/doManualRefresh');
959
- },
960
- get,
961
- dasherize,
962
- muchSelect(value) {
963
- console.log(value);
964
-
965
- this.isMuchSelected = !this.isMuchSelected;
966
- this.onToggleAll(value);
967
- },
968
-
969
- onScroll() {
970
- if (this.hasLiveColumns || this.hasDelayedColumns) {
971
- clearTimeout(this._liveColumnsTimer);
972
- clearTimeout(this._scrollTimer);
973
- clearTimeout(this._delayedColumnsTimer);
974
- this._scrollTimer = setTimeout(() => {
975
- this.updateLiveColumns();
976
- this.updateDelayedColumns();
977
- }, 300);
978
- }
979
- },
980
-
981
- watcherUpdateLiveAndDelayed(neu, old) {
982
- if (neu !== old) {
983
- this.$nextTick(() => this.updateLiveAndDelayed());
984
- }
985
- },
986
-
987
- updateLiveAndDelayed() {
988
- if (this.hasLiveColumns) {
989
- this.updateLiveColumns();
990
- }
991
-
992
- if (this.hasDelayedColumns) {
993
- this.updateDelayedColumns();
994
- }
995
- },
996
-
997
- updateDelayedColumns() {
998
- clearTimeout(this._delayedColumnsTimer);
999
-
1000
- if (!this.$refs.column || this.pagedRows.length === 0) {
1001
- return;
1002
- }
1003
-
1004
- const delayedColumns = this.$refs.column.filter((c) => c.startDelayedLoading && !c.__delayedLoading);
1005
- // We add 100 pixels here - so we will render the delayed columns for a few extra rows below what is visible
1006
- // This way if you scroll slowly, you won't see the columns being loaded
1007
- const clientHeight = (window.innerHeight || document.documentElement.clientHeight) + 100;
1008
-
1009
- let scheduled = 0;
1010
-
1011
- for (let i = 0; i < delayedColumns.length; i++) {
1012
- const dc = delayedColumns[i];
1013
- const y = dc.$el.getBoundingClientRect().y;
1014
-
1015
- if (y >= 0 && y <= clientHeight) {
1016
- dc.startDelayedLoading(true);
1017
- dc.__delayedLoading = true;
1018
-
1019
- scheduled++;
1020
-
1021
- // Only update 4 at a time
1022
- if (scheduled === 4) {
1023
- this._delayedColumnsTimer = setTimeout(this.updateDelayedColumns, 100);
1024
-
1025
- return;
1026
- }
1027
- }
1028
- }
1029
- },
1030
-
1031
- updateLiveColumns() {
1032
- clearTimeout(this._liveColumnsTimer);
1033
-
1034
- if (!this.$refs.column || !this.hasLiveColumns || this.pagedRows.length === 0) {
1035
- return;
1036
- }
1037
-
1038
- const clientHeight = window.innerHeight || document.documentElement.clientHeight;
1039
- const liveColumns = this.$refs.column.filter((c) => !!c.liveUpdate);
1040
- const now = day();
1041
- let next = Number.MAX_SAFE_INTEGER;
1042
-
1043
- for (let i = 0; i < liveColumns.length; i++) {
1044
- const column = liveColumns[i];
1045
- const y = column.$el.getBoundingClientRect().y;
1046
-
1047
- if (y >= 0 && y <= clientHeight) {
1048
- const diff = column.liveUpdate(now);
1049
-
1050
- if (diff < next) {
1051
- next = diff;
1052
- }
1053
- }
1054
- }
1055
-
1056
- if (next < 1 ) {
1057
- next = 1;
1058
- }
1059
-
1060
- // Schedule again
1061
- this._liveColumnsTimer = setTimeout(() => this.updateLiveColumns(), next * 1000);
1062
- },
1063
-
1064
- labelFor(col) {
1065
- if ( col.labelKey ) {
1066
- return this.t(col.labelKey, undefined, true);
1067
- } else if ( col.label ) {
1068
- return col.label;
1069
- }
1070
-
1071
- return ucFirst(col.name);
1072
- },
1073
-
1074
- valueFor(row, col, isLabel) {
1075
- if (typeof col.value === 'function') {
1076
- return col.value(row);
1077
- }
1078
-
1079
- if (isLabel) {
1080
- if (row.metadata?.labels && row.metadata?.labels[col.label]) {
1081
- return row.metadata?.labels[col.label];
1082
- }
1083
-
1084
- return '';
1085
- }
1086
-
1087
- // Use to debug table columns using expensive value getters
1088
- // console.warn(`Performance: Table valueFor: ${ col.name } ${ col.value }`); // eslint-disable-line no-console
1089
-
1090
- const expr = col.value || col.name;
1091
-
1092
- if (!expr) {
1093
- console.error('No path has been defined for this column, unable to get value of cell', col); // eslint-disable-line no-console
1094
-
1095
- return '';
1096
- }
1097
- const out = get(row, expr);
1098
-
1099
- if ( out === null || out === undefined ) {
1100
- return '';
1101
- }
1102
-
1103
- return out;
1104
- },
1105
-
1106
- isExpanded(row) {
1107
- const key = row[this.keyField];
1108
-
1109
- return !!this.expanded[key];
1110
- },
1111
-
1112
- toggleExpand(row) {
1113
- const key = row[this.keyField];
1114
- const val = !this.expanded[key];
1115
-
1116
- this.expanded[key] = val;
1117
- this.expanded = { ...this.expanded };
1118
-
1119
- return val;
1120
- },
1121
-
1122
- setBulkActionOfInterest(action) {
1123
- this.actionOfInterest = action;
1124
- },
1125
-
1126
- // Can the action of interest be applied to the specified resource?
1127
- canRunBulkActionOfInterest(resource) {
1128
- if ( !this.actionOfInterest || isEmpty(resource?.availableActions) ) {
1129
- return false;
1130
- }
1131
-
1132
- const matchingResourceAction = resource.availableActions?.find((a) => a.action === this.actionOfInterest.action);
1133
-
1134
- return matchingResourceAction?.enabled;
1135
- },
1136
-
1137
- focusSearch() {
1138
- if ( this.$refs.searchQuery ) {
1139
- this.$refs.searchQuery.focus();
1140
- this.$refs.searchQuery.select();
1141
- }
1142
- },
1143
-
1144
- nearestCheckbox() {
1145
- return document.activeElement.closest('tr.main-row')?.querySelector('.checkbox-custom');
1146
- },
1147
-
1148
- focusAdjacent(next = true) {
1149
- const all = Array.from(this.$el.querySelectorAll('.checkbox-custom'));
1150
-
1151
- const cur = this.nearestCheckbox();
1152
- let idx = -1;
1153
-
1154
- if ( cur ) {
1155
- idx = all.indexOf(cur) + (next ? 1 : -1 );
1156
- } else if ( next ) {
1157
- idx = 1;
1158
- } else {
1159
- idx = all.length - 1;
1160
- }
1161
-
1162
- if ( idx < 1 ) { // Don't go up to the check all button
1163
- idx = 1;
1164
-
1165
- return null;
1166
- }
1167
-
1168
- if ( idx >= all.length ) {
1169
- idx = all.length - 1;
1170
-
1171
- return null;
1172
- }
1173
-
1174
- if ( all[idx] ) {
1175
- all[idx].focus();
1176
-
1177
- return all[idx];
1178
- }
1179
- },
1180
-
1181
- focusNext: throttle(function(event, more = false) {
1182
- const elem = this.focusAdjacent(true);
1183
- const row = getParent(elem, 'tr');
1184
-
1185
- if (row?.classList.contains('row-selected')) {
1186
- return;
1187
- }
1188
-
1189
- this.keySelectRow(row, more);
1190
- }, 50),
1191
-
1192
- focusPrevious: throttle(function(event, more = false) {
1193
- const elem = this.focusAdjacent(false);
1194
- const row = getParent(elem, 'tr');
1195
-
1196
- if (row?.classList.contains('row-selected')) {
1197
- return;
1198
- }
1199
-
1200
- this.keySelectRow(row, more);
1201
- }, 50),
1202
-
1203
- showSubRow(row, keyField) {
1204
- const hasInjectedSubRows = this.subRows && (!this.subExpandable || this.expanded[get(row, keyField)]);
1205
- const hasStateDescription = this.subRowsDescription && row.stateDescription;
1206
-
1207
- return hasInjectedSubRows || hasStateDescription;
1208
- },
1209
-
1210
- handleActionButtonClick(i, event) {
1211
- // Each row in the table gets its own ref with
1212
- // a number based on its index. If you are using
1213
- // an ActionMenu that doen't have a dependency on Vuex,
1214
- // these refs are useful because you can reuse the
1215
- // same ActionMenu component on a page with many different
1216
- // target elements in a list,
1217
- // so you can still avoid the performance problems that
1218
- // could result if the ActionMenu was in every row. The menu
1219
- // will open on whichever target element is clicked.
1220
- this.$emit('clickedActionButton', {
1221
- event,
1222
- targetElement: this.$refs[`actionButton${ i }`][0],
1223
- });
1224
- },
1225
-
1226
- paginationChanged() {
1227
- if (!this.externalPaginationEnabled) {
1228
- return;
1229
- }
1230
-
1231
- this.$emit('pagination-changed', {
1232
- page: this.page,
1233
- perPage: this.perPage,
1234
- filter: {
1235
- searchFields: this.searchFields,
1236
- searchQuery: this.searchQuery
1237
- },
1238
- sort: this.sortFields,
1239
- descending: this.descending
1240
- });
1241
- }
1242
- }
1243
- };
1244
- </script>
1245
-
1246
- <template>
1247
- <div
1248
- ref="container"
1249
- :data-testid="componentTestid + '-list-container'"
1250
- >
1251
- <!-- 主标题和过滤器区域 -->
1252
- <div
1253
- :class="{'titled': $slots.title && $slots.title.length, 'mb-40': isFilterLabel}"
1254
- class="sortable-table-header mb-20"
1255
- >
1256
- <slot name="title" />
1257
-
1258
- <!-- 顶部功能行区域 -->
1259
- <div
1260
- v-if="showHeaderRow"
1261
- class="fixed-header-table-actions"
1262
- :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering, }"
1263
- style="display: flex;"
1264
- >
1265
-
1266
- <!-- 搜索栏、右插槽、刷新按钮、高级筛选等区域 -->
1267
- <div
1268
- v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || $slots['header-right']"
1269
- class="search row"
1270
- data-testid="search-box-filter-row"
1271
- style="max-height: 32px;"
1272
- >
1273
-
1274
- <!-- 已应用的高级筛选 -->
1275
- <ul
1276
- v-if="hasAdvancedFiltering"
1277
- class="advanced-filters-applied"
1278
- >
1279
- <li
1280
- v-for="(filter, i) in advancedFilteringValues"
1281
- :key="i"
1282
- >
1283
- <span class="label">{{ `"${filter.value}" ${ t('sortableTable.in') } ${filter.label}` }}</span>
1284
- <span
1285
- class="cross"
1286
- @click="clearAdvancedFilter(i)"
1287
- >&#10005;</span>
1288
- <div class="bg" />
1289
- </li>
1290
- </ul>
1291
-
1292
- <slot name="header-right" />
1293
-
1294
- <div
1295
- v-if="hasAdvancedFiltering"
1296
- ref="advanced-filter-group"
1297
- class="advanced-filter-group"
1298
- >
1299
- <button
1300
- class="btn role-primary"
1301
- @click="advancedFilteringVisibility = !advancedFilteringVisibility;"
1302
- >
1303
- {{ t('sortableTable.addFilter') }}
1304
- </button>
1305
- <div
1306
- v-show="advancedFilteringVisibility"
1307
- class="advanced-filter-container"
1308
- >
1309
- <input
1310
- ref="advancedSearchQuery"
1311
- v-model="advFilterSearchTerm"
1312
- type="search"
1313
- class="advanced-search-box"
1314
- :placeholder="t('sortableTable.filterFor')"
1315
- >
1316
- <div class="middle-block">
1317
- <span>{{ t('sortableTable.in') }}</span>
1318
- <LabeledSelect
1319
- v-model:value="advFilterSelectedProp"
1320
- class="filter-select"
1321
- :clearable="true"
1322
- :options="advFilterSelectOptions"
1323
- :disabled="false"
1324
- :searchable="false"
1325
- mode="edit"
1326
- :multiple="false"
1327
- :taggable="false"
1328
- :placeholder="t('sortableTable.selectCol')"
1329
- @selecting="(col) => advFilterSelectedLabel = col.label"
1330
- />
1331
- </div>
1332
- <div class="bottom-block">
1333
- <button
1334
- class="btn role-secondary"
1335
- :disabled="!advancedFilteringValues.length"
1336
- @click="clearAllAdvancedFilters"
1337
- >
1338
- {{ t('sortableTable.resetFilters') }}
1339
- </button>
1340
- <button
1341
- class="btn role-primary"
1342
- @click="addAdvancedFilter"
1343
- >
1344
- {{ t('sortableTable.add') }}
1345
- </button>
1346
- </div>
1347
- </div>
1348
- </div>
1349
-
1350
- <!-- 搜索描述文本(隐藏) -->
1351
- <p
1352
- v-else-if="search"
1353
- id="describe-filter-sortable-table"
1354
- hidden
1355
- >
1356
- {{ t('sortableTable.filteringDescription') }}
1357
- </p>
1358
- <slot name="header-button" />
1359
-
1360
- <div style="display: flex;">
1361
-
1362
- <slot name="search-main-button" />
1363
-
1364
- <!-- 搜索输入框 -->
1365
- <input
1366
- v-if="search"
1367
- ref="searchQuery"
1368
- v-model="eventualSearchQuery"
1369
- type="search"
1370
- class="input-sm search-box"
1371
- :aria-label="t('sortableTable.searchLabel')"
1372
- aria-describedby="describe-filter-sortable-table"
1373
- :placeholder="t('sortableTable.search')+searchPlaceholder"
1374
- >
1375
- <!-- <button v-if="search" @click="getTableList(eventualSearchQuery)" calss="search-btn role-secondary">
1376
- 检索
1377
- </button> -->
1378
-
1379
- <!-- 手动刷新按钮 -->
1380
- <AsyncButton
1381
- v-if="isTooManyItemsToAutoUpdate"
1382
- mode="manual-refresh"
1383
- :size="manualRefreshButtonSize"
1384
- :current-phase="refreshButtonPhase"
1385
- @click="debouncedRefreshTableData"
1386
- />
1387
-
1388
- </div>
1389
-
1390
- </div>
1391
-
1392
- <!-- 中间区域插槽 -->
1393
- <div
1394
- v-if="!hasAdvancedFiltering && $slots['header-middle']"
1395
- class="middle"
1396
- style="margin-left: 10px;"
1397
- >
1398
- <slot name="header-middle" />
1399
- </div>
1400
- </div>
1401
- </div>
1402
-
1403
- <div v-if="$slots['banner']">
1404
- <slot name="banner"></slot>
1405
- </div>
1406
-
1407
- <div class="sort-table-div">
1408
- <table
1409
- ref="table"
1410
- class="sortable-table"
1411
- :class="classObject"
1412
- width="100%"
1413
- role="table"
1414
- >
1415
- <THead
1416
- v-if="showHeaders"
1417
- :label-for="labelFor"
1418
- :columns="columns"
1419
- :group="group"
1420
- :group-options="advGroupOptions"
1421
- :has-advanced-filtering="hasAdvancedFiltering"
1422
- :adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
1423
- :table-actions="tableActions"
1424
- :table-cols-options="columnOptions"
1425
- :row-actions="rowActions"
1426
- :sub-expand-column="subExpandColumn"
1427
- :row-actions-width="rowActionsWidth"
1428
- :how-much-selected="howMuchSelected"
1429
- :sort-by="sortBy"
1430
- :default-sort-by="_defaultSortBy"
1431
- :descending="descending"
1432
- :no-rows="noRows"
1433
- :loading="isLoading && !loadingDelay"
1434
- :no-results="noResults"
1435
- @on-toggle-all="onToggleAll"
1436
- @on-sort-change="changeSort"
1437
- @col-visibility-change="changeColVisibility"
1438
- @group-value-change="(val) => $emit('group-value-change', val)"
1439
- @update-cols-options="updateColsOptions"
1440
- />
1441
-
1442
- <!-- Don't display anything if we're loading and the delay has yet to pass -->
1443
- <div v-if="isLoading && !loadingDelay" />
1444
-
1445
- <tbody v-else-if="isLoading && !altLoading">
1446
- <slot name="loading">
1447
- <tr>
1448
- <td :colspan="fullColspan">
1449
- <div class="data-loading">
1450
- <i class="icon-spin icon icon-spinner" />
1451
- <t
1452
- k="generic.loading"
1453
- :raw="true"
1454
- />
1455
- </div>
1456
- </td>
1457
- </tr>
1458
- </slot>
1459
- </tbody>
1460
- <tbody v-else-if="noRows">
1461
- <slot name="no-rows">
1462
- <tr class="no-rows">
1463
- <td :colspan="fullColspan">
1464
- <t
1465
- v-if="showNoRows"
1466
- :k="noRowsKey"
1467
- />
1468
- </td>
1469
- </tr>
1470
- </slot>
1471
- </tbody>
1472
- <tbody v-else-if="noResults">
1473
- <slot name="no-results">
1474
- <tr class="no-results">
1475
- <td
1476
- :colspan="fullColspan"
1477
- class="text-center"
1478
- >
1479
- <t :k="noDataKey" />
1480
- </td>
1481
- </tr>
1482
- </slot>
1483
- </tbody>
1484
- <tbody
1485
- v-for="(groupedRows) in displayRows"
1486
- v-else
1487
- :key="groupedRows.key"
1488
- tabindex="-1"
1489
- :class="{ group: groupBy }"
1490
- >
1491
- <slot
1492
- v-if="groupBy"
1493
- name="group-row"
1494
- :group="groupedRows"
1495
- :fullColspan="fullColspan"
1496
- >
1497
- <tr class="group-row">
1498
- <td :colspan="fullColspan">
1499
- <slot
1500
- name="group-by"
1501
- :group="groupedRows.grp"
1502
- >
1503
- <div
1504
- v-trim-whitespace
1505
- class="group-tab"
1506
- >
1507
- {{ groupedRows.ref }}
1508
- </div>
1509
- </slot>
1510
- </td>
1511
- </tr>
1512
- </slot>
1513
- <template
1514
- v-for="(row, i) in groupedRows.rows"
1515
- :key="i"
1516
- >
1517
- <slot
1518
- name="main-row"
1519
- :row="row.row"
1520
- >
1521
- <slot
1522
- :name="'main-row:' + (row.row.mainRowKey || i)"
1523
- :full-colspan="fullColspan"
1524
- >
1525
- <!-- The data-cant-run-bulk-action-of-interest attribute is being used instead of :class because
1526
- because our selection.js invokes toggleClass and :class clobbers what was added by toggleClass if
1527
- the value of :class changes. -->
1528
- <tr
1529
- class="main-row"
1530
- :data-testid="componentTestid + '-' + i + '-row'"
1531
- :class="{ 'has-sub-row': row.showSubRow}"
1532
- :data-node-id="row.key"
1533
- :data-cant-run-bulk-action-of-interest="actionOfInterest && !row.canRunBulkActionOfInterest"
1534
- >
1535
- <td
1536
- v-if="tableActions"
1537
- class="row-check"
1538
- align="middle"
1539
- >
1540
- {{ row.mainRowKey }}
1541
- <Checkbox
1542
- class="selection-checkbox"
1543
- :data-node-id="row.key"
1544
- :data-testid="componentTestid + '-' + i + '-checkbox'"
1545
- :value="selectedRows.includes(row.row)"
1546
- :alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
1547
- />
1548
- </td>
1549
- <td
1550
- v-if="subExpandColumn"
1551
- class="row-expand"
1552
- align="middle"
1553
- >
1554
- <i
1555
- data-title="Toggle Expand"
1556
- :class="{
1557
- icon: true,
1558
- 'icon-chevron-right': !expanded[row.row[keyField]],
1559
- 'icon-chevron-down': !!expanded[row.row[keyField]]
1560
- }"
1561
- @click.stop="toggleExpand(row.row)"
1562
- />
1563
- </td>
1564
- <template
1565
- v-for="(col, j) in row.columns"
1566
- :key="j"
1567
- >
1568
- <slot
1569
- :name="'col:' + col.col.name"
1570
- :row="row.row"
1571
- :col="col.col"
1572
- :dt="dt"
1573
- :expanded="expanded"
1574
- :rowKey="row.key"
1575
- >
1576
- <td
1577
- v-show="!hasAdvancedFiltering || (hasAdvancedFiltering && col.col.isColVisible)"
1578
- :key="col.col.name"
1579
- :data-title="col.col.label"
1580
- :data-testid="`sortable-cell-${ i }-${ j }`"
1581
- :align="'left'"
1582
- :class="{['col-'+col.dasherize]: !!col.col.formatter, [col.col.breakpoint]: !!col.col.breakpoint, ['skip-select']: col.col.skipSelect}"
1583
- :width="col.col.width"
1584
- >
1585
- <slot
1586
- :name="'cell:' + col.col.name"
1587
- :row="row.row"
1588
- :col="col.col"
1589
- :value="col.value"
1590
- >
1591
- <component
1592
- :is="col.component"
1593
- v-if="col.component && col.needRef"
1594
- ref="column"
1595
- :value="col.value"
1596
- :row="row.row"
1597
- :col="col.col"
1598
- :get-custom-detail-link="getCustomDetailLink"
1599
- v-bind="col.col.formatterOpts"
1600
- :row-key="row.key"
1601
- />
1602
- <component
1603
- :is="col.component"
1604
- v-else-if="col.component"
1605
- :value="col.value"
1606
- :row="row.row"
1607
- :col="col.col"
1608
- v-bind="col.col.formatterOpts"
1609
- :row-key="row.key"
1610
- />
1611
- <component
1612
- :is="col.col.formatter"
1613
- v-else-if="col.col.formatter"
1614
- :value="col.value"
1615
- :row="row.row"
1616
- :col="col.col"
1617
- v-bind="col.col.formatterOpts"
1618
- :row-key="row.key"
1619
- />
1620
- <template v-else-if="col.value !== ''">
1621
- {{ col.formatted }}
1622
- </template>
1623
- <template v-else-if="col.col.dashIfEmpty">
1624
- <span class="text-muted">&mdash;</span>
1625
- </template>
1626
- </slot>
1627
- </td>
1628
- </slot>
1629
- </template>
1630
- <td
1631
- v-if="rowActions"
1632
- :align="'left'"
1633
- style="height:60px"
1634
- >
1635
- <div style="display: flex;align-items: center;">
1636
- <slot
1637
- name="row-actions"
1638
- :row="row.row"
1639
- :index="i"
1640
- >
1641
- </slot>
1642
- <template v-if="featureDropdownMenu">
1643
- <ActionMenu
1644
- :resource="row.row"
1645
- :data-testid="componentTestid + '-' + i + '-action-button'"
1646
- :button-aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1647
- />
1648
- </template>
1649
- <template v-else>
1650
- <ButtonMultiAction
1651
- :id="`actionButton+${i}+${(row.row && row.row.name) ? row.row.name : ''}`"
1652
- :ref="`actionButton${i}`"
1653
- aria-haspopup="true"
1654
- aria-expanded="false"
1655
- :aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1656
- :data-testid="componentTestid + '-' + i + '-action-button'"
1657
- :borderless="true"
1658
- @click="handleActionButtonClick(i, $event)"
1659
- @keyup.enter="handleActionButtonClick(i, $event)"
1660
- @keyup.space="handleActionButtonClick(i, $event)"
1661
- />
1662
- </template>
1663
- </div>
1664
- </td>
1665
- </tr>
1666
- </slot>
1667
- </slot>
1668
- <!-- <slot
1669
- v-if="row.showSubRow"
1670
- name="sub-row"
1671
- :full-colspan="fullColspan"
1672
- :row="row.row"
1673
- :sub-matches="subMatches"
1674
- :keyField="keyField"
1675
- :componentTestid="componentTestid"
1676
- :i="i"
1677
- :onRowMouseEnter="onRowMouseEnter"
1678
- :onRowMouseLeave="onRowMouseLeave"
1679
- >
1680
- <tr
1681
- v-if="row.row.stateDescription"
1682
- :key="row.row[keyField] + '-description'"
1683
- :data-testid="componentTestid + '-' + i + '-row-description'"
1684
- class="state-description sub-row"
1685
- @mouseenter="onRowMouseEnter"
1686
- @mouseleave="onRowMouseLeave"
1687
- >
1688
- <td
1689
- v-if="tableActions"
1690
- class="row-check"
1691
- align="middle"
1692
- />
1693
- <td
1694
- :colspan="fullColspan - (tableActions ? 1: 0)"
1695
- :class="{ 'text-error' : row.row.stateObj.error }"
1696
- >
1697
- {{ row.row.stateDescription }}
1698
- </td>
1699
- </tr>
1700
- </slot> -->
1701
- </template>
1702
- </tbody>
1703
- </table>
1704
- </div>
1705
- <div
1706
- v-if="!noRows && !noResults"
1707
- :class="$route.path=== '/account'? 'chebox-padding':''"
1708
- style="display: flex;justify-content: flex-start;align-content: center;height: 62px;position: sticky;bottom: 0;background-color: var(--header-bg);padding: 15px 20px 0 30px;margin: 0 -20px 0 -20px;z-index:13"
1709
- >
1710
- <div style="display: flex;justify-content: center;height: 32px;">
1711
- <Checkbox
1712
- v-if="tableActions&&availableActions.some(item => item.action != 'download')"
1713
- :value="isMuchSelected"
1714
- class="check"
1715
- data-testid="sortable-table_check_select_all"
1716
- :disabled="noRows || noResults"
1717
- style="display: flex;justify-content: center;align-content: center;"
1718
- @update:value = "muchSelect"
1719
- />
1720
- </div>
1721
- <div
1722
- :class="{'titled': $slots.title && $slots.title.length}"
1723
- class="sortable-table-header"
1724
- style="margin-left: 10px;min-width: 55%;"
1725
- >
1726
- <slot name="title" />
1727
- <div
1728
- v-if="showHeaderRow"
1729
- class="fixed-footer-actions"
1730
- :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering,}"
1731
- >
1732
- <div
1733
- :class="bulkActionsClass"
1734
- class="bulk"
1735
- >
1736
- <slot name="header-left">
1737
- <template v-if="tableActions">
1738
- <button
1739
- v-for="(act) in availableActions"
1740
- :id="act.action"
1741
- :key="act.action"
1742
- v-clean-tooltip="actionTooltip"
1743
- type="button"
1744
- class="btn role-primary"
1745
- :class="{[bulkActionClass]:true}"
1746
- :disabled="!act.enabled"
1747
- :data-testid="componentTestid + '-' + act.action"
1748
- role="button"
1749
- :aria-label="act.label"
1750
- @click="applyTableAction(act, null, $event)"
1751
- @keydown.enter.stop
1752
- @mouseover="setBulkActionOfInterest(act)"
1753
- @mouseleave="setBulkActionOfInterest(null)"
1754
- >
1755
- <i
1756
- v-if="act.icon"
1757
- :class="act.icon"
1758
- />
1759
- <span v-clean-html="act.label" />
1760
- </button>
1761
- <template v-if="featureDropdownMenu">
1762
- <ActionDropdownShell
1763
- :disabled="!selectedRows.length"
1764
- :hidden-actions="hiddenActions"
1765
- :action-tooltip="actionTooltip"
1766
- @click="applyTableAction"
1767
- @mouseover="setBulkActionOfInterest"
1768
- @mouseleave="setBulkActionOfInterest"
1769
- />
1770
- </template>
1771
- <template v-else>
1772
- <ActionDropdown
1773
- :class="bulkActionsDropdownClass"
1774
- class="bulk-actions-dropdown"
1775
- :disable-button="!selectedRows.length"
1776
- size="sm"
1777
- >
1778
- <template #button-content>
1779
- <button
1780
- ref="actionDropDown"
1781
- class="btn bg-primary mr-0"
1782
- :disabled="!selectedRows.length"
1783
- >
1784
- <i class="icon icon-gear" />
1785
- <span>{{ t('sortableTable.bulkActions.collapsed.label') }}</span>
1786
- <i class="ml-10 icon icon-chevron-down" />
1787
- </button>
1788
- </template>
1789
- <template #popover-content>
1790
- <ul class="list-unstyled menu">
1791
- <li
1792
- v-for="(act, i) in hiddenActions"
1793
- :key="i"
1794
- v-close-popper
1795
- v-clean-tooltip="{
1796
- content: actionTooltip,
1797
- placement: 'right'
1798
- }"
1799
- :class="{ disabled: !act.enabled }"
1800
- @click="applyTableAction(act, null, $event)"
1801
- @mouseover="setBulkActionOfInterest(act)"
1802
- @mouseleave="setBulkActionOfInterest(null)"
1803
- >
1804
- <i
1805
- v-if="act.icon"
1806
- :class="act.icon"
1807
- />
1808
- <span v-clean-html="act.label" />
1809
- </li>
1810
- </ul>
1811
- </template>
1812
- </ActionDropdown>
1813
- </template>
1814
- <label
1815
- v-if="selectedRowsText"
1816
- :class="bulkActionAvailabilityClass"
1817
- class="action-availability"
1818
- >
1819
- {{ tableActions&&availableActions.some(item => item.action != 'download') ?selectedRowsText: '' }}
1820
- </label>
1821
-
1822
- </template>
1823
- </slot>
1824
- </div>
1825
- </div>
1826
- </div>
1827
-
1828
- <!-- 分页 -->
1829
- <div
1830
- v-if="showPaging"
1831
- class="paging"
1832
- >
1833
- <div style="height: 100%; align-content: center;">
1834
- 共 {{ filteredRows.length }} 条
1835
- </div>
1836
-
1837
- <button
1838
- type="button"
1839
- class="btn btn-sm role-multi-action page-btn-normal"
1840
- :disabled="page == 1"
1841
- :style="{ color: page <= totalPages ? `var(--default-text) !important` : `var(--paimary)`,border: page <= totalPages ? `solid thin var(--border)` : `solid thin var(--paimary)`}"
1842
- @click="goToPage('prev')"
1843
- >
1844
- <!-- <i class="icon icon-chevron-left" /> -->
1845
- <
1846
- </button>
1847
- <button
1848
- type="button"
1849
- class="btn btn-sm role-multi-action page-btn-normal"
1850
- :style="{ color: (page == 1) ? `var(--primary)`:`var(--default-text) !important`,border: (page == 1) ? `solid thin var(--primary)` : `solid thin var(--border)`}"
1851
- @click="goToPage('first')"
1852
- >
1853
- <!-- <i class="icon icon-chevron-beginning" /> -->
1854
- {{ 1 }}
1855
- </button>
1856
- <template v-if="totalPages > 2">
1857
- <div style="display: flex;flex-direction: row;gap: 10px;">
1858
- <button
1859
- v-if="page - 2 > 1 && page <= totalPages "
1860
- type="button"
1861
- class="btn btn-sm role-multi-action page-btn-normal"
1862
- :style="{ color: `var(--default-text) !important`,border: `solid thin white`}"
1863
- >
1864
- ...
1865
- </button>
1866
- <button
1867
- v-if="page - 1 > 1 && page <= totalPages "
1868
- type="button"
1869
- class="btn btn-sm role-multi-action page-btn-normal"
1870
- :style="{ color: `var(--default-text) !important`,border: `solid thin var(--border)`}"
1871
- @click="setPage(page-1)"
1872
- >
1873
- {{ page-1 }}
1874
- </button>
1875
- <button
1876
- v-if="page > 1 && page < totalPages"
1877
- type="button"
1878
- class="btn btn-sm role-multi-action page-btn-normal"
1879
- :style="{ color: `var(--default-text)`,border: `solid thin var(--primary)`}"
1880
- @click="setPage(page)"
1881
- >
1882
- {{ page }}
1883
- </button>
1884
- <button
1885
- v-if="page + 1 < totalPages "
1886
- type="button"
1887
- class="btn btn-sm role-multi-action page-btn-normal"
1888
- :style="{ color: `var(--default-text) !important`,border: `solid thin var(--border)`}"
1889
- @click="setPage(page+1)"
1890
- >
1891
- {{ page+1 }}
1892
- </button>
1893
- <button
1894
- v-if="page +2 < totalPages "
1895
- type="button"
1896
- class="btn btn-sm role-multi-action page-btn-normal"
1897
- :style="{ color: `var(--default-text) !important`,border: `solid thin white`}"
1898
- >
1899
- ...
1900
- </button>
1901
- </div>
1902
- </template>
1903
- <!-- <button
1904
- type="button"
1905
- class="btn btn-sm role-multi-action"
1906
- style="padding: 0;max-width: 32px;background-color: white !important;"
1907
- >
1908
- {{ page }}
1909
- </button> -->
1910
- <button
1911
- v-if="totalPages > 1"
1912
- type="button"
1913
- class="btn btn-sm role-multi-action page-btn-normal"
1914
- :style="{ color: (page == totalPages) ? `var(--primary)`:`var(--default-text) !important`,border: (page == totalPages) ? `solid thin var(--primary)` : `solid thin var(--border)`}"
1915
- @click="goToPage('last')"
1916
- >
1917
- <!-- <i class="icon icon-chevron-end" /> -->
1918
- {{ totalPages }}
1919
- </button>
1920
- <button
1921
- type="button"
1922
- class="btn btn-sm role-multi-action page-btn-normal"
1923
- :disabled="page == totalPages"
1924
- :style="{ color: page <= totalPages ? `var(--default-text) !important` : `var(--paimary)`,border: page <= totalPages ? `solid thin var(--border)` : `solid thin var(--paimary)`}"
1925
- @click="goToPage('next')"
1926
- >
1927
- <!-- <i class="icon icon-chevron-right" /> -->
1928
- >
1929
- </button>
1930
-
1931
- <!-- 分页页码切换 -->
1932
- <Select
1933
- :mode="inputPerPage"
1934
- :searchable="false"
1935
- :clearable="false"
1936
- :options="perPageOptions"
1937
- v-model:value="inputPerPage"
1938
- class="pageSelect"
1939
- @update:value="changePerPage"
1940
- />
1941
-
1942
- <div style="height: 100%; align-content: center;">
1943
- 跳至
1944
- </div>
1945
- <input
1946
- v-model="inputPage"
1947
- type="number"
1948
- min="1"
1949
- step="1"
1950
- style="padding: 0px 10px;"
1951
- @keyup.enter="handleToPage"
1952
- >
1953
- <div style="height: 100%; align-content: center;">
1954
-
1955
- </div>
1956
- <!-- <button
1957
- type="button"
1958
- class="btn btn-sm role-multi-action"
1959
- style="padding: 0;max-width: 80px;background-color: white !important;"
1960
- @click="setPage(inputPage)"
1961
- >
1962
-
1963
- </button> -->
1964
- </div>
1965
- </div>
1966
- <button
1967
- v-if="search"
1968
- v-shortkey.once="['/']"
1969
- class="hide"
1970
- @shortkey="focusSearch()"
1971
- />
1972
- <template v-if="tableActions">
1973
- <button
1974
- v-shortkey="['j']"
1975
- class="hide"
1976
- @shortkey="focusNext($event)"
1977
- />
1978
- <button
1979
- v-shortkey="['k']"
1980
- class="hide"
1981
- @shortkey="focusPrevious($event)"
1982
- />
1983
- <button
1984
- v-shortkey="['shift','j']"
1985
- class="hide"
1986
- @shortkey="focusNext($event, true)"
1987
- />
1988
- <button
1989
- v-shortkey="['shift','k']"
1990
- class="hide"
1991
- @shortkey="focusPrevious($event, true)"
1992
- />
1993
- <slot name="shortkeys" />
1994
- </template>
1995
- </div>
1996
- </template>
1997
-
1998
- <style lang="scss" scoped>
1999
- .sortable-table.alt-loading {
2000
- opacity: 0.5;
2001
- pointer-events: none;
2002
- }
2003
- .advanced-filter-group {
2004
- position: relative;
2005
- margin-left: 10px;
2006
- .advanced-filter-container {
2007
- position: absolute;
2008
- top: 38px;
2009
- right: 0;
2010
- width: 300px;
2011
- border: 1px solid var(--primary);
2012
- background-color: var(--body-bg);
2013
- padding: 20px;
2014
- z-index: 2;
2015
-
2016
- .middle-block {
2017
- display: flex;
2018
- align-items: center;
2019
- margin-top: 20px;
2020
-
2021
- span {
2022
- margin-right: 20px;
2023
- }
2024
-
2025
- button {
2026
- margin-left: 20px;
2027
- }
2028
- }
2029
-
2030
- .bottom-block {
2031
- display: flex;
2032
- align-items: center;
2033
- margin-top: 40px;
2034
- justify-content: space-between;
2035
- }
2036
- }
2037
- }
2038
-
2039
- .advanced-filters-applied {
2040
- display: inline-flex;
2041
- margin: 0;
2042
- padding: 0;
2043
- list-style: none;
2044
- max-width: 100%;
2045
- flex-wrap: wrap;
2046
- justify-content: flex-end;
2047
-
2048
- li {
2049
- margin: 0 20px 10px 0;
2050
- padding: 2px 5px;
2051
- border: 1px solid;
2052
- display: flex;
2053
- align-items: center;
2054
- position: relative;
2055
- height: 20px;
2056
-
2057
- &:nth-child(4n+1) {
2058
- border-color: var(--success);
2059
-
2060
- .bg {
2061
- background-color: var(--success);
2062
- }
2063
- }
2064
-
2065
- &:nth-child(4n+2) {
2066
- border-color: var(--warning);
2067
-
2068
- .bg {
2069
- background-color: var(--warning);
2070
- }
2071
- }
2072
-
2073
- &:nth-child(4n+3) {
2074
- border-color: var(--info);
2075
-
2076
- .bg {
2077
- background-color: var(--info);
2078
- }
2079
- }
2080
-
2081
- &:nth-child(4n+4) {
2082
- border-color: var(--error);
2083
-
2084
- .bg {
2085
- background-color: var(--error);
2086
- }
2087
- }
2088
-
2089
- .bg {
2090
- position: absolute;
2091
- top: 0;
2092
- left: 0;
2093
- width: 100%;
2094
- height: 100%;
2095
- opacity: 0.2;
2096
- z-index: -1;
2097
- }
2098
-
2099
- .label {
2100
- margin-right: 10px;
2101
- font-size: 11px;
2102
- }
2103
- .cross {
2104
- font-size: 12px;
2105
- font-weight: bold;
2106
- cursor: pointer;
2107
- }
2108
- }
2109
- }
2110
-
2111
- td {
2112
- // Aligns with COLUMN_BREAKPOINTS
2113
- @media only screen and (max-width: map-get($breakpoints, '--viewport-4')) {
2114
- // HIDE column on sizes below 480px
2115
- &.tablet, &.laptop, &.desktop {
2116
- display: none;
2117
- }
2118
- }
2119
- @media only screen and (max-width: map-get($breakpoints, '--viewport-9')) {
2120
- // HIDE column on sizes below 992px
2121
- &.laptop, &.desktop {
2122
- display: none;
2123
- }
2124
- }
2125
- @media only screen and (max-width: map-get($breakpoints, '--viewport-12')) {
2126
- // HIDE column on sizes below 1281px
2127
- &.desktop {
2128
- display: none;
2129
- }
2130
- }
2131
- }
2132
-
2133
- // Loading indicator row
2134
- tr td div.data-loading {
2135
- align-items: center;
2136
- display: flex;
2137
- justify-content: center;
2138
- padding: 20px 0;
2139
- > i {
2140
- font-size: 20px;
2141
- height: 20px;
2142
- margin-right: 5px;
2143
- width: 20px;
2144
- }
2145
- }
2146
-
2147
- .search-box {
2148
- height: 32px;
2149
- margin-left: 0px;
2150
- /* min-width: 180px; */
2151
- min-width: 280px;
2152
- width: 280px !important;
2153
- border: 1px solid rgb(217, 217, 217);
2154
- }
2155
- </style>
2156
-
2157
- <style lang="scss">
2158
- //
2159
- // Important: Almost all selectors in here need to be ">"-ed together so they
2160
- // apply only to the current table, not one nested inside another table.
2161
- //
2162
-
2163
- $group-row-height: 40px;
2164
- $group-separation: 40px;
2165
- $divider-height: 1px;
2166
-
2167
- $separator: 20;
2168
- $remove: 100;
2169
- $spacing: 10px;
2170
-
2171
- .filter-select .vs__selected-options .vs__selected {
2172
- text-align: left;
2173
- }
2174
-
2175
- .sortable-table {
2176
- border-collapse: collapse;
2177
- min-width: 400px;
2178
- border-radius: 5px 5px 0 0;
2179
- border-bottom: 1px solid var(--border);
2180
- /* outline: 1px solid var(--border); */
2181
- background: var(--sortable-table-bg);
2182
- border-radius: 4px;
2183
-
2184
- &.overflow-x {
2185
- overflow-x: visible;
2186
- }
2187
- &.overflow-y {
2188
- overflow-y: visible;
2189
- }
2190
-
2191
- td {
2192
- padding: 8px 5px;
2193
- border: 0;
2194
-
2195
- &:first-child {
2196
- padding-left: 10px;
2197
- }
2198
-
2199
- &:last-child {
2200
- padding-right: 10px;
2201
- }
2202
-
2203
- &.row-check {
2204
- padding-top: 12px;
2205
- }
2206
- }
2207
-
2208
- tbody {
2209
- tr {
2210
- border-bottom: 1px solid var(--sortable-table-top-divider);
2211
- background-color: var(--sortable-table-row-bg);
2212
-
2213
- &.main-row.has-sub-row {
2214
- border-bottom: 0;
2215
- }
2216
-
2217
- // if a main-row is hovered also hover it's sibling sub row. note - the reverse is handled in selection.js
2218
- &.main-row:not(.row-selected):hover + .sub-row {
2219
- background-color: var(--sortable-table-hover-bg);
2220
- }
2221
-
2222
- &:last-of-type {
2223
- border-bottom: 0;
2224
- }
2225
-
2226
- &:hover, &.sub-row-hovered {
2227
- /* background-color: var(--sortable-table-hover-bg); */
2228
- }
2229
-
2230
- &.state-description > td {
2231
- font-size: 13px;
2232
- padding-top: 0;
2233
- overflow-wrap: anywhere;
2234
- }
2235
- }
2236
-
2237
- tr.active-row {
2238
- color: var(--sortable-table-header-bg);
2239
- }
2240
-
2241
- tr.row-selected {
2242
- /* background: var(--sortable-table-selected-bg); */
2243
- }
2244
-
2245
- .no-rows {
2246
- td {
2247
- padding: 30px 0;
2248
- text-align: center;
2249
- }
2250
- }
2251
-
2252
- .no-rows, .no-results {
2253
- &:hover {
2254
- background-color: var(--body-bg);
2255
- }
2256
- }
2257
- .no-results{
2258
- height: 60px;
2259
- }
2260
-
2261
- &.group {
2262
- &:before {
2263
- content: "";
2264
- display: block;
2265
- height: 0px;
2266
- background-color: transparent;
2267
- }
2268
- }
2269
-
2270
- tr.group-row {
2271
- background-color: initial;
2272
-
2273
- &:first-child {
2274
- border-bottom: 2px solid var(--sortable-table-row-bg);
2275
- }
2276
-
2277
- &:not(:first-child) {
2278
- margin-top: 20px;
2279
- }
2280
-
2281
- td {
2282
- padding: 0;
2283
-
2284
- &:first-of-type {
2285
- border-left: 1px solid var(--sortable-table-accent-bg);
2286
- }
2287
- }
2288
-
2289
- .group-tab {
2290
- @include clearfix;
2291
- height: $group-row-height;
2292
- line-height: $group-row-height;
2293
- padding: 0 10px;
2294
- border-radius: 4px 4px 0px 0px;
2295
- background-color: var(--sortable-table-row-bg);
2296
- position: relative;
2297
- top: 1px;
2298
- display: inline-block;
2299
- z-index: z-index('tableGroup');
2300
- min-width: $group-row-height * 1.8;
2301
-
2302
- > SPAN {
2303
- color: var(--sortable-table-group-label);
2304
- }
2305
- }
2306
-
2307
- .group-tab:after {
2308
- height: $group-row-height;
2309
- width: 70px;
2310
- border-radius: 5px 5px 0px 0px;
2311
- background-color: var(--sortable-table-row-bg);
2312
- content: "";
2313
- position: absolute;
2314
- right: -15px;
2315
- top: 0px;
2316
- transform: skewX(40deg);
2317
- z-index: -1;
2318
- }
2319
- }
2320
- }
2321
- }
2322
-
2323
- .for-inputs{
2324
- & TABLE.sortable-table {
2325
- width: 100%;
2326
- border-collapse: collapse;
2327
- margin-bottom: $spacing;
2328
-
2329
- >TBODY>TR>TD, >THEAD>TR>TH {
2330
- padding-right: $spacing;
2331
- padding-bottom: $spacing;
2332
-
2333
- &:last-of-type {
2334
- padding-right: 0;
2335
- }
2336
- }
2337
-
2338
- >TBODY>TR:first-of-type>TD {
2339
- padding-top: $spacing;
2340
- }
2341
-
2342
- >TBODY>TR:last-of-type>TD {
2343
- padding-bottom: 0;
2344
- }
2345
- }
2346
-
2347
- &.edit, &.create, &.clone {
2348
- TABLE.sortable-table>THEAD>TR>TH {
2349
- border-color: transparent;
2350
- }
2351
- }
2352
- }
2353
-
2354
- .sortable-table-header {
2355
- position: relative;
2356
- z-index: z-index('fixedTableHeader');
2357
-
2358
- &.titled {
2359
- display: flex;
2360
- align-items: center;
2361
- }
2362
- }
2363
- .fixed-footer-actions.button{
2364
- grid-template-columns: [bulk] auto [middle] min-content [search] minmax(min-content, 350px);
2365
- }
2366
-
2367
- .fixed-footer-actions {
2368
- /* padding: 0 0 20px 0; */
2369
- width: 100%;
2370
- z-index: z-index('fixedTableHeader');
2371
- background: transparent;
2372
- display: grid;
2373
- grid-template-columns: [bulk] auto [middle] min-content [search] minmax(min-content, 200px);
2374
- grid-column-gap: 10px;
2375
-
2376
- &.advanced-filtering {
2377
- grid-template-columns: [bulk] auto [middle] minmax(min-content, auto) [search] minmax(min-content, auto);
2378
- }
2379
-
2380
- .bulk {
2381
- grid-area: bulk;
2382
-
2383
- $gap: 10px;
2384
-
2385
- & > BUTTON {
2386
- display: none; // Handled dynamically
2387
- }
2388
-
2389
- & > BUTTON:not(:last-of-type) {
2390
- margin-right: $gap;
2391
- }
2392
-
2393
- .action-availability {
2394
- display: none; // Handled dynamically
2395
- margin-left: $gap;
2396
- vertical-align: middle;
2397
- margin-top: 2px;
2398
- }
2399
-
2400
- .dropdown-button {
2401
- $disabled-color: var(--disabled-text);
2402
- $disabled-cursor: not-allowed;
2403
- li.disabled {
2404
- color: $disabled-color;
2405
- cursor: $disabled-cursor;
2406
-
2407
- &:hover {
2408
- color: $disabled-color;
2409
- background-color: unset;
2410
- cursor: $disabled-cursor;
2411
- }
2412
- }
2413
- }
2414
-
2415
- .bulk-action {
2416
- .icon {
2417
- vertical-align: -10%;
2418
- }
2419
- }
2420
- }
2421
-
2422
- .middle {
2423
- grid-area: middle;
2424
- white-space: nowrap;
2425
-
2426
- .icon.icon-backup.animate {
2427
- animation-name: spin;
2428
- animation-duration: 1000ms;
2429
- animation-iteration-count: infinite;
2430
- animation-timing-function: linear;
2431
- }
2432
-
2433
- @keyframes spin {
2434
- from {
2435
- transform:rotate(0deg);
2436
- }
2437
- to {
2438
- transform:rotate(360deg);
2439
- }
2440
- }
2441
- }
2442
-
2443
- .search {
2444
- grid-area: search;
2445
- text-align: right;
2446
- justify-content: flex-end;
2447
- }
2448
-
2449
- .bulk-actions-dropdown {
2450
- display: none; // Handled dynamically
2451
-
2452
- .dropdown-button {
2453
- background-color: var(--primary);
2454
-
2455
- &:hover {
2456
- background-color: var(--primary-hover-bg);
2457
- color: var(--primary-hover-text);
2458
- }
2459
-
2460
- > *, .icon-chevron-down {
2461
- color: var(--primary-text);
2462
- }
2463
-
2464
- .button-divider {
2465
- border-color: var(--primary-text);
2466
- }
2467
-
2468
- &.disabled {
2469
- border-color: var(--disabled-bg);
2470
-
2471
- .icon-chevron-down {
2472
- color: var(--disabled-text) !important;
2473
- }
2474
-
2475
- .button-divider {
2476
- border-color: var(--disabled-text);
2477
- }
2478
- }
2479
- }
2480
- }
2481
- }
2482
-
2483
-
2484
- .fixed-header-table-actions {
2485
- width: 100%;
2486
- z-index: z-index('fixedTableHeader');
2487
- background: transparent;
2488
- display: flex;
2489
- justify-content: space-between;
2490
-
2491
-
2492
- .bulk {
2493
- $gap: 10px;
2494
-
2495
- & > BUTTON {
2496
- display: none; // Handled dynamically
2497
- }
2498
-
2499
- & > BUTTON:not(:last-of-type) {
2500
- margin-right: $gap;
2501
- }
2502
-
2503
- .action-availability {
2504
- display: none; // Handled dynamically
2505
- margin-left: $gap;
2506
- vertical-align: middle;
2507
- margin-top: 2px;
2508
- }
2509
-
2510
- .dropdown-button {
2511
- $disabled-color: var(--disabled-text);
2512
- $disabled-cursor: not-allowed;
2513
- li.disabled {
2514
- color: $disabled-color;
2515
- cursor: $disabled-cursor;
2516
-
2517
- &:hover {
2518
- color: $disabled-color;
2519
- background-color: unset;
2520
- cursor: $disabled-cursor;
2521
- }
2522
- }
2523
- }
2524
-
2525
- .bulk-action {
2526
- .icon {
2527
- vertical-align: -10%;
2528
- }
2529
- }
2530
- }
2531
-
2532
- .middle {
2533
- white-space: nowrap;
2534
-
2535
- .icon.icon-backup.animate {
2536
- animation-name: spin;
2537
- animation-duration: 1000ms;
2538
- animation-iteration-count: infinite;
2539
- animation-timing-function: linear;
2540
- }
2541
-
2542
- @keyframes spin {
2543
- from {
2544
- transform:rotate(0deg);
2545
- }
2546
- to {
2547
- transform:rotate(360deg);
2548
- }
2549
- }
2550
- }
2551
-
2552
- .search {
2553
- text-align: right;
2554
- justify-content: flex-end;
2555
- }
2556
-
2557
- .bulk-actions-dropdown {
2558
- display: none; // Handled dynamically
2559
-
2560
- .dropdown-button {
2561
- background-color: var(--primary);
2562
-
2563
- &:hover {
2564
- background-color: var(--primary-hover-bg);
2565
- color: var(--primary-hover-text);
2566
- }
2567
-
2568
- > *, .icon-chevron-down {
2569
- color: var(--primary-text);
2570
- }
2571
-
2572
- .button-divider {
2573
- border-color: var(--primary-text);
2574
- }
2575
-
2576
- &.disabled {
2577
- border-color: var(--disabled-bg);
2578
-
2579
- .icon-chevron-down {
2580
- color: var(--disabled-text) !important;
2581
- }
2582
-
2583
- .button-divider {
2584
- border-color: var(--disabled-text);
2585
- }
2586
- }
2587
- }
2588
- }
2589
- }
2590
-
2591
- .paging {
2592
- //text-align: center;
2593
- display: flex;
2594
- justify-content: flex-end;
2595
- gap: 0 10px;
2596
- text-align: center;
2597
- max-height: 32px;
2598
- background-color: transparent;
2599
- flex: 1;
2600
- SPAN {
2601
- display: inline-block;
2602
- //min-width: 200px;
2603
- min-width: auto;
2604
- }
2605
-
2606
- /* 针对Webkit浏览器(如Chrome, Safari) */
2607
- input[type="number"]::-webkit-inner-spin-button,
2608
- input[type="number"]::-webkit-outer-spin-button {
2609
- -webkit-appearance: none;
2610
- margin: 0;
2611
- }
2612
-
2613
- /* 针对Firefox */
2614
- input[type="number"] {
2615
- -moz-appearance: textfield;
2616
- // background-color: var(--disabled-bg) !important;
2617
- border: 1px var(--border) solid;
2618
- border-radius: 2px;
2619
- width: 50px;
2620
- height: 100%;
2621
- }
2622
- }
2623
-
2624
- </style>
2625
- <style scoped lang="scss">
2626
-
2627
- :deep() .role-link{
2628
- min-width: unset !important;
2629
- width: 38px;
2630
- min-height: 20px !important;
2631
- height: 20px !important;
2632
- line-height: 20px !important;
2633
- &:hover{
2634
- background-color: unset !important;
2635
- }
2636
- }
2637
- :deep() .checkbox-outer-container-extra{
2638
- margin-top: 0px !important;
2639
- }
2640
- .pageSelect {
2641
- max-width: 100px;
2642
- }
2643
- .page-btn-normal {
2644
- padding: 0;
2645
- max-width: 32px;
2646
- background-color:white !important;
2647
- }
2648
-
2649
- .pageSelect{
2650
- &:deep() .vs__actions:after{
2651
- padding-top: 10px;
2652
- }
2653
- }
2654
- .sort-table-div{
2655
- width:100%;
2656
- white-space:nowrap;
2657
- overflow-x: auto;
2658
- }
2659
-
2660
- /* 滚动阴影左边 */
2661
- .shadow-left td:nth-child(2)::after{
2662
- content: "";
2663
- position: absolute;
2664
- top: 0;
2665
- width: 10px;
2666
- height: 100%;
2667
- right: -10px;
2668
- background: linear-gradient(to right, rgba(5, 5, 5, 0.06), transparent);
2669
- }
2670
- .shadow-left{
2671
- &:deep() th:nth-child(2)::after{
2672
- content: "";
2673
- position: absolute;
2674
- top: 0;
2675
- width: 10px;
2676
- height: 100%;
2677
- right: -10px;
2678
- background: linear-gradient(to right, rgba(5, 5, 5, 0.06), transparent);
2679
- }
2680
- }
2681
-
2682
- /* 滚动阴影右边 */
2683
- .shadow-right td:nth-last-child(1)::after{
2684
- content: "";
2685
- position: absolute;
2686
- top: 0;
2687
- width: 10px;
2688
- height: 100%;
2689
- left: -10px;
2690
- background: linear-gradient(to left, rgba(5, 5, 5, 0.06), transparent);
2691
- }
2692
-
2693
- .shadow-right{
2694
- &:deep() th:nth-last-child(1)::after {
2695
- content: "";
2696
- position: absolute;
2697
- top: 0;
2698
- width: 10px;
2699
- height: 100%;
2700
- left: -10px;
2701
- background: linear-gradient(to left, rgba(5, 5, 5, 0.06), transparent);
2702
- }
2703
- }
2704
-
2705
- /* 滚动阴影垂直修正 */
2706
- .shadow-y td:nth-child(-n + 2), /* 前两列 */
2707
- .shadow-y td:nth-last-child(1) /* 后一列 */
2708
- {
2709
- z-index: 3;
2710
- }
2711
- </style>
2712
-