@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
@@ -0,0 +1,235 @@
1
+ import { removeMatchingNotifications, createLogger, LOCAL_STORAGE_CONTENT_DEBUG_LOG } from '../util';
2
+ import { Context, Configuration } from '../types';
3
+
4
+ describe('util.ts', () => {
5
+ describe('removeMatchingNotifications', () => {
6
+ let mockContext: Context;
7
+ let mockDispatch: jest.Mock;
8
+ let mockGetters: any;
9
+ let mockLogger: any;
10
+
11
+ beforeEach(() => {
12
+ mockDispatch = jest.fn();
13
+ mockGetters = { 'notifications/all': [] };
14
+ mockLogger = { debug: jest.fn() };
15
+ mockContext = {
16
+ dispatch: mockDispatch,
17
+ getters: mockGetters,
18
+ logger: mockLogger,
19
+ // The following properties are not used by this function but are required by the type
20
+ axios: {},
21
+ isAdmin: true,
22
+ config: {} as any,
23
+ settings: {} as any,
24
+ };
25
+ });
26
+
27
+ it('should return false and not remove anything if no notifications exist', async() => {
28
+ const found = await removeMatchingNotifications(mockContext, 'prefix-', 'current');
29
+
30
+ expect(found).toBe(false);
31
+ expect(mockDispatch).not.toHaveBeenCalled();
32
+ });
33
+
34
+ it('should return false and not remove anything if no notifications match the prefix', async() => {
35
+ mockGetters['notifications/all'] = [
36
+ { id: 'other-1' },
37
+ { id: 'other-2' },
38
+ ];
39
+ const found = await removeMatchingNotifications(mockContext, 'prefix-', 'current');
40
+
41
+ expect(found).toBe(false);
42
+ expect(mockDispatch).not.toHaveBeenCalled();
43
+ });
44
+
45
+ it('should return true and not remove anything if the current notification is the only one matching', async() => {
46
+ mockGetters['notifications/all'] = [
47
+ { id: 'prefix-current' },
48
+ { id: 'other-1' },
49
+ ];
50
+ const found = await removeMatchingNotifications(mockContext, 'prefix-', 'current');
51
+
52
+ expect(found).toBe(true);
53
+ expect(mockDispatch).not.toHaveBeenCalled();
54
+ });
55
+
56
+ it('should return false and remove a notification that matches the prefix but not the currentId', async() => {
57
+ mockGetters['notifications/all'] = [
58
+ { id: 'prefix-old' },
59
+ { id: 'other-1' },
60
+ ];
61
+ const found = await removeMatchingNotifications(mockContext, 'prefix-', 'current');
62
+
63
+ expect(found).toBe(false);
64
+ expect(mockDispatch).toHaveBeenCalledTimes(1);
65
+ expect(mockDispatch).toHaveBeenCalledWith('notifications/remove', 'prefix-old');
66
+ });
67
+
68
+ it('should return true and remove old notifications when the current one also exists', async() => {
69
+ mockGetters['notifications/all'] = [
70
+ { id: 'prefix-old-1' },
71
+ { id: 'prefix-current' },
72
+ { id: 'prefix-old-2' },
73
+ { id: 'other-1' },
74
+ ];
75
+ const found = await removeMatchingNotifications(mockContext, 'prefix-', 'current');
76
+
77
+ expect(found).toBe(true);
78
+ expect(mockDispatch).toHaveBeenCalledTimes(2);
79
+ expect(mockDispatch).toHaveBeenCalledWith('notifications/remove', 'prefix-old-1');
80
+ expect(mockDispatch).toHaveBeenCalledWith('notifications/remove', 'prefix-old-2');
81
+ });
82
+ });
83
+
84
+ describe('createLogger / log', () => {
85
+ let mockLocalStorage: { [key: string]: string };
86
+ let consoleErrorSpy: jest.SpyInstance;
87
+ let consoleInfoSpy: jest.SpyInstance;
88
+ let consoleDebugSpy: jest.SpyInstance;
89
+ let dispatchEventSpy: jest.SpyInstance;
90
+
91
+ beforeEach(() => {
92
+ // Mock localStorage
93
+ mockLocalStorage = {};
94
+ jest.spyOn(Storage.prototype, 'getItem').mockImplementation((key) => mockLocalStorage[key] || null);
95
+ jest.spyOn(Storage.prototype, 'setItem').mockImplementation((key, value) => {
96
+ mockLocalStorage[key] = value;
97
+ });
98
+
99
+ // Mock console
100
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
101
+ consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation(() => {});
102
+ consoleDebugSpy = jest.spyOn(console, 'debug').mockImplementation(() => {});
103
+
104
+ // Mock dispatchEvent
105
+ dispatchEventSpy = jest.spyOn(window, 'dispatchEvent').mockImplementation(() => true);
106
+ });
107
+
108
+ afterEach(() => {
109
+ jest.restoreAllMocks();
110
+ });
111
+
112
+ it('should always log errors to console, but only to localStorage if config.log is true', () => {
113
+ const config: Configuration = {
114
+ enabled: true, debug: false, log: false, endpoint: '', prime: false, distribution: 'community'
115
+ };
116
+ const logger = createLogger(config);
117
+
118
+ logger.error('test error');
119
+
120
+ expect(consoleErrorSpy).toHaveBeenCalledWith('test error');
121
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeUndefined();
122
+
123
+ // Test with arg
124
+ logger.error('test error', 'with arg');
125
+
126
+ expect(consoleErrorSpy).toHaveBeenCalledWith('test error', 'with arg');
127
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeUndefined();
128
+
129
+ config.log = true;
130
+
131
+ logger.error('test error with log');
132
+
133
+ expect(consoleErrorSpy).toHaveBeenCalledWith('test error with log');
134
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeDefined();
135
+ expect(JSON.parse(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG])[0].message).toBe('test error with log');
136
+ });
137
+
138
+ it('should log info to console and localStorage only if config.log is true', () => {
139
+ const config: Configuration = {
140
+ enabled: true, debug: false, log: false, endpoint: '', prime: false, distribution: 'community'
141
+ };
142
+ const logger = createLogger(config);
143
+
144
+ logger.info('test info');
145
+
146
+ expect(consoleInfoSpy).not.toHaveBeenCalled();
147
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeUndefined();
148
+
149
+ config.log = true;
150
+ logger.info('test info with log');
151
+
152
+ expect(consoleInfoSpy).toHaveBeenCalledWith('test info with log');
153
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeDefined();
154
+ expect(JSON.parse(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG])[0].message).toBe('test info with log');
155
+
156
+ // Test with arg
157
+ logger.info('test info', 'with arg');
158
+
159
+ expect(consoleInfoSpy).toHaveBeenCalledWith('test info', 'with arg');
160
+ });
161
+
162
+ it('should log debug to console only if config.debug is true, and localStorage if config.log is true', () => {
163
+ const config: Configuration = {
164
+ enabled: true, debug: false, log: false, endpoint: '', prime: false, distribution: 'community'
165
+ };
166
+ const logger = createLogger(config);
167
+
168
+ logger.debug('test debug');
169
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
170
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeUndefined();
171
+
172
+ config.log = true;
173
+ logger.debug('test debug with log');
174
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
175
+ expect(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]).toBeDefined();
176
+ expect(JSON.parse(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG])[0].message).toBe('test debug with log');
177
+
178
+ config.debug = true;
179
+ logger.debug('test debug with debug and log');
180
+ expect(consoleDebugSpy).toHaveBeenCalledWith('test debug with debug and log');
181
+ });
182
+
183
+ it('should dispatch a custom event when logging to localStorage', () => {
184
+ const config: Configuration = {
185
+ enabled: true, debug: false, log: true, endpoint: '', prime: false, distribution: 'community'
186
+ };
187
+ const logger = createLogger(config);
188
+
189
+ logger.info('test event');
190
+
191
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
192
+ const event = dispatchEventSpy.mock.calls[0][0] as CustomEvent;
193
+
194
+ expect(event.type).toBe('dynamicContentLog');
195
+ expect(event.detail.message).toBe('test event');
196
+ });
197
+
198
+ it('should limit the number of log messages in localStorage', () => {
199
+ const config: Configuration = {
200
+ enabled: true, debug: false, log: true, endpoint: '', prime: false, distribution: 'community'
201
+ };
202
+ const logger = createLogger(config);
203
+
204
+ // MAX_LOG_MESSAGES is 50
205
+ for (let i = 0; i < 60; i++) {
206
+ logger.info(`message ${ i }`);
207
+ }
208
+
209
+ const logs = JSON.parse(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]);
210
+
211
+ expect(logs).toHaveLength(50);
212
+ expect(logs[0].message).toBe('message 59'); // Most recent
213
+ expect(logs[49].message).toBe('message 10'); // Oldest
214
+ });
215
+
216
+ it('should not throw if localStorage is corrupted', () => {
217
+ const config: Configuration = {
218
+ enabled: true, debug: false, log: true, endpoint: '', prime: false, distribution: 'community'
219
+ };
220
+ const logger = createLogger(config);
221
+
222
+ mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG] = 'this is not valid json';
223
+
224
+ expect(() => {
225
+ logger.info('test message');
226
+ }).not.toThrow();
227
+
228
+ // It should have overwritten the bad data
229
+ const logs = JSON.parse(mockLocalStorage[LOCAL_STORAGE_CONTENT_DEBUG_LOG]);
230
+
231
+ expect(logs).toHaveLength(1);
232
+ expect(logs[0].message).toBe('test message');
233
+ });
234
+ });
235
+ });
@@ -0,0 +1,142 @@
1
+ /**
2
+ *
3
+ * The code in this file is responsible for adding 'announcement 'notifications driven off of the dynamic content metadata
4
+ *
5
+ * Announcements will be able to be shown in different places in the UI
6
+ *
7
+ */
8
+
9
+ import semver from 'semver';
10
+ import { NotificationLevel, Notification } from '@shell/types/notifications';
11
+ import { READ_ANNOUNCEMENTS } from '@shell/store/prefs';
12
+ import { Context, VersionInfo, Announcement } from './types';
13
+ import { DynamicContentAnnouncementHandlerName } from './notification-handler';
14
+
15
+ // Prefixes used in the notifications IDs created here
16
+ export const ANNOUNCEMENT_PREFIX = 'announcement-';
17
+
18
+ const TARGET_NOTIFICATION_CENTER = 'notification';
19
+ const TARGET_HOME_PAGE = 'homepage';
20
+ const ALLOWED_TARGETS = [TARGET_NOTIFICATION_CENTER, TARGET_HOME_PAGE];
21
+
22
+ const ALLOWED_NOTIFICATIONS: Record<string, NotificationLevel> = {
23
+ announcement: NotificationLevel.Announcement,
24
+ info: NotificationLevel.Info,
25
+ warning: NotificationLevel.Warning,
26
+ homepage: NotificationLevel.Hidden,
27
+ };
28
+
29
+ /**
30
+ * Main exported function that will process the announcements
31
+ *
32
+ * @param context Context helper providing access to config, logger, store
33
+ * @param announcements Announcement information
34
+ * @param versionInfo Version information
35
+ */
36
+ export async function processAnnouncements(context: Context, announcements: Announcement[] | undefined, versionInfo: VersionInfo): Promise<void> {
37
+ if (!announcements || !announcements.length || !versionInfo?.version) {
38
+ return;
39
+ }
40
+
41
+ const { dispatch, getters, logger } = context;
42
+
43
+ // Process each announcement
44
+ await Promise.all(announcements.map(async(announcement: Announcement) => {
45
+ // Check version
46
+ if (announcement.version && !semver.satisfies(versionInfo.version, announcement.version)) {
47
+ return;
48
+ }
49
+
50
+ // Check audience (currently only admin or all, but may add more in the future)
51
+ if (announcement.audience === 'admin' && !context.isAdmin) {
52
+ return;
53
+ }
54
+
55
+ if (!announcement.id) {
56
+ logger.error(`No ID For announcement - not going to add a notification for the announcement`);
57
+
58
+ return;
59
+ }
60
+
61
+ // Check type
62
+ const targetSplit = announcement.target.split('/');
63
+ const target = targetSplit[0];
64
+
65
+ // Make sure that the target is supported
66
+ if (ALLOWED_TARGETS.includes(target)) {
67
+ let level = NotificationLevel.Announcement;
68
+ let data: any = {};
69
+
70
+ if (target === TARGET_NOTIFICATION_CENTER) {
71
+ // Show a notification
72
+ const subType = targetSplit.length === 2 ? targetSplit[1] : 'announcement';
73
+
74
+ if (!(subType in ALLOWED_NOTIFICATIONS)) {
75
+ logger.error(`Announcement notification type ${ subType } is not supported`);
76
+
77
+ return;
78
+ }
79
+
80
+ level = ALLOWED_NOTIFICATIONS[subType];
81
+ } else if (target === TARGET_HOME_PAGE) {
82
+ level = NotificationLevel.Hidden;
83
+ data = {
84
+ icon: announcement.icon,
85
+ location: targetSplit.length === 2 ? targetSplit[1] : 'banner',
86
+ };
87
+
88
+ if (announcement.style) {
89
+ data.style = announcement.style;
90
+ }
91
+ }
92
+
93
+ logger.info(`Going to add a notification for announcement ${ announcement.target }`);
94
+
95
+ // We should check if the notification already exists
96
+ const id = `${ ANNOUNCEMENT_PREFIX }${ announcement.id }`;
97
+ const existing = getters['notifications/item'](id);
98
+
99
+ // Check if the pref for 'read announcements' has the id
100
+ const pref = getters['prefs/get'](READ_ANNOUNCEMENTS) || '';
101
+ const prefExists = pref.split(',').includes(announcement.id);
102
+
103
+ if (existing || prefExists) {
104
+ logger.info(`Not adding announcement with ID ${ id } as it already exists or has been read previously (title: ${ announcement.title })`);
105
+
106
+ return;
107
+ }
108
+
109
+ const notification: Notification = {
110
+ id,
111
+ level,
112
+ title: announcement.title,
113
+ message: announcement.message,
114
+ handlerName: DynamicContentAnnouncementHandlerName,
115
+ };
116
+
117
+ if (data && Object.keys(data).length > 0) {
118
+ notification.data = data;
119
+ }
120
+
121
+ if (announcement.cta?.primary) {
122
+ notification.primaryAction = {
123
+ label: announcement.cta.primary.action,
124
+ target: announcement.cta.primary.link,
125
+ };
126
+ }
127
+
128
+ if (announcement.cta?.secondary) {
129
+ notification.secondaryAction = {
130
+ label: announcement.cta.secondary.action,
131
+ target: announcement.cta.secondary.link,
132
+ };
133
+ }
134
+
135
+ logger.info(`Adding announcement with ID ${ id } (title: ${ announcement.title }, target: ${ announcement.target })`);
136
+
137
+ await dispatch('notifications/add', notification);
138
+ } else {
139
+ logger.error(`Announcement type ${ announcement.target } is not supported`);
140
+ }
141
+ }));
142
+ }
@@ -0,0 +1,55 @@
1
+ import { SETTING } from '@shell/config/settings';
2
+ import { isRancherPrime } from '@shell/config/version';
3
+ import { Configuration, Distribution } from './types';
4
+ import { MANAGEMENT } from '@shell/config/types';
5
+
6
+ // Default endpoint ($dist is either 'community' or 'prime')
7
+ const DEFAULT_ENDPOINT = 'https://updates.rancher.io/rancher/$dist/updates';
8
+
9
+ // We only support retrieving content from secure endpoints
10
+ const HTTPS_PREFIX = 'https://';
11
+
12
+ /**
13
+ * Get configuration data based on the distribution and Rancher settings
14
+ *
15
+ * @param getters Store getters to access the store
16
+ * @returns Dynamic Content configuration
17
+ */
18
+ export function getConfig(getters: any): Configuration {
19
+ const prime = isRancherPrime();
20
+ const distribution: Distribution = prime ? 'prime' : 'community';
21
+
22
+ // Default configuration
23
+ const config: Configuration = {
24
+ enabled: true,
25
+ debug: false,
26
+ log: false,
27
+ endpoint: DEFAULT_ENDPOINT,
28
+ prime,
29
+ distribution,
30
+ };
31
+
32
+ // Update 'enabled' and 'endpoint' from Rancher settings, if applicable
33
+ try {
34
+ const enabledSetting = getters['management/byId'](MANAGEMENT.SETTING, SETTING.DYNAMIC_CONTENT_ENABLED);
35
+
36
+ if (enabledSetting?.value) {
37
+ // Any value other than 'false' means enabled (can't disable on Prime)
38
+ config.enabled = config.prime ? enabledSetting.value !== 'false' : true;
39
+ config.debug = enabledSetting.value === 'debug';
40
+ config.log = enabledSetting.value === 'log' || config.debug;
41
+ }
42
+
43
+ // Can only override the url when Prime
44
+ const urlSetting = getters['management/byId'](MANAGEMENT.SETTING, SETTING.DYNAMIC_CONTENT_ENDPOINT);
45
+
46
+ // Are we Prime, do we have a URL and does the URL start with the https prefix? If so, use it
47
+ if (prime && urlSetting?.value && urlSetting.value.startsWith(HTTPS_PREFIX)) {
48
+ config.endpoint = urlSetting.value;
49
+ }
50
+ } catch (e) {
51
+ console.error('Error reading dynamic content settings', e); // eslint-disable-line no-console
52
+ }
53
+
54
+ return config;
55
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "version": 1,
3
+ "releases": [
4
+ {
5
+ "name": "2.12.2"
6
+ },
7
+ {
8
+ "name": "2.11.3"
9
+ },
10
+ {
11
+ "name": "2.10.3"
12
+ }
13
+ ],
14
+ "announcements": [
15
+ {
16
+ "id": "security-update",
17
+ "target": "notification/announcement",
18
+ "title": "Important Security Update",
19
+ "message": "A critical security vulnerability has been discovered in version 2.10.1. Users are strongly advised to update to version 2.12.2 immediately to ensure their systems remain secure.",
20
+ "cta": {
21
+ "primary" : {
22
+ "action": "Update Now",
23
+ "link": "https://www.suse.com/"
24
+ }
25
+ }
26
+ },
27
+ {
28
+ "id": "suse-rocks",
29
+ "target": "homepage/banner",
30
+ "title": "Important Security Update",
31
+ "message": "A critical security vulnerability has been discovered in version 2.10.1. Users are strongly advised to update to version 2.12.2 immediately to ensure their systems remain secure.",
32
+ "cta": {
33
+ "primary" : {
34
+ "action": "Update Now",
35
+ "link": "https://www.suse.com/"
36
+ }
37
+ }
38
+ }
39
+ ]
40
+ }