@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.3

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 (272) hide show
  1. package/apis/impl/apis.ts +6 -0
  2. package/apis/index.ts +26 -0
  3. package/apis/intf/resources-api/cluster-api.ts +18 -0
  4. package/apis/intf/resources-api/mgmt-api.ts +15 -0
  5. package/apis/intf/resources-api/resource-base.ts +107 -0
  6. package/apis/intf/resources-api/resource-constants.ts +147 -0
  7. package/apis/intf/resources-api/resources-api.ts +143 -0
  8. package/apis/intf/resources.ts +49 -0
  9. package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
  10. package/apis/intf/shell-api/proxy.ts +216 -0
  11. package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
  12. package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
  13. package/apis/intf/shell.ts +12 -6
  14. package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
  15. package/apis/resources/index.ts +22 -0
  16. package/apis/resources/resources-api-class.ts +187 -0
  17. package/apis/shell/__tests__/proxy.test.ts +369 -0
  18. package/apis/shell/index.ts +8 -1
  19. package/apis/shell/modal.ts +4 -1
  20. package/apis/shell/notifications.ts +9 -6
  21. package/apis/shell/proxy.ts +256 -0
  22. package/apis/shell/slide-in.ts +4 -1
  23. package/apis/vue-shim.d.ts +2 -1
  24. package/assets/data/aws-regions.json +4 -0
  25. package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
  26. package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
  27. package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
  28. package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
  29. package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
  30. package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
  31. package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
  32. package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
  33. package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
  34. package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
  35. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
  36. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
  37. package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
  38. package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
  39. package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
  40. package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
  41. package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
  42. package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
  43. package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
  44. package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
  45. package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
  46. package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
  47. package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
  48. package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
  49. package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
  50. package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
  51. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
  52. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
  53. package/assets/styles/base/_variables.scss +2 -0
  54. package/assets/styles/fonts/_fontstack.scss +132 -8
  55. package/assets/translations/en-us.yaml +22 -5
  56. package/chart/monitoring/index.vue +10 -1
  57. package/components/ActionDropdownShell.vue +2 -1
  58. package/components/CruResourceFooter.vue +9 -5
  59. package/components/ExplorerProjectsNamespaces.vue +1 -1
  60. package/components/InstallHelmCharts.vue +2 -2
  61. package/components/LandingPagePreference.vue +14 -5
  62. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
  63. package/components/Resource/Detail/Metadata/index.vue +6 -0
  64. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  65. package/components/Resource/Detail/SpacedRow.vue +3 -1
  66. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  67. package/components/ResourceList/Masthead.vue +12 -8
  68. package/components/SelectIconGrid.vue +0 -10
  69. package/components/SingleClusterInfo.vue +1 -0
  70. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  71. package/components/SortableTable/index.vue +6 -9
  72. package/components/SortableTable/selection.js +23 -5
  73. package/components/SortableTable/sorting.js +6 -3
  74. package/components/Wizard.vue +14 -13
  75. package/components/fleet/FleetBundles.vue +100 -12
  76. package/components/fleet/FleetClusterTargets/index.vue +37 -15
  77. package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
  78. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  79. package/components/form/LabeledSelect.vue +20 -3
  80. package/components/form/NameNsDescription.vue +11 -0
  81. package/components/form/Security.vue +6 -2
  82. package/components/form/WorkloadPorts.vue +2 -7
  83. package/components/form/__tests__/Security.test.ts +76 -0
  84. package/components/formatter/Autoscaler.vue +4 -4
  85. package/components/formatter/ClusterKubeVersion.vue +27 -0
  86. package/components/formatter/ClusterLink.vue +1 -7
  87. package/components/formatter/ClusterProvider.vue +6 -10
  88. package/components/formatter/FleetSummaryGraph.vue +0 -3
  89. package/components/formatter/MachineSummaryGraph.vue +1 -1
  90. package/components/formatter/PodsUsage.vue +2 -2
  91. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  92. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  93. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  94. package/components/nav/NamespaceFilter.vue +2 -2
  95. package/components/nav/TopLevelMenu.helper.ts +15 -3
  96. package/components/nav/TopLevelMenu.vue +16 -5
  97. package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
  98. package/components/templates/home.vue +18 -0
  99. package/components/templates/plain.vue +18 -0
  100. package/components/templates/standalone.vue +17 -0
  101. package/composables/useFormValidation.ts +93 -0
  102. package/composables/useVeeValidateField.test.ts +159 -0
  103. package/composables/useVeeValidateField.ts +67 -0
  104. package/config/pagination-table-headers.js +18 -1
  105. package/config/product/manager.js +82 -21
  106. package/config/router/routes.js +6 -0
  107. package/config/table-headers.js +20 -1
  108. package/config/types.js +2 -1
  109. package/core/__tests__/plugin-products.test.ts +904 -20
  110. package/core/plugin-products-base.ts +107 -7
  111. package/core/plugin-products.ts +4 -0
  112. package/core/plugin-types.ts +111 -1
  113. package/core/plugin.ts +15 -7
  114. package/core/productDebugger.js +9 -4
  115. package/core/types-provisioning.ts +43 -30
  116. package/core/types.ts +57 -20
  117. package/detail/__tests__/pod.test.ts +41 -0
  118. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  119. package/detail/pod.vue +1 -1
  120. package/detail/provisioning.cattle.io.cluster.vue +4 -10
  121. package/edit/auth/__tests__/azuread.test.ts +217 -34
  122. package/edit/auth/azuread.vue +122 -14
  123. package/edit/auth/oidc.vue +2 -2
  124. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  125. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  126. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  127. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  128. package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
  129. package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
  130. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
  131. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  132. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  133. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  134. package/edit/secret/__tests__/ssh.test.ts +5 -6
  135. package/edit/secret/basic.vue +31 -0
  136. package/edit/secret/index.vue +68 -17
  137. package/edit/secret/registry.vue +38 -0
  138. package/edit/secret/ssh.vue +29 -0
  139. package/edit/secret/tls.vue +30 -0
  140. package/edit/service.vue +4 -4
  141. package/edit/workload/Upgrading.vue +3 -3
  142. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  143. package/edit/workload/mixins/workload.js +2 -1
  144. package/list/fleet.cattle.io.bundle.vue +7 -104
  145. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  146. package/list/provisioning.cattle.io.cluster.vue +262 -180
  147. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  148. package/mixins/__tests__/chart.test.ts +112 -0
  149. package/mixins/brand.js +2 -1
  150. package/mixins/chart.js +12 -8
  151. package/mixins/resource-fetch-api-pagination.js +41 -5
  152. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  153. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  154. package/models/__tests__/management.cattle.io.node.ts +6 -5
  155. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  156. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
  157. package/models/base-cluster.x-k8s.io.js +26 -0
  158. package/models/cluster.js +1 -1
  159. package/models/cluster.x-k8s.io.machine.js +4 -22
  160. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  161. package/models/cluster.x-k8s.io.machineset.js +2 -20
  162. package/models/compliance.cattle.io.clusterscan.js +130 -2
  163. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  164. package/models/fleet-application.js +3 -1
  165. package/models/management.cattle.io.cluster.js +417 -40
  166. package/models/management.cattle.io.node.js +6 -4
  167. package/models/management.cattle.io.nodepool.js +1 -1
  168. package/models/networking.k8s.io.ingress.js +12 -4
  169. package/models/provisioning.cattle.io.cluster.js +47 -330
  170. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  171. package/package.json +11 -29
  172. package/pages/__tests__/readme.test.ts +49 -0
  173. package/pages/auth/setup.vue +2 -3
  174. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
  175. package/pages/c/_cluster/apps/charts/chart.vue +60 -8
  176. package/pages/c/_cluster/apps/charts/install.vue +10 -7
  177. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  178. package/pages/c/_cluster/explorer/index.vue +5 -49
  179. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  180. package/pages/c/_cluster/istio/index.vue +21 -6
  181. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
  182. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +719 -2
  183. package/pages/c/_cluster/uiplugins/index.vue +203 -197
  184. package/pages/diagnostic.vue +13 -17
  185. package/pages/fail-whale.vue +18 -0
  186. package/pages/home.vue +77 -260
  187. package/pages/readme.vue +88 -0
  188. package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
  189. package/plugins/dashboard-store/actions.js +40 -18
  190. package/plugins/dashboard-store/resource-class.js +5 -2
  191. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  192. package/plugins/steve/steve-pagination-utils.ts +11 -3
  193. package/plugins/steve/subscribe.js +35 -5
  194. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
  195. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
  196. package/rancher-components/RcButton/RcButton.test.ts +37 -1
  197. package/rancher-components/RcButton/RcButton.vue +38 -8
  198. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  199. package/store/__tests__/catalog.test.ts +115 -1
  200. package/store/__tests__/type-map.test.ts +556 -1
  201. package/store/action-menu.js +8 -3
  202. package/store/auth.js +1 -1
  203. package/store/aws.js +27 -16
  204. package/store/catalog.js +27 -3
  205. package/store/digitalocean.js +20 -38
  206. package/store/index.js +2 -0
  207. package/store/linode.js +25 -40
  208. package/store/pnap.js +1 -0
  209. package/store/type-map.js +111 -29
  210. package/tsconfig.paths.json +8 -8
  211. package/types/kube/kube-api.ts +14 -1
  212. package/types/rancher/steve.api.ts +12 -12
  213. package/types/resources/settings.d.ts +2 -1
  214. package/types/shell/index.d.ts +102 -2
  215. package/types/store/dashboard-store.types.ts +108 -11
  216. package/types/store/pagination.types.ts +6 -3
  217. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  218. package/utils/__tests__/async.test.ts +87 -0
  219. package/utils/__tests__/aws.test.ts +140 -0
  220. package/utils/__tests__/banners.test.ts +176 -0
  221. package/utils/__tests__/chart.test.ts +64 -1
  222. package/utils/__tests__/color.test.ts +226 -0
  223. package/utils/__tests__/duration.test.ts +140 -0
  224. package/utils/__tests__/fleet.test.ts +340 -0
  225. package/utils/__tests__/ingress.test.ts +553 -0
  226. package/utils/__tests__/kube.test.ts +68 -0
  227. package/utils/__tests__/namespace-filter.test.ts +109 -0
  228. package/utils/__tests__/pagination-utils.test.ts +361 -0
  229. package/utils/__tests__/parse-externalid.test.ts +137 -0
  230. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  231. package/utils/__tests__/poller-sequential.test.ts +177 -0
  232. package/utils/__tests__/poller.test.ts +170 -0
  233. package/utils/__tests__/promise.test.ts +346 -0
  234. package/utils/__tests__/settings.test.ts +140 -0
  235. package/utils/__tests__/sort-utils.test.ts +301 -0
  236. package/utils/__tests__/string-utils.test.ts +798 -0
  237. package/utils/__tests__/string.test.ts +23 -1
  238. package/utils/__tests__/style.test.ts +154 -0
  239. package/utils/__tests__/svg-filter.test.ts +184 -0
  240. package/utils/__tests__/units.test.ts +417 -0
  241. package/utils/__tests__/versions.test.ts +128 -0
  242. package/utils/__tests__/xccdf.test.ts +391 -0
  243. package/utils/chart.js +36 -0
  244. package/utils/fleet.ts +13 -3
  245. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  246. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  247. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  248. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  249. package/utils/gc/__tests__/gc.test.ts +487 -0
  250. package/utils/ingress.ts +9 -1
  251. package/utils/pagination-utils.ts +2 -1
  252. package/utils/string.js +25 -2
  253. package/utils/uiplugins.ts +5 -5
  254. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  255. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  256. package/utils/validators/__tests__/index.test.ts +481 -0
  257. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  258. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  259. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  260. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  261. package/utils/validators/__tests__/role-template.test.ts +149 -0
  262. package/utils/validators/__tests__/service.test.ts +283 -0
  263. package/utils/validators/__tests__/setting.test.js +32 -0
  264. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  265. package/utils/validators/formRules/index.ts +5 -5
  266. package/utils/validators/machine-pool.ts +1 -1
  267. package/utils/validators/setting.js +18 -3
  268. package/utils/xccdf.ts +418 -0
  269. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  270. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  271. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  272. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.12-rc.2",
3
+ "version": "3.0.12-rc.3",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancher/dashboard",
6
6
  "license": "Apache-2.0",
@@ -20,25 +20,20 @@
20
20
  "dev": "./node_modules/.bin/vue-cli-service dev",
21
21
  "build": "./node_modules/.bin/vue-cli-service build",
22
22
  "analyze": "./node_modules/.bin/vue-cli-service build --report",
23
- "start": "./node_modules/.bin/vue-cli-service start",
24
- "cy:run": "cypress run",
25
- "cy:open": "cypress open",
26
- "e2e:pre": "NODE_ENV=dev yarn build",
27
- "e2e:run": "NODE_ENV=dev START_SERVER_AND_TEST_INSECURE=1 start-server-and-test start https://localhost:8005/ cy:run",
28
- "e2e:dev": "start-server-and-test dev https://localhost:8005 cy:open"
23
+ "start": "./node_modules/.bin/vue-cli-service start"
29
24
  },
30
25
  "dependencies": {
31
- "@aws-sdk/client-ec2": "3.863.0",
32
- "@aws-sdk/client-eks": "3.879.0",
33
- "@aws-sdk/client-iam": "3.863.0",
34
- "@aws-sdk/client-kms": "3.863.0",
26
+ "@aws-sdk/client-ec2": "3.1041.0",
27
+ "@aws-sdk/client-eks": "3.1041.0",
28
+ "@aws-sdk/client-iam": "3.1041.0",
29
+ "@aws-sdk/client-kms": "3.1041.0",
35
30
  "@babel/plugin-proposal-optional-chaining": "7.21.0",
36
31
  "@babel/plugin-proposal-private-methods": "7.18.6",
37
32
  "@babel/plugin-proposal-private-property-in-object": "7.14.5",
38
33
  "@babel/preset-typescript": "7.16.7",
39
34
  "@novnc/novnc": "1.2.0",
40
35
  "@popperjs/core": "2.11.8",
41
- "@rancher/icons": "2.0.55",
36
+ "@rancher/icons": "2.0.60",
42
37
  "@smithy/fetch-http-handler": "5.1.1",
43
38
  "@types/is-url": "1.2.30",
44
39
  "@types/node": "25.3.3",
@@ -52,10 +47,9 @@
52
47
  "@vue/vue3-jest": "27.0.0",
53
48
  "add": "2.0.6",
54
49
  "ansi_up": "5.0.0",
55
- "axios": "1.15.0",
50
+ "axios": "1.15.2",
56
51
  "axios-retry": "3.1.9",
57
52
  "babel-eslint": "10.1.0",
58
- "babel-plugin-module-resolver": "5.0.2",
59
53
  "babel-preset-vue": "2.0.2",
60
54
  "cache-loader": "4.1.0",
61
55
  "chart.js": "4.5.1",
@@ -63,28 +57,24 @@
63
57
  "codemirror": ">=5.64.0 <6",
64
58
  "codemirror-editor-vue3": "2.8.0",
65
59
  "color": "5.0.3",
66
- "cookie": "0.7.0",
67
60
  "cookie-universal": "2.2.2",
68
61
  "core-js": "3.48.0",
69
62
  "cron-validator": "1.4.0",
70
63
  "cronstrue": "3.9.0",
71
- "cross-env": "7.0.3",
72
64
  "css-loader": "6.7.3",
73
65
  "csv-loader": "3.0.3",
74
66
  "custom-event-polyfill": "^1.0.7",
75
- "cypress": "11.1.0",
76
67
  "d3": "7.3.0",
77
- "d3-selection": "3.0.0",
78
68
  "dayjs": "1.11.18",
69
+ "diff": "9.0.0",
79
70
  "diff2html": "3.4.24",
80
- "dompurify": "3.2.5",
71
+ "dompurify": "3.3.2",
81
72
  "element-matches": "^0.1.2",
82
73
  "entities": "4.5.0",
83
74
  "eslint": "7.32.0",
84
75
  "eslint-config-standard": "16.0.3",
85
76
  "eslint-import-resolver-node": "0.3.9",
86
77
  "eslint-module-utils": "2.6.1",
87
- "eslint-plugin-cypress": "2.12.1",
88
78
  "eslint-plugin-import": "2.32.0",
89
79
  "eslint-plugin-jest": "24.4.0",
90
80
  "eslint-plugin-n": "15.2.0",
@@ -103,10 +93,8 @@
103
93
  "jest-serializer-vue": "2.0.2",
104
94
  "jexl": "2.3.0",
105
95
  "jquery": "3.5.1",
106
- "js-cookie": "3.0.5",
107
96
  "js-yaml": "4.1.1",
108
97
  "js-yaml-loader": "1.2.2",
109
- "jsdiff": "1.1.1",
110
98
  "jsonpath-plus": "10.3.0",
111
99
  "jsrsasign": "11.1.1",
112
100
  "jszip": "3.10.1",
@@ -120,21 +108,14 @@
120
108
  "sass": "1.97.3",
121
109
  "sass-loader": "12.6.0",
122
110
  "serve-static": "1.14.1",
123
- "set-cookie-parser": "2.4.6",
124
- "shell-quote": "1.7.3",
125
- "sinon": "8.1.1",
126
- "start-server-and-test": "2.0.10",
127
111
  "style-loader": "1.2.1",
128
- "ts-node": "8.10.2",
129
112
  "typescript": "5.6.3",
130
113
  "ufo": "0.7.11",
131
114
  "unfetch": "4.2.0",
132
- "url-parse": "1.5.10",
133
115
  "vee-validate": "^4.15.1",
134
116
  "vue": "3.5.29",
135
117
  "vue-router": "4.6.4",
136
118
  "vue-select": "4.0.0-beta.6",
137
- "vue-server-renderer": "2.7.16",
138
119
  "vue3-resize": "0.2.0",
139
120
  "vue3-virtual-scroll-list": "0.2.1",
140
121
  "vuedraggable": "4.1.0",
@@ -142,6 +123,7 @@
142
123
  "webpack-bundle-analyzer": "4.10.2",
143
124
  "webpack-virtual-modules": "0.6.2",
144
125
  "worker-loader": "3.0.8",
126
+ "xmlbuilder2": "4.0.1",
145
127
  "xterm": "5.2.1",
146
128
  "xterm-addon-canvas": "0.5.0",
147
129
  "xterm-addon-fit": "0.8.0",
@@ -0,0 +1,49 @@
1
+ import Readme from '@shell/pages/readme.vue';
2
+
3
+ describe('page: Readme', () => {
4
+ describe('computed', () => {
5
+ it('showAppReadme defaults to false', () => {
6
+ const thisContext = { $route: { query: {} } };
7
+
8
+ const result = (Readme.computed!.showAppReadme as () => boolean).call(thisContext);
9
+
10
+ expect(result).toBe(false);
11
+ });
12
+
13
+ it('hideReadmeFirstTitle defaults to false', () => {
14
+ const thisContext = { $route: { query: {} } };
15
+
16
+ const result = (Readme.computed!.hideReadmeFirstTitle as () => boolean).call(thisContext);
17
+
18
+ expect(result).toBe(false);
19
+ });
20
+
21
+ it('parses showAppReadme and hideReadmeFirstTitle from query', () => {
22
+ const thisContext = {
23
+ $route: {
24
+ query: {
25
+ showAppReadme: 'true',
26
+ hideReadmeFirstTitle: 'true',
27
+ }
28
+ }
29
+ };
30
+
31
+ const showAppReadme = (Readme.computed!.showAppReadme as () => boolean).call(thisContext);
32
+ const hideReadmeFirstTitle = (Readme.computed!.hideReadmeFirstTitle as () => boolean).call(thisContext);
33
+
34
+ expect(showAppReadme).toBe(true);
35
+ expect(hideReadmeFirstTitle).toBe(true);
36
+ });
37
+ });
38
+
39
+ describe('fetch', () => {
40
+ it('calls fetchChart', async() => {
41
+ const fetchChart = jest.fn();
42
+ const thisContext = { fetchChart };
43
+
44
+ await (Readme.fetch as () => Promise<void>).call(thisContext);
45
+
46
+ expect(fetchChart).toHaveBeenCalledWith();
47
+ });
48
+ });
49
+ });
@@ -17,8 +17,7 @@ import BrandImage from '@shell/components/BrandImage';
17
17
  import { waitFor } from '@shell/utils/async';
18
18
  import { Banner } from '@components/Banner';
19
19
  import FormValidation from '@shell/mixins/form-validation';
20
- import isUrl from 'is-url';
21
- import { isLocalhost } from '@shell/utils/validators/setting';
20
+ import { isLocalhost, isValidUrl } from '@shell/utils/validators/setting';
22
21
  import Loading from '@shell/components/Loading';
23
22
  import { getBrandMeta } from '@shell/utils/brand';
24
23
 
@@ -171,7 +170,7 @@ export default {
171
170
  }
172
171
  }
173
172
 
174
- if (!isUrl(this.serverUrl) || this.fvGetPathErrors(['serverUrl']).length > 0) {
173
+ if (!isValidUrl(this.serverUrl) || this.fvGetPathErrors(['serverUrl']).length > 0) {
175
174
  return false;
176
175
  }
177
176
 
@@ -1,5 +1,8 @@
1
1
  import Chart from '@shell/pages/c/_cluster/apps/charts/chart.vue';
2
2
  import { APP_UPGRADE_STATUS } from '@shell/store/catalog';
3
+ import {
4
+ CHART, REPO, REPO_TYPE, VERSION, DEPRECATED
5
+ } from '@shell/config/query-params';
3
6
 
4
7
  jest.mock('clipboard-polyfill', () => ({ writeText: () => {} }));
5
8
 
@@ -321,4 +324,77 @@ describe('page: Chart Detail', () => {
321
324
  expect(result[2].label).toBe('monitoring/app-three');
322
325
  });
323
326
  });
327
+
328
+ describe('methods: openReadme', () => {
329
+ it('opens standalone readme URL with chart context and without theme query', () => {
330
+ const openSpy = jest.spyOn(window, 'open').mockImplementation(() => null);
331
+ const resolve = jest.fn(() => ({ href: '/c/local/readme?x=y' }));
332
+ const thisContext = {
333
+ $router: { resolve },
334
+ $route: { params: { cluster: 'local' } },
335
+ query: {
336
+ repoType: 'cluster',
337
+ repoName: 'rancher-charts',
338
+ chartName: 'test-chart',
339
+ versionName: '',
340
+ deprecated: 'false',
341
+ },
342
+ targetVersion: '1.2.3'
343
+ };
344
+
345
+ (Chart.methods!.openReadme as () => void).call(thisContext);
346
+
347
+ expect(resolve).toHaveBeenCalledWith({
348
+ name: 'readme',
349
+ params: { cluster: 'local' },
350
+ query: {
351
+ [REPO_TYPE]: 'cluster',
352
+ [REPO]: 'rancher-charts',
353
+ [CHART]: 'test-chart',
354
+ [VERSION]: '1.2.3',
355
+ [DEPRECATED]: 'false',
356
+ showAppReadme: 'false',
357
+ hideReadmeFirstTitle: 'false',
358
+ }
359
+ });
360
+ expect(openSpy).toHaveBeenCalledWith('/c/local/readme?x=y', '_blank');
361
+ openSpy.mockRestore();
362
+ });
363
+ });
364
+
365
+ describe('methods: installNewInstance', () => {
366
+ it('should navigate to install page with correct query parameters', () => {
367
+ const mockRouterPush = jest.fn();
368
+ const thisContext = {
369
+ $router: { push: mockRouterPush },
370
+ $route: { params: { cluster: 'local' } },
371
+ $store: { getters: { productId: 'explorer' } },
372
+ query: {
373
+ repoType: 'cluster',
374
+ repoName: 'rancher-charts',
375
+ chartName: 'my-chart',
376
+ versionName: '1.2.3',
377
+ deprecated: 'false'
378
+ }
379
+ };
380
+
381
+ (Chart.methods!.installNewInstance as () => void).call(thisContext);
382
+
383
+ expect(mockRouterPush).toHaveBeenCalledWith({
384
+ name: 'c-cluster-apps-charts-install',
385
+ params: {
386
+ cluster: 'local',
387
+ product: 'explorer',
388
+ },
389
+ query: {
390
+ 'repo-type': 'cluster',
391
+ repo: 'rancher-charts',
392
+ chart: 'my-chart',
393
+ version: '1.2.3',
394
+ deprecated: 'false',
395
+ 'new-instance': null
396
+ }
397
+ });
398
+ });
399
+ });
324
400
  });
@@ -14,7 +14,7 @@ import { isMissingDate } from '@shell/utils/time';
14
14
  import { escapeHtml } from '@shell/utils/string';
15
15
  import { mapGetters } from 'vuex';
16
16
  import { APP_UPGRADE_STATUS, compatibleVersionsFor } from '@shell/store/catalog';
17
- import { compareChartVersions } from '@shell/utils/chart';
17
+ import { compareChartVersions, getStandaloneReadmeUrl } from '@shell/utils/chart';
18
18
  import AppChartCardSubHeader from '@shell/pages/c/_cluster/apps/charts/AppChartCardSubHeader';
19
19
  import AppChartCardFooter from '@shell/pages/c/_cluster/apps/charts/AppChartCardFooter';
20
20
  import day from 'dayjs';
@@ -306,6 +306,7 @@ export default {
306
306
  [REPO_TYPE]: this.query.repoType,
307
307
  [REPO]: this.query.repoName,
308
308
  [CHART]: this.query.chartName,
309
+ [VERSION]: this.query.versionName,
309
310
  [DEPRECATED]: this.query.deprecated,
310
311
  [NEW_APP_INSTANCE]: _FLAGGED,
311
312
  }
@@ -364,6 +365,20 @@ export default {
364
365
  [VERSION]: version,
365
366
  }
366
367
  };
368
+ },
369
+ openReadme() {
370
+ const url = getStandaloneReadmeUrl(this.$router, {
371
+ cluster: this.$route.params.cluster,
372
+ repoType: this.query.repoType,
373
+ repoName: this.query.repoName,
374
+ chartName: this.query.chartName,
375
+ versionName: this.query.versionName || this.targetVersion,
376
+ deprecated: this.query.deprecated,
377
+ showAppReadme: false,
378
+ hideReadmeFirstTitle: false,
379
+ });
380
+
381
+ window.open(url, '_blank');
367
382
  }
368
383
  },
369
384
  };
@@ -535,13 +550,27 @@ export default {
535
550
  </div>
536
551
 
537
552
  <div class="chart-body">
538
- <ChartReadme
553
+ <div
539
554
  v-if="hasReadme"
540
- :version-info="versionInfo"
541
- :show-app-readme="false"
542
- :hide-readme-first-title="false"
543
- class="chart-body__readme"
544
- />
555
+ class="readme-wrapper"
556
+ >
557
+ <RcButton
558
+ v-clean-tooltip="t('catalog.chart.viewReadmeSeparately.tooltip')"
559
+ class="open-readme-button"
560
+ secondary
561
+ rightIcon="external-link"
562
+ @click="openReadme()"
563
+ >
564
+ {{ t('catalog.chart.viewReadmeSeparately.label') }}
565
+ <span class="sr-only">{{ t('generic.opensInNewTab') }}</span>
566
+ </RcButton>
567
+ <ChartReadme
568
+ :version-info="versionInfo"
569
+ :show-app-readme="false"
570
+ :hide-readme-first-title="false"
571
+ class="chart-body__readme"
572
+ />
573
+ </div>
545
574
  <div
546
575
  v-else
547
576
  class="chart-body__readme"
@@ -806,7 +835,7 @@ export default {
806
835
  display: flex;
807
836
  align-items: flex-start;
808
837
  flex-shrink: 0;
809
- gap: 8px;
838
+ gap: 16px;
810
839
 
811
840
  .installed-apps-selector {
812
841
  width: 340px;
@@ -827,6 +856,29 @@ export default {
827
856
 
828
857
  .chart-body {
829
858
  display: flex;
859
+ .readme-wrapper {
860
+ position: relative;
861
+ flex: 1;
862
+
863
+ .open-readme-button {
864
+ display: flex;
865
+ opacity: 0;
866
+ pointer-events: none;
867
+ transition: opacity 100ms ease-in;
868
+ position: absolute;
869
+ top: 12px;
870
+ right: 24px;
871
+ }
872
+
873
+ &:hover,
874
+ &:focus-within {
875
+ .open-readme-button {
876
+ opacity: 1;
877
+ pointer-events: auto;
878
+ }
879
+ }
880
+ }
881
+
830
882
  &__readme {
831
883
  flex: 1;
832
884
  min-width: 400px;
@@ -41,7 +41,7 @@ import {
41
41
  import { ignoreVariables } from './install.helpers';
42
42
  import { findBy, insertAt } from '@shell/utils/array';
43
43
  import { saferDump } from '@shell/utils/create-yaml';
44
- import { LINUX, WINDOWS } from '@shell/store/catalog';
44
+ import { WINDOWS, isRancherRepo, getPermittedOSs } from '@shell/store/catalog';
45
45
  import { SETTING } from '@shell/config/settings';
46
46
  import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret.vue';
47
47
  import { generateRandomAlphaString } from '@shell/utils/string';
@@ -766,14 +766,17 @@ export default {
766
766
  },
767
767
 
768
768
  windowsIncompatible() {
769
- if (this.chart?.windowsIncompatible) {
770
- return this.t('catalog.charts.windowsIncompatible');
771
- }
772
769
  if (this.versionInfo) {
773
- const incompatibleVersion = !(this.versionInfo?.chart?.annotations?.[CATALOG_ANNOTATIONS.PERMITTED_OS] || LINUX).includes('windows');
770
+ const isRancher = isRancherRepo(this.repo, this.chart);
771
+ const permittedSystems = getPermittedOSs(this.versionInfo?.chart?.annotations, isRancher);
772
+ const incompatibleVersion = permittedSystems.length > 0 && !permittedSystems.includes('windows');
773
+
774
+ if (incompatibleVersion) {
775
+ if (!this.chart?.windowsIncompatible) {
776
+ return this.t('catalog.charts.versionWindowsIncompatible');
777
+ }
774
778
 
775
- if (incompatibleVersion && !this.chart.windowsIncompatible) {
776
- return this.t('catalog.charts.versionWindowsIncompatible');
779
+ return this.t('catalog.charts.windowsIncompatible');
777
780
  }
778
781
  }
779
782
 
@@ -1,12 +1,11 @@
1
- import { clone } from '@shell/utils/object';
1
+ import { mergeWithReplace } from '@shell/utils/object';
2
2
  import Dashboard from '@shell/pages/c/_cluster/explorer/index.vue';
3
3
  import { shallowMount } from '@vue/test-utils';
4
4
  import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
5
- import { NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
6
5
  import { WORKLOAD_TYPES } from '@shell/config/types';
7
6
 
8
7
  describe('page: cluster dashboard', () => {
9
- const mountOptions = {
8
+ const createMountOptions = () => ({
10
9
  global: {
11
10
  stubs: {
12
11
  'router-link': true,
@@ -17,12 +16,11 @@ describe('page: cluster dashboard', () => {
17
16
  dispatch: jest.fn(),
18
17
  getters: {
19
18
  currentCluster: {
20
- id: 'cluster',
21
- metadata: { creationTimestamp: Date.now() },
22
- status: { provider: 'foo' },
23
- kubernetesVersionBase: '0.0.0',
24
- kubernetesVersionExtension: 'k3s',
19
+ id: 'cluster',
20
+ metadata: { creationTimestamp: Date.now() },
21
+ status: { provider: 'foo' },
25
22
  },
23
+ 'management/byId': jest.fn(),
26
24
  'cluster/inError': () => false,
27
25
  'cluster/schemaFor': jest.fn(),
28
26
  'cluster/canList': jest.fn(),
@@ -36,7 +34,7 @@ describe('page: cluster dashboard', () => {
36
34
  }
37
35
  },
38
36
  }
39
- };
37
+ });
40
38
 
41
39
  describe.each([
42
40
  'etcd',
@@ -49,7 +47,7 @@ describe('page: cluster dashboard', () => {
49
47
  [STATES_ENUM.HEALTHY, 'icon-checkmark', `${ componentId }foo`, [{ status: 'True' }]],
50
48
  [STATES_ENUM.UNHEALTHY, 'icon-warning', `${ componentId }foo`, [{ status: 'False' }]],
51
49
  ])('should show %p status', (status, iconClass, name, conditions) => {
52
- const options = clone(mountOptions);
50
+ const options = createMountOptions();
53
51
 
54
52
  options.global.mocks.$store.getters.currentCluster.status = {
55
53
  provider: 'provider',
@@ -100,7 +98,7 @@ describe('page: cluster dashboard', () => {
100
98
  ]]
101
99
  ])('%p cluster - %p agent health box :', (_, agentId, isLocal, agentResources, statuses) => {
102
100
  it.each(statuses)('should NOT show %p status due to missing canList permissions', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
103
- const options = clone(mountOptions);
101
+ const options = createMountOptions();
104
102
 
105
103
  options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
106
104
 
@@ -168,7 +166,7 @@ describe('page: cluster dashboard', () => {
168
166
  it.each(statuses)('should show %p status', async(status, iconClass, clickable, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
169
167
  let agentRoute = null;
170
168
 
171
- const options = clone(mountOptions);
169
+ const options = createMountOptions();
172
170
 
173
171
  options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
174
172
 
@@ -221,7 +219,7 @@ describe('page: cluster dashboard', () => {
221
219
  });
222
220
 
223
221
  it('local cluster - cattle agent health box - should be hidden', () => {
224
- const options = clone(mountOptions);
222
+ const options = createMountOptions();
225
223
 
226
224
  options.global.mocks.$store.getters.currentCluster.isLocal = true;
227
225
 
@@ -241,18 +239,18 @@ describe('page: cluster dashboard', () => {
241
239
 
242
240
  describe('cluster details', () => {
243
241
  it.each([
244
- ['clusterProvider', 'other', []],
245
- ['kubernetesVersion', 'glance.version', []],
246
- ['created', 'glance.created', []],
247
- ['architecture', 'mixed', [{ labels: { [NODE_ARCHITECTURE]: 'amd64' } }, { labels: { [NODE_ARCHITECTURE]: 'intel' } }]],
248
- ['architecture', 'mixed', [{ labels: { [NODE_ARCHITECTURE]: 'amd64' } }, { labels: { } }]],
249
- ['architecture', 'amd64', [{ labels: { [NODE_ARCHITECTURE]: 'amd64' } }]],
250
- ['architecture', 'unknown', [{ labels: { } }]],
251
- ['architecture', 'glance.architecture', [{ metadata: { state: { transitioning: true } } }]],
252
- ])('should show %p label %p', (label, text, nodes) => {
253
- const options = clone(mountOptions);
254
-
255
- options.global.mocks.$store.getters['cluster/all'] = () => nodes;
242
+ ['clusterProvider', 'abc', { provisionerDisplay: 'abc' }],
243
+ ['kubernetesVersion', 'glance.version', null],
244
+ ['created', 'glance.created', null],
245
+ ['architecture', 'mixed', { architecture: { label: 'mixed' } }],
246
+ ['architecture', 'amd64', { architecture: { label: 'amd64' } }],
247
+ ['architecture', 'glance.architecture', { architecture: { label: null } }],
248
+ ])('should show %p label %p', (label, text, mgmtCluster) => {
249
+ const options = createMountOptions();
250
+
251
+ const currentCluster = options.global.mocks.$store.getters['currentCluster'];
252
+
253
+ options.global.mocks.$store.getters['currentCluster'] = mgmtCluster ? mergeWithReplace(currentCluster, mgmtCluster) : currentCluster; // eslint-disable-line jest/no-if
256
254
 
257
255
  const wrapper = shallowMount(Dashboard, options);
258
256
 
@@ -17,7 +17,6 @@ import {
17
17
  CATALOG,
18
18
  SECRET
19
19
  } from '@shell/config/types';
20
- import { NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
21
20
  import { setPromiseResult } from '@shell/utils/promise';
22
21
  import AlertTable from '@shell/components/AlertTable';
23
22
  import { Banner } from '@components/Banner';
@@ -220,51 +219,11 @@ export default {
220
219
  },
221
220
 
222
221
  displayProvider() {
223
- const other = 'other';
224
-
225
- let provider = this.currentCluster?.status?.provider || this.currentCluster?.status?.driver.toLowerCase() || other;
226
-
227
- if (provider === 'rke.windows') {
228
- provider = 'rkeWindows';
229
- }
230
-
231
- if (!this.$store.getters['i18n/exists'](`cluster.provider.${ provider }`)) {
232
- provider = 'other';
233
- }
234
-
235
- return this.t(`cluster.provider.${ provider }`);
236
- },
237
-
238
- nodesArchitecture() {
239
- const obj = {};
240
-
241
- this.nodes?.forEach((node) => {
242
- if (!node.metadata?.state?.transitioning) {
243
- const architecture = node.labels?.[NODE_ARCHITECTURE];
244
-
245
- const key = architecture || this.t('cluster.architecture.label.unknown');
246
-
247
- obj[key] = (obj[key] || 0) + 1;
248
- }
249
- });
250
-
251
- return obj;
222
+ return this.currentCluster?.provisionerDisplay;
252
223
  },
253
224
 
254
225
  architecture() {
255
- const keys = Object.keys(this.nodesArchitecture);
256
-
257
- switch (keys.length) {
258
- case 0:
259
- return { label: this.t('generic.provisioning') };
260
- case 1:
261
- return { label: keys[0] };
262
- default:
263
- return {
264
- label: this.t('cluster.architecture.label.mixed'),
265
- tooltip: keys.reduce((acc, k) => `${ acc }${ k }: ${ this.nodesArchitecture[k] }<br>`, '')
266
- };
267
- }
226
+ return this.currentCluster?.architecture;
268
227
  },
269
228
 
270
229
  isHarvesterCluster() {
@@ -395,6 +354,7 @@ export default {
395
354
 
396
355
  metricAggregations() {
397
356
  const metrics = this.nodeMetrics.filter((nodeMetrics) => {
357
+ // This should use cluster/byId getter
398
358
  const node = this.nodes.find((nd) => nd.id === nodeMetrics.id);
399
359
 
400
360
  return node;
@@ -464,9 +424,6 @@ export default {
464
424
  }
465
425
  };
466
426
  },
467
- hasNodes() {
468
- return this.nodes?.length > 0;
469
- },
470
427
  kubernetesVersion() {
471
428
  const base = this.currentCluster?.kubernetesVersionBase || '';
472
429
  const extension = this.currentCluster?.kubernetesVersionExtension || '';
@@ -584,8 +541,7 @@ export default {
584
541
 
585
542
  async goToHarvesterCluster() {
586
543
  try {
587
- const provClusters = await this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
588
- const provCluster = provClusters.find((p) => p.mgmt.id === this.currentCluster.id);
544
+ const provCluster = await this.$store.dispatch('management/find', { type: CAPI.RANCHER_CLUSTER, id: this.currentCluster.provClusterId });
589
545
 
590
546
  await provCluster.goToHarvesterCluster();
591
547
  } catch {
@@ -653,7 +609,7 @@ export default {
653
609
  <span>{{ kubernetesVersion }}</span>
654
610
  </div>
655
611
  <div
656
- v-if="hasNodes"
612
+ v-if="architecture"
657
613
  data-testid="architecture__label"
658
614
  >
659
615
  <label>{{ t('glance.architecture') }}: </label>