@rancher/shell 3.0.8-rc.1 → 3.0.8-rc.12

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 (345) 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/styles/base/_typography.scss +1 -0
  27. package/assets/styles/fonts/_fontstack.scss +53 -1
  28. package/assets/styles/global/_cards.scss +0 -3
  29. package/assets/styles/global/_layout.scss +21 -35
  30. package/assets/styles/themes/_dark.scss +1 -1
  31. package/assets/styles/themes/_light.scss +1 -1
  32. package/assets/styles/themes/_modern.scss +11 -3
  33. package/assets/styles/themes/_suse.scss +116 -24
  34. package/assets/translations/en-us.yaml +94 -10
  35. package/components/AutoscalerCard.vue +113 -0
  36. package/components/AutoscalerTab.vue +94 -0
  37. package/components/BackLink.vue +8 -0
  38. package/components/BannerGraphic.vue +36 -21
  39. package/components/BrandImage.vue +17 -6
  40. package/components/ClusterIconMenu.vue +1 -1
  41. package/components/ClusterProviderIcon.vue +1 -1
  42. package/components/Cron/CronExpressionEditor.vue +1 -1
  43. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  44. package/components/Drawer/Chrome.vue +2 -6
  45. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
  46. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
  47. package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
  48. package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
  49. package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
  50. package/components/Drawer/types.ts +3 -0
  51. package/components/DynamicContent/DynamicContentBanner.vue +102 -0
  52. package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
  53. package/components/DynamicContent/DynamicContentIcon.vue +132 -0
  54. package/components/DynamicContent/DynamicContentPanel.vue +112 -0
  55. package/components/DynamicContent/content.ts +78 -0
  56. package/components/EmberPage.vue +1 -1
  57. package/components/IconOrSvg.vue +2 -2
  58. package/components/PaginatedResourceTable.vue +2 -6
  59. package/components/PopoverCard.vue +192 -0
  60. package/components/Questions/__tests__/index.test.ts +159 -0
  61. package/components/Resource/Detail/CopyToClipboard.vue +4 -1
  62. package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
  63. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  64. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
  65. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
  66. package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
  67. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  68. package/components/Resource/Detail/Metadata/composables.ts +9 -9
  69. package/components/Resource/Detail/Metadata/index.vue +3 -3
  70. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
  71. package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
  72. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
  73. package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
  74. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
  75. package/components/Resource/Detail/TitleBar/composables.ts +2 -1
  76. package/components/Resource/Detail/TitleBar/index.vue +10 -6
  77. package/components/Resource/Detail/composables.ts +12 -0
  78. package/components/ResourceDetail/Masthead/latest.vue +29 -0
  79. package/components/ResourceDetail/index.vue +4 -1
  80. package/components/ResourceList/Masthead.vue +1 -1
  81. package/components/ResourceTable.vue +1 -1
  82. package/components/SortableTable/index.vue +2 -1
  83. package/components/Tabbed/__tests__/index.test.ts +86 -0
  84. package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
  85. package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
  86. package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
  87. package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
  88. package/components/__tests__/AutoscalerCard.test.ts +154 -0
  89. package/components/__tests__/AutoscalerTab.test.ts +125 -0
  90. package/components/__tests__/PopoverCard.test.ts +204 -0
  91. package/components/auth/SelectPrincipal.vue +24 -6
  92. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  93. package/components/auth/login/ldap.vue +3 -3
  94. package/components/form/NodeScheduling.vue +2 -2
  95. package/components/formatter/Autoscaler.vue +97 -0
  96. package/components/formatter/InternalExternalIP.vue +198 -24
  97. package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
  98. package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
  99. package/components/google/util/__tests__/formatter.test.ts +47 -0
  100. package/components/google/util/formatter.ts +5 -2
  101. package/components/nav/Group.vue +21 -5
  102. package/components/nav/Header.vue +37 -17
  103. package/components/nav/NamespaceFilter.vue +13 -1
  104. package/components/nav/NotificationCenter/index.vue +2 -1
  105. package/components/nav/TopLevelMenu.helper.ts +16 -6
  106. package/components/nav/TopLevelMenu.vue +4 -2
  107. package/components/nav/Type.vue +8 -3
  108. package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
  109. package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
  110. package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
  111. package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
  112. package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
  113. package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
  114. package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
  115. package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
  116. package/components/nav/WindowManager/constants.ts +23 -0
  117. package/components/nav/WindowManager/index.vue +61 -575
  118. package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
  119. package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
  120. package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
  121. package/components/nav/__tests__/Type.test.ts +59 -0
  122. package/components/templates/default.vue +4 -40
  123. package/components/templates/home.vue +31 -5
  124. package/components/templates/plain.vue +30 -4
  125. package/components/templates/standalone.vue +1 -1
  126. package/composables/useI18n.ts +10 -1
  127. package/composables/useInterval.ts +15 -0
  128. package/config/__test__/uiplugins.test.ts +309 -0
  129. package/config/labels-annotations.js +9 -1
  130. package/config/product/explorer.js +3 -1
  131. package/config/product/manager.js +20 -9
  132. package/config/router/navigation-guards/clusters.js +3 -3
  133. package/config/router/navigation-guards/products.js +1 -1
  134. package/config/router/routes.js +10 -2
  135. package/config/settings.ts +2 -1
  136. package/config/store.js +4 -2
  137. package/config/table-headers.js +8 -0
  138. package/config/types.js +9 -0
  139. package/config/uiplugins.js +46 -2
  140. package/config/version.js +1 -1
  141. package/core/__test__/extension-manager-impl.test.js +236 -0
  142. package/core/extension-manager-impl.js +21 -4
  143. package/core/plugin-helpers.ts +4 -2
  144. package/core/plugins-loader.js +2 -2
  145. package/core/types-provisioning.ts +8 -1
  146. package/detail/pod.vue +1 -0
  147. package/detail/provisioning.cattle.io.cluster.vue +19 -7
  148. package/dialog/DeveloperLoadExtensionDialog.vue +13 -4
  149. package/dialog/RollbackWorkloadDialog.vue +2 -5
  150. package/dialog/SearchDialog.vue +1 -0
  151. package/directives/ui-context.ts +103 -0
  152. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
  153. package/edit/auth/__tests__/oidc.test.ts +26 -0
  154. package/edit/auth/github.vue +5 -0
  155. package/edit/auth/oidc.vue +5 -1
  156. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  157. package/edit/cloudcredential.vue +1 -1
  158. package/edit/configmap.vue +1 -0
  159. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  160. package/edit/fleet.cattle.io.gitrepo.vue +0 -10
  161. package/edit/fleet.cattle.io.helmop.vue +6 -6
  162. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  163. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  164. package/edit/logging-flow/index.vue +1 -0
  165. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  166. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  167. package/edit/management.cattle.io.project.vue +1 -0
  168. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  169. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  170. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  171. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  172. package/edit/monitoring.coreos.com.route.vue +1 -1
  173. package/edit/namespace.vue +1 -0
  174. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  175. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  176. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  177. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  178. package/edit/node.vue +1 -0
  179. package/edit/persistentvolume/index.vue +27 -22
  180. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  181. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  182. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  183. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  184. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  185. package/edit/persistentvolume/plugins/csi.vue +18 -16
  186. package/edit/persistentvolume/plugins/fc.vue +13 -14
  187. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  188. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  189. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  190. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  191. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  192. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  193. package/edit/persistentvolume/plugins/local.vue +1 -3
  194. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  195. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  196. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  197. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  198. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  199. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  200. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  201. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  202. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  203. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
  204. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
  205. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
  206. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
  207. package/edit/provisioning.cattle.io.cluster/index.vue +28 -18
  208. package/edit/provisioning.cattle.io.cluster/rke2.vue +50 -16
  209. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
  210. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
  211. package/edit/secret/index.vue +1 -1
  212. package/edit/service.vue +9 -4
  213. package/edit/serviceaccount.vue +1 -0
  214. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  215. package/edit/workload/index.vue +2 -1
  216. package/edit/workload/mixins/workload.js +1 -1
  217. package/initialize/App.vue +4 -4
  218. package/initialize/install-directives.js +2 -0
  219. package/initialize/install-plugins.js +19 -2
  220. package/list/provisioning.cattle.io.cluster.vue +15 -2
  221. package/machine-config/amazonec2.vue +42 -135
  222. package/machine-config/components/EC2Networking.vue +490 -0
  223. package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
  224. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
  225. package/machine-config/digitalocean.vue +11 -0
  226. package/machine-config/google.vue +1 -1
  227. package/mixins/__tests__/brand.spec.ts +2 -2
  228. package/mixins/__tests__/chart.test.ts +21 -0
  229. package/mixins/brand.js +1 -7
  230. package/mixins/chart.js +7 -1
  231. package/mixins/create-edit-view/index.js +5 -0
  232. package/models/__tests__/chart.test.ts +33 -4
  233. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
  234. package/models/chart.js +25 -13
  235. package/models/cluster/node.js +13 -6
  236. package/models/cluster.x-k8s.io.machine.js +10 -20
  237. package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
  238. package/models/management.cattle.io.cluster.js +21 -3
  239. package/models/management.cattle.io.kontainerdriver.js +1 -0
  240. package/models/provisioning.cattle.io.cluster.js +249 -33
  241. package/package.json +8 -7
  242. package/pages/auth/login.vue +41 -5
  243. package/pages/auth/setup.vue +1 -1
  244. package/pages/auth/verify.vue +3 -3
  245. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  246. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  247. package/pages/c/_cluster/apps/charts/index.vue +11 -13
  248. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  249. package/pages/c/_cluster/explorer/index.vue +8 -6
  250. package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
  251. package/pages/c/_cluster/settings/brand.vue +1 -1
  252. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  253. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  254. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  255. package/pages/home.vue +14 -4
  256. package/pkg/auto-import.js +3 -3
  257. package/pkg/dynamic-importer.lib.js +5 -1
  258. package/pkg/import.js +1 -1
  259. package/plugins/dashboard-client-init.js +3 -0
  260. package/plugins/dashboard-store/getters.js +19 -2
  261. package/plugins/dashboard-store/model-loader.js +1 -1
  262. package/plugins/dashboard-store/resource-class.js +10 -6
  263. package/plugins/dynamic-content.js +13 -0
  264. package/plugins/i18n.js +8 -0
  265. package/plugins/plugin.js +2 -2
  266. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
  267. package/plugins/steve/steve-class.js +1 -1
  268. package/plugins/steve/steve-pagination-utils.ts +39 -20
  269. package/plugins/steve/subscribe.js +17 -9
  270. package/plugins/subscribe-events.ts +4 -2
  271. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  272. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
  273. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  274. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  275. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  276. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  277. package/rancher-components/Pill/types.ts +0 -1
  278. package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
  279. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
  280. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  281. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  282. package/rancher-components/RcIcon/index.ts +1 -0
  283. package/rancher-components/RcIcon/types.ts +160 -0
  284. package/rancher-components/utils/status.test.ts +67 -0
  285. package/rancher-components/utils/status.ts +77 -0
  286. package/scripts/typegen.sh +1 -0
  287. package/store/__tests__/catalog.test.ts +1 -1
  288. package/store/action-menu.js +8 -0
  289. package/store/auth.js +4 -4
  290. package/store/catalog.js +6 -0
  291. package/store/features.js +1 -0
  292. package/store/i18n.js +3 -3
  293. package/store/index.js +40 -19
  294. package/store/notifications.ts +51 -4
  295. package/store/plugins.js +7 -3
  296. package/store/prefs.js +6 -6
  297. package/store/type-map.js +7 -7
  298. package/store/ui-context.ts +86 -0
  299. package/store/wm.ts +244 -0
  300. package/types/notifications/index.ts +27 -3
  301. package/types/shell/index.d.ts +80 -4
  302. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  303. package/types/store/pagination.types.ts +157 -9
  304. package/types/store/subscribe-events.types.ts +8 -1
  305. package/types/store/subscribe.types.ts +1 -0
  306. package/types/window-manager.ts +24 -0
  307. package/utils/__tests__/object.test.ts +19 -0
  308. package/utils/__tests__/provider.test.ts +98 -0
  309. package/utils/__tests__/selector-typed.test.ts +263 -0
  310. package/utils/__tests__/version.test.ts +19 -1
  311. package/utils/autoscaler-utils.ts +7 -0
  312. package/utils/back-off.ts +3 -3
  313. package/utils/brand.ts +29 -0
  314. package/utils/chart.js +18 -0
  315. package/utils/color.js +1 -1
  316. package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
  317. package/utils/dynamic-content/__tests__/info.test.ts +21 -9
  318. package/utils/dynamic-content/announcement.ts +142 -0
  319. package/utils/dynamic-content/example.json +40 -0
  320. package/utils/dynamic-content/index.ts +6 -2
  321. package/utils/dynamic-content/info.ts +44 -2
  322. package/utils/dynamic-content/new-release.ts +1 -1
  323. package/utils/dynamic-content/notification-handler.ts +48 -0
  324. package/utils/dynamic-content/types.d.ts +53 -1
  325. package/utils/dynamic-importer.js +2 -2
  326. package/utils/favicon.js +4 -4
  327. package/utils/object.js +20 -2
  328. package/utils/pagination-utils.ts +2 -2
  329. package/utils/pagination-wrapper.ts +13 -9
  330. package/utils/provider.ts +14 -0
  331. package/utils/scroll.js +7 -0
  332. package/utils/selector-typed.ts +6 -2
  333. package/utils/settings.ts +15 -0
  334. package/utils/unit-tests/pagination-utils.spec.ts +8 -8
  335. package/utils/validators/machine-pool.ts +13 -3
  336. package/utils/version.js +15 -0
  337. package/vue.config.js +3 -3
  338. package/assets/images/icons/document.svg +0 -3
  339. package/plugins/nuxt-client-init.js +0 -3
  340. package/store/wm.js +0 -95
  341. /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
  342. /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
  343. /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
  344. /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
  345. /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
@@ -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,
@@ -32,8 +32,6 @@ export interface TitleBarProps {
32
32
  actionMenuResource?: any;
33
33
  onShowConfiguration?: (returnFocusSelector: string) => void;
34
34
  }
35
-
36
- const showConfigurationIcon = require(`@shell/assets/images/icons/document.svg`);
37
35
  </script>
38
36
 
39
37
  <script setup lang="ts">
@@ -84,6 +82,7 @@ watch(
84
82
  </span>
85
83
  <BadgeState
86
84
  v-if="badge"
85
+ v-ui-context="{ store: store, icon: 'icon-folder', hookable: true, value: resource, tag: '__details-state', description: 'Details' }"
87
86
  class="badge-state"
88
87
  :color="badge.color"
89
88
  :label="badge.label"
@@ -99,11 +98,10 @@ watch(
99
98
  :aria-label="i18n.t('component.resource.detail.titleBar.ariaLabel.showConfiguration', { resource: resourceName })"
100
99
  @click="() => emit('show-configuration', showConfigurationReturnFocusSelector)"
101
100
  >
102
- <img
103
- :src="showConfigurationIcon"
104
- class="mmr-3"
101
+ <i
102
+ class="icon icon-document"
105
103
  aria-hidden="true"
106
- >
104
+ />
107
105
  {{ i18n.t('component.resource.detail.titleBar.showConfiguration') }}
108
106
  </RcButton>
109
107
  <ActionMenu
@@ -139,6 +137,12 @@ watch(
139
137
  position: relative;
140
138
  }
141
139
 
140
+ .icon-document {
141
+ width: 15px;
142
+ font-size: 16px;
143
+ margin-right: 10px;
144
+ }
145
+
142
146
  .show-configuration {
143
147
  margin-left: 16px;
144
148
  }
@@ -2,6 +2,7 @@ import { computed, Ref, toValue } from 'vue';
2
2
  import { useStore } from 'vuex';
3
3
  import { Props as BannerProps } from '@components/Banner/Banner.vue';
4
4
  import { useI18n } from '@shell/composables/useI18n';
5
+ import ResourceClass from '@shell/plugins/dashboard-store/resource-class';
5
6
 
6
7
  export const useResourceDetailBannerProps = (resource: any): Ref<BannerProps | undefined> => {
7
8
  const store = useStore();
@@ -43,3 +44,14 @@ export const useResourceDetailBannerProps = (resource: any): Ref<BannerProps | u
43
44
  return undefined;
44
45
  });
45
46
  };
47
+
48
+ export const useOnShowConfiguration = (resource: any) => {
49
+ return (returnFocusSelector?: string, defaultTab?: string) => {
50
+ const resourceValue = toValue(resource);
51
+ // Because extensions can make a copy of the resource-class it's possible that an extension will have a resource-class which predates the inclusion of showConfiguration
52
+ // to still the rest of shell to consume
53
+ const showConfiguration = resourceValue.showConfiguration ? resourceValue.showConfiguration.bind(resourceValue) : ResourceClass.prototype.showConfiguration.bind(resourceValue);
54
+
55
+ showConfiguration(returnFocusSelector, defaultTab);
56
+ };
57
+ };
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ /* eslint-disable */
2
3
  import { Banner } from '@components/Banner';
3
4
  import TitleBar from '@shell/components/Resource/Detail/TitleBar/index.vue';
4
5
  import { useDefaultTitleBarProps } from '@shell/components/Resource/Detail/TitleBar/composables';
@@ -7,6 +8,7 @@ import { useDefaultMetadataForLegacyPagesProps } from '@shell/components/Resourc
7
8
  import { useResourceDetailBannerProps } from '@shell/components/Resource/Detail/composables';
8
9
  import { computed } from 'vue';
9
10
 
11
+ // We are disabling eslint for this script to allow the use of the Props interface
10
12
  export interface Props {
11
13
  value?: Object;
12
14
  resourceSubtype?: string;
@@ -15,18 +17,45 @@ export interface Props {
15
17
  </script>
16
18
 
17
19
  <script lang="ts" setup>
20
+ import { useStore } from 'vuex';
21
+
18
22
  const props = withDefaults(defineProps<Props>(), { value: () => ({}), resourceSubtype: undefined });
19
23
 
24
+ const uiCtxResource = computed(() => {
25
+ const {
26
+ name, metadata, kind, state
27
+ } = (props.value || {}) as any;
28
+
29
+ return {
30
+ name,
31
+ namespace: metadata?.namespace,
32
+ kind,
33
+ state,
34
+ };
35
+ });
20
36
  const resourceSubtype = computed(() => props.resourceSubtype);
21
37
  const titleBarProps = useDefaultTitleBarProps(props.value, resourceSubtype);
22
38
  const metadataProps = useDefaultMetadataForLegacyPagesProps(props.value);
23
39
  const bannerProps = useResourceDetailBannerProps(props.value);
40
+
41
+ const store = useStore();
24
42
  </script>
25
43
 
26
44
  <template>
27
45
  <TitleBar v-bind="titleBarProps" />
28
46
  <Banner
29
47
  v-if="bannerProps"
48
+ v-ui-context="{
49
+ store: store,
50
+ icon: 'icon-info',
51
+ hookable: true,
52
+ value: {
53
+ bannerProps,
54
+ resource: uiCtxResource
55
+ },
56
+ tag: '__details-state-banner',
57
+ description: 'Status Message'
58
+ }"
30
59
  class="new state-banner"
31
60
  v-bind="bannerProps"
32
61
  />
@@ -310,7 +310,7 @@ export default {
310
310
  }), {});
311
311
  },
312
312
  isFullPageOverride() {
313
- return this.isView && this.value.fullDetailPageOverride;
313
+ return this.isView && this.value.fullDetailPageOverride && !this.isYaml;
314
314
  }
315
315
  },
316
316
 
@@ -430,6 +430,7 @@ export default {
430
430
  :is="showComponent"
431
431
  v-else-if="isFullPageOverride"
432
432
  v-model:value="value"
433
+ v-ui-context="{ icon: 'icon-folder', value: value.name, tag: value.kind?.toLowerCase(), description: value.kind }"
433
434
  v-bind="$data"
434
435
  :done-params="doneParams"
435
436
  :done-route="doneRoute"
@@ -446,6 +447,7 @@ export default {
446
447
  <div v-else>
447
448
  <Masthead
448
449
  v-if="showMasthead"
450
+ v-ui-context="{ icon: 'icon-folder', value: liveModel.name, tag: liveModel.kind?.toLowerCase(), description: liveModel.kind }"
449
451
  :resource="resourceType"
450
452
  :value="liveModel"
451
453
  :mode="mode"
@@ -499,6 +501,7 @@ export default {
499
501
  v-else
500
502
  ref="comp"
501
503
  v-model:value="value"
504
+ v-ui-context="{ icon: 'icon-folder', value: value.name, tag: value.kind?.toLowerCase(), description: value.kind }"
502
505
  v-bind="$data"
503
506
  :done-params="doneParams"
504
507
  :done-route="doneRoute"
@@ -141,7 +141,7 @@ export default {
141
141
  }
142
142
 
143
143
  // blocked-post means you can post through norman, but not through steve.
144
- if ( this.schema && !this.schema?.collectionMethods.find((x) => ['blocked-post', 'post'].includes(x.toLowerCase())) ) {
144
+ if ( this.schema && this.schema?.collectionMethods && !this.schema?.collectionMethods.find((x) => ['blocked-post', 'post'].includes(x.toLowerCase())) ) {
145
145
  return false;
146
146
  }
147
147
 
@@ -316,7 +316,7 @@ export default {
316
316
 
317
317
  // add custom table columns provided by the extensions ExtensionPoint.TABLE_COL hook
318
318
  // gate it so that we prevent errors on older versions of dashboard
319
- if (this.$store.$plugin?.getUIConfig) {
319
+ if (this.$store.$extension?.getUIConfig) {
320
320
  // { column: TableColumn, paginationColumn: PaginationTableColumn }[]
321
321
  const extensionCols = getApplicableExtensionEnhancements(this, ExtensionPoint.TABLE_COL, TableColumnLocation.RESOURCE, this.$route);
322
322
 
@@ -765,7 +765,7 @@ export default {
765
765
  needRef = true;
766
766
  } else {
767
767
  // Check if we have a formatter from a plugin
768
- const pluginFormatter = this.$plugin?.getDynamic('formatters', c.formatter);
768
+ const pluginFormatter = this.$extension?.getDynamic('formatters', c.formatter);
769
769
 
770
770
  if (pluginFormatter) {
771
771
  component = defineAsyncComponent(pluginFormatter);
@@ -1474,6 +1474,7 @@ export default {
1474
1474
  <td
1475
1475
  v-show="!hasAdvancedFiltering || (hasAdvancedFiltering && col.col.isColVisible)"
1476
1476
  :key="col.col.name"
1477
+ v-ui-context="col.col.name === 'state' ? { icon: 'icon-folder', hookable: true, value: row.row, tag: '__sortable-table-row', description: 'Row' } : undefined"
1477
1478
  :data-title="col.col.label"
1478
1479
  :data-testid="`sortable-cell-${ i }-${ j }`"
1479
1480
  :align="col.col.align || 'left'"
@@ -0,0 +1,86 @@
1
+ import { mount, VueWrapper } from '@vue/test-utils';
2
+ import Tabbed from '@shell/components/Tabbed/index.vue';
3
+ import Tab from '@shell/components/Tabbed/Tab.vue';
4
+
5
+ jest.mock('@shell/components/form/ResourceTabs/composable', () => ({ useTabCountWatcher: () => ({}) }));
6
+
7
+ const mockT = (key: string) => key;
8
+
9
+ const defaultGlobalMountOptions = {
10
+ components: { Tab },
11
+ mocks: {
12
+ $router: {
13
+ replace: jest.fn(),
14
+ currentRoute: { _value: { hash: '' } }
15
+ },
16
+ $route: { hash: '' },
17
+ t: mockT,
18
+ store: { getters: { 'i18n/t': mockT } }
19
+ }
20
+ };
21
+
22
+ describe('component: Tabbed', () => {
23
+ const findTabNav = (wrapper: VueWrapper<any>) => wrapper.find('[data-testid="tabbed-block"]');
24
+
25
+ it('should display tab navigation for a single tab when hideSingleTab is false (default)', async() => {
26
+ const wrapper = mount(Tabbed, {
27
+ slots: { default: { components: { Tab }, template: '<Tab name="tab1" label="Tab 1" />' } },
28
+ global: { ...defaultGlobalMountOptions },
29
+ });
30
+
31
+ await wrapper.vm.$nextTick();
32
+
33
+ expect(findTabNav(wrapper).exists()).toBe(true);
34
+ });
35
+
36
+ it('should display tab navigation for multiple tabs when hideSingleTab is false (default)', async() => {
37
+ const wrapper = mount(Tabbed, {
38
+ slots: {
39
+ default: {
40
+ components: { Tab },
41
+ template: `
42
+ <Tab name="tab1" label="Tab 1" />
43
+ <Tab name="tab2" label="Tab 2" />
44
+ `,
45
+ },
46
+ },
47
+ global: { ...defaultGlobalMountOptions },
48
+ });
49
+
50
+ await wrapper.vm.$nextTick();
51
+
52
+ expect(findTabNav(wrapper).exists()).toBe(true);
53
+ });
54
+
55
+ it('should NOT display tab navigation for a single tab when hideSingleTab is true', async() => {
56
+ const wrapper = mount(Tabbed, {
57
+ props: { hideSingleTab: true },
58
+ slots: { default: { components: { Tab }, template: '<Tab name="tab1" label="Tab 1" />' } },
59
+ global: { ...defaultGlobalMountOptions },
60
+ });
61
+
62
+ await wrapper.vm.$nextTick();
63
+
64
+ expect(findTabNav(wrapper).exists()).toBe(false);
65
+ });
66
+
67
+ it('should display tab navigation for multiple tabs when hideSingleTab is true', async() => {
68
+ const wrapper = mount(Tabbed, {
69
+ props: { hideSingleTab: true },
70
+ slots: {
71
+ default: {
72
+ components: { Tab },
73
+ template: `
74
+ <Tab name="tab1" label="Tab 1" />
75
+ <Tab name="tab2" label="Tab 2" />
76
+ `,
77
+ },
78
+ },
79
+ global: { ...defaultGlobalMountOptions },
80
+ });
81
+
82
+ await wrapper.vm.$nextTick();
83
+
84
+ expect(findTabNav(wrapper).exists()).toBe(true);
85
+ });
86
+ });
@@ -10,7 +10,7 @@ import AsyncButton from '@shell/components/AsyncButton';
10
10
  import Select from '@shell/components/form/Select';
11
11
  import VirtualList from 'vue3-virtual-scroll-list';
12
12
  import LogItem from '@shell/components/LogItem';
13
- import ContainerLogsActions from '@shell/components/nav/WindowManager/ContainerLogsActions.vue';
13
+ import ContainerLogsActions from '@shell/components/Window/ContainerLogsActions.vue';
14
14
  import { shallowRef } from 'vue';
15
15
  import { useStore } from 'vuex';
16
16
  import { debounce } from 'lodash';
@@ -49,6 +49,7 @@ defineEmits([
49
49
  <rc-dropdown-item-select
50
50
  :model-value="range"
51
51
  :options="rangeOptions"
52
+ :label="t('wm.containerLogs.range.label')"
52
53
  @select="$emit('toggleRange', $event)"
53
54
  />
54
55
  <rc-dropdown-item-checkbox
@@ -1,6 +1,6 @@
1
1
  import { nextTick } from 'vue';
2
2
  import { shallowMount } from '@vue/test-utils';
3
- import ContainerLogs from '@shell/components/nav/WindowManager/ContainerLogs.vue';
3
+ import ContainerLogs from '@shell/components/Window/ContainerLogs.vue';
4
4
  import { base64Encode } from '@shell/utils/crypto';
5
5
  import { Buffer } from 'buffer';
6
6
  import { addEventListener } from '@shell/utils/socket';
@@ -1,9 +1,9 @@
1
1
  import { flushPromises, mount, Wrapper } from '@vue/test-utils';
2
- import ContainerShell from '@shell/components/nav/WindowManager/ContainerShell.vue';
2
+ import ContainerShell from '@shell/components/Window/ContainerShell.vue';
3
3
  import Socket, {
4
4
  addEventListener, EVENT_CONNECTED, EVENT_CONNECTING, EVENT_DISCONNECTED, EVENT_MESSAGE, EVENT_CONNECT_ERROR
5
5
  } from '@shell/utils/socket';
6
- import Window from '@shell/components/nav/WindowManager/Window.vue';
6
+ import Window from '@shell/components/Window/Window.vue';
7
7
 
8
8
  jest.mock('@shell/utils/socket');
9
9
  jest.mock('@shell/utils/crypto', () => {