@rancher/shell 3.0.7 → 3.0.8-rc.10

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 (375) hide show
  1. package/assets/brand/suse/banner.svg +1 -0
  2. package/assets/brand/suse/dark/banner.svg +1 -0
  3. package/assets/brand/suse/dark/login-landscape.svg +1 -0
  4. package/assets/brand/suse/dark/rancher-logo.svg +1 -1
  5. package/assets/brand/suse/favicon.png +0 -0
  6. package/assets/brand/suse/login-landscape.svg +1 -0
  7. package/assets/brand/suse/metadata.json +11 -1
  8. package/assets/brand/suse/rancher-logo.svg +1 -1
  9. package/assets/fonts/suse/suse-v2-latin-300.woff +0 -0
  10. package/assets/fonts/suse/suse-v2-latin-300.woff2 +0 -0
  11. package/assets/fonts/suse/suse-v2-latin-600.woff +0 -0
  12. package/assets/fonts/suse/suse-v2-latin-600.woff2 +0 -0
  13. package/assets/fonts/suse/suse-v2-latin-700.woff +0 -0
  14. package/assets/fonts/suse/suse-v2-latin-700.woff2 +0 -0
  15. package/assets/fonts/suse/suse-v2-latin-800.woff +0 -0
  16. package/assets/fonts/suse/suse-v2-latin-800.woff2 +0 -0
  17. package/assets/fonts/suse/suse-v2-latin-regular.woff +0 -0
  18. package/assets/fonts/suse/suse-v2-latin-regular.woff2 +0 -0
  19. package/assets/images/content/README.md +5 -0
  20. package/assets/images/content/cloud-native.svg +84 -0
  21. package/assets/images/content/dark/cloud-native.svg +21 -0
  22. package/assets/images/content/dark/shield.svg +59 -0
  23. package/assets/images/content/dark/suse.svg +10 -0
  24. package/assets/images/content/shield.svg +59 -0
  25. package/assets/images/content/suse.svg +10 -0
  26. package/assets/images/vendor/githubapp.svg +13 -0
  27. package/assets/styles/base/_typography.scss +2 -1
  28. package/assets/styles/fonts/_fontstack.scss +53 -1
  29. package/assets/styles/global/_cards.scss +0 -3
  30. package/assets/styles/global/_layout.scss +21 -35
  31. package/assets/styles/themes/_dark.scss +1 -1
  32. package/assets/styles/themes/_light.scss +1 -1
  33. package/assets/styles/themes/_modern.scss +16 -8
  34. package/assets/styles/themes/_suse.scss +116 -24
  35. package/assets/translations/en-us.yaml +185 -21
  36. package/assets/translations/zh-hans.yaml +0 -4
  37. package/components/AutoscalerCard.vue +113 -0
  38. package/components/AutoscalerTab.vue +94 -0
  39. package/components/BackLink.vue +8 -0
  40. package/components/BannerGraphic.vue +36 -21
  41. package/components/BrandImage.vue +17 -6
  42. package/components/ClusterIconMenu.vue +1 -1
  43. package/components/ClusterProviderIcon.vue +1 -1
  44. package/components/Cron/CronExpressionEditor.vue +1 -1
  45. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  46. package/components/Drawer/Chrome.vue +2 -6
  47. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
  48. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
  49. package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
  50. package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
  51. package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
  52. package/components/Drawer/types.ts +3 -0
  53. package/components/DynamicContent/DynamicContentBanner.vue +102 -0
  54. package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
  55. package/components/DynamicContent/DynamicContentIcon.vue +132 -0
  56. package/components/DynamicContent/DynamicContentPanel.vue +112 -0
  57. package/components/DynamicContent/content.ts +78 -0
  58. package/components/EmberPage.vue +1 -1
  59. package/components/IconOrSvg.vue +2 -2
  60. package/components/Inactivity.vue +222 -106
  61. package/components/InstallHelmCharts.vue +2 -2
  62. package/components/PaginatedResourceTable.vue +2 -6
  63. package/components/PopoverCard.vue +192 -0
  64. package/components/Questions/__tests__/index.test.ts +159 -0
  65. package/components/Resource/Detail/CopyToClipboard.vue +4 -1
  66. package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
  67. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  68. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
  69. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
  70. package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
  71. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  72. package/components/Resource/Detail/Metadata/composables.ts +9 -9
  73. package/components/Resource/Detail/Metadata/index.vue +3 -3
  74. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
  75. package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
  76. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
  77. package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
  78. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
  79. package/components/Resource/Detail/TitleBar/composables.ts +2 -1
  80. package/components/Resource/Detail/TitleBar/index.vue +10 -6
  81. package/components/Resource/Detail/composables.ts +12 -0
  82. package/components/ResourceDetail/Masthead/latest.vue +29 -0
  83. package/components/ResourceDetail/index.vue +5 -2
  84. package/components/ResourceList/Masthead.vue +1 -1
  85. package/components/SortableTable/index.vue +18 -2
  86. package/components/Tabbed/__tests__/index.test.ts +86 -0
  87. package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
  88. package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
  89. package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
  90. package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
  91. package/components/__tests__/AutoscalerCard.test.ts +154 -0
  92. package/components/__tests__/AutoscalerTab.test.ts +125 -0
  93. package/components/__tests__/PopoverCard.test.ts +204 -0
  94. package/components/auth/SelectPrincipal.vue +24 -6
  95. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  96. package/components/fleet/FleetConfigMapSelector.vue +117 -0
  97. package/components/fleet/FleetSecretSelector.vue +127 -0
  98. package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
  99. package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
  100. package/components/form/FileImageSelector.vue +13 -4
  101. package/components/form/FileSelector.vue +11 -2
  102. package/components/form/ResourceLabeledSelect.vue +1 -0
  103. package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
  104. package/components/formatter/Autoscaler.vue +97 -0
  105. package/components/formatter/InternalExternalIP.vue +198 -24
  106. package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
  107. package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
  108. package/components/google/util/__tests__/formatter.test.ts +47 -0
  109. package/components/google/util/formatter.ts +5 -2
  110. package/components/nav/Group.vue +12 -3
  111. package/components/nav/Header.vue +37 -16
  112. package/components/nav/NamespaceFilter.vue +13 -1
  113. package/components/nav/NotificationCenter/index.vue +2 -1
  114. package/components/nav/TopLevelMenu.helper.ts +16 -6
  115. package/components/nav/TopLevelMenu.vue +4 -2
  116. package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
  117. package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
  118. package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
  119. package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
  120. package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
  121. package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
  122. package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
  123. package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
  124. package/components/nav/WindowManager/constants.ts +23 -0
  125. package/components/nav/WindowManager/index.vue +61 -575
  126. package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
  127. package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
  128. package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
  129. package/components/templates/default.vue +4 -40
  130. package/components/templates/home.vue +31 -5
  131. package/components/templates/plain.vue +30 -4
  132. package/components/templates/standalone.vue +1 -1
  133. package/composables/useI18n.ts +10 -1
  134. package/composables/useInterval.ts +15 -0
  135. package/config/__test__/uiplugins.test.ts +309 -0
  136. package/config/labels-annotations.js +9 -1
  137. package/config/product/auth.js +1 -0
  138. package/config/product/explorer.js +3 -1
  139. package/config/product/manager.js +20 -9
  140. package/config/query-params.js +1 -0
  141. package/config/router/routes.js +10 -2
  142. package/config/settings.ts +10 -2
  143. package/config/store.js +4 -2
  144. package/config/table-headers.js +8 -0
  145. package/config/types.js +11 -0
  146. package/config/uiplugins.js +46 -2
  147. package/config/version.js +1 -1
  148. package/core/__test__/extension-manager-impl.test.js +236 -0
  149. package/core/extension-manager-impl.js +23 -6
  150. package/core/plugin-helpers.ts +2 -0
  151. package/core/types-provisioning.ts +4 -1
  152. package/detail/pod.vue +1 -0
  153. package/detail/provisioning.cattle.io.cluster.vue +13 -1
  154. package/dialog/AddonConfigConfirmationDialog.vue +45 -1
  155. package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
  156. package/dialog/RollbackWorkloadDialog.vue +2 -5
  157. package/directives/ui-context.ts +103 -0
  158. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
  159. package/edit/auth/AuthProviderWarningBanners.vue +14 -1
  160. package/edit/auth/__tests__/oidc.test.ts +26 -0
  161. package/edit/auth/github-app-steps.vue +97 -0
  162. package/edit/auth/github-steps.vue +75 -0
  163. package/edit/auth/github.vue +99 -65
  164. package/edit/auth/oidc.vue +5 -1
  165. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  166. package/edit/cloudcredential.vue +1 -1
  167. package/edit/configmap.vue +1 -0
  168. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  169. package/edit/fleet.cattle.io.gitrepo.vue +0 -10
  170. package/edit/fleet.cattle.io.helmop.vue +51 -2
  171. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  172. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  173. package/edit/logging-flow/index.vue +1 -0
  174. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  175. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  176. package/edit/management.cattle.io.project.vue +1 -0
  177. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  178. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  179. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  180. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  181. package/edit/monitoring.coreos.com.route.vue +1 -1
  182. package/edit/namespace.vue +1 -0
  183. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  184. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  185. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
  186. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  187. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  188. package/edit/node.vue +1 -0
  189. package/edit/persistentvolume/index.vue +27 -22
  190. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  191. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  192. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  193. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  194. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  195. package/edit/persistentvolume/plugins/csi.vue +18 -16
  196. package/edit/persistentvolume/plugins/fc.vue +13 -14
  197. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  198. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  199. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  200. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  201. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  202. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  203. package/edit/persistentvolume/plugins/local.vue +1 -3
  204. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  205. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  206. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  207. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  208. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  209. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  210. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  211. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  212. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  213. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
  214. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
  215. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
  216. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
  217. package/edit/provisioning.cattle.io.cluster/index.vue +25 -15
  218. package/edit/provisioning.cattle.io.cluster/rke2.vue +98 -17
  219. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
  220. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
  221. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
  222. package/edit/secret/index.vue +1 -1
  223. package/edit/service.vue +9 -4
  224. package/edit/serviceaccount.vue +1 -0
  225. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  226. package/edit/workload/index.vue +2 -1
  227. package/edit/workload/mixins/workload.js +1 -1
  228. package/initialize/App.vue +4 -4
  229. package/initialize/install-directives.js +2 -0
  230. package/initialize/install-plugins.js +19 -2
  231. package/list/projectsecret.vue +1 -1
  232. package/list/provisioning.cattle.io.cluster.vue +15 -2
  233. package/machine-config/amazonec2.vue +42 -135
  234. package/machine-config/azure.vue +1 -1
  235. package/machine-config/components/EC2Networking.vue +490 -0
  236. package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
  237. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
  238. package/machine-config/digitalocean.vue +11 -0
  239. package/machine-config/google.vue +1 -1
  240. package/mixins/__tests__/brand.spec.ts +2 -2
  241. package/mixins/__tests__/chart.test.ts +21 -0
  242. package/mixins/brand.js +1 -7
  243. package/mixins/chart.js +8 -2
  244. package/mixins/create-edit-view/index.js +5 -0
  245. package/models/__tests__/chart.test.ts +49 -12
  246. package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
  247. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
  248. package/models/catalog.cattle.io.app.js +1 -1
  249. package/models/chart.js +28 -14
  250. package/models/cluster/node.js +13 -6
  251. package/models/cluster.x-k8s.io.machine.js +10 -20
  252. package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
  253. package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
  254. package/models/management.cattle.io.authconfig.js +1 -0
  255. package/models/management.cattle.io.cluster.js +21 -3
  256. package/models/management.cattle.io.kontainerdriver.js +1 -0
  257. package/models/provisioning.cattle.io.cluster.js +249 -33
  258. package/package.json +6 -5
  259. package/pages/auth/login.vue +43 -4
  260. package/pages/auth/verify.vue +1 -1
  261. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
  262. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  263. package/pages/c/_cluster/apps/charts/chart.vue +35 -17
  264. package/pages/c/_cluster/apps/charts/index.vue +11 -13
  265. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  266. package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
  267. package/pages/c/_cluster/explorer/index.vue +8 -6
  268. package/pages/c/_cluster/explorer/tools/index.vue +3 -3
  269. package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
  270. package/pages/c/_cluster/settings/brand.vue +1 -1
  271. package/pages/c/_cluster/settings/performance.vue +12 -25
  272. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  273. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  274. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  275. package/pages/home.vue +327 -16
  276. package/pkg/dynamic-importer.lib.js +4 -0
  277. package/plugins/axios.js +2 -1
  278. package/plugins/dashboard-client-init.js +3 -0
  279. package/plugins/dashboard-store/actions.js +1 -1
  280. package/plugins/dashboard-store/getters.js +18 -1
  281. package/plugins/dashboard-store/resource-class.js +21 -6
  282. package/plugins/dynamic-content.js +13 -0
  283. package/plugins/i18n.js +8 -0
  284. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
  285. package/plugins/steve/steve-pagination-utils.ts +41 -22
  286. package/plugins/steve/subscribe.js +17 -9
  287. package/plugins/subscribe-events.ts +4 -2
  288. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  289. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
  290. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  291. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  292. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  293. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  294. package/rancher-components/Pill/types.ts +0 -1
  295. package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
  296. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
  297. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  298. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  299. package/rancher-components/RcIcon/index.ts +1 -0
  300. package/rancher-components/RcIcon/types.ts +160 -0
  301. package/rancher-components/utils/status.test.ts +67 -0
  302. package/rancher-components/utils/status.ts +77 -0
  303. package/scripts/extension/publish +1 -1
  304. package/scripts/typegen.sh +1 -0
  305. package/store/action-menu.js +8 -0
  306. package/store/auth.js +11 -6
  307. package/store/aws.js +8 -6
  308. package/store/catalog.js +6 -0
  309. package/store/features.js +2 -0
  310. package/store/index.js +45 -20
  311. package/store/notifications.ts +51 -4
  312. package/store/plugins.js +7 -3
  313. package/store/prefs.js +12 -6
  314. package/store/type-map.js +3 -3
  315. package/store/ui-context.ts +86 -0
  316. package/store/wm.ts +244 -0
  317. package/types/kube/kube-api.ts +2 -1
  318. package/types/notifications/index.ts +27 -3
  319. package/types/rancher/index.d.ts +1 -0
  320. package/types/resources/settings.d.ts +29 -7
  321. package/types/shell/index.d.ts +138 -4
  322. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  323. package/types/store/pagination.types.ts +157 -9
  324. package/types/store/subscribe-events.types.ts +8 -1
  325. package/types/store/subscribe.types.ts +1 -0
  326. package/types/window-manager.ts +24 -0
  327. package/utils/__tests__/cluster.test.ts +379 -1
  328. package/utils/__tests__/object.test.ts +19 -0
  329. package/utils/__tests__/provider.test.ts +98 -0
  330. package/utils/__tests__/selector-typed.test.ts +263 -0
  331. package/utils/__tests__/version.test.ts +19 -1
  332. package/utils/autoscaler-utils.ts +7 -0
  333. package/utils/back-off.ts +3 -3
  334. package/utils/brand.ts +29 -0
  335. package/utils/chart.js +18 -0
  336. package/utils/cluster.js +157 -3
  337. package/utils/color.js +1 -1
  338. package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
  339. package/utils/dynamic-content/__tests__/config.test.ts +187 -0
  340. package/utils/dynamic-content/__tests__/index.test.ts +390 -0
  341. package/utils/dynamic-content/__tests__/info.test.ts +275 -0
  342. package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
  343. package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
  344. package/utils/dynamic-content/__tests__/util.test.ts +235 -0
  345. package/utils/dynamic-content/announcement.ts +142 -0
  346. package/utils/dynamic-content/config.ts +55 -0
  347. package/utils/dynamic-content/example.json +40 -0
  348. package/utils/dynamic-content/index.ts +277 -0
  349. package/utils/dynamic-content/info.ts +261 -0
  350. package/utils/dynamic-content/new-release.ts +126 -0
  351. package/utils/dynamic-content/notification-handler.ts +48 -0
  352. package/utils/dynamic-content/support-notice.ts +169 -0
  353. package/utils/dynamic-content/types.d.ts +153 -0
  354. package/utils/dynamic-content/util.ts +122 -0
  355. package/utils/dynamic-importer.js +2 -2
  356. package/utils/favicon.js +4 -4
  357. package/utils/inactivity.ts +104 -0
  358. package/utils/object.js +20 -2
  359. package/utils/pagination-utils.ts +19 -4
  360. package/utils/pagination-wrapper.ts +12 -8
  361. package/utils/provider.ts +14 -0
  362. package/utils/release-notes.ts +1 -1
  363. package/utils/scroll.js +7 -0
  364. package/utils/selector-typed.ts +6 -2
  365. package/utils/settings.ts +15 -0
  366. package/utils/validators/machine-pool.ts +13 -3
  367. package/utils/version.js +15 -0
  368. package/assets/images/icons/document.svg +0 -3
  369. package/plugins/nuxt-client-init.js +0 -3
  370. package/store/wm.js +0 -95
  371. /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
  372. /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
  373. /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
  374. /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
  375. /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
@@ -1,12 +1,7 @@
1
1
  import { mount, RouterLinkStub } from '@vue/test-utils';
2
2
  import { createStore } from 'vuex';
3
3
  import ResourcePopover from '@shell/components/Resource/Detail/ResourcePopover/index.vue';
4
-
5
- const mockI18n = { t: (key: string, args: any) => JSON.stringify({ key, args }) };
6
- const mockFocusTrap = jest.fn();
7
-
8
- jest.mock('@shell/composables/useI18n', () => ({ useI18n: () => mockI18n }));
9
- jest.mock('@shell/composables/focusTrap', () => ({ useWatcherBasedSetupFocusTrapWithDestroyIncluded: (...args: any) => mockFocusTrap(...args) }));
4
+ import PopoverCard from '@shell/components/PopoverCard.vue';
10
5
 
11
6
  const mockResource = {
12
7
  id: 'test-ns/test-pod',
@@ -14,7 +9,6 @@ const mockResource = {
14
9
  nameDisplay: 'My Test Pod',
15
10
  stateBackground: 'bg-success',
16
11
  detailLocation: { name: 'pod-detail', params: { id: 'test-pod' } },
17
- glance: [{ label: 'Status', content: 'Active' }],
18
12
  parentNameOverride: 'Overridden Pod',
19
13
  };
20
14
 
@@ -23,223 +17,211 @@ describe('component: ResourcePopover/index.vue', () => {
23
17
  const mockClusterFind = jest.fn();
24
18
  const mockSomethingFind = jest.fn();
25
19
 
26
- const createWrapper = async(props: any = { type: 'pod', id: 'test-ns/test-pod' }) => {
27
- store = createStore({
28
- getters: {
29
- 'i18n/t': () => (key: string) => key,
30
- currentStore: () => () => 'cluster',
31
- 'cluster/schemaFor': () => () => ({ id: 'pod' }),
32
- 'type-map/labelFor': () => () => 'Pod',
33
- },
34
- actions: { 'cluster/find': mockClusterFind, 'something/find': mockSomethingFind }
35
- });
20
+ const defaultStore = {
21
+ getters: {
22
+ 'i18n/t': () => (key: string) => key,
23
+ currentStore: () => () => 'cluster',
24
+ 'cluster/schemaFor': () => () => ({ id: 'pod' }),
25
+ 'type-map/labelFor': () => () => 'Pod',
26
+ },
27
+ actions: { 'cluster/find': mockClusterFind, 'something/find': mockSomethingFind }
28
+ };
36
29
 
37
- const wrapper = mount(ResourcePopover, {
38
- props,
30
+ const PopoverCardStub = {
31
+ PopoverCard: {
32
+ template: `
33
+ <div>
34
+ <slot />
35
+ <slot name="heading-action" :close="() => {}" />
36
+ <slot name="card-body" />
37
+ </div>
38
+ `,
39
+ },
40
+ };
41
+
42
+ const createWrapper = (props: any = {}, storeConfig: any = defaultStore, stubs: any = {}) => {
43
+ store = createStore(storeConfig);
44
+
45
+ return mount(ResourcePopover, {
46
+ props: {
47
+ type: 'pod',
48
+ id: 'test-ns/test-pod',
49
+ ...props,
50
+ },
39
51
  global: {
40
52
  plugins: [store],
41
53
  stubs: {
42
- 'v-dropdown': { name: 'v-dropdown', template: '<div><slot /><slot name="popper" /></div>' },
43
- 'router-link': RouterLinkStub,
44
- ResourcePopoverCard: {
45
- name: 'ResourcePopoverCard',
46
- template: '<div id="resource-popover-card" />'
47
- },
48
- RcStatusIndicator: true,
54
+ RouterLink: RouterLinkStub,
55
+ RcStatusIndicator: true,
56
+ ActionMenu: true,
57
+ ResourcePopoverCard: true,
58
+ VDropdown: true,
59
+ ...stubs
49
60
  },
50
61
  },
51
62
  });
52
-
53
- // Requires two so the fetch can be resolved
54
- await wrapper.vm.$nextTick();
55
- await wrapper.vm.$nextTick();
56
-
57
- return wrapper;
58
63
  };
59
64
 
60
- // Reset mocks before each test
61
65
  beforeEach(() => {
62
66
  jest.clearAllMocks();
63
67
  });
64
68
 
65
- describe('data Fetching and Initial State', () => {
66
- it('should show loading state initially', async() => {
67
- const wrapper = await createWrapper(); // Override default fetch value
69
+ describe('data Fetching and Rendering', () => {
70
+ it('should display a loading indicator while fetching data', async() => {
71
+ mockClusterFind.mockImplementation(() => new Promise(() => { }));
72
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
73
+
74
+ await wrapper.vm.$nextTick();
75
+ await wrapper.vm.$nextTick();
76
+ await wrapper.vm.$nextTick();
68
77
 
69
- expect(wrapper.find('.display').exists()).toBe(false);
70
78
  expect(wrapper.text()).toContain('...');
79
+ expect(wrapper.find('.display').exists()).toBe(false);
71
80
  });
72
81
 
73
- it('should call the fetch composable and dispatch a store action', async() => {
74
- await createWrapper();
82
+ it('should fetch data using the default store', async() => {
83
+ const wrapper = createWrapper();
84
+
85
+ await wrapper.vm.$nextTick();
86
+ await wrapper.vm.$nextTick();
75
87
 
76
- expect(mockClusterFind).toHaveBeenCalledWith(expect.objectContaining({}), expect.objectContaining({ type: 'pod', id: 'test-ns/test-pod' }));
88
+ expect(mockClusterFind).toHaveBeenCalledWith(expect.any(Object), { type: 'pod', id: 'test-ns/test-pod' });
77
89
  });
78
90
 
79
- it('should dispatch to the specified store', async() => {
80
- await createWrapper({
81
- type: 'pod', id: 'test-ns/test-pod', currentStore: 'something'
82
- });
91
+ it('should fetch data using the store specified in props', async() => {
92
+ mockClusterFind.mockReturnValue(mockResource);
93
+ const wrapper = createWrapper({ currentStore: 'something' });
83
94
 
84
- expect(mockSomethingFind).toHaveBeenCalledWith(expect.objectContaining({}), expect.objectContaining({ type: 'pod', id: 'test-ns/test-pod' }));
95
+ await wrapper.vm.$nextTick();
96
+ await wrapper.vm.$nextTick();
97
+
98
+ expect(mockSomethingFind).toHaveBeenCalledWith(expect.any(Object), { type: 'pod', id: 'test-ns/test-pod' });
99
+ expect(mockClusterFind).not.toHaveBeenCalled();
85
100
  });
86
101
 
87
- it('should render resource name and link when data is loaded', async() => {
102
+ it('should display resource details after data is fetched', async() => {
88
103
  mockClusterFind.mockReturnValue(mockResource);
89
- const wrapper = await createWrapper();
104
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
105
+
106
+ await wrapper.vm.$nextTick();
107
+ await wrapper.vm.$nextTick();
108
+ await wrapper.vm.$nextTick();
109
+
90
110
  const link = wrapper.findComponent(RouterLinkStub);
91
111
 
92
- expect(link.exists()).toBe(true);
93
112
  expect(link.text()).toBe(mockResource.nameDisplay);
94
113
  expect(link.props('to')).toStrictEqual(mockResource.detailLocation);
95
114
  });
96
115
 
97
- it('should use `detailLocation` prop for router-link if provided', async() => {
98
- const detailLocationProp = { name: 'custom-route' };
116
+ it('should use detailLocation prop for the link if provided', async() => {
117
+ const customLocation = { name: 'custom-route' };
99
118
 
100
- const wrapper = await createWrapper({
101
- type: 'pod',
102
- id: 'test-ns/test-pod',
103
- detailLocation: detailLocationProp
104
- });
119
+ mockClusterFind.mockReturnValue(mockResource);
120
+ const wrapper = createWrapper({ detailLocation: customLocation }, undefined, PopoverCardStub);
121
+
122
+ await wrapper.vm.$nextTick();
123
+ await wrapper.vm.$nextTick();
124
+ await wrapper.vm.$nextTick();
105
125
 
106
126
  const link = wrapper.findComponent(RouterLinkStub);
107
127
 
108
- expect(link.props('to')).toStrictEqual(detailLocationProp);
128
+ expect(link.props('to')).toStrictEqual(customLocation);
109
129
  });
110
130
  });
111
131
 
112
132
  describe('computed Properties', () => {
113
- it('should return empty resourceTypeLabel if no data', async() => {
114
- mockClusterFind.mockReturnValue(null);
115
-
116
- const wrapper = await createWrapper();
133
+ it('resourceTypeLabel: should be empty if data is not loaded', async() => {
134
+ mockClusterFind.mockReturnValue(undefined);
135
+ const wrapper = createWrapper();
117
136
 
118
- expect(wrapper.vm.resourceTypeLabel).toBe('');
119
- });
120
-
121
- it('should return resourceTypeLabel from type-map getter', async() => {
122
- const resourceWithoutOverride = { ...mockResource, parentNameOverride: undefined };
137
+ await wrapper.vm.$nextTick();
138
+ await wrapper.vm.$nextTick();
139
+ await wrapper.vm.$nextTick();
123
140
 
124
- mockClusterFind.mockReturnValue(resourceWithoutOverride);
125
- const wrapper = await createWrapper();
141
+ const popoverCard = wrapper.findComponent(PopoverCard);
142
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
126
143
 
127
- expect(wrapper.vm.resourceTypeLabel).toBe('Pod');
144
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"\",\"resource\":\"\"}');
128
145
  });
129
146
 
130
- it('should generate correct aria-labels', async() => {
131
- mockClusterFind.mockReturnValue(mockResource);
132
- const wrapper = await createWrapper();
133
-
134
- const expectedAriaLabel = JSON.stringify({ key: 'component.resource.detail.glance.ariaLabel.showDetails', args: { name: mockResource.nameDisplay, resource: mockResource.parentNameOverride } });
135
- const dropdown = wrapper.findComponent({ name: 'v-dropdown' });
136
- const button = wrapper.find('.focus-button');
147
+ it('resourceTypeLabel: should use parentNameOverride when available', async() => {
148
+ mockClusterFind.mockResolvedValue(mockResource);
149
+ const wrapper = createWrapper();
137
150
 
138
- expect(dropdown.attributes('aria-label')).toBe(expectedAriaLabel);
139
- expect(button.attributes('aria-label')).toBe(expectedAriaLabel);
140
- });
141
- });
151
+ await wrapper.vm.$nextTick();
152
+ await wrapper.vm.$nextTick();
153
+ await wrapper.vm.$nextTick();
142
154
 
143
- describe('popover Visibility', () => {
144
- it('should not show popover card initially', async() => {
145
- mockClusterFind.mockReturnValue(mockResource);
146
- const wrapper = await createWrapper();
155
+ const popoverCard = wrapper.findComponent(PopoverCard);
156
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
147
157
 
148
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
158
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Overridden Pod\"}');
149
159
  });
150
160
 
151
- it('should show popover on mouseenter', async() => {
152
- mockClusterFind.mockReturnValue(mockResource);
153
- const wrapper = await createWrapper();
161
+ it('resourceTypeLabel: should use type-map label as a fallback', async() => {
162
+ const resourceWithoutOverride = { ...mockResource, parentNameOverride: null };
154
163
 
155
- await wrapper.find('.display').trigger('mouseenter');
156
- expect(wrapper.vm.showPopover).toBe(true);
157
- await wrapper.vm.$nextTick();
158
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(true);
159
- });
164
+ mockClusterFind.mockResolvedValue(resourceWithoutOverride);
165
+ const wrapper = createWrapper();
160
166
 
161
- it('should hide popover on mouseleave', async() => {
162
- mockClusterFind.mockReturnValue(mockResource);
163
- const wrapper = await createWrapper();
167
+ await wrapper.vm.$nextTick();
168
+ await wrapper.vm.$nextTick();
169
+ await wrapper.vm.$nextTick();
164
170
 
165
- await wrapper.find('.display').trigger('mouseenter');
166
- expect(wrapper.vm.showPopover).toBe(true);
171
+ const popoverCard = wrapper.findComponent(PopoverCard);
172
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
167
173
 
168
- await wrapper.find('.resource-popover').trigger('mouseleave');
169
- expect(wrapper.vm.showPopover).toBe(false);
170
- await wrapper.vm.$nextTick();
171
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
174
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Pod\"}');
172
175
  });
176
+ });
173
177
 
174
- it('should show popover on focus button click', async() => {
175
- mockClusterFind.mockReturnValue(mockResource);
176
- const wrapper = await createWrapper();
178
+ describe('props passed to child components', () => {
179
+ it('should pass correct props to PopoverCard', async() => {
180
+ mockClusterFind.mockResolvedValue(mockResource);
181
+ const wrapper = createWrapper();
177
182
 
178
- await wrapper.find('.focus-button').trigger('click');
179
- expect(wrapper.vm.showPopover).toBe(true);
180
- expect(wrapper.vm.focusOpen).toBe(true);
181
183
  await wrapper.vm.$nextTick();
182
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(true);
183
- });
184
+ await wrapper.vm.$nextTick();
185
+ await wrapper.vm.$nextTick();
184
186
 
185
- it('should hide popover when action is invoked from card', async() => {
186
- mockClusterFind.mockReturnValue(mockResource);
187
- const wrapper = await createWrapper();
187
+ const popoverCard = wrapper.findComponent(PopoverCard);
188
188
 
189
- await wrapper.find('.display').trigger('mouseenter');
190
- await wrapper.vm.$nextTick();
189
+ expect(popoverCard.props('cardTitle')).toBe(mockResource.nameDisplay);
190
+ expect(popoverCard.props('fallbackFocus')).toBe("[data-testid='resource-popover-action-menu']");
191
191
 
192
- const card = wrapper.findComponent({ name: 'ResourcePopoverCard' });
192
+ const expectedAriaLabel = 'component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Overridden Pod\"}';
193
193
 
194
- await card.vm.$emit('action-invoked');
195
- expect(wrapper.vm.showPopover).toBe(false);
196
- await wrapper.vm.$nextTick();
197
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
194
+ expect(popoverCard.props('showPopoverAriaLabel')).toBe(expectedAriaLabel);
198
195
  });
199
196
 
200
- it('should hide popover on Escape keydown', async() => {
201
- mockClusterFind.mockReturnValue(mockResource);
202
- const wrapper = await createWrapper();
197
+ it('should pass correct props to ActionMenu', async() => {
198
+ mockClusterFind.mockResolvedValue(mockResource);
199
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
203
200
 
204
- await wrapper.find('.focus-button').trigger('click');
205
201
  await wrapper.vm.$nextTick();
206
-
207
- const card = wrapper.findComponent({ name: 'ResourcePopoverCard' });
208
-
209
- await card.trigger('keydown.escape');
202
+ await wrapper.vm.$nextTick();
210
203
  await wrapper.vm.$nextTick();
211
204
 
212
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
213
- });
214
- });
205
+ const actionMenu = wrapper.findComponent({ name: 'ActionMenu' });
215
206
 
216
- describe('focus Trap', () => {
217
- it('should not setup focus trap on mouseenter', async() => {
218
- mockClusterFind.mockReturnValue(mockResource);
219
- const wrapper = await createWrapper();
207
+ expect(actionMenu.props('resource')).toStrictEqual(mockResource);
220
208
 
221
- await wrapper.find('.display').trigger('mouseenter');
222
- await wrapper.vm.$nextTick();
209
+ const expectedAriaLabel = 'component.resource.detail.glance.ariaLabel.actionMenu-{\"resource\":\"My Test Pod\"}';
223
210
 
224
- expect(wrapper.vm.focusOpen).toBe(false);
225
- expect(mockFocusTrap).not.toHaveBeenCalled();
211
+ expect(actionMenu.props('buttonAriaLabel')).toBe(expectedAriaLabel);
226
212
  });
227
213
 
228
- it('should setup focus trap when opened via focus button', async() => {
229
- mockClusterFind.mockReturnValue(mockResource);
230
- const wrapper = await createWrapper();
214
+ it('should pass correct props to ResourcePopoverCard', async() => {
215
+ mockClusterFind.mockResolvedValue(mockResource);
216
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
231
217
 
232
- await wrapper.find('.focus-button').trigger('click');
233
- await wrapper.vm.$nextTick(); // Triggers the watch
234
-
235
- expect(wrapper.vm.focusOpen).toBe(true);
236
- expect(mockFocusTrap).toHaveBeenCalledTimes(1);
218
+ await wrapper.vm.$nextTick();
219
+ await wrapper.vm.$nextTick();
220
+ await wrapper.vm.$nextTick();
237
221
 
238
- // Verify the options passed to the focus trap
239
- const focusTrapOptions = mockFocusTrap.mock.calls[0][2];
222
+ const resourceCard = wrapper.findComponent({ name: 'ResourcePopoverCard' });
240
223
 
241
- expect(focusTrapOptions.fallbackFocus).toBe('#first-glance-item');
242
- expect(focusTrapOptions.setReturnFocus()).toBe('.focus-button');
224
+ expect(resourceCard.props('resource')).toStrictEqual(mockResource);
243
225
  });
244
226
  });
245
227
  });
@@ -4,11 +4,9 @@ import { useStore } from 'vuex';
4
4
  import ResourcePopoverCard from '@shell/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue';
5
5
  import RcStatusIndicator from '@components/Pill/RcStatusIndicator/RcStatusIndicator.vue';
6
6
  import { useI18n } from '@shell/composables/useI18n';
7
- import { computed, ref, watch } from 'vue';
8
- import {
9
- DEFAULT_FOCUS_TRAP_OPTS,
10
- useWatcherBasedSetupFocusTrapWithDestroyIncluded
11
- } from '@shell/composables/focusTrap';
7
+ import { computed, ref } from 'vue';
8
+ import PopoverCard from '@shell/components/PopoverCard.vue';
9
+ import ActionMenu from '@shell/components/ActionMenuShell.vue';
12
10
 
13
11
  export interface Props {
14
12
  type: string;
@@ -23,14 +21,14 @@ const store = useStore();
23
21
  const i18n = useI18n(store);
24
22
  const props = defineProps<Props>();
25
23
  const card = ref<any>(null);
26
- const popoverContainer = ref(null);
27
24
  const showPopover = ref<boolean>(false);
28
- const focusOpen = ref<boolean>(false);
29
25
 
30
26
  const fetch = useFetch(async() => {
31
27
  const currentStore = props.currentStore || store.getters['currentStore'](props.type);
32
28
 
33
- return store.dispatch(`${ currentStore }/find`, { type: props.type, id: props.id });
29
+ const r = await store.dispatch(`${ currentStore }/find`, { type: props.type, id: props.id });
30
+
31
+ return r;
34
32
  });
35
33
 
36
34
  const resourceTypeLabel = computed(() => {
@@ -45,88 +43,63 @@ const resourceTypeLabel = computed(() => {
45
43
  return resource.parentNameOverride || store.getters['type-map/labelFor'](schema);
46
44
  });
47
45
 
46
+ const nameDisplay = computed(() => {
47
+ return fetch.value.data?.nameDisplay || '';
48
+ });
49
+
48
50
  const actionInvoked = () => {
49
51
  showPopover.value = false;
50
52
  };
51
-
52
- // Set focus trap when card opened using keyboard
53
- watch(
54
- () => card.value,
55
- (neu) => {
56
- if (neu && focusOpen.value) {
57
- const opts = {
58
- ...DEFAULT_FOCUS_TRAP_OPTS,
59
- fallbackFocus: '#first-glance-item',
60
- setReturnFocus: () => '.focus-button'
61
- };
62
-
63
- useWatcherBasedSetupFocusTrapWithDestroyIncluded(() => showPopover.value, '#resource-popover-card', opts);
64
- }
65
- }
66
- );
67
53
  </script>
68
54
 
69
55
  <template>
70
- <div
56
+ <PopoverCard
71
57
  class="resource-popover"
72
- @mouseleave="showPopover=false"
58
+ :card-title="nameDisplay"
59
+ fallback-focus="[data-testid='resource-popover-action-menu']"
60
+ :show-popover-aria-label="i18n.t('component.resource.detail.glance.ariaLabel.showDetails', { name: nameDisplay, resource: resourceTypeLabel })"
73
61
  >
74
- <v-dropdown
75
- :triggers="[]"
76
- :container="popoverContainer"
77
- :shown="showPopover"
78
- placement="bottom-start"
79
- :aria-label="i18n.t('component.resource.detail.glance.ariaLabel.showDetails', { name: fetch.data?.nameDisplay, resource: resourceTypeLabel })"
80
- >
81
- <div class="target">
82
- <span class="display-container">
83
- <span
84
- v-if="fetch.data"
85
- class="display"
86
- @mouseenter="showPopover=true"
87
- >
88
- <RcStatusIndicator
89
- shape="disc"
90
- :status="fetch.data?.stateBackground || 'unknown'"
91
- />
92
- <router-link
93
- :to="props.detailLocation || fetch.data.detailLocation || '#'"
94
- >
95
- {{ fetch.data.nameDisplay }}
96
- </router-link>
97
- <div
98
- ref="popoverContainer"
99
- class="resource-popover-container"
100
- >
101
- <!--Empty container for mounting popper content-->
102
- </div>
103
- </span>
104
- <span v-else>...</span>
105
- <button
106
- v-if="fetch.data"
107
- class="focus-button role-secondary"
108
- :aria-label="i18n.t('component.resource.detail.glance.ariaLabel.showDetails', { name: fetch.data?.nameDisplay, resource: resourceTypeLabel })"
109
- aria-haspopup="true"
110
- :aria-expanded="showPopover"
111
- @click="showPopover=true; focusOpen=true;"
112
- >
113
- <i class="icon icon-chevron-down icon-sm" />
114
- </button>
115
- </span>
116
- </div>
117
-
118
- <template #popper>
119
- <ResourcePopoverCard
120
- v-if="showPopover"
121
- id="resource-popover-card"
122
- ref="card"
123
- :resource="fetch.data"
124
- @action-invoked="actionInvoked"
125
- @keydown.escape="showPopover=false; focusOpen=false"
62
+ <span>
63
+ <span
64
+ v-if="fetch.data"
65
+ class="display"
66
+ @mouseenter="showPopover=true"
67
+ >
68
+ <RcStatusIndicator
69
+ shape="disc"
70
+ :status="fetch.data?.stateBackground || 'unknown'"
126
71
  />
127
- </template>
128
- </v-dropdown>
129
- </div>
72
+ <router-link
73
+ :to="props.detailLocation || fetch.data.detailLocation || '#'"
74
+ >
75
+ {{ nameDisplay }}
76
+ </router-link>
77
+ </span>
78
+ <span v-else>{{ fetch.loading }}...</span>
79
+ </span>
80
+ <template
81
+ v-if="fetch.data"
82
+ #heading-action="{close}"
83
+ >
84
+ <ActionMenu
85
+ :resource="fetch.data"
86
+ :button-aria-label="i18n.t('component.resource.detail.glance.ariaLabel.actionMenu', { resource: nameDisplay })"
87
+ data-testid="resource-popover-action-menu"
88
+ @action-invoked="close"
89
+ />
90
+ </template>
91
+ <template
92
+ v-if="fetch.data"
93
+ #card-body
94
+ >
95
+ <ResourcePopoverCard
96
+ id="resource-popover-card"
97
+ ref="card"
98
+ :resource="fetch.data"
99
+ @action-invoked="actionInvoked"
100
+ />
101
+ </template>
102
+ </PopoverCard>
130
103
  </template>
131
104
 
132
105
  <style lang="scss" scoped>
@@ -134,44 +107,8 @@ watch(
134
107
  position: relative;
135
108
  width: 100%;
136
109
 
137
- .target, a {
138
- @include clip;
139
- }
140
-
141
- .display-container {
142
- position: absolute;
143
- left: 0;
144
- right: 0;
145
- top: 0;
146
- bottom: 0;
147
- }
148
-
149
110
  .display {
150
111
  display: inline-flex;
151
- max-width: 100%;
152
- a {
153
- flex: 1;
154
- }
155
- }
156
-
157
- .target {
158
- width: 100%;
159
- height: 17px;
160
- }
161
-
162
- .focus-button {
163
- margin-left: 4px;
164
- padding: 0;
165
- width: 0px;
166
- height: initial;
167
- min-height: initial;
168
- overflow: hidden;
169
- border-width: 0;
170
-
171
- &:focus {
172
- width: initial;
173
- border-width: 1px;
174
- }
175
112
  }
176
113
 
177
114
  .rc-status-indicator {
@@ -180,47 +117,5 @@ watch(
180
117
  height: initial;
181
118
  line-height: initial;
182
119
  }
183
-
184
- .resource-popover-card {
185
- border: none;
186
- }
187
-
188
- .resource-popover-container {
189
- position: absolute;
190
- $size: 10px;
191
- height: $size;
192
- bottom: -$size;
193
- width: 100%;
194
- }
195
-
196
- &:deep() {
197
- & > .v-popper > .btn.role-link {
198
- padding: 0;
199
- min-height: initial;
200
- line-height: initial;
201
-
202
- &:hover {
203
- background: none;
204
- }
205
- }
206
-
207
- .resource-popover-container > .v-popper__popper {
208
- border-radius: 6px;
209
- box-shadow: 4px 4px 8px 0 rgba(0, 0, 0, 0.04);
210
-
211
- & > .v-popper__wrapper {
212
- .v-popper__arrow-container {
213
- display: none;
214
- }
215
-
216
- & > .v-popper__inner {
217
- overflow: initial;
218
- &, & > div > .dropdownTarget {
219
- padding: 0;
220
- }
221
- }
222
- }
223
- }
224
- }
225
120
  }
226
121
  </style>
@@ -3,8 +3,6 @@ import TitleBar from '@shell/components/Resource/Detail/TitleBar/index.vue';
3
3
  import ActionMenu from '@shell/components/ActionMenuShell.vue';
4
4
  import { createStore } from 'vuex';
5
5
 
6
- jest.mock(`@shell/assets/images/icons/document.svg`, () => `@shell/assets/images/icons/document.svg`);
7
-
8
6
  describe('component: TitleBar/index', () => {
9
7
  const resourceTypeLabel = 'RESOURCE_TYPE_LABEL';
10
8
  const resourceTo = 'RESOURCE_TO';
@@ -1,3 +1,4 @@
1
+ import { useOnShowConfiguration } from '@shell/components/Resource/Detail/composables';
1
2
  import { TitleBarProps } from '@shell/components/Resource/Detail/TitleBar/index.vue';
2
3
  import { computed, Ref, toValue } from 'vue';
3
4
  import { useRoute } from 'vue-router';
@@ -23,7 +24,7 @@ export const useDefaultTitleBarProps = (resource: any, resourceSubtype?: Ref<str
23
24
  resource: resourceValue.type
24
25
  }
25
26
  };
26
- const onShowConfiguration = resourceValue.disableResourceDetailDrawer ? undefined : (returnFocusSelector: string) => resourceValue.showConfiguration(returnFocusSelector);
27
+ const onShowConfiguration = resourceValue.disableResourceDetailDrawer ? undefined : useOnShowConfiguration(resource);
27
28
 
28
29
  return {
29
30
  resource: resourceValue,