@rancher/shell 0.3.0 → 0.3.2

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 (342) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_gauges.scss +1 -1
  4. package/assets/styles/global/_layout.scss +5 -2
  5. package/assets/styles/global/_select.scss +1 -4
  6. package/assets/styles/themes/_dark.scss +5 -4
  7. package/assets/styles/themes/_light.scss +4 -3
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/styles/vendor/vue-select.scss +4 -3
  10. package/assets/translations/en-us.yaml +673 -73
  11. package/assets/translations/zh-hans.yaml +720 -207
  12. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  13. package/cloud-credential/azure.vue +23 -0
  14. package/cloud-credential/harvester.vue +25 -62
  15. package/cloud-credential/pnap.vue +80 -0
  16. package/components/.DS_Store +0 -0
  17. package/components/ActionMenu.vue +28 -7
  18. package/components/AdvancedSection.vue +9 -2
  19. package/components/Alert.vue +2 -2
  20. package/components/ButtonDropdown.vue +0 -2
  21. package/components/ButtonGroup.vue +1 -0
  22. package/components/CollapsibleCard.vue +0 -1
  23. package/components/CruResource.vue +41 -4
  24. package/components/DetailTop.vue +72 -4
  25. package/components/DisableAuthProviderModal.vue +106 -0
  26. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  27. package/components/ExplorerMembers.vue +253 -30
  28. package/components/ExplorerProjectsNamespaces.vue +77 -33
  29. package/components/ExtensionPanel.vue +42 -0
  30. package/components/GrowlManager.vue +3 -3
  31. package/components/IconOrSvg.vue +178 -0
  32. package/components/LogItem.vue +69 -0
  33. package/components/PodSecurityAdmission.vue +302 -0
  34. package/components/PromptModal.vue +1 -0
  35. package/components/ResourceDetail/Masthead.vue +69 -4
  36. package/components/ResourceDetail/index.vue +12 -5
  37. package/components/ResourceList/Masthead.vue +11 -1
  38. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  39. package/components/ResourceList/index.vue +66 -12
  40. package/components/ResourceList/resource-list.config.js +7 -0
  41. package/components/ResourceTable.vue +33 -6
  42. package/components/SimpleBox.vue +1 -1
  43. package/components/SortableTable/THead.vue +21 -14
  44. package/components/SortableTable/filtering.js +1 -1
  45. package/components/SortableTable/index.vue +21 -10
  46. package/components/SortableTable/selection.js +15 -3
  47. package/components/Tabbed/Tab.vue +1 -1
  48. package/components/Tabbed/index.vue +20 -15
  49. package/components/__tests__/.DS_Store +0 -0
  50. package/components/__tests__/AsyncButton.test.ts +140 -0
  51. package/components/__tests__/BackLink.test.ts +33 -0
  52. package/components/__tests__/ButtonGroup.test.ts +124 -0
  53. package/components/__tests__/ClusterBadge.test.ts +32 -0
  54. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  55. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  56. package/components/__tests__/CruResource.test.ts +3 -2
  57. package/components/__tests__/FixedBanner.test.ts +129 -0
  58. package/components/__tests__/GrowlManager.test.ts +147 -0
  59. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  60. package/components/__tests__/PercentageBar.test.ts +32 -0
  61. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  62. package/components/auth/AuthBanner.vue +20 -10
  63. package/components/auth/RoleDetailEdit.vue +26 -17
  64. package/components/auth/SelectPrincipal.vue +36 -5
  65. package/components/form/ArrayList.vue +3 -35
  66. package/components/form/ArrayListGrouped.vue +13 -4
  67. package/components/form/ArrayListSelect.vue +5 -5
  68. package/components/form/Error.vue +8 -0
  69. package/components/form/KeyValue.vue +39 -7
  70. package/components/form/LabeledSelect.vue +5 -2
  71. package/components/form/Labels.vue +46 -16
  72. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  73. package/components/form/Members/MembershipEditor.vue +12 -12
  74. package/components/form/NameNsDescription.vue +1 -1
  75. package/components/form/NodeScheduling.vue +1 -1
  76. package/components/form/Probe.vue +3 -3
  77. package/components/form/ResourceQuota/Project.vue +6 -6
  78. package/components/form/ResourceTabs/index.vue +24 -6
  79. package/components/form/Security.vue +7 -6
  80. package/components/form/Select.vue +3 -2
  81. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  82. package/components/form/ServicePorts.vue +8 -0
  83. package/components/form/WorkloadPorts.vue +7 -1
  84. package/components/form/__tests__/ArrayList.test.ts +74 -0
  85. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  86. package/components/formatter/Checked.vue +1 -1
  87. package/components/formatter/ClusterLink.vue +5 -0
  88. package/components/formatter/IconIsDefault.vue +2 -2
  89. package/components/formatter/InternalExternalIP.vue +11 -8
  90. package/components/formatter/LiveDuration.vue +78 -0
  91. package/components/formatter/WorkloadHealthScale.vue +5 -3
  92. package/components/nav/Header.vue +74 -7
  93. package/components/nav/NamespaceFilter.vue +146 -63
  94. package/components/nav/TopLevelMenu.vue +22 -19
  95. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  96. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  97. package/components/nav/WindowManager/Window.vue +2 -0
  98. package/components/nav/WindowManager/index.vue +10 -0
  99. package/config/elemental-types.js +9 -0
  100. package/config/features.js +2 -0
  101. package/config/home-links.js +4 -1
  102. package/config/pod-security-admission.ts +82 -0
  103. package/config/product/apps.js +1 -1
  104. package/config/product/auth.js +6 -5
  105. package/config/product/backup.js +1 -1
  106. package/config/product/explorer.js +6 -6
  107. package/config/product/fleet.js +1 -1
  108. package/config/product/manager.js +6 -2
  109. package/config/query-params.js +1 -0
  110. package/config/secret.js +0 -1
  111. package/config/settings.ts +26 -9
  112. package/config/table-headers.js +22 -11
  113. package/config/types.js +4 -1
  114. package/config/uiplugins.js +3 -3
  115. package/content/docs/zh-hans/getting-started.md +113 -137
  116. package/content/docs/zh-hans/whats-new.md +8 -46
  117. package/core/plugin-helpers.js +171 -0
  118. package/core/plugin.ts +61 -1
  119. package/core/plugins.js +33 -0
  120. package/core/types.ts +128 -2
  121. package/creators/pkg/package-lock.json +37 -0
  122. package/creators/pkg/package.json +1 -1
  123. package/detail/catalog.cattle.io.app.vue +1 -1
  124. package/detail/pod.vue +1 -1
  125. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  126. package/detail/service.vue +2 -9
  127. package/detail/workload/index.vue +0 -1
  128. package/dialog/AddClusterMemberDialog.vue +22 -28
  129. package/dialog/AddProjectMemberDialog.vue +53 -9
  130. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  131. package/dialog/DrainNode.vue +44 -48
  132. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  133. package/dialog/GenericPrompt.vue +15 -20
  134. package/dialog/RollbackWorkloadDialog.vue +15 -46
  135. package/dialog/RotateCertificatesDialog.vue +5 -7
  136. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  137. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  138. package/dialog/ScaleMachineDownDialog.vue +1 -1
  139. package/dialog/ScalePoolDownDialog.vue +121 -0
  140. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  141. package/edit/auth/azuread.vue +16 -16
  142. package/edit/auth/github.vue +8 -0
  143. package/edit/auth/googleoauth.vue +10 -1
  144. package/edit/auth/ldap/index.vue +10 -0
  145. package/edit/auth/oidc.vue +10 -0
  146. package/edit/auth/saml.vue +10 -0
  147. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  148. package/edit/catalog.cattle.io.clusterrepo.vue +3 -0
  149. package/edit/cloudcredential.vue +3 -7
  150. package/edit/logging-flow/Match.vue +39 -8
  151. package/edit/logging-flow/index.vue +27 -4
  152. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  153. package/edit/management.cattle.io.project.vue +8 -1
  154. package/edit/management.cattle.io.setting.vue +5 -2
  155. package/edit/management.cattle.io.user.vue +7 -1
  156. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +36 -8
  157. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  158. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  159. package/edit/namespace.vue +18 -4
  160. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  161. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  162. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  163. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  164. package/edit/persistentvolume/index.vue +30 -27
  165. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  166. package/edit/persistentvolume/plugins/csi.vue +102 -62
  167. package/edit/persistentvolume/plugins/fc.vue +19 -19
  168. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  169. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  170. package/edit/persistentvolumeclaim.vue +78 -75
  171. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  172. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  173. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  174. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  175. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +96 -0
  176. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  177. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  178. package/edit/provisioning.cattle.io.cluster/rke2.vue +445 -154
  179. package/edit/secret/index.vue +3 -7
  180. package/edit/service.vue +3 -1
  181. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  182. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  183. package/edit/workload/__tests__/index.test.ts +98 -0
  184. package/edit/workload/index.vue +58 -8
  185. package/edit/workload/mixins/workload.js +107 -70
  186. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  187. package/edit/workload/storage/emptyDir.vue +88 -0
  188. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  189. package/edit/workload/storage/index.vue +8 -0
  190. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  191. package/layouts/default.vue +57 -44
  192. package/list/__tests__/workload.test.ts +5 -2
  193. package/list/catalog.cattle.io.app.vue +1 -0
  194. package/list/cis.cattle.io.clusterscan.vue +1 -0
  195. package/list/fleet.cattle.io.bundle.vue +5 -6
  196. package/list/fleet.cattle.io.cluster.vue +6 -3
  197. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  198. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  199. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  200. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  201. package/list/logging.banzaicloud.io.flow.vue +6 -5
  202. package/list/management.cattle.io.cluster.vue +1 -0
  203. package/list/management.cattle.io.feature.vue +3 -4
  204. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  205. package/list/management.cattle.io.setting.vue +2 -2
  206. package/list/management.cattle.io.user.vue +4 -10
  207. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  208. package/list/node.vue +8 -5
  209. package/list/persistentvolume.vue +3 -3
  210. package/list/persistentvolumeclaim.vue +3 -4
  211. package/list/provisioning.cattle.io.cluster.vue +18 -19
  212. package/list/service.vue +6 -14
  213. package/list/workload.vue +43 -38
  214. package/machine-config/azure.vue +429 -60
  215. package/machine-config/pnap.vue +288 -0
  216. package/mixins/auth-config.js +1 -3
  217. package/mixins/browser-tab-visibility.js +8 -14
  218. package/mixins/chart.js +1 -1
  219. package/mixins/create-edit-view/impl.js +4 -0
  220. package/mixins/create-edit-view/index.js +4 -2
  221. package/mixins/resource-fetch-namespaced.js +98 -0
  222. package/mixins/resource-fetch.js +79 -45
  223. package/mixins/resource-manager.js +1 -23
  224. package/models/apps.controllerrevision.js +7 -0
  225. package/models/apps.daemonset.js +18 -0
  226. package/models/apps.deployment.js +44 -0
  227. package/models/apps.replicaset.js +7 -0
  228. package/models/apps.statefulset.js +18 -0
  229. package/models/batch.job.js +7 -14
  230. package/models/cluster/node.js +10 -2
  231. package/models/cluster.x-k8s.io.machine.js +26 -4
  232. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  233. package/models/event.js +7 -0
  234. package/models/logging.banzaicloud.io.flow.js +4 -0
  235. package/models/management.cattle.io.cluster.js +1 -1
  236. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  237. package/models/management.cattle.io.globalrole.js +2 -2
  238. package/models/management.cattle.io.node.js +37 -2
  239. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  240. package/models/management.cattle.io.project.js +30 -11
  241. package/models/management.cattle.io.setting.js +1 -1
  242. package/models/management.cattle.io.user.js +37 -1
  243. package/models/namespace.js +42 -5
  244. package/models/persistentvolume.js +14 -2
  245. package/models/pod.js +15 -0
  246. package/models/projectroletemplatebinding.js +7 -0
  247. package/models/provisioning.cattle.io.cluster.js +61 -10
  248. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  249. package/models/service.js +14 -13
  250. package/models/storage.k8s.io.storageclass.js +33 -18
  251. package/models/workload.js +38 -7
  252. package/nuxt.config.js +27 -17
  253. package/package.json +7 -7
  254. package/pages/about.vue +14 -2
  255. package/pages/c/_cluster/apps/charts/index.vue +21 -3
  256. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  257. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  258. package/pages/c/_cluster/auth/config/index.vue +8 -6
  259. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  260. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  261. package/pages/c/_cluster/explorer/index.vue +51 -6
  262. package/pages/c/_cluster/longhorn/index.vue +1 -1
  263. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  264. package/pages/c/_cluster/monitoring/index.vue +1 -1
  265. package/pages/c/_cluster/neuvector/index.vue +1 -1
  266. package/pages/c/_cluster/settings/performance.vue +48 -2
  267. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +2 -0
  268. package/pages/c/_cluster/uiplugins/InstallDialog.vue +3 -0
  269. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +42 -2
  270. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -0
  271. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +1 -0
  272. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +2 -0
  273. package/pages/c/_cluster/uiplugins/index.vue +42 -3
  274. package/pages/diagnostic.vue +5 -4
  275. package/pages/home.vue +105 -30
  276. package/pages/prefs.vue +23 -12
  277. package/pages/rio/mesh.vue +1 -1
  278. package/pkg/dynamic-importer.lib.js +8 -0
  279. package/pkg/vue.config.js +4 -0
  280. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  281. package/plugins/dashboard-store/actions.js +32 -25
  282. package/plugins/dashboard-store/getters.js +50 -33
  283. package/plugins/dashboard-store/mutations.js +134 -28
  284. package/plugins/dashboard-store/resource-class.js +37 -42
  285. package/plugins/steve/actions.js +30 -0
  286. package/plugins/steve/caches/resourceCache.js +60 -0
  287. package/plugins/steve/getters.js +44 -1
  288. package/plugins/steve/mutations.js +97 -36
  289. package/plugins/steve/resourceWatcher.js +277 -0
  290. package/plugins/steve/schema.utils.js +25 -0
  291. package/plugins/steve/subscribe.js +288 -115
  292. package/plugins/steve/worker/index.js +17 -0
  293. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  294. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  295. package/rancher-components/Card/Card.vue +3 -3
  296. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  297. package/rancher-components/StringList/StringList.test.ts +45 -420
  298. package/rancher-components/StringList/StringList.vue +1 -10
  299. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  300. package/rancher-components/components/Banner/Banner.vue +130 -61
  301. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  302. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  303. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  304. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  305. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  306. package/rancher-components/components/StringList/StringList.vue +21 -15
  307. package/scripts/test-plugins-build.sh +8 -0
  308. package/static/loading-indicator.html +1 -1
  309. package/store/action-menu.js +4 -3
  310. package/store/index.js +54 -3
  311. package/store/plugins.js +0 -17
  312. package/store/pnap.js +128 -0
  313. package/store/prefs.js +4 -2
  314. package/store/type-map.js +81 -13
  315. package/types/pod-security-admission.ts +36 -0
  316. package/types/shell/index.d.ts +497 -396
  317. package/utils/__tests__/object.test.ts +17 -1
  318. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  319. package/utils/async.ts +36 -0
  320. package/utils/color.js +45 -0
  321. package/utils/crypto/browserHashUtils.js +18 -0
  322. package/utils/dynamic-importer.js +8 -0
  323. package/utils/install-redirect.js +1 -1
  324. package/utils/object.js +24 -0
  325. package/utils/pod-security-admission.ts +39 -0
  326. package/utils/socket.js +61 -24
  327. package/utils/string.js +2 -0
  328. package/utils/svg-filter.js +301 -0
  329. package/utils/time.js +49 -0
  330. package/utils/validators/cidr.js +4 -0
  331. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  332. package/utils/validators/formRules/index.ts +14 -0
  333. package/config/product/harvester-manager.js +0 -162
  334. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  335. package/list/harvesterhci.io.management.cluster.vue +0 -241
  336. package/machine-config/harvester.vue +0 -693
  337. package/models/harvesterhci.io.management.cluster.js +0 -228
  338. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  339. package/rancher-components/Card/Card.test.ts +0 -39
  340. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  341. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  342. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -10,6 +10,8 @@ import { HIDE_SENSITIVE } from '@shell/store/prefs';
10
10
  import {
11
11
  AS, _DETAIL, _CONFIG, _YAML, MODE, _CREATE, _EDIT, _VIEW, _UNFLAG, _GRAPH
12
12
  } from '@shell/config/query-params';
13
+ import { ExtensionPoint, PanelLocation } from '@shell/core/types';
14
+ import ExtensionPanel from '@shell/components/ExtensionPanel';
13
15
 
14
16
  /**
15
17
  * Resource Detail Masthead component.
@@ -21,7 +23,7 @@ export default {
21
23
  name: 'MastheadResourceDetail',
22
24
 
23
25
  components: {
24
- BadgeState, Banner, ButtonGroup
26
+ BadgeState, Banner, ButtonGroup, ExtensionPanel
25
27
  },
26
28
  props: {
27
29
  value: {
@@ -82,6 +84,14 @@ export default {
82
84
  },
83
85
  },
84
86
 
87
+ data() {
88
+ return {
89
+ DETAIL_VIEW: _DETAIL,
90
+ extensionType: ExtensionPoint.PANEL,
91
+ extensionLocation: PanelLocation.DETAILS_MASTHEAD,
92
+ };
93
+ },
94
+
85
95
  computed: {
86
96
  schema() {
87
97
  const inStore = this.storeOverride || this.$store.getters['currentStore'](this.resource);
@@ -125,6 +135,10 @@ export default {
125
135
  return null;
126
136
  },
127
137
 
138
+ detailsAction() {
139
+ return this.value?.detailsAction;
140
+ },
141
+
128
142
  shouldHifenize() {
129
143
  return (this.mode === 'view' || this.mode === 'edit') && this.resourceSubtype?.length && this.value?.nameDisplay?.length;
130
144
  },
@@ -354,6 +368,10 @@ export default {
354
368
 
355
369
  return parent?.location;
356
370
  },
371
+
372
+ hideNamespaceLocation() {
373
+ return this.$store.getters['currentProduct'].hideNamespaceLocation;
374
+ },
357
375
  },
358
376
 
359
377
  methods: {
@@ -368,6 +386,18 @@ export default {
368
386
 
369
387
  toggleSensitiveData(e) {
370
388
  this.$store.dispatch('prefs/set', { key: HIDE_SENSITIVE, value: !!e });
389
+ },
390
+
391
+ invokeDetailsAction() {
392
+ const action = this.detailsAction;
393
+
394
+ if (action) {
395
+ const fn = this.value[action.action];
396
+
397
+ if (fn) {
398
+ fn.apply(this.value, []);
399
+ }
400
+ }
371
401
  }
372
402
  }
373
403
  };
@@ -375,7 +405,7 @@ export default {
375
405
 
376
406
  <template>
377
407
  <div class="masthead">
378
- <header class="header-layout">
408
+ <header>
379
409
  <div class="title">
380
410
  <div class="primaryheader">
381
411
  <h1>
@@ -407,7 +437,18 @@ export default {
407
437
  >
408
438
  <span v-if="isNamespace && project">{{ t("resourceDetail.masthead.project") }}: <nuxt-link :to="project.detailLocation">{{ project.nameDisplay }}</nuxt-link></span>
409
439
  <span v-else-if="isWorkspace">{{ t("resourceDetail.masthead.workspace") }}: <nuxt-link :to="workspaceLocation">{{ namespace }}</nuxt-link></span>
410
- <span v-else-if="namespace && !hasMultipleNamespaces">{{ t("resourceDetail.masthead.namespace") }}: <nuxt-link :to="namespaceLocation">{{ namespace }}</nuxt-link></span>
440
+ <span v-else-if="namespace && !hasMultipleNamespaces">
441
+ {{ t("resourceDetail.masthead.namespace") }}:
442
+ <nuxt-link
443
+ v-if="!hideNamespaceLocation"
444
+ :to="namespaceLocation"
445
+ >
446
+ {{ namespace }}
447
+ </nuxt-link>
448
+ <span v-else>
449
+ {{ namespace }}
450
+ </span>
451
+ </span>
411
452
  <span v-if="parent.showAge">{{ t("resourceDetail.masthead.age") }}: <LiveDate
412
453
  class="live-date"
413
454
  :value="value.creationTimestamp"
@@ -416,13 +457,23 @@ export default {
416
457
  </div>
417
458
  </div>
418
459
  <slot name="right">
419
- <div class="actions-container">
460
+ <div class="actions-container align-start">
420
461
  <div class="actions">
462
+ <button
463
+ v-if="detailsAction && currentView === DETAIL_VIEW && isView"
464
+ type="button"
465
+ class="btn role-primary actions mr-10"
466
+ :disabled="!detailsAction.enabled"
467
+ @click="invokeDetailsAction"
468
+ >
469
+ {{ detailsAction.label }}
470
+ </button>
421
471
  <ButtonGroup
422
472
  v-if="showSensitiveToggle"
423
473
  :value="!!hideSensitiveData"
424
474
  icon-size="lg"
425
475
  :options="sensitiveOptions"
476
+ class="mr-10"
426
477
  @input="toggleSensitiveData"
427
478
  />
428
479
 
@@ -430,6 +481,7 @@ export default {
430
481
  v-if="viewOptions && isView"
431
482
  v-model="currentView"
432
483
  :options="viewOptions"
484
+ class="mr-10"
433
485
  />
434
486
 
435
487
  <button
@@ -447,6 +499,13 @@ export default {
447
499
  </slot>
448
500
  </header>
449
501
 
502
+ <!-- Extension area -->
503
+ <ExtensionPanel
504
+ :resource="value"
505
+ :type="extensionType"
506
+ :location="extensionLocation"
507
+ />
508
+
450
509
  <Banner
451
510
  v-if="banner && isView && !parent.hideBanner"
452
511
  class="state-banner mb-10"
@@ -522,4 +581,10 @@ export default {
522
581
  }
523
582
  }
524
583
 
584
+ div.actions-container > div.actions {
585
+ display: flex;
586
+ flex-direction: row;
587
+ justify-content: flex-end;
588
+ }
589
+
525
590
  </style>
@@ -26,7 +26,8 @@ function modeFor(route) {
26
26
  }
27
27
  }
28
28
 
29
- async function getYaml(model) {
29
+ async function getYaml(store, model) {
30
+ const inStore = store.getters['currentStore'](model.type);
30
31
  let yaml;
31
32
  const opt = { headers: { accept: 'application/yaml' } };
32
33
 
@@ -34,7 +35,9 @@ async function getYaml(model) {
34
35
  yaml = (await model.followLink('view', opt)).data;
35
36
  }
36
37
 
37
- return yaml;
38
+ const cleanedYaml = await store.dispatch(`${ inStore }/cleanForDownload`, yaml);
39
+
40
+ return cleanedYaml;
38
41
  }
39
42
 
40
43
  export default {
@@ -146,6 +149,11 @@ export default {
146
149
  initialModel = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
147
150
  model = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
148
151
 
152
+ if (model.forceYaml === true) {
153
+ as = _YAML;
154
+ this.as = as;
155
+ }
156
+
149
157
  if ( as === _YAML ) {
150
158
  yaml = createYaml(schemas, resource, data);
151
159
  }
@@ -182,7 +190,7 @@ export default {
182
190
  initialModel = await store.dispatch(`${ inStore }/clone`, { resource: liveModel });
183
191
 
184
192
  if ( as === _YAML ) {
185
- yaml = await getYaml(liveModel);
193
+ yaml = await getYaml(this.$store, liveModel);
186
194
  }
187
195
 
188
196
  if ( as === _GRAPH ) {
@@ -222,7 +230,6 @@ export default {
222
230
  this.value.applyDefaults(this, realMode);
223
231
  }
224
232
  },
225
-
226
233
  data() {
227
234
  return {
228
235
  chartData: null,
@@ -306,7 +313,7 @@ export default {
306
313
  // Auto refresh YAML when the model changes
307
314
  async 'value.metadata.resourceVersion'(a, b) {
308
315
  if ( this.mode === _VIEW && this.as === _YAML && a && b && a !== b) {
309
- this.yaml = await getYaml(this.liveModel);
316
+ this.yaml = await getYaml(this.$store, this.liveModel);
310
317
  }
311
318
  }
312
319
  },
@@ -65,6 +65,11 @@ export default {
65
65
  default: false
66
66
  },
67
67
 
68
+ loadNamespace: {
69
+ type: String,
70
+ default: null
71
+ },
72
+
68
73
  showIncrementalLoadingIndicator: {
69
74
  type: Boolean,
70
75
  default: false
@@ -163,7 +168,7 @@ export default {
163
168
  </script>
164
169
 
165
170
  <template>
166
- <header class="header-layout">
171
+ <header>
167
172
  <slot name="typeDescription">
168
173
  <TypeDescription :resource="resource" />
169
174
  </slot>
@@ -178,6 +183,7 @@ export default {
178
183
  v-if="showIncrementalLoadingIndicator"
179
184
  :resources="loadResources"
180
185
  :indeterminate="loadIndeterminate"
186
+ :namespace="loadNamespace"
181
187
  />
182
188
  </div>
183
189
  <div class="actions-container">
@@ -217,4 +223,8 @@ export default {
217
223
  margin: 0;
218
224
  }
219
225
  }
226
+
227
+ header {
228
+ margin-bottom: 20px;
229
+ }
220
230
  </style>
@@ -16,7 +16,11 @@ export default {
16
16
  indeterminate: {
17
17
  type: Boolean,
18
18
  default: false,
19
- }
19
+ },
20
+ namespace: {
21
+ type: String,
22
+ default: undefined
23
+ },
20
24
  },
21
25
 
22
26
  data() {
@@ -40,6 +44,10 @@ export default {
40
44
  // Have we loaded all resources for the types that are needed
41
45
  haveAll() {
42
46
  return this.resources.reduce((acc, r) => {
47
+ if (this.namespace) {
48
+ return acc && this.$store.getters[`${ this.inStore }/haveAllNamespace`](r, this.namespace);
49
+ }
50
+
43
51
  return acc && this.$store.getters[`${ this.inStore }/haveAll`](r);
44
52
  }, true);
45
53
  },
@@ -49,7 +57,9 @@ export default {
49
57
  const clusterCounts = this.$store.getters[`${ this.inStore }/all`](COUNT);
50
58
 
51
59
  return this.resources.reduce((acc, r) => {
52
- const count = clusterCounts?.[0]?.counts?.[r]?.summary?.count || 0;
60
+ const resourceCounts = clusterCounts?.[0]?.counts?.[r];
61
+ const resourceCount = this.namespace ? resourceCounts?.namespaces?.[this.namespace]?.count : resourceCounts?.summary?.count;
62
+ const count = resourceCount || 0;
53
63
 
54
64
  return acc + count;
55
65
  }, 0);
@@ -4,13 +4,21 @@ import Loading from '@shell/components/Loading';
4
4
  import Masthead from './Masthead';
5
5
  import ResourceLoadingIndicator from './ResourceLoadingIndicator';
6
6
  import ResourceFetch from '@shell/mixins/resource-fetch';
7
+ import IconMessage from '@shell/components/IconMessage.vue';
8
+ import { ResourceListComponentName } from './resource-list.config';
9
+ import { PanelLocation, ExtensionPoint } from '@shell/core/types';
10
+ import ExtensionPanel from '@shell/components/ExtensionPanel';
7
11
 
8
12
  export default {
13
+ name: ResourceListComponentName,
14
+
9
15
  components: {
10
16
  Loading,
11
17
  ResourceTable,
12
18
  Masthead,
13
- ResourceLoadingIndicator
19
+ ResourceLoadingIndicator,
20
+ IconMessage,
21
+ ExtensionPanel
14
22
  },
15
23
  mixins: [ResourceFetch],
16
24
 
@@ -28,19 +36,16 @@ export default {
28
36
  default: false
29
37
  },
30
38
  },
39
+
31
40
  async fetch() {
32
41
  const store = this.$store;
33
42
  const resource = this.resource;
34
43
 
35
- let hasFetch = false;
36
-
37
- const inStore = store.getters['currentStore'](resource);
38
-
39
- const schema = store.getters[`${ inStore }/schemaFor`](resource);
44
+ const schema = this.schema;
40
45
 
41
46
  if ( this.hasListComponent ) {
42
47
  // If you provide your own list then call its asyncData
43
- const importer = store.getters['type-map/importList'](resource);
48
+ const importer = this.listComponent;
44
49
  const component = (await importer())?.default;
45
50
 
46
51
  if ( component?.typeDisplay ) {
@@ -49,7 +54,7 @@ export default {
49
54
 
50
55
  // If your list page has a fetch then it's responsible for populating rows itself
51
56
  if ( component?.fetch ) {
52
- hasFetch = true;
57
+ this.hasFetch = true;
53
58
  }
54
59
 
55
60
  // If the custom component supports it, ask it what resources it loads, so we can
@@ -62,14 +67,17 @@ export default {
62
67
  }
63
68
  }
64
69
 
65
- if ( !hasFetch ) {
70
+ if ( !this.hasFetch ) {
66
71
  if ( !schema ) {
67
72
  store.dispatch('loadingError', new Error(`Type ${ resource } not found, unable to display list`));
68
73
 
69
74
  return;
70
75
  }
71
76
 
72
- await this.$fetchType(resource);
77
+ // See comment for `namespaceFilterRequired` watcher, skip fetch if we don't have a valid NS
78
+ if (!this.namespaceFilterRequired) {
79
+ await this.$fetchType(resource);
80
+ }
73
81
  }
74
82
  },
75
83
 
@@ -91,6 +99,10 @@ export default {
91
99
  hasListComponent,
92
100
  showMasthead: showMasthead === undefined ? true : showMasthead,
93
101
  resource,
102
+ extensionType: ExtensionPoint.PANEL,
103
+ extensionLocation: PanelLocation.RESOURCE_LIST,
104
+ loadResources: [resource], // List of resources that will be loaded, this could be many (`Workloads`)
105
+ hasFetch: false,
94
106
  // manual refresh
95
107
  manualRefreshInit: false,
96
108
  watch: false,
@@ -98,7 +110,6 @@ export default {
98
110
  // Provided by fetch later
99
111
  customTypeDisplay: null,
100
112
  // incremental loading
101
- loadResources: [resource],
102
113
  loadIndeterminate: false,
103
114
  // query param for simple filtering
104
115
  useQueryParamsForSimpleFiltering: true
@@ -121,6 +132,24 @@ export default {
121
132
 
122
133
  showIncrementalLoadingIndicator() {
123
134
  return this.perfConfig?.incrementalLoading?.enabled;
135
+ },
136
+
137
+ },
138
+
139
+ watch: {
140
+ /**
141
+ * When a NS filter is required and the user selects a different one, kick off a new set of API requests
142
+ *
143
+ * ResourceList has two modes
144
+ * 1) ResourceList component handles API request to fetch resources
145
+ * 2) Custom list component handles API request to fetch resources
146
+ *
147
+ * This covers case 1
148
+ */
149
+ namespaceFilter(neu) {
150
+ if (neu && !this.hasFetch) {
151
+ this.$fetchType(this.resource);
152
+ }
124
153
  }
125
154
  },
126
155
 
@@ -140,7 +169,20 @@ export default {
140
169
  </script>
141
170
 
142
171
  <template>
143
- <div>
172
+ <IconMessage
173
+ v-if="namespaceFilterRequired"
174
+ :vertical="true"
175
+ :subtle="false"
176
+ icon="icon-filter_alt"
177
+ >
178
+ <template #message>
179
+ <span
180
+ class="filter"
181
+ v-html="t('resourceList.nsFiltering', { resource: $store.getters['type-map/labelFor'](schema, 2) || customTypeDisplay }, true)"
182
+ />
183
+ </template>
184
+ </IconMessage>
185
+ <div v-else>
144
186
  <Masthead
145
187
  v-if="showMasthead"
146
188
  :type-display="customTypeDisplay"
@@ -149,11 +191,19 @@ export default {
149
191
  :show-incremental-loading-indicator="showIncrementalLoadingIndicator"
150
192
  :load-resources="loadResources"
151
193
  :load-indeterminate="loadIndeterminate"
194
+ :load-namespace="namespaceFilter"
152
195
  >
153
196
  <template slot="extraActions">
154
197
  <slot name="extraActions" />
155
198
  </template>
156
199
  </Masthead>
200
+ <!-- Extensions area -->
201
+ <ExtensionPanel
202
+ :resource="{}"
203
+ :type="extensionType"
204
+ :location="extensionLocation"
205
+ />
206
+
157
207
  <div v-if="hasListComponent">
158
208
  <component
159
209
  :is="listComponent"
@@ -173,6 +223,7 @@ export default {
173
223
  :adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
174
224
  :adv-filter-prevent-filtering-labels="advFilterPreventFilteringLabels"
175
225
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
226
+ :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
176
227
  />
177
228
  </div>
178
229
  </template>
@@ -185,6 +236,9 @@ export default {
185
236
  position: relative;
186
237
  margin: 0 0 20px 0;
187
238
  }
239
+ .filter{
240
+ line-height: 45px;
241
+ }
188
242
  .right-action {
189
243
  position: absolute;
190
244
  top: 10px;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Component name of the `ResourceList`
3
+ *
4
+ * This needs to be a in separate file to avoid circular dependency of
5
+ * index.vue --> resource-fetch mixin --> resource-fetch-namespaced mixin --> index.vue
6
+ */
7
+ export const ResourceListComponentName = 'ResourceList';
@@ -140,9 +140,30 @@ export default {
140
140
  useQueryParamsForSimpleFiltering: {
141
141
  type: Boolean,
142
142
  default: false
143
+ },
144
+ /**
145
+ * Manaul force the update of live and delayed cells. Change this number to kick off the update
146
+ */
147
+ forceUpdateLiveAndDelayed: {
148
+ type: Number,
149
+ default: 0
143
150
  }
144
151
  },
145
152
 
153
+ mounted() {
154
+ /**
155
+ * v-shortkey prevents the event's propagation:
156
+ * https://github.com/fgr-araujo/vue-shortkey/blob/55d802ea305cadcc2ea970b55a3b8b86c7b44c05/src/index.js#L156-L157
157
+ *
158
+ * 'Enter' key press is handled via event listener in order to allow the event propagation
159
+ */
160
+ window.addEventListener('keyup', this.handleEnterKeyPress);
161
+ },
162
+
163
+ beforeDestroy() {
164
+ window.removeEventListener('keyup', this.handleEnterKeyPress);
165
+ },
166
+
146
167
  data() {
147
168
  const options = this.$store.getters[`type-map/optionsFor`](this.schema);
148
169
  const listGroups = options?.listGroups || [];
@@ -232,11 +253,16 @@ export default {
232
253
  return [];
233
254
  }
234
255
 
256
+ const haveAllNamespace = this.$store.getters['haveAllNamespace'];
257
+
235
258
  return this.rows.filter((row) => {
236
259
  if (this.currentProduct?.hideSystemResources && this.isNamespaced) {
237
260
  return !!includedNamespaces[row.metadata.namespace] && !row.isSystemResource;
238
261
  } else if (!this.isNamespaced) {
239
262
  return true;
263
+ } else if (haveAllNamespace) {
264
+ // `rows` only contains resource from a single namespace
265
+ return true;
240
266
  } else {
241
267
  return !!includedNamespaces[row.metadata.namespace];
242
268
  }
@@ -375,8 +401,13 @@ export default {
375
401
 
376
402
  handleActionButtonClick(event) {
377
403
  this.$emit('clickedActionButton', event);
378
- }
404
+ },
379
405
 
406
+ handleEnterKeyPress(event) {
407
+ if (event.key === 'Enter') {
408
+ this.keyAction('detail');
409
+ }
410
+ }
380
411
  }
381
412
  };
382
413
  </script>
@@ -406,6 +437,7 @@ export default {
406
437
  key-field="_key"
407
438
  :sort-generation-fn="safeSortGenerationFn"
408
439
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
440
+ :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
409
441
  @clickedActionButton="handleActionButtonClick"
410
442
  @group-value-change="group = $event"
411
443
  v-on="$listeners"
@@ -447,11 +479,6 @@ export default {
447
479
  </template>
448
480
 
449
481
  <template #shortkeys>
450
- <button
451
- v-shortkey.once="['enter']"
452
- class="hide detail"
453
- @shortkey="keyAction('detail')"
454
- />
455
482
  <button
456
483
  v-shortkey.once="['e']"
457
484
  class="hide"
@@ -74,7 +74,7 @@ export default {
74
74
  justify-content: center;
75
75
  padding: 2px;
76
76
  > i {
77
- font-size: 20px;
77
+ font-size: 14px;
78
78
  opacity: 0.5;
79
79
  }
80
80
  &:hover {
@@ -191,6 +191,16 @@ export default {
191
191
  value
192
192
  });
193
193
  },
194
+
195
+ tooltip(col) {
196
+ if (!col.tooltip) {
197
+ return null;
198
+ }
199
+
200
+ const exists = this.$store.getters['i18n/exists'];
201
+
202
+ return exists(col.tooltip) ? this.t(col.tooltip) : col.tooltip;
203
+ },
194
204
  }
195
205
 
196
206
  };
@@ -230,7 +240,7 @@ export default {
230
240
  >
231
241
  <span
232
242
  v-if="col.sort"
233
- v-tooltip="col.tooltip"
243
+ v-tooltip="tooltip(col)"
234
244
  >
235
245
  <span v-html="labelFor(col)" />
236
246
  <i
@@ -252,7 +262,7 @@ export default {
252
262
  </span>
253
263
  <span
254
264
  v-else
255
- v-tooltip="col.tooltip"
265
+ v-tooltip="tooltip(col)"
256
266
  >{{ labelFor(col) }}</span>
257
267
  </div>
258
268
  </th>
@@ -338,7 +348,7 @@ export default {
338
348
  }
339
349
  }
340
350
  .table-options-container {
341
- width: 320px;
351
+ width: 350px;
342
352
  border: 1px solid var(--primary);
343
353
  background-color: var(--body-bg);
344
354
  padding: 20px;
@@ -359,11 +369,10 @@ export default {
359
369
  list-style: none;
360
370
  margin: 0;
361
371
  padding: 0;
362
- display: flex;
363
- flex-wrap: wrap;
372
+ max-height: 200px;
373
+ overflow-y: auto;
364
374
 
365
375
  li {
366
- flex: 1 1 136px;
367
376
  margin: 0;
368
377
  padding: 0;
369
378
 
@@ -405,11 +414,11 @@ export default {
405
414
  color: var(--body-text);
406
415
 
407
416
  .table-header-container {
408
- display: flex;
409
- align-items: center;
417
+ display: inherit;
410
418
 
411
419
  > span {
412
- display: contents;
420
+ display: flex;
421
+ align-items: center;
413
422
  }
414
423
 
415
424
  &.not-filterable {
@@ -476,12 +485,10 @@ export default {
476
485
  }
477
486
  </style>
478
487
  <style lang="scss">
488
+ .table-options-checkbox .checkbox-custom {
489
+ min-width: 14px;
490
+ }
479
491
  .table-options-checkbox .checkbox-label {
480
492
  color: var(--body-text);
481
- text-overflow: ellipsis;
482
- width: 100px;
483
- display: inline-block;
484
- white-space: nowrap;
485
- overflow: hidden;
486
493
  }
487
494
  </style>
@@ -254,7 +254,7 @@ function matches(fields, token, item) {
254
254
  }
255
255
 
256
256
  if ( !modifier ) {
257
- if ( val.includes(token) ) {
257
+ if ( val.includes((`${ token }`).toLowerCase()) ) {
258
258
  return true;
259
259
  }
260
260
  } else if ( modifier === 'exact' ) {