@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
@@ -2,7 +2,6 @@
2
2
  import * as d3 from 'd3';
3
3
  import { STATES } from '@shell/plugins/dashboard-store/resource-class';
4
4
  import { BadgeState } from '@components/BadgeState';
5
- import { getChartIcon } from './chartIcons.js';
6
5
 
7
6
  export default {
8
7
  name: 'ForceDirectedTreeChart',
@@ -17,8 +16,24 @@ export default {
17
16
  required: true
18
17
  }
19
18
  },
19
+
20
+ async fetch() {
21
+ this.canViewChart = await this.fdcConfig.checkSchemaPermissions(this.$store);
22
+
23
+ if (this.canViewChart) {
24
+ // set watcher for the chart data
25
+ this.dataWatcher = this.$watch(this.fdcConfig.watcherProp, (newValue) => {
26
+ this.watcherFunction(newValue);
27
+ }, {
28
+ deep: true,
29
+ immediate: true
30
+ });
31
+ }
32
+ },
33
+
20
34
  data() {
21
35
  return {
36
+ canViewChart: null,
22
37
  dataWatcher: undefined,
23
38
  parsedInfo: undefined,
24
39
  root: undefined,
@@ -37,7 +52,7 @@ export default {
37
52
  },
38
53
  methods: {
39
54
  watcherFunction(newValue) {
40
- if (newValue.length) {
55
+ if (newValue?.length) {
41
56
  if (!this.isChartFirstRendered) {
42
57
  this.parsedInfo = this.fdcConfig.parseData(this.data);
43
58
 
@@ -158,16 +173,11 @@ export default {
158
173
  .attr('r', this.setNodeRadius);
159
174
 
160
175
  nodeEnter.append('circle')
161
- .attr('r', (d) => {
162
- return this.setNodeRadius(d) - 5;
163
- })
176
+ .attr('r', (d) => this.setNodeRadius(d) - 5)
164
177
  .attr('class', 'node-hover-layer');
165
178
 
166
- nodeEnter.append('svg').html((d) => {
167
- const icon = this.fdcConfig.fetchNodeIcon(d);
168
-
169
- return getChartIcon(icon);
170
- })
179
+ nodeEnter.append('svg')
180
+ .html((d) => this.fdcConfig.fetchNodeIcon(d))
171
181
  .attr('x', this.nodeImagePosition)
172
182
  .attr('y', this.nodeImagePosition)
173
183
  .attr('height', this.nodeImageSize)
@@ -177,9 +187,7 @@ export default {
177
187
 
178
188
  this.simulation.nodes(this.allNodesData);
179
189
  this.simulation.force('link', d3.forceLink()
180
- .id((d) => {
181
- return d.id;
182
- })
190
+ .id((d) => d.id)
183
191
  .distance(100)
184
192
  .links(this.allLinks)
185
193
  );
@@ -188,10 +196,10 @@ export default {
188
196
  const lowerCaseStatus = d.data?.state ? d.data.state.toLowerCase() : 'unkown_status';
189
197
  const defaultClassArray = ['node'];
190
198
 
191
- if (STATES[lowerCaseStatus] && STATES[lowerCaseStatus].color) {
192
- defaultClassArray.push(`node-${ STATES[lowerCaseStatus].color }`);
193
- } else {
199
+ if (d?.data?.muteStatus) {
194
200
  defaultClassArray.push(`node-default-fill`);
201
+ } else if (STATES[lowerCaseStatus] && STATES[lowerCaseStatus].color) {
202
+ defaultClassArray.push(`node-${ STATES[lowerCaseStatus].color }`);
195
203
  }
196
204
 
197
205
  // node active (clicked)
@@ -334,14 +342,6 @@ export default {
334
342
  this.svg = d3.select('#tree').append('svg')
335
343
  .attr('viewBox', `0 0 ${ this.fdcConfig.chartWidth } ${ this.fdcConfig.chartHeight }`)
336
344
  .attr('preserveAspectRatio', 'none');
337
-
338
- // set watcher for the chart data
339
- this.dataWatcher = this.$watch(this.fdcConfig.watcherProp, function(newValue) {
340
- this.watcherFunction(newValue);
341
- }, {
342
- deep: true,
343
- immediate: true
344
- });
345
345
  },
346
346
  unmounted() {
347
347
  this.dataWatcher();
@@ -353,20 +353,26 @@ export default {
353
353
  <div>
354
354
  <div
355
355
  class="chart-container"
356
- data-testid="gitrepo_graph"
356
+ data-testid="resource-graph"
357
357
  >
358
358
  <!-- loading status container -->
359
359
  <div
360
360
  v-if="!isChartFirstRenderAnimationFinished"
361
361
  class="loading-container"
362
362
  >
363
- <p v-show="!isChartFirstRendered">
364
- {{ t('fleet.fdc.loadingChart') }}
363
+ <p v-if="canViewChart === false">
364
+ {{ t('graph.noPermissions') }}
365
+ </p>
366
+ <p v-else-if="!isChartFirstRendered">
367
+ {{ t('graph.loading') }}
365
368
  </p>
366
- <p v-show="isChartFirstRendered && !isChartFirstRenderAnimationFinished">
367
- {{ t('fleet.fdc.renderingChart') }}
369
+ <p v-else-if="!isChartFirstRenderAnimationFinished">
370
+ {{ t('graph.rendering') }}
368
371
  </p>
369
- <i class="mt-10 icon-spinner icon-spin" />
372
+ <i
373
+ v-if="canViewChart !== false"
374
+ class="mt-10 icon-spinner icon-spin"
375
+ />
370
376
  </div>
371
377
  <!-- main div for svg container -->
372
378
  <div id="tree" />
@@ -416,6 +422,9 @@ export default {
416
422
  >
417
423
  <p>{{ item.value }}</p>
418
424
  </td>
425
+ <td v-else-if="item.type === 'resource-type'">
426
+ {{ t(`typeLabel."${ item.valueKey }"`, { count: 1 }) }}
427
+ </td>
419
428
  <!-- default template -->
420
429
  <td v-else>
421
430
  {{ item.value }}
@@ -478,32 +487,29 @@ export default {
478
487
  }
479
488
  }
480
489
 
481
- &.repo.active > circle {
482
- transform: scale(1.2);
483
- }
484
-
485
490
  &.bundle.active > circle {
486
491
  transform: scale(1.35);
487
492
  }
488
493
 
489
- &.bundle-deployment.active > circle {
494
+ &.bundledeployment.active > circle {
490
495
  transform: scale(1.6);
491
496
  }
492
497
 
493
- &.node-default-fill > circle,
494
- &.repo > circle {
498
+ &.node-default-fill > circle {
499
+ transform: scale(1.2);
495
500
  fill: var(--muted);
496
501
  }
497
- &:not(.repo).node-success > circle {
502
+
503
+ &.node-success > circle {
498
504
  fill: var(--success);
499
505
  }
500
- &:not(.repo).node-info > circle {
506
+ &.node-info > circle {
501
507
  fill: var(--info);
502
508
  }
503
- &:not(.repo).node-warning > circle {
509
+ &.node-warning > circle {
504
510
  fill: var(--warning);
505
511
  }
506
- &:not(.repo).node-error > circle {
512
+ &.node-error > circle {
507
513
  fill: var(--error);
508
514
  }
509
515
 
@@ -61,41 +61,16 @@ export default {
61
61
  },
62
62
 
63
63
  methods: {
64
+ getComputedStyleFor(cssVar) {
65
+ return normalizeHex(mapStandardColors((window.getComputedStyle(document.body).getPropertyValue(cssVar)).trim()));
66
+ },
67
+
64
68
  setColor() {
65
- const currTheme = this.$store.getters['prefs/theme'];
66
- let uiColor, hoverColor;
67
-
68
- // grab css vars values based on the actual stylesheets, depending on the theme applied
69
- // use for loops to minimize computation
70
- for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
71
- let found = false;
72
- const stylesheet = document.styleSheets[i];
73
-
74
- if (stylesheet && stylesheet.cssRules) {
75
- for (let x = 0; x < Object.keys(stylesheet.cssRules).length; x++) {
76
- const cssRules = stylesheet.cssRules[x];
77
-
78
- if (cssRules.selectorText && ((currTheme === 'light' && (cssRules.selectorText.includes('body') || cssRules.selectorText.includes('BODY')) &&
79
- cssRules.selectorText.includes('.theme-light') && cssRules.style.cssText.includes('--link:')) ||
80
- (currTheme === 'dark' && cssRules.selectorText.includes('.theme-dark')))) {
81
- // grab the colors to be used on the icon from the css rules
82
- uiColor = mapStandardColors(cssRules.style.getPropertyValue(colors[this.color].color).trim());
83
- hoverColor = mapStandardColors(cssRules.style.getPropertyValue(colors[this.color].hover).trim());
84
-
85
- // normalize hex colors (#xxx to #xxxxxx)
86
- uiColor = normalizeHex(uiColor);
87
- hoverColor = normalizeHex(hoverColor);
88
-
89
- found = true;
90
- break;
91
- }
92
- }
93
- }
94
- if (found) {
95
- break;
96
- } else {
97
- continue;
98
- }
69
+ const uiColor = this.getComputedStyleFor(colors[this.color].color);
70
+ const hoverColor = this.getComputedStyleFor(colors[this.color].hover);
71
+
72
+ if (!uiColor || !hoverColor) {
73
+ return;
99
74
  }
100
75
 
101
76
  const uiColorRGB = colorToRgb(uiColor);
@@ -142,7 +117,11 @@ export default {
142
117
  }
143
118
  a.option:hover > img.${ className } {
144
119
  ${ hoverFilter };
145
- } `;
120
+ }
121
+ a.option.active-menu-link > img.${ className } {
122
+ ${ hoverFilter };
123
+ }
124
+ `;
146
125
 
147
126
  const styleSheet = document.createElement('style');
148
127
 
@@ -95,6 +95,12 @@ export default defineComponent({
95
95
 
96
96
  return customHeaders || this.$store.getters['type-map/headersFor'](this.schema, this.canPaginate);
97
97
  }
98
+ },
99
+
100
+ methods: {
101
+ clearSelection() {
102
+ this.$refs.table.clearSelection();
103
+ },
98
104
  }
99
105
  });
100
106
 
@@ -103,6 +109,7 @@ export default defineComponent({
103
109
  <template>
104
110
  <div>
105
111
  <ResourceTable
112
+ ref="table"
106
113
  v-bind="$attrs"
107
114
  :schema="schema"
108
115
  :rows="rows"
@@ -43,6 +43,7 @@ export default {
43
43
  chartsToRemoveIsApp: false,
44
44
  chartsDeleteCrd: false,
45
45
  showModal: false,
46
+ cachedDoneLocation: null
46
47
  };
47
48
  },
48
49
  computed: {
@@ -220,6 +221,7 @@ export default {
220
221
  this.error = '';
221
222
  this.chartsDeleteCrd = false;
222
223
  this.chartsToRemoveIsApp = false;
224
+ this.cachedDoneLocation = null;
223
225
  this.$store.commit('action-menu/togglePromptRemove');
224
226
  },
225
227
 
@@ -227,6 +229,8 @@ export default {
227
229
  if (this.doneLocation) {
228
230
  // doneLocation will recompute to undefined when delete request completes
229
231
  this.cachedDoneLocation = { ...this.doneLocation };
232
+ } else {
233
+ this.cachedDoneLocation = null;
230
234
  }
231
235
 
232
236
  if (this.hasCustomRemove && this.$refs?.customPrompt?.remove) {
@@ -294,7 +298,7 @@ export default {
294
298
  }
295
299
  },
296
300
  done() {
297
- if ( this.cachedDoneLocation && !isEmpty(this.cachedDoneLocation) ) {
301
+ if (!isEmpty(this.cachedDoneLocation) && this.currentRouter) {
298
302
  this.currentRouter.push(this.cachedDoneLocation);
299
303
  }
300
304
  this.close();
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <span class="bubble">
3
+ <slot name="default" />
4
+ </span>
5
+ </template>
6
+
7
+ <style lang="scss" scoped>
8
+ .bubble {
9
+ border-radius: 40%;
10
+ background-color: var(--bubble-bg);
11
+ padding: 2px 6px;
12
+ }
13
+ </style>
@@ -0,0 +1,30 @@
1
+ import { useI18n } from '@shell/composables/useI18n';
2
+ import { toValue } from 'vue';
3
+ import { useStore } from 'vuex';
4
+
5
+ export type ScaleFn = () => Promise<void>;
6
+ export const useScaling = (workloadName: string, scaleUpFn: ScaleFn, scaleDownFn: ScaleFn) => {
7
+ const store = useStore();
8
+ const i18n = useI18n(store);
9
+
10
+ const scale = (scaleFn: () => Promise<void>, workloadName: string, direction: 'up' | 'down') => {
11
+ return async() => {
12
+ try {
13
+ await scaleFn();
14
+ } catch (err) {
15
+ store.dispatch('growl/fromError', {
16
+ title: i18n.t('workload.list.errorCannotScale', { workloadName, direction }),
17
+ err
18
+ },
19
+ { root: true });
20
+ }
21
+ };
22
+ };
23
+
24
+ const workloadNameValue = toValue(workloadName);
25
+
26
+ return {
27
+ scaleUp: scale(() => scaleUpFn(), workloadNameValue, 'up'),
28
+ scaleDown: scale(() => scaleDownFn(), workloadNameValue, 'down')
29
+ };
30
+ };
@@ -0,0 +1,118 @@
1
+ <script lang="ts">
2
+ import Card from '@shell/components/Resource/Detail/Card/index.vue';
3
+ import Scaler from '@shell/components/Resource/Detail/Card/Scaler.vue';
4
+ import VerticalGap from '@shell/components/Resource/Detail/Card/VerticalGap.vue';
5
+ import StatusBar from '@shell/components/Resource/Detail/StatusBar.vue';
6
+ import StatusRow from '@shell/components/Resource/Detail/StatusRow.vue';
7
+ import { useI18n } from '@shell/composables/useI18n';
8
+ import { StateColor } from '@shell/utils/style';
9
+ import { computed } from 'vue';
10
+ import { useStore } from 'vuex';
11
+
12
+ export interface Props {
13
+ pods?: any[];
14
+ showScaling?: boolean;
15
+ }
16
+ </script>
17
+
18
+ <script setup lang="ts">
19
+ const store = useStore();
20
+ const i18n = useI18n(store);
21
+
22
+ const props = withDefaults(defineProps<Props>(), { pods: undefined, showScaling: false });
23
+ const emit = defineEmits(['decrease', 'increase']);
24
+
25
+ const segmentAccumulator = computed(() => {
26
+ interface Value {
27
+ count: number;
28
+ }
29
+ const accumulator: {[key in StateColor]?: Value} = {};
30
+
31
+ props.pods?.forEach((pod: any) => {
32
+ const color: StateColor = pod.stateSimpleColor;
33
+
34
+ accumulator[color] = accumulator[color] || { count: 0 };
35
+ accumulator[color].count++;
36
+ });
37
+
38
+ return accumulator;
39
+ });
40
+
41
+ const rowAccumulator = computed(() => {
42
+ interface Value {
43
+ count: number;
44
+ color: StateColor;
45
+ }
46
+ const accumulator: {[key in string]: Value} = {};
47
+
48
+ props.pods?.forEach((pod: any) => {
49
+ accumulator[pod.stateDisplay] = accumulator[pod.stateDisplay] || { count: 0 };
50
+ accumulator[pod.stateDisplay].count++;
51
+ accumulator[pod.stateDisplay].color = pod.stateSimpleColor.replace('text-', '') as StateColor;
52
+ });
53
+
54
+ return accumulator;
55
+ });
56
+
57
+ const percent = (count: number, total: number) => {
58
+ return count / total * 100;
59
+ };
60
+
61
+ const count = computed(() => props.pods?.length || 0);
62
+
63
+ const segmentColors = computed(() => Object.keys(segmentAccumulator.value) as StateColor[]);
64
+ const segments = computed(() => segmentColors.value.map((color: StateColor) => ({
65
+ color,
66
+ percent: percent(segmentAccumulator.value[color]?.count || 0, count.value)
67
+ })));
68
+
69
+ const rowStates = computed(() => {
70
+ return Object.keys(rowAccumulator.value);
71
+ });
72
+
73
+ const rows = computed(() => {
74
+ return rowStates.value.map((state) => ({
75
+ color: rowAccumulator.value[state].color,
76
+ label: state,
77
+ count: rowAccumulator.value[state].count,
78
+ percent: percent(rowAccumulator.value[state].count, count.value)
79
+ }));
80
+ });
81
+
82
+ </script>
83
+
84
+ <template>
85
+ <Card :title="i18n.t('component.resource.detail.card.podsCard.title')">
86
+ <template
87
+ v-if="props.showScaling"
88
+ #heading-action
89
+ >
90
+ <Scaler
91
+ :ariaResourceName="i18n.t('component.resource.detail.card.podsCard.ariaResourceName')"
92
+ :value="count"
93
+ :min="0"
94
+ @increase="(newValue) => emit('increase', newValue)"
95
+ @decrease="(newValue) => emit('decrease', newValue)"
96
+ />
97
+ </template>
98
+ <StatusBar :segments="segments" />
99
+ <VerticalGap />
100
+ <div class="pod-distribution">
101
+ <StatusRow
102
+ v-for="(row, i) in rows"
103
+ :key="i"
104
+ :color="row.color"
105
+ :label="row.label"
106
+ :count="row.count"
107
+ :percent="row.percent"
108
+ />
109
+ </div>
110
+ </Card>
111
+ </template>
112
+
113
+ <style lang="scss" scoped>
114
+ .pod-distribution {
115
+ display: flex;
116
+ flex-direction: column;
117
+ }
118
+ </style>
@@ -0,0 +1,51 @@
1
+ import { Props } from '@shell/components/Resource/Detail/Card/ResourceUsageCard/index.vue';
2
+ import { useI18n } from '@shell/composables/useI18n';
3
+ import { computed } from 'vue';
4
+ import { useStore } from 'vuex';
5
+
6
+ export const useCpuUsageCardDefaultProps = (resource: any): Props => {
7
+ const store = useStore();
8
+ const i18n = useI18n(store);
9
+
10
+ // const resourceValue = toValue(resource);
11
+
12
+ return computed(() => {
13
+ return {
14
+ title: i18n.t('component.resource.detail.card.resourceUsage.cpu'),
15
+ used: 1.20,
16
+ available: 1.93
17
+ };
18
+ }).value;
19
+ };
20
+
21
+ export const useMemoryUsageCardDefaultProps = (resource: any): Props => {
22
+ const store = useStore();
23
+ const i18n = useI18n(store);
24
+
25
+ // const resourceValue = toValue(resource);
26
+
27
+ return computed(() => {
28
+ return {
29
+ title: i18n.t('component.resource.detail.card.resourceUsage.memory'),
30
+ used: 870,
31
+ available: 3290,
32
+ availableFormatter: (n: number) => (n / 1000).toFixed(2),
33
+ unit: 'GiB',
34
+ };
35
+ }).value;
36
+ };
37
+
38
+ export const usePodUsageCardDefaultProps = (resource: any): Props => {
39
+ const store = useStore();
40
+ const i18n = useI18n(store);
41
+
42
+ // const resourceValue = toValue(resource);
43
+
44
+ return computed(() => {
45
+ return {
46
+ title: i18n.t('component.resource.detail.card.resourceUsage.pods'),
47
+ used: 9,
48
+ available: 17
49
+ };
50
+ }).value;
51
+ };
@@ -0,0 +1,79 @@
1
+ <script lang="ts">
2
+ import Card from '@shell/components/Resource/Detail/Card/index.vue';
3
+ import PercentageBar from '@shell/components/Resource/Detail/PercentageBar.vue';
4
+ import { useI18n } from '@shell/composables/useI18n';
5
+ import { computed } from 'vue';
6
+ import { useStore } from 'vuex';
7
+
8
+ export interface Props {
9
+ title: string;
10
+ unit?: string;
11
+ used: number;
12
+ usedFormatter?: (n: number) => string;
13
+ available: number;
14
+ availableFormatter?: (n: number) => string
15
+ }
16
+ </script>
17
+ <script setup lang="ts">
18
+ const store = useStore();
19
+ const i18n = useI18n(store);
20
+
21
+ const props = withDefaults(
22
+ defineProps<Props>(),
23
+ {
24
+ usedFormatter: (n: number) => n.toString(),
25
+ availableFormatter: (n: number) => n.toString(),
26
+ unit: undefined
27
+ }
28
+ );
29
+
30
+ const percentage = computed(() => {
31
+ const numerator = props.used || 0;
32
+ const denominator = props.available || 0;
33
+
34
+ return denominator === 0 ? 0 : Math.floor((numerator / denominator) * 100);
35
+ });
36
+
37
+ const used = computed(() => props.usedFormatter(props.used));
38
+ const available = computed(() => props.availableFormatter(props.available));
39
+ </script>
40
+
41
+ <template>
42
+ <Card :title="props.title">
43
+ <div class="numerical">
44
+ <div class="used">
45
+ {{ i18n.t('component.resource.detail.card.resourceUsage.used') }}
46
+ </div>
47
+ <div class="data">
48
+ <span class="amount">{{ i18n.t('component.resource.detail.card.resourceUsage.amount', {used, available}) }}</span>
49
+ <span
50
+ v-if="props.unit"
51
+ class="unit"
52
+ >
53
+ {{ props.unit }}
54
+ </span>
55
+ <span class="spacer">/</span>
56
+ <span class="percentage">{{ percentage }}%</span>
57
+ </div>
58
+ </div>
59
+ <PercentageBar :percent="percentage" />
60
+ </Card>
61
+ </template>
62
+
63
+ <style lang="scss" scoped>
64
+ .numerical {
65
+ display: flex;
66
+ flex-direction: row;
67
+ justify-content: space-between;
68
+
69
+ margin-bottom: 8px;
70
+
71
+ .spacer {
72
+ margin: 0 8px;
73
+ }
74
+
75
+ .percentage {
76
+ font-weight: bold;
77
+ }
78
+ }
79
+ </style>
@@ -0,0 +1,89 @@
1
+ <script setup lang="ts">
2
+ import { useI18n } from '@shell/composables/useI18n';
3
+ import { useStore } from 'vuex';
4
+
5
+ export interface Props {
6
+ ariaResourceName: string;
7
+ value?: number;
8
+ min?: number;
9
+ max?: number;
10
+ }
11
+
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ value: 0, min: undefined, max: undefined
14
+ });
15
+ const emit = defineEmits(['decrease', 'increase']);
16
+
17
+ const store = useStore();
18
+ const i18n = useI18n(store);
19
+ </script>
20
+
21
+ <template>
22
+ <div class="scaler">
23
+ <button
24
+ class="decrease"
25
+ :aria-label="i18n.t('component.resource.detail.card.scaler.ariaLabel.decrease', {resourceName: props.ariaResourceName})"
26
+ :disabled="!!props.min && (props.value <= props.min)"
27
+ @click="() => emit('decrease', props.value - 1)"
28
+ >
29
+ <i class="icon icon-sm icon-minus" />
30
+ </button>
31
+ <div class="value">
32
+ {{ props.value }}
33
+ </div>
34
+ <button
35
+ class="increase"
36
+ :aria-label="i18n.t('component.resource.detail.card.scaler.ariaLabel.increase', {resourceName: props.ariaResourceName})"
37
+ :disabled="!!props.max && (props.value >= props.max)"
38
+ @click="() => emit('increase', props.value + 1)"
39
+ >
40
+ <i class="icon icon-sm icon-plus" />
41
+ </button>
42
+ </div>
43
+ </template>
44
+
45
+ <style lang="scss" scoped>
46
+ .scaler {
47
+ display: inline-flex;
48
+ align-items: center;
49
+ background-color: hsl(from var(--primary) h s calc(l + 30));
50
+ border-radius: var(--border-radius-md);
51
+ border: 1px solid var(--primary);
52
+ overflow: hidden;
53
+
54
+ button {
55
+ all: initial;
56
+ cursor: pointer;
57
+ background: none;
58
+ height: 100%;
59
+ width: 32px;
60
+ height: 32px;
61
+
62
+ text-align: center;
63
+ font-size: 20px;
64
+ font-weight: bold;
65
+ color: var(--primary);
66
+
67
+ i.icon {
68
+ font-size: 0.6em;
69
+ }
70
+
71
+ &:hover {
72
+ background-color: hsl(from var(--primary) h s calc(l + 20));
73
+ }
74
+
75
+ &[disabled] {
76
+ cursor: not-allowed;
77
+ background: var(--disabled-bg);
78
+ color: var(--disabled-text);
79
+ }
80
+ }
81
+
82
+ .value {
83
+ color: initial;
84
+ cursor: default;
85
+ padding: 4px;
86
+ padding-top: 5px;
87
+ }
88
+ }
89
+ </style>