@rancher/shell 3.0.5-rc.2 → 3.0.5-rc.5

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 (289) hide show
  1. package/assets/data/aws-regions.json +2 -0
  2. package/assets/images/icons/document.svg +3 -0
  3. package/assets/images/vendor/cognito.svg +1 -0
  4. package/assets/styles/app.scss +1 -0
  5. package/assets/styles/base/_basic.scss +10 -0
  6. package/assets/styles/base/_spacing.scss +29 -0
  7. package/assets/styles/global/_layout.scss +1 -2
  8. package/assets/styles/themes/_dark.scss +25 -0
  9. package/assets/styles/themes/_light.scss +65 -0
  10. package/assets/translations/en-us.yaml +377 -37
  11. package/assets/translations/zh-hans.yaml +8 -15
  12. package/chart/monitoring/index.vue +1 -1
  13. package/components/AsyncButton.vue +2 -0
  14. package/components/Certificates.vue +5 -0
  15. package/components/CodeMirror.vue +3 -3
  16. package/components/CruResource.vue +103 -15
  17. package/components/ExplorerProjectsNamespaces.vue +7 -2
  18. package/components/FilterPanel.vue +156 -0
  19. package/components/FixedBanner.vue +19 -5
  20. package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
  21. package/components/IconOrSvg.vue +14 -35
  22. package/components/PaginatedResourceTable.vue +7 -0
  23. package/components/PromptRemove.vue +5 -1
  24. package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
  25. package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
  26. package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
  27. package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
  28. package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
  29. package/components/Resource/Detail/Card/Scaler.vue +89 -0
  30. package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
  31. package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
  32. package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
  33. package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
  34. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
  35. package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
  36. package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
  37. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
  38. package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
  39. package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
  40. package/components/Resource/Detail/Card/index.vue +56 -0
  41. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
  42. package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
  43. package/components/Resource/Detail/Metadata/Annotations/index.vue +26 -0
  44. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
  45. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +281 -0
  46. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +111 -0
  47. package/components/Resource/Detail/Metadata/KeyValue.vue +130 -0
  48. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
  49. package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
  50. package/components/Resource/Detail/Metadata/Labels/index.vue +27 -0
  51. package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
  52. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
  53. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
  54. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
  55. package/components/Resource/Detail/Metadata/composables.ts +29 -0
  56. package/components/Resource/Detail/Metadata/index.vue +66 -0
  57. package/components/Resource/Detail/Page.vue +22 -0
  58. package/components/Resource/Detail/PercentageBar.vue +40 -0
  59. package/components/Resource/Detail/ResourceRow.vue +119 -0
  60. package/components/Resource/Detail/SpacedRow.vue +14 -0
  61. package/components/Resource/Detail/StatusBar.vue +59 -0
  62. package/components/Resource/Detail/StatusRow.vue +61 -0
  63. package/components/Resource/Detail/TitleBar/Title.vue +13 -0
  64. package/components/Resource/Detail/TitleBar/Top.vue +14 -0
  65. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
  66. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
  67. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
  68. package/components/Resource/Detail/TitleBar/composable.ts +31 -0
  69. package/components/Resource/Detail/TitleBar/index.vue +124 -0
  70. package/components/Resource/Detail/Top/index.vue +34 -0
  71. package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
  72. package/components/ResourceDetail/Masthead.vue +0 -1
  73. package/components/ResourceDetail/__tests__/index.test.ts +114 -0
  74. package/components/ResourceDetail/index.vue +64 -562
  75. package/components/ResourceDetail/legacy.vue +545 -0
  76. package/components/ResourceList/index.vue +2 -1
  77. package/components/ResourceTable.vue +41 -7
  78. package/components/SlideInPanelManager.vue +77 -10
  79. package/components/SortableTable/index.vue +13 -2
  80. package/components/SortableTable/selection.js +22 -9
  81. package/components/StatusBadge.vue +6 -4
  82. package/components/SubtleLink.vue +25 -0
  83. package/components/Tabbed/index.vue +6 -0
  84. package/components/Wizard.vue +12 -1
  85. package/components/YamlEditor.vue +1 -1
  86. package/components/__tests__/AsyncButton.test.ts +39 -0
  87. package/components/__tests__/CruResource.test.ts +63 -0
  88. package/components/__tests__/FilterPanel.test.ts +81 -0
  89. package/components/__tests__/PromptModal.test.ts +0 -2
  90. package/components/auth/AuthBanner.vue +2 -3
  91. package/components/auth/RoleDetailEdit.vue +45 -3
  92. package/components/auth/login/oidc.vue +6 -1
  93. package/components/fleet/FleetApplications.vue +181 -0
  94. package/components/fleet/FleetHelmOps.vue +115 -0
  95. package/components/fleet/FleetIntro.vue +58 -28
  96. package/components/fleet/FleetNoWorkspaces.vue +5 -1
  97. package/components/fleet/FleetOCIStorageSecret.vue +171 -0
  98. package/components/fleet/FleetRepos.vue +38 -76
  99. package/components/fleet/FleetResources.vue +50 -22
  100. package/components/fleet/FleetSummary.vue +26 -51
  101. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
  102. package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
  103. package/components/fleet/dashboard/Empty.vue +73 -0
  104. package/components/fleet/dashboard/ResourceCard.vue +183 -0
  105. package/components/fleet/dashboard/ResourceCardSummary.vue +199 -0
  106. package/components/fleet/dashboard/ResourceDetails.vue +196 -0
  107. package/components/fleet/dashboard/ResourcePanel.vue +376 -0
  108. package/components/form/ArrayList.vue +139 -117
  109. package/components/form/BannerSettings.vue +145 -96
  110. package/components/form/KeyValue.vue +10 -7
  111. package/components/form/LabeledSelect.vue +9 -2
  112. package/components/form/MatchExpressions.vue +5 -1
  113. package/components/form/NameNsDescription.vue +1 -1
  114. package/components/form/ResourceSelector.vue +26 -23
  115. package/components/form/ResourceTabs/index.vue +2 -1
  116. package/components/form/Select.vue +9 -2
  117. package/components/form/SimpleSecretSelector.vue +8 -2
  118. package/components/form/UnitInput.vue +13 -0
  119. package/components/form/ValueFromResource.vue +31 -19
  120. package/components/form/__tests__/ArrayList.test.ts +32 -0
  121. package/components/form/__tests__/KeyValue.test.ts +36 -0
  122. package/components/form/__tests__/LabeledSelect.test.ts +33 -0
  123. package/components/form/__tests__/Select.test.ts +34 -1
  124. package/components/form/__tests__/UnitInput.test.ts +23 -1
  125. package/components/formatter/ClusterLink.vue +5 -8
  126. package/components/formatter/Description.vue +30 -0
  127. package/components/formatter/FleetApplicationClustersReady.vue +77 -0
  128. package/components/formatter/FleetApplicationSource.vue +71 -0
  129. package/components/formatter/FleetSummaryGraph.vue +7 -0
  130. package/components/formatter/__tests__/ClusterLink.test.ts +2 -32
  131. package/components/nav/Header.vue +8 -7
  132. package/components/nav/NamespaceFilter.vue +1 -1
  133. package/components/nav/TopLevelMenu.helper.ts +55 -34
  134. package/components/nav/TopLevelMenu.vue +11 -0
  135. package/components/nav/Type.vue +4 -1
  136. package/components/nav/WindowManager/index.vue +1 -0
  137. package/composables/useI18n.ts +12 -11
  138. package/config/labels-annotations.js +14 -11
  139. package/config/product/auth.js +1 -0
  140. package/config/product/explorer.js +16 -13
  141. package/config/product/fleet.js +70 -17
  142. package/config/product/manager.js +1 -28
  143. package/config/query-params.js +3 -1
  144. package/config/roles.ts +1 -0
  145. package/config/router/routes.js +20 -2
  146. package/config/secret.ts +15 -0
  147. package/config/settings.ts +14 -15
  148. package/config/table-headers.js +59 -27
  149. package/config/types.js +2 -0
  150. package/core/plugin-helpers.ts +3 -2
  151. package/detail/catalog.cattle.io.app.vue +0 -1
  152. package/detail/fleet.cattle.io.cluster.vue +28 -15
  153. package/detail/fleet.cattle.io.gitrepo.vue +10 -1
  154. package/detail/fleet.cattle.io.helmop.vue +157 -0
  155. package/detail/provisioning.cattle.io.cluster.vue +13 -3
  156. package/detail/service.vue +0 -1
  157. package/detail/workload/index.vue +21 -34
  158. package/dialog/ExtensionCatalogUninstallDialog.vue +14 -8
  159. package/dialog/HelmOpForceUpdateDialog.vue +132 -0
  160. package/dialog/RedeployWorkloadDialog.vue +164 -0
  161. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +56 -67
  162. package/edit/__tests__/service.test.ts +2 -1
  163. package/edit/auth/oidc.vue +159 -93
  164. package/edit/fleet.cattle.io.gitrepo.vue +26 -33
  165. package/edit/fleet.cattle.io.helmop.vue +997 -0
  166. package/edit/management.cattle.io.fleetworkspace.vue +43 -10
  167. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -14
  168. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +57 -62
  169. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +3 -14
  170. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.test.ts +72 -41
  171. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +17 -1
  172. package/edit/networking.k8s.io.networkpolicy/index.vue +18 -30
  173. package/edit/provisioning.cattle.io.cluster/index.vue +21 -73
  174. package/edit/service.vue +13 -28
  175. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  176. package/list/fleet.cattle.io.helmop.vue +108 -0
  177. package/list/namespace.vue +5 -2
  178. package/list/workload.vue +6 -1
  179. package/mixins/auth-config.js +8 -1
  180. package/mixins/preset.js +100 -0
  181. package/mixins/resource-fetch-api-pagination.js +57 -43
  182. package/mixins/resource-fetch.js +15 -6
  183. package/mixins/resource-table-watch.js +45 -0
  184. package/models/__tests__/chart.test.ts +273 -0
  185. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  186. package/models/__tests__/workload.test.ts +1 -0
  187. package/models/chart.js +144 -2
  188. package/models/cluster/node.js +1 -0
  189. package/models/cluster.js +32 -2
  190. package/models/fleet-application.js +385 -0
  191. package/models/fleet.cattle.io.bundle.js +9 -8
  192. package/models/fleet.cattle.io.gitrepo.js +41 -365
  193. package/models/fleet.cattle.io.helmop.js +228 -0
  194. package/models/management.cattle.io.authconfig.js +1 -0
  195. package/models/management.cattle.io.cluster.js +0 -20
  196. package/models/management.cattle.io.fleetworkspace.js +12 -0
  197. package/models/management.cattle.io.node.js +7 -22
  198. package/models/management.cattle.io.nodepool.js +12 -0
  199. package/models/namespace.js +5 -0
  200. package/models/provisioning.cattle.io.cluster.js +18 -64
  201. package/models/service.js +24 -9
  202. package/models/workload.js +84 -49
  203. package/package.json +2 -1
  204. package/pages/auth/verify.vue +13 -1
  205. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +37 -0
  206. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
  207. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
  208. package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
  209. package/pages/c/_cluster/apps/charts/index.vue +302 -484
  210. package/pages/c/_cluster/apps/charts/install.vue +0 -1
  211. package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
  212. package/pages/c/_cluster/explorer/index.vue +11 -0
  213. package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
  214. package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
  215. package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
  216. package/pages/c/_cluster/fleet/application/create.vue +340 -0
  217. package/pages/c/_cluster/fleet/application/index.vue +139 -0
  218. package/pages/c/_cluster/fleet/graph/config.js +277 -0
  219. package/pages/c/_cluster/fleet/index.vue +772 -330
  220. package/pages/c/_cluster/longhorn/index.vue +2 -2
  221. package/pages/c/_cluster/settings/banners.vue +56 -2
  222. package/pages/c/_cluster/settings/performance.vue +7 -26
  223. package/pages/explorer/resource/detail/configmap.vue +19 -0
  224. package/pages/home.vue +11 -52
  225. package/plugins/clean-html.js +2 -0
  226. package/plugins/dashboard-store/__tests__/actions.test.ts +4 -1
  227. package/plugins/dashboard-store/actions.js +153 -30
  228. package/plugins/dashboard-store/getters.js +108 -24
  229. package/plugins/dashboard-store/mutations.js +61 -12
  230. package/plugins/dashboard-store/resource-class.js +36 -4
  231. package/plugins/steve/__tests__/getters.test.ts +18 -11
  232. package/plugins/steve/__tests__/steve-class.test.ts +1 -0
  233. package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
  234. package/plugins/steve/actions.js +37 -12
  235. package/plugins/steve/getters.js +39 -10
  236. package/plugins/steve/steve-class.js +5 -0
  237. package/plugins/steve/steve-pagination-utils.ts +213 -50
  238. package/plugins/steve/subscribe.js +229 -42
  239. package/plugins/steve/worker/web-worker.advanced.js +3 -1
  240. package/rancher-components/BadgeState/BadgeState.vue +3 -1
  241. package/rancher-components/Banner/Banner.test.ts +51 -3
  242. package/rancher-components/Banner/Banner.vue +28 -6
  243. package/rancher-components/Form/Checkbox/Checkbox.vue +2 -2
  244. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +5 -1
  245. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +21 -1
  246. package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
  247. package/rancher-components/RcItemCard/RcItemCard.vue +425 -0
  248. package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
  249. package/rancher-components/RcItemCard/index.ts +2 -0
  250. package/store/auth.js +1 -0
  251. package/store/catalog.js +62 -24
  252. package/store/features.js +0 -1
  253. package/store/index.js +33 -14
  254. package/store/slideInPanel.ts +6 -0
  255. package/store/type-map.js +1 -0
  256. package/store/type-map.utils.ts +45 -2
  257. package/types/fleet.d.ts +36 -1
  258. package/types/kube/kube-api.ts +22 -0
  259. package/types/resources/settings.d.ts +19 -5
  260. package/types/shell/index.d.ts +595 -471
  261. package/types/store/dashboard-store.types.ts +41 -4
  262. package/types/store/pagination.types.ts +25 -3
  263. package/types/store/subscribe.types.ts +50 -0
  264. package/utils/auth.js +32 -3
  265. package/utils/cluster.js +24 -20
  266. package/utils/fleet-types.ts +0 -0
  267. package/utils/fleet.ts +200 -1
  268. package/utils/grafana.js +1 -0
  269. package/utils/object.js +0 -12
  270. package/utils/pagination-utils.ts +32 -3
  271. package/utils/pagination-wrapper.ts +132 -50
  272. package/utils/perf-setting.utils.ts +28 -0
  273. package/utils/selector-typed.ts +205 -0
  274. package/utils/selector.js +29 -6
  275. package/utils/settings.ts +4 -1
  276. package/utils/style.ts +39 -0
  277. package/utils/uiplugins.ts +10 -6
  278. package/utils/v-sphere.ts +5 -1
  279. package/utils/validators/formRules/__tests__/index.test.ts +36 -3
  280. package/utils/validators/formRules/index.ts +10 -3
  281. package/utils/window.js +11 -7
  282. package/components/__tests__/ApplicationCard.test.ts +0 -27
  283. package/components/cards/ApplicationCard.vue +0 -145
  284. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
  285. package/components/formatter/RKETemplateName.vue +0 -37
  286. package/config/secret.js +0 -14
  287. package/dialog/SaveAsRKETemplateDialog.vue +0 -139
  288. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
  289. /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
@@ -1,569 +1,71 @@
1
- <script>
2
- import CreateEditView from '@shell/mixins/create-edit-view/impl';
3
- import Loading from '@shell/components/Loading';
4
- import ResourceYaml from '@shell/components/ResourceYaml';
5
- import {
6
- _VIEW, _EDIT, _CLONE, _IMPORT, _STAGE, _CREATE,
7
- AS, _YAML, _DETAIL, _CONFIG, _GRAPH, PREVIEW, MODE,
8
- } from '@shell/config/query-params';
9
- import { FLEET, SCHEMA } from '@shell/config/types';
10
- import { createYaml } from '@shell/utils/create-yaml';
11
- import Masthead from '@shell/components/ResourceDetail/Masthead';
12
- import DetailTop from '@shell/components/DetailTop';
13
- import { clone, diff } from '@shell/utils/object';
14
- import IconMessage from '@shell/components/IconMessage';
15
- import ForceDirectedTreeChart from '@shell/components/fleet/ForceDirectedTreeChart';
16
- import { checkSchemasForFindAllHash } from '@shell/utils/auth';
17
- import { stringify } from '@shell/utils/error';
18
- import { Banner } from '@components/Banner';
19
-
20
- function modeFor(route) {
21
- if ( route.query?.mode === _IMPORT ) {
22
- return _IMPORT;
23
- }
24
-
25
- if ( route.params?.id ) {
26
- return route.query.mode || _VIEW;
27
- } else {
28
- return _CREATE;
29
- }
30
- }
31
-
32
- async function getYaml(store, model) {
33
- let yaml;
34
- const opt = { headers: { accept: 'application/yaml' } };
35
-
36
- if ( model.hasLink('view') ) {
37
- yaml = (await model.followLink('view', opt)).data;
38
- }
39
-
40
- return model.cleanForDownload(yaml);
1
+ <script lang="ts" setup>
2
+ import { useRoute } from 'vue-router';
3
+ import { computed, defineAsyncComponent } from 'vue';
4
+
5
+ import { MODE, _VIEW, LEGACY } from '@shell/config/query-params';
6
+ import Legacy from '@shell/components/ResourceDetail/legacy.vue';
7
+ import Loading from '@shell/components/Loading.vue';
8
+
9
+ export interface Props {
10
+ flexContent?: boolean;
11
+ componentTestId?: string;
12
+ storeOverride?: string;
13
+ resourceOverride?: string;
14
+ parentRouteOverride?: string;
15
+ errorsMap?: any;
41
16
  }
42
17
 
43
- export default {
44
- emits: ['input'],
45
-
46
- components: {
47
- Loading,
48
- DetailTop,
49
- ForceDirectedTreeChart,
50
- ResourceYaml,
51
- Masthead,
52
- IconMessage,
53
- Banner
54
- },
55
-
56
- mixins: [CreateEditView],
57
-
58
- props: {
59
- storeOverride: {
60
- type: String,
61
- default: null,
62
- },
63
-
64
- resourceOverride: {
65
- type: String,
66
- default: null,
67
- },
68
-
69
- parentRouteOverride: {
70
- type: String,
71
- default: null,
72
- },
73
-
74
- flexContent: {
75
- type: Boolean,
76
- default: false,
77
- },
78
-
79
- /**
80
- * Inherited global identifier prefix for tests
81
- * Define a term based on the parent component to avoid conflicts on multiple components
82
- */
83
- componentTestid: {
84
- type: String,
85
- default: 'resource-details'
86
- },
87
- errorsMap: {
88
- type: Object,
89
- default: null
90
- },
91
- },
92
-
93
- async fetch() {
94
- const store = this.$store;
95
- const route = this.$route;
96
- const params = route.params;
97
- let resourceType = this.resourceOverride || params.resource;
98
-
99
- const inStore = this.storeOverride || store.getters['currentStore'](resourceType);
100
- const realMode = this.realMode;
101
-
102
- // eslint-disable-next-line prefer-const
103
- let { namespace, id } = params;
104
-
105
- // There are 6 "real" modes that can be put into the query string
106
- // These are mapped down to the 3 regular page "mode"s that create-edit-view components
107
- // know about: view, edit, create (stage, import and clone become "create")
108
- const mode = ([_CLONE, _IMPORT, _STAGE].includes(realMode) ? _CREATE : realMode);
109
-
110
- const getGraphConfig = store.getters['type-map/hasGraph'](resourceType);
111
- const hasGraph = !!getGraphConfig;
112
- const hasCustomDetail = store.getters['type-map/hasCustomDetail'](resourceType, id);
113
- const hasCustomEdit = store.getters['type-map/hasCustomEdit'](resourceType, id);
114
-
115
- const schemas = store.getters[`${ inStore }/all`](SCHEMA);
116
-
117
- // As determines what component will be rendered
118
- const requested = route.query[AS];
119
- let as;
120
- let notFound = false;
121
-
122
- if ( mode === _VIEW && hasCustomDetail && (!requested || requested === _DETAIL) ) {
123
- as = _DETAIL;
124
- } else if ( mode === _VIEW && hasGraph && requested === _GRAPH) {
125
- as = _GRAPH;
126
- } else if ( hasCustomEdit && (!requested || requested === _CONFIG) ) {
127
- as = _CONFIG;
128
- } else {
129
- as = _YAML;
130
- }
131
-
132
- this.as = as;
133
-
134
- const options = store.getters[`type-map/optionsFor`](resourceType);
135
-
136
- this.showMasthead = [_CREATE, _EDIT].includes(mode) ? options.resourceEditMasthead : true;
137
- const canViewYaml = options.canYaml;
138
-
139
- if ( options.resource ) {
140
- resourceType = options.resource;
141
- }
142
-
143
- const schema = store.getters[`${ inStore }/schemaFor`](resourceType);
144
- let model, initialModel, liveModel, yaml;
145
-
146
- if ( realMode === _CREATE || realMode === _IMPORT ) {
147
- if ( !namespace ) {
148
- namespace = store.getters['defaultNamespace'];
149
- }
150
-
151
- const data = { type: resourceType };
152
-
153
- if ( schema?.attributes?.namespaced ) {
154
- data.metadata = { namespace };
155
- }
156
-
157
- liveModel = await store.dispatch(`${ inStore }/create`, data);
158
- initialModel = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
159
- model = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
160
-
161
- if (model.forceYaml === true) {
162
- as = _YAML;
163
- this.as = as;
164
- }
165
-
166
- if ( as === _YAML ) {
167
- if (schema?.fetchResourceFields) {
168
- // fetch resourceFields for createYaml
169
- await schema.fetchResourceFields();
170
- }
171
-
172
- yaml = createYaml(schemas, resourceType, data);
173
- }
174
- } else {
175
- if ( as === _GRAPH ) {
176
- const graphSchema = await checkSchemasForFindAllHash({
177
- cluster: {
178
- inStoreType: 'management',
179
- type: FLEET.CLUSTER
180
- },
181
- bundle: {
182
- inStoreType: 'management',
183
- type: FLEET.BUNDLE,
184
- opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] },
185
- },
186
-
187
- bundleDeployment: {
188
- inStoreType: 'management',
189
- type: FLEET.BUNDLE_DEPLOYMENT
190
- }
191
-
192
- }, this.$store);
193
-
194
- this.canViewChart = graphSchema.cluster && graphSchema.bundle && graphSchema.bundleDeployment;
195
- }
196
-
197
- let fqid = id;
198
-
199
- if ( schema.attributes?.namespaced && namespace ) {
200
- fqid = `${ namespace }/${ fqid }`;
201
- }
202
-
203
- try {
204
- liveModel = await store.dispatch(`${ inStore }/find`, {
205
- type: resourceType,
206
- id: fqid,
207
- opt: { watch: true }
208
- });
209
- } catch (e) {
210
- if (e.status === 404 || e.status === 403) {
211
- store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceIdNotFound', { resource: resourceType, fqid }, true)));
212
- }
213
- liveModel = {};
214
- notFound = fqid;
215
- }
216
-
217
- try {
218
- if (realMode === _VIEW) {
219
- model = liveModel;
220
- } else {
221
- model = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
222
- }
223
- initialModel = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
224
-
225
- if ( as === _YAML ) {
226
- yaml = await getYaml(this.$store, liveModel);
227
- }
228
- } catch (e) {
229
- this.errors.push(e);
230
- }
231
- if ( as === _YAML ) {
232
- try {
233
- yaml = await getYaml(this.$store, liveModel);
234
- } catch (e) {
235
- this.errors.push(e);
236
- }
237
- }
238
-
239
- if ( as === _GRAPH ) {
240
- this.chartData = liveModel;
241
- }
242
-
243
- if ( [_CLONE, _IMPORT, _STAGE].includes(realMode) ) {
244
- model.cleanForNew();
245
- yaml = model.cleanYaml(yaml, realMode);
246
- }
247
- }
248
-
249
- // Ensure common properties exists
250
- try {
251
- model = await store.dispatch(`${ inStore }/cleanForDetail`, model);
252
- } catch (e) {
253
- this.errors.push(e);
254
- }
255
-
256
- const out = {
257
- hasGraph,
258
- getGraphConfig,
259
- hasCustomDetail,
260
- hasCustomEdit,
261
- canViewYaml,
262
- resourceType,
263
- as,
264
- yaml,
265
- initialModel,
266
- liveModel,
267
- mode,
268
- value: model,
269
- notFound,
270
- };
271
-
272
- for ( const key in out ) {
273
- this[key] = out[key];
274
- }
275
-
276
- if ( this.mode === _CREATE ) {
277
- this.value.applyDefaults(this, realMode);
278
- }
279
- },
280
- data() {
281
- return {
282
- chartData: null,
283
- resourceSubtype: null,
284
-
285
- // Set by fetch
286
- hasGraph: null,
287
- hasCustomDetail: null,
288
- hasCustomEdit: null,
289
- resourceType: null,
290
- asYaml: null,
291
- yaml: null,
292
- liveModel: null,
293
- initialModel: null,
294
- mode: null,
295
- as: null,
296
- value: null,
297
- model: null,
298
- notFound: null,
299
- canViewChart: true,
300
- canViewYaml: null,
301
- errors: []
302
- };
303
- },
304
-
305
- computed: {
306
- realMode() {
307
- // There are 5 "real" modes that you can start in: view, edit, create, stage, clone
308
- const realMode = modeFor(this.$route);
309
-
310
- return realMode;
311
- },
312
-
313
- isView() {
314
- return this.mode === _VIEW;
315
- },
316
-
317
- isYaml() {
318
- return this.as === _YAML;
319
- },
320
-
321
- isDetail() {
322
- return this.as === _DETAIL;
323
- },
324
-
325
- isGraph() {
326
- return this.as === _GRAPH;
327
- },
328
-
329
- offerPreview() {
330
- return this.as === _YAML && [_EDIT, _CLONE, _IMPORT, _STAGE].includes(this.mode);
331
- },
332
-
333
- showComponent() {
334
- switch ( this.as ) {
335
- case _DETAIL: return this.detailComponent;
336
- case _CONFIG: return this.editComponent;
337
- }
338
-
339
- return null;
340
- },
341
- hasErrors() {
342
- return this.errors?.length && Array.isArray(this.errors);
343
- },
344
- mappedErrors() {
345
- return !this.errors ? {} : this.errorsMap || this.errors.reduce((acc, error) => ({
346
- ...acc,
347
- [error]: {
348
- message: error?.data?.message || error,
349
- icon: null
350
- }
351
- }), {});
352
- },
353
- },
354
-
355
- watch: {
356
- '$route'(current, prev) {
357
- if (current.name !== prev.name) {
358
- return;
359
- }
360
- const neu = clone(current.query);
361
- const old = clone(prev.query);
362
-
363
- delete neu[PREVIEW];
364
- delete old[PREVIEW];
365
-
366
- if ( !this.isView ) {
367
- delete neu[AS];
368
- delete old[AS];
369
- }
370
-
371
- const queryDiff = Object.keys(diff(neu, old));
372
-
373
- if (queryDiff.includes(MODE) || queryDiff.includes(AS)) {
374
- this.$fetch();
375
- }
376
- },
377
-
378
- // Auto refresh YAML when the model changes
379
- async 'value.metadata.resourceVersion'(a, b) {
380
- if ( this.mode === _VIEW && this.as === _YAML && a && b && a !== b) {
381
- this.yaml = await getYaml(this.$store, this.liveModel);
382
- }
383
- }
384
- },
385
-
386
- created() {
387
- this.configureResource();
388
- },
389
-
390
- methods: {
391
- stringify,
392
- setSubtype(subtype) {
393
- this.resourceSubtype = subtype;
394
- },
395
-
396
- keyAction(act) {
397
- const m = this.liveModel;
398
-
399
- if ( m?.[act] ) {
400
- m[act]();
401
- }
402
- },
403
- closeError(index) {
404
- this.errors = this.errors.filter((_, i) => i !== index);
405
- },
406
- /**
407
- * Initializes the resource components based on the provided user and
408
- * resource override.
409
- *
410
- * Configures the detail and edit components for a resource based on the
411
- * user's ID and the specified resource.
412
- *
413
- * @param {Object} user - The user object containing user-specific
414
- * information.
415
- * @param {string|null} resourceOverride - An optional resource override
416
- * string. If not provided, the method will use the default resource from
417
- * the route parameters or the instance's resourceOverride property.
418
- */
419
- configureResource(userId = '', resourceOverride = null) {
420
- const id = userId || this.$route.params.id;
421
- const resource = resourceOverride || this.resourceOverride || this.$route.params.resource;
422
- const options = this.$store.getters[`type-map/optionsFor`](resource);
423
-
424
- const detailResource = options.resourceDetail || options.resource || resource;
425
- const editResource = options.resourceEdit || options.resource || resource;
426
-
427
- // FIXME: These aren't right... signature is (rawType, subType).. not (rawType, resourceId)
428
- // Remove id? How does subtype get in (cluster/node)
429
- this.detailComponent = this.$store.getters['type-map/importDetail'](detailResource, id);
430
- this.editComponent = this.$store.getters['type-map/importEdit'](editResource, id);
431
- },
432
- /**
433
- * Sets the mode and initializes the resource components.
434
- *
435
- * This method sets the mode of the component and configures the resource
436
- * components based on the provided user and resource.
437
- *
438
- * @param {Object} payload - An object containing the mode, user, and
439
- * resource properties.
440
- * @param {string} payload.mode - The mode to set.
441
- * @param {Object} payload.user - The user object containing user-specific
442
- * information.
443
- * @param {string} payload.resource - The resource string to use for
444
- * initialization.
445
- */
446
- setMode({ mode, userId, resource }) {
447
- this.mode = mode;
448
- this.value.id = userId;
449
- this.configureResource(userId, resource);
450
- }
451
- }
18
+ // Ideally I'd prefer to have separate routes/pages for each of these but our app makes a
19
+ // fair amount of assumptions around having one detail page for each resource and that the
20
+ // detail, config, edit, yaml, create pages are all derived from the same page.
21
+ //
22
+ // I could also dynamically check for and import these pages but I wanted this to be easier
23
+ // to be explicit and easier to search for.
24
+ const resourceToPage: any = {
25
+ // 'apps.daemonset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.daemonset.vue')),
26
+ // 'apps.deployment': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.deployment.vue')),
27
+ // 'apps.statefulset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.statefulset.vue')),
28
+ // 'batch.cronjob': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.cronjob.vue')),
29
+ // 'batch.job': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.job.vue')),
30
+ // 'cluster-dashboard': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/cluster-dashboard.vue')),
31
+ configmap: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/configmap.vue')),
32
+ // namespace: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/namespace.vue')),
33
+ // node: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/node.vue')),
34
+ // pod: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/pod.vue')),
35
+ // secret: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/secret.vue')),
452
36
  };
37
+
38
+ const route = useRoute();
39
+ const props = withDefaults(defineProps<Props>(), {
40
+ flexContent: false,
41
+ componentTestId: 'resource-details',
42
+ storeOverride: undefined,
43
+ resourceOverride: undefined,
44
+ parentRouteOverride: undefined,
45
+ errorsMap: undefined
46
+ });
47
+
48
+ const currentResourceName = computed<string>(() => route.params.resource as string);
49
+ const mode = computed(() => route.query[MODE]);
50
+ const isView = computed(() => !mode.value || mode.value === _VIEW);
51
+ // We're defaulting to legacy being on, we'll switch this once we want to enable the new detail page by default
52
+ const isLegacy = computed(() => route.query[LEGACY] !== 'false');
53
+ const page = computed(() => resourceToPage[currentResourceName.value]);
54
+
55
+ const useLatest = computed(() => !!(!isLegacy.value && isView.value && page.value));
453
56
  </script>
454
57
 
455
58
  <template>
456
- <Loading v-if="$fetchState.pending || notFound" />
457
- <div v-else>
458
- <Masthead
459
- v-if="showMasthead"
460
- :resource="resourceType"
461
- :value="liveModel"
462
- :mode="mode"
463
- :real-mode="realMode"
464
- :as="as"
465
- :has-graph="hasGraph"
466
- :has-detail="hasCustomDetail"
467
- :has-edit="hasCustomEdit"
468
- :can-view-yaml="canViewYaml"
469
- :resource-subtype="resourceSubtype"
470
- :parent-route-override="parentRouteOverride"
471
- :store-override="storeOverride"
472
- >
473
- <DetailTop
474
- v-if="isView && isDetail"
475
- :value="liveModel"
476
- />
477
- </Masthead>
478
- <div
479
- v-if="hasErrors"
480
- id="cru-errors"
481
- class="cru__errors"
482
- >
483
- <Banner
484
- v-for="(err, i) in errors"
485
- :key="i"
486
- color="error"
487
- :data-testid="`error-banner${i}`"
488
- :label="stringify(mappedErrors[err].message)"
489
- :icon="mappedErrors[err].icon"
490
- :closable="true"
491
- @close="closeError(i)"
492
- />
493
- </div>
494
-
495
- <ForceDirectedTreeChart
496
- v-if="isGraph && canViewChart"
497
- :data="chartData"
498
- :fdc-config="getGraphConfig"
499
- />
500
-
501
- <ResourceYaml
502
- v-else-if="isYaml"
503
- ref="resourceyaml"
504
- :value="value"
505
- :mode="mode"
506
- :yaml="yaml"
507
- :offer-preview="offerPreview"
508
- :done-route="doneRoute"
509
- :done-override="value ? value.doneOverride : null"
510
- @update:value="$emit('input', $event)"
511
- @error="e=>errors.push(e)"
512
- />
513
-
514
- <component
515
- :is="showComponent"
516
- v-else
517
- ref="comp"
518
- v-model:value="value"
519
- v-bind="$data"
520
- :done-params="doneParams"
521
- :done-route="doneRoute"
522
- :mode="mode"
523
- :initial-value="initialModel"
524
- :live-value="liveModel"
525
- :real-mode="realMode"
526
- :class="{'flex-content': flexContent}"
527
- @update:value="$emit('input', $event)"
528
- @update:mode="setMode"
529
- @set-subtype="setSubtype"
530
- />
531
-
532
- <button
533
- v-if="isView"
534
- v-shortkey.once="['shift','d']"
535
- :data-testid="componentTestid + '-detail'"
536
- class="hide"
537
- @shortkey="keyAction('goToDetail')"
538
- />
539
- <button
540
- v-if="isView"
541
- v-shortkey.once="['shift','c']"
542
- :data-testid="componentTestid + '-config'"
543
- class="hide"
544
- @shortkey="keyAction('goToViewConfig')"
545
- />
546
- <button
547
- v-if="isView"
548
- v-shortkey.once="['shift','y']"
549
- :data-testid="componentTestid + '-yaml'"
550
- class="hide"
551
- @shortkey="keyAction('goToViewYaml')"
552
- />
553
- <button
554
- v-if="isView"
555
- v-shortkey.once="['shift','e']"
556
- :data-testid="componentTestid + '-edit'"
557
- class="hide"
558
- @shortkey="keyAction('goToEdit')"
559
- />
560
- </div>
59
+ <Suspense v-if="useLatest">
60
+ <template #default>
61
+ <component :is="page" />
62
+ </template>
63
+ <template #fallback>
64
+ <Loading />
65
+ </template>
66
+ </Suspense>
67
+ <Legacy
68
+ v-else
69
+ v-bind="props"
70
+ />
561
71
  </template>
562
-
563
- <style lang='scss' scoped>
564
- .flex-content {
565
- display: flex;
566
- flex-direction: column;
567
- flex-grow: 1;
568
- }
569
- </style>