@rancher/shell 0.3.4 → 0.3.6

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/images/providers/outscale.svg +19 -0
  2. package/assets/styles/app.scss +1 -1
  3. package/assets/styles/base/_basic.scss +18 -0
  4. package/assets/styles/base/_mixins.scss +0 -11
  5. package/assets/styles/base/_variables.scss +2 -4
  6. package/assets/styles/fonts/_fontstack.scss +11 -11
  7. package/assets/styles/global/_button.scss +12 -2
  8. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  9. package/assets/translations/en-us.yaml +113 -22
  10. package/assets/translations/zh-hans.yaml +113 -24
  11. package/babel.config.js +13 -0
  12. package/chart/gatekeeper.vue +78 -0
  13. package/chart/istio.vue +135 -112
  14. package/chart/logging/index.vue +13 -4
  15. package/chart/monitoring/index.vue +15 -5
  16. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  17. package/chart/rancher-backup/index.vue +10 -3
  18. package/cloud-credential/aws.vue +1 -1
  19. package/cloud-credential/digitalocean.vue +1 -1
  20. package/cloud-credential/gcp.vue +1 -1
  21. package/cloud-credential/generic.vue +2 -2
  22. package/cloud-credential/linode.vue +1 -1
  23. package/cloud-credential/pnap.vue +1 -1
  24. package/components/ActionMenu.vue +3 -4
  25. package/components/AssignTo.vue +1 -1
  26. package/components/AsyncButton.vue +1 -1
  27. package/components/BannerGraphic.vue +1 -1
  28. package/components/BrandImage.vue +1 -4
  29. package/components/ButtonDropdown.vue +2 -3
  30. package/components/Carousel.vue +85 -37
  31. package/components/ChartPsp.vue +76 -0
  32. package/components/CruResource.vue +6 -2
  33. package/components/DashboardMetrics.vue +12 -10
  34. package/components/DetailText.vue +1 -1
  35. package/components/DisableAuthProviderModal.vue +1 -1
  36. package/components/EmberPage.vue +1 -1
  37. package/components/EtcdInfoBanner.vue +12 -7
  38. package/components/ExplorerMembers.vue +101 -6
  39. package/components/ExplorerProjectsNamespaces.vue +46 -3
  40. package/components/FileDiff.vue +6 -7
  41. package/components/GrafanaDashboard.vue +27 -23
  42. package/components/LazyImage.vue +10 -12
  43. package/components/LogItem.vue +1 -1
  44. package/components/Markdown.vue +1 -1
  45. package/components/PromptRemove.vue +2 -2
  46. package/components/PromptRestore.vue +1 -1
  47. package/components/ResourceDetail/Masthead.vue +16 -0
  48. package/components/ResourceDetail/index.vue +21 -4
  49. package/components/ResourceList/index.vue +1 -1
  50. package/components/ResourceTable.vue +4 -1
  51. package/components/SingleClusterInfo.vue +2 -2
  52. package/components/SortableTable/THead.vue +1 -1
  53. package/components/SortableTable/index.vue +28 -13
  54. package/components/SortableTable/selection.js +58 -50
  55. package/components/Wizard.vue +4 -2
  56. package/components/__tests__/AsyncButton.test.ts +3 -1
  57. package/components/__tests__/ChartPsp.test.ts +75 -0
  58. package/components/__tests__/CruResource.test.ts +3 -1
  59. package/components/auth/Principal.vue +1 -1
  60. package/components/auth/RoleDetailEdit.vue +2 -2
  61. package/components/fleet/FleetBundles.vue +3 -1
  62. package/components/fleet/FleetClusters.vue +1 -2
  63. package/components/fleet/FleetIntro.vue +9 -1
  64. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  65. package/components/fleet/FleetSummary.vue +7 -1
  66. package/components/form/HookOption.vue +14 -10
  67. package/components/form/LabeledSelect.vue +14 -11
  68. package/components/form/Labels.vue +32 -27
  69. package/components/form/MatchExpressions.vue +19 -4
  70. package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
  71. package/components/form/NameNsDescription.vue +32 -46
  72. package/components/form/ProjectMemberEditor.vue +46 -21
  73. package/components/form/ResourceSelector.vue +1 -1
  74. package/components/form/SecretSelector.vue +5 -1
  75. package/components/form/ServiceNameSelect.vue +1 -1
  76. package/components/form/SimpleSecretSelector.vue +9 -9
  77. package/components/form/Tolerations.vue +4 -1
  78. package/components/form/ValueFromResource.vue +14 -9
  79. package/components/form/WorkloadPorts.vue +2 -2
  80. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  81. package/components/form/__tests__/NameNsDescription.ts +59 -0
  82. package/components/formatter/InternalExternalIP.vue +6 -0
  83. package/components/formatter/InvolvedObjectLink.vue +54 -0
  84. package/components/formatter/Link.vue +20 -4
  85. package/components/formatter/LinkName.vue +6 -1
  86. package/components/formatter/ServiceTargets.vue +1 -1
  87. package/components/formatter/WorkloadHealthScale.vue +8 -2
  88. package/components/nav/Group.vue +2 -2
  89. package/components/nav/NamespaceFilter.vue +23 -11
  90. package/components/nav/TopLevelMenu.vue +2 -4
  91. package/components/nav/Type.vue +1 -1
  92. package/components/nav/WorkspaceSwitcher.vue +46 -5
  93. package/components/nuxt/nuxt-build-indicator.vue +143 -0
  94. package/components/nuxt/nuxt-child.js +122 -0
  95. package/components/nuxt/nuxt-error.vue +98 -0
  96. package/components/nuxt/nuxt-link.client.js +98 -0
  97. package/components/nuxt/nuxt-link.server.js +16 -0
  98. package/components/nuxt/nuxt-loading.vue +154 -0
  99. package/components/nuxt/nuxt.js +101 -0
  100. package/config/labels-annotations.js +17 -0
  101. package/config/middleware.js +12 -0
  102. package/config/product/auth.js +3 -2
  103. package/config/product/explorer.js +34 -6
  104. package/config/product/fleet.js +2 -0
  105. package/config/query-params.js +1 -0
  106. package/config/router.js +414 -0
  107. package/config/store.js +181 -0
  108. package/config/table-headers.js +54 -12
  109. package/config/types.js +18 -8
  110. package/config/uiplugins.js +30 -0
  111. package/content/docs/en-us/whats-new.md +10 -0
  112. package/content/docs/zh-hans/whats-new.md +11 -1
  113. package/core/plugin-routes.ts +23 -0
  114. package/core/plugin.ts +4 -2
  115. package/core/types.ts +258 -1
  116. package/creators/app/app.package.json +2 -1
  117. package/creators/app/files/.eslintrc.js +1 -1
  118. package/creators/app/files/babel.config.js +1 -18
  119. package/creators/app/files/tsconfig.json +0 -1
  120. package/creators/app/files/vue.config.js +6 -0
  121. package/creators/app/init +5 -5
  122. package/creators/pkg/files/.github/workflows/build-extension.yml +110 -0
  123. package/creators/pkg/files/tsconfig.json +0 -1
  124. package/creators/pkg/init +35 -4
  125. package/creators/pkg/pkg.package.json +3 -3
  126. package/creators/update/init +1 -1
  127. package/detail/constraints.gatekeeper.sh.constraint.vue +34 -17
  128. package/detail/fleet.cattle.io.clustergroup.vue +7 -1
  129. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  130. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  131. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  132. package/detail/workload/index.vue +3 -3
  133. package/dialog/AddClusterMemberDialog.vue +1 -1
  134. package/dialog/AddProjectMemberDialog.vue +2 -2
  135. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  136. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  137. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  138. package/dialog/GenericPrompt.vue +18 -6
  139. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  140. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  141. package/dialog/ScaleMachineDownDialog.vue +1 -1
  142. package/edit/auth/github.vue +8 -8
  143. package/edit/auth/googleoauth.vue +5 -5
  144. package/edit/auth/ldap/index.vue +1 -1
  145. package/edit/auth/oidc.vue +1 -1
  146. package/edit/auth/saml.vue +1 -1
  147. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  148. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  149. package/edit/fleet.cattle.io.gitrepo.vue +32 -4
  150. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  151. package/edit/logging.banzaicloud.io.output/index.vue +18 -5
  152. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
  153. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  154. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  155. package/edit/management.cattle.io.setting.vue +1 -1
  156. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  157. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  158. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  159. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  160. package/edit/namespace.vue +14 -10
  161. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  162. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +21 -4
  164. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  165. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  166. package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
  167. package/edit/provisioning.cattle.io.cluster/rke2.vue +344 -102
  168. package/edit/resources.cattle.io.backup.vue +1 -1
  169. package/edit/service.vue +1 -1
  170. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  171. package/edit/workload/__tests__/Job.test.ts +3 -1
  172. package/edit/workload/index.vue +8 -3
  173. package/edit/workload/mixins/workload.js +22 -7
  174. package/edit/workload/storage/Mount.vue +3 -3
  175. package/initialize/App.js +206 -0
  176. package/initialize/client.js +863 -0
  177. package/initialize/index.js +364 -0
  178. package/layouts/default.vue +7 -3
  179. package/layouts/standalone.vue +13 -0
  180. package/list/catalog.cattle.io.clusterrepo.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +6 -3
  182. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  183. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  184. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  185. package/list/node.vue +69 -16
  186. package/list/provisioning.cattle.io.cluster.vue +30 -1
  187. package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
  188. package/list/workload.vue +6 -4
  189. package/machine-config/azure.vue +97 -38
  190. package/middleware/authenticated.js +34 -0
  191. package/mixins/chart.js +101 -2
  192. package/mixins/fetch.client.js +95 -0
  193. package/mixins/fetch.server.js +73 -0
  194. package/mixins/labeled-form-element.ts +2 -2
  195. package/mixins/resource-fetch.js +2 -2
  196. package/models/apps.statefulset.js +28 -0
  197. package/models/cluster/node.js +23 -2
  198. package/models/cluster.x-k8s.io.machine.js +4 -2
  199. package/models/clusterroletemplatebinding.js +7 -0
  200. package/models/constraints.gatekeeper.sh.constraint.js +46 -0
  201. package/models/fleet.cattle.io.cluster.js +19 -10
  202. package/models/fleet.cattle.io.gitrepo.js +7 -2
  203. package/models/management.cattle.io.cluster.js +1 -1
  204. package/models/management.cattle.io.fleetworkspace.js +12 -0
  205. package/models/management.cattle.io.gitreporestriction.js +5 -0
  206. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  207. package/models/pod.js +4 -0
  208. package/models/provisioning.cattle.io.cluster.js +7 -5
  209. package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
  210. package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
  211. package/package.json +13 -21
  212. package/pages/auth/setup.vue +2 -2
  213. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  214. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  215. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  216. package/pages/c/_cluster/apps/charts/install.vue +98 -102
  217. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  218. package/pages/c/_cluster/explorer/index.vue +29 -25
  219. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  220. package/pages/c/_cluster/fleet/index.vue +95 -34
  221. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  222. package/pages/c/_cluster/istio/index.vue +5 -5
  223. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  224. package/pages/c/_cluster/monitoring/index.vue +7 -0
  225. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  226. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  227. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  228. package/pages/diagnostic.vue +32 -25
  229. package/pages/home.vue +9 -4
  230. package/pages/index.vue +10 -1
  231. package/pages/rio/mesh.vue +1 -2
  232. package/pkg/tsconfig.json +0 -1
  233. package/plugins/clean-html-directive.js +34 -0
  234. package/plugins/dashboard-store/actions.js +32 -9
  235. package/plugins/dashboard-store/index.js +1 -1
  236. package/plugins/dashboard-store/mutations.js +5 -2
  237. package/plugins/dashboard-store/resource-class.js +8 -1
  238. package/plugins/plugin.js +0 -14
  239. package/plugins/portal-vue.js +4 -0
  240. package/plugins/steve/mutations.js +3 -2
  241. package/plugins/steve/steve-description-class.js +5 -1
  242. package/plugins/steve/subscribe.js +63 -54
  243. package/plugins/steve-create-worker.js +14 -0
  244. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  245. package/promptRemove/management.cattle.io.project.vue +2 -2
  246. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  247. package/promptRemove/pod.vue +1 -1
  248. package/public/index.html +65 -0
  249. package/rancher-components/components/Banner/Banner.test.ts +7 -1
  250. package/rancher-components/components/Banner/Banner.vue +2 -1
  251. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  252. package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
  253. package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
  254. package/scripts/build-pkg.sh +1 -0
  255. package/scripts/clean +6 -0
  256. package/scripts/extension/bundle +58 -0
  257. package/scripts/extension/helmpatch +89 -0
  258. package/scripts/extension/publish +333 -0
  259. package/scripts/serve-pkgs +6 -2
  260. package/scripts/test-plugins-build.sh +4 -0
  261. package/store/__tests__/index.test.ts +110 -0
  262. package/store/index.js +145 -58
  263. package/store/type-map.js +6 -2
  264. package/tsconfig.default.json +36 -0
  265. package/tsconfig.json +23 -0
  266. package/types/rancher/index.d.ts +2 -0
  267. package/types/shell/index.d.ts +466 -320
  268. package/utils/__tests__/grafana.test.ts +44 -0
  269. package/utils/__tests__/string.test.ts +12 -0
  270. package/utils/auth.js +65 -0
  271. package/utils/axios.js +190 -0
  272. package/utils/cookie-universal-nuxt.js +10 -0
  273. package/utils/dom.js +15 -0
  274. package/utils/grafana.js +35 -16
  275. package/utils/monitoring.js +2 -1
  276. package/utils/nuxt.js +659 -0
  277. package/utils/position.js +5 -8
  278. package/utils/router.scrollBehavior.js +80 -0
  279. package/utils/select.js +1 -3
  280. package/utils/socket.js +1 -0
  281. package/utils/string.js +13 -0
  282. package/utils/time.js +9 -0
  283. package/vue.config.js +690 -0
  284. package/chart/rancher-alerting-drivers.vue +0 -53
  285. package/chart/rancher-gatekeeper.vue +0 -37
  286. package/creators/app/files/nuxt.config.js +0 -6
  287. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  288. package/nuxt.config.js +0 -798
  289. package/plugins/dashboard-store/extensions.js +0 -22
@@ -0,0 +1,138 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
3
+
4
+ describe('component: LabeledSelect', () => {
5
+ describe('should display correct label', () => {
6
+ it('given an existing value and option', () => {
7
+ const label = 'Foo';
8
+ const value = 'foo';
9
+ const wrapper = mount(LabeledSelect, {
10
+ propsData: {
11
+ value,
12
+ options: [
13
+ { label, value },
14
+ ],
15
+ }
16
+ });
17
+
18
+ // Component is from a library and class is not going to be changed
19
+ expect(wrapper.find('.vs__selected').text()).toBe(label);
20
+ });
21
+
22
+ it('using value as label if no options', () => {
23
+ const value = 'foo';
24
+ const wrapper = mount(LabeledSelect, {
25
+ propsData: {
26
+ value,
27
+ options: [],
28
+ }
29
+ });
30
+
31
+ // Component is from a library and class is not going to be changed
32
+ expect(wrapper.find('.vs__selected').text()).toBe(value);
33
+ });
34
+
35
+ it('using custom key as label for option object', () => {
36
+ const value = 'foo';
37
+ const label = 'Foo';
38
+ const customLabelKey = 'bananas';
39
+ const wrapper = mount(LabeledSelect, {
40
+ propsData: {
41
+ value,
42
+ optionLabel: customLabelKey,
43
+ options: [{
44
+ [customLabelKey]: label,
45
+ value
46
+ }],
47
+ }
48
+ });
49
+
50
+ // Component is from a library and class is not going to be changed
51
+ expect(wrapper.find('.vs__selected').text()).toBe(label);
52
+ });
53
+
54
+ it('translating localized cases', () => {
55
+ const value = 'foo';
56
+ const translation = 'bananas';
57
+ const wrapper = mount(LabeledSelect, {
58
+ propsData: {
59
+ localizedLabel: true,
60
+ value,
61
+ options: [{ label: 'whatever', value }],
62
+ },
63
+ mocks: { $store: { getters: { 'i18n/t': () => translation } } }
64
+ });
65
+
66
+ // Component is from a library and class is not going to be changed
67
+ expect(wrapper.find('.vs__selected').text()).toBe(translation);
68
+ });
69
+
70
+ describe('updating the value on options change', () => {
71
+ it('using new label', async() => {
72
+ const value = 'foo';
73
+ const oldLabel = 'Foo';
74
+ const newLabel = 'Baz';
75
+ const wrapper = mount(LabeledSelect, {
76
+ propsData: {
77
+ value,
78
+ options: [
79
+ { label: oldLabel, value },
80
+ ],
81
+ }
82
+ });
83
+
84
+ await wrapper.setProps({
85
+ options: [
86
+ { label: newLabel, value },
87
+ ]
88
+ });
89
+
90
+ // Component is from a library and class is not going to be changed
91
+ expect(wrapper.find('.vs__selected').text()).toBe(newLabel);
92
+ });
93
+
94
+ it('using values only and no labels', async() => {
95
+ const value = 'foo';
96
+ const newValue = 'bananas';
97
+ const wrapper = mount(LabeledSelect, {
98
+ propsData: {
99
+ value,
100
+ options: [value],
101
+ }
102
+ });
103
+
104
+ await wrapper.setProps({ options: [newValue] });
105
+
106
+ // Component is from a library and class is not going to be changed
107
+ expect(wrapper.find('.vs__selected').text()).toBe(value);
108
+ });
109
+
110
+ it('using translated value', async() => {
111
+ const value = 'foo';
112
+ const oldLabel = 'Foo';
113
+ const newLabel = 'Baz';
114
+ const translation = 'bananas';
115
+ const i18nMap: Record<string, string> = { [newLabel]: translation };
116
+ const wrapper = mount(LabeledSelect, {
117
+ propsData: {
118
+ value,
119
+ localizedLabel: true,
120
+ options: [
121
+ { label: oldLabel, value },
122
+ ],
123
+ },
124
+ mocks: { $store: { getters: { 'i18n/t': (text: string) => i18nMap[text] } } }
125
+ });
126
+
127
+ await wrapper.setProps({
128
+ options: [
129
+ { label: newLabel, value },
130
+ ]
131
+ });
132
+
133
+ // Component is from a library and class is not going to be changed
134
+ expect(wrapper.find('.vs__selected').text()).toBe(translation);
135
+ });
136
+ });
137
+ });
138
+ });
@@ -0,0 +1,59 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import NameNsDescription from '@shell/components/form/NameNsDescription.vue';
3
+
4
+ describe('component: NameNsDescription', () => {
5
+ // Accessing to computed value due code complexity
6
+ it('should map namespaces to options', () => {
7
+ const namespaceName = 'test';
8
+ const result = [{
9
+ label: namespaceName,
10
+ value: namespaceName
11
+ }];
12
+ const wrapper = mount(NameNsDescription, {
13
+ propsData: {
14
+ value: {},
15
+ mode: 'create',
16
+ },
17
+ mocks: {
18
+ $store: {
19
+ getters: {
20
+ namespaces: jest.fn(),
21
+ allowedNamespaces: () => ({ [namespaceName]: true }),
22
+ currentStore: () => 'cluster',
23
+ 'cluster/schemaFor': jest.fn(),
24
+ 'i18n/t': jest.fn()
25
+ },
26
+ },
27
+ }
28
+ });
29
+
30
+ expect((wrapper.vm as any).options).toStrictEqual(result);
31
+ });
32
+
33
+ it('should emit in case of new namespace', () => {
34
+ const namespaceName = 'test';
35
+ const newNamespaceName = 'bananas';
36
+ const wrapper = mount(NameNsDescription, {
37
+ propsData: {
38
+ value: { metadata: {} },
39
+ mode: 'create',
40
+ },
41
+ mocks: {
42
+ $store: {
43
+ getters: {
44
+ namespaces: jest.fn(),
45
+ allowedNamespaces: () => ({ [namespaceName]: true }),
46
+ currentStore: () => 'cluster',
47
+ 'cluster/schemaFor': jest.fn(),
48
+ 'i18n/t': jest.fn()
49
+ },
50
+ },
51
+ $refs: { name: { focus: jest.fn() } }
52
+ }
53
+ });
54
+
55
+ (wrapper.vm as any).updateNamespace(newNamespaceName);
56
+
57
+ expect(wrapper.emitted().isNamespaceNew?.[0][0]).toBe(true);
58
+ });
59
+ });
@@ -56,3 +56,9 @@ export default {
56
56
  </template>
57
57
  </span>
58
58
  </template>
59
+
60
+ <style lang='scss' scoped>
61
+ .icon-btn {
62
+ margin-left: 8px;
63
+ }
64
+ </style>
@@ -0,0 +1,54 @@
1
+ <script>
2
+
3
+ import LinkName from '@shell/components/formatter/LinkName.vue';
4
+ import { NAME as EXPLORER } from '@shell/config/product/explorer';
5
+
6
+ export default {
7
+ components: { LinkName },
8
+
9
+ props: {
10
+ value: {
11
+ type: null,
12
+ required: true
13
+ },
14
+ product: {
15
+ type: String,
16
+ default: EXPLORER,
17
+ }
18
+ },
19
+
20
+ computed: {
21
+ kind() {
22
+ // this cover most of the usecases for events
23
+ if (this.value?.apiVersion && typeof this.value?.apiVersion === 'string') {
24
+ const versionParts = this.value.apiVersion.split('/');
25
+
26
+ if (versionParts.length === 1) {
27
+ return this.value.kind.toLowerCase();
28
+ }
29
+
30
+ return `${ versionParts[0] }.${ this.value.kind.toLowerCase() }`;
31
+ // covers Node events usecase
32
+ } else if (this.value?.kind && typeof this.value?.kind === 'string') {
33
+ return this.value?.kind.toLowerCase();
34
+ }
35
+
36
+ return '';
37
+ }
38
+ }
39
+ };
40
+ </script>
41
+
42
+ <template>
43
+ <span v-if="kind && value.kind && value.name">
44
+ <LinkName
45
+ :type="kind"
46
+ :value="`${value.kind} ${value.name}`"
47
+ :object-id="value.name"
48
+ :namespace="value.namespace"
49
+ :product="product"
50
+ :show-type="true"
51
+ />
52
+ </span>
53
+ <span v-else />
54
+ </template>
@@ -138,17 +138,18 @@ export default {
138
138
  <n-link
139
139
  v-if="isInternal && href"
140
140
  :to="href"
141
+ class="link-text-icon"
141
142
  >
142
143
  <i
143
144
  v-if="beforeIconClass"
144
145
  :class="beforeIconClass"
145
- style="position: relative; top: -2px;"
146
+ class="prefix"
146
147
  />
147
148
  {{ label }}
148
149
  <i
149
150
  v-if="afterIconClass"
150
151
  :class="afterIconClass"
151
- style="position: relative; top: -2px;"
152
+ class="suffix"
152
153
  />
153
154
  </n-link>
154
155
  <a
@@ -156,18 +157,33 @@ export default {
156
157
  :href="href"
157
158
  :rel="rel"
158
159
  :target="target"
160
+ class="link-text-icon"
159
161
  >
160
162
  <i
161
163
  v-if="beforeIconClass"
162
164
  :class="beforeIconClass"
163
- style="position: relative; top: -2px;"
165
+ class="prefix"
164
166
  />
165
167
  {{ label }}
166
168
  <i
167
169
  v-if="afterIconClass"
168
170
  :class="afterIconClass"
169
- style="position: relative; top: -2px;"
171
+ class="suffix"
170
172
  />
171
173
  </a>
172
174
  <span v-else> {{ href }} {{ label }}</span>
173
175
  </template>
176
+ <style lang="scss" scoped>
177
+ .link-text-icon {
178
+ display: flex;
179
+ align-items: top;
180
+
181
+ .prefix {
182
+ margin: 2px 2px 0 0;
183
+ }
184
+
185
+ .suffix {
186
+ margin: 2px 0 0 2px;
187
+ }
188
+ }
189
+ </style>
@@ -18,6 +18,11 @@ export default {
18
18
  default: '',
19
19
  },
20
20
 
21
+ objectId: {
22
+ type: String,
23
+ default: '',
24
+ },
25
+
21
26
  product: {
22
27
  type: String,
23
28
  default: EXPLORER,
@@ -31,7 +36,7 @@ export default {
31
36
  const params = {
32
37
  resource: this.type,
33
38
  namespace: this.namespace,
34
- id: this.value,
39
+ id: this.objectId ? this.objectId : this.value,
35
40
  product: this.product || EXPLORER,
36
41
  };
37
42
 
@@ -115,7 +115,7 @@ export default {
115
115
  :key="index"
116
116
  class="text-small"
117
117
  >
118
- <span v-html="port.label" />
118
+ <span v-clean-html="port.label" />
119
119
  </div>
120
120
  </div>
121
121
  </template>
@@ -2,10 +2,11 @@
2
2
  import Vue from 'vue';
3
3
  import ProgressBarMulti from '@shell/components/ProgressBarMulti';
4
4
  import PlusMinus from '@shell/components/form/PlusMinus';
5
- import { SCALABLE_WORKLOAD_TYPES } from '@shell/config/types';
5
+ import { POD, SCALABLE_WORKLOAD_TYPES } from '@shell/config/types';
6
6
  import { ucFirst } from '@shell/utils/string';
7
7
 
8
8
  const SCALABLE_TYPES = Object.values(SCALABLE_WORKLOAD_TYPES);
9
+ const INVALID_TYPES = [POD];
9
10
 
10
11
  export default {
11
12
  components: { PlusMinus, ProgressBarMulti },
@@ -47,6 +48,10 @@ export default {
47
48
  return !!SCALABLE_TYPES.includes(this.row.type) && this.row.canUpdate;
48
49
  },
49
50
 
51
+ canShow() {
52
+ return !INVALID_TYPES.includes(this.row.type);
53
+ },
54
+
50
55
  parts() {
51
56
  return this.cParts;
52
57
  },
@@ -162,8 +167,9 @@ export default {
162
167
  </script>
163
168
 
164
169
  <template>
170
+ <div v-if="!canShow" />
165
171
  <div
166
- v-if="loading"
172
+ v-else-if="loading"
167
173
  class="hs-popover__loader"
168
174
  >
169
175
  <i class="icon icon-spinner" />
@@ -202,11 +202,11 @@ export default {
202
202
  :to="group.children[0].route"
203
203
  :exact="group.children[0].exact"
204
204
  >
205
- <h6 v-html="group.labelDisplay || group.label" />
205
+ <h6 v-clean-html="group.labelDisplay || group.label" />
206
206
  </n-link>
207
207
  <h6
208
208
  v-else
209
- v-html="group.labelDisplay || group.label"
209
+ v-clean-html="group.labelDisplay || group.label"
210
210
  />
211
211
  </slot>
212
212
  <i
@@ -105,13 +105,27 @@ export default {
105
105
  const t = this.$store.getters['i18n/t'];
106
106
  let out = [];
107
107
 
108
+ const params = { ...this.$route.params };
109
+ const resource = params.resource;
110
+ // Sometimes, different pages may have different namespaces to filter
111
+ const notFilterNamespaces = this.$store.getters[`type-map/optionsFor`](resource).notFilterNamespace || [];
112
+
108
113
  // TODO: Add return info
109
114
  if (this.currentProduct?.customNamespaceFilter && this.currentProduct?.inStore) {
110
115
  // Sometimes the component can show before the 'currentProduct' has caught up, so access the product via the getter rather
111
116
  // than caching it in the `fetch`
117
+
118
+ // The namespace display on the list and edit pages should be the same as in the namespaceFilter component
119
+ if (this.$store.getters[`${ this.currentProduct.inStore }/filterNamespace`]) {
120
+ const allNamespaces = this.$store.getters[`${ this.currentProduct.inStore }/filterNamespace`](notFilterNamespaces);
121
+
122
+ this.$store.commit('changeAllNamespaces', allNamespaces);
123
+ }
124
+
112
125
  return this.$store.getters[`${ this.currentProduct.inStore }/namespaceFilterOptions`]({
113
126
  addNamespace,
114
- divider
127
+ divider,
128
+ notFilterNamespaces
115
129
  });
116
130
  }
117
131
 
@@ -371,17 +385,7 @@ export default {
371
385
  return namespaces;
372
386
  }
373
387
 
374
- const isVirtualCluster = this.$store.getters['isVirtualCluster'];
375
-
376
388
  return namespaces.filter((namespace) => {
377
- const isSettingSystemNamespace = this.$store.getters['systemNamespaces'].includes(namespace.metadata.name);
378
- const systemNS = namespace.isSystem || namespace.isFleetManaged || isSettingSystemNamespace;
379
-
380
- // For Harvester, filter out system namespaces AND obscure namespaces.
381
- if (isVirtualCluster) {
382
- return !systemNS && !namespace.isObscure;
383
- }
384
-
385
389
  // Otherwise only filter out obscure namespaces, such as namespaces
386
390
  // that Rancher uses to manage RBAC for projects, which should not be
387
391
  // edited or deleted by Rancher users.
@@ -949,6 +953,14 @@ export default {
949
953
  color: var(--dropdown-hover-bg);
950
954
  }
951
955
  }
956
+
957
+ &:focus {
958
+ .ns-item {
959
+ > * {
960
+ color: var(--dropdown-hover-text);
961
+ }
962
+ }
963
+ }
952
964
  }
953
965
  }
954
966
 
@@ -3,7 +3,6 @@ import BrandImage from '@shell/components/BrandImage';
3
3
  import ClusterProviderIcon from '@shell/components/ClusterProviderIcon';
4
4
  import IconOrSvg from '../IconOrSvg';
5
5
  import { mapGetters } from 'vuex';
6
- import $ from 'jquery';
7
6
  import { CAPI, MANAGEMENT } from '@shell/config/types';
8
7
  import { mapPref, MENU_MAX_CLUSTERS } from '@shell/store/prefs';
9
8
  import { sortBy } from '@shell/utils/sort';
@@ -188,11 +187,10 @@ export default {
188
187
  const max = Math.min(maxToShow, this.clusters.length);
189
188
 
190
189
  if (el) {
191
- const $el = $(el);
192
190
  const h = 33 * max;
193
191
 
194
- $el.css('min-height', `${ h }px`);
195
- $el.css('max-height', `${ h }px`);
192
+ el.style.minHeight = `${ h }px`;
193
+ el.style.maxHeight = `${ h }px`;
196
194
  }
197
195
  },
198
196
  handler(e) {
@@ -90,9 +90,9 @@ export default {
90
90
  ><t :k="type.labelKey" /></span>
91
91
  <span
92
92
  v-else
93
+ v-clean-html="type.labelDisplay || type.label"
93
94
  class="label"
94
95
  :class="{'no-icon': !type.icon}"
95
- v-html="type.labelDisplay || type.label"
96
96
  />
97
97
  <span
98
98
  v-if="showFavorite || showCount"
@@ -1,17 +1,19 @@
1
1
  <script>
2
- import { WORKSPACE } from '@shell/store/prefs';
2
+ import { LAST_NAMESPACE, WORKSPACE } from '@shell/store/prefs';
3
3
  import { mapState } from 'vuex';
4
4
  import Select from '@shell/components/form/Select';
5
+ import { WORKSPACE_ANNOTATION } from '@shell/config/labels-annotations';
5
6
 
6
7
  export default {
8
+ name: 'WorkspaceSwitcher',
7
9
  components: { Select },
8
10
 
9
11
  computed: {
10
- ...mapState(['allWorkspaces', 'workspace']),
12
+ ...mapState(['allWorkspaces', 'workspace', 'allNamespaces', 'defaultNamespace', 'getActiveNamespaces']),
11
13
 
12
14
  value: {
13
15
  get() {
14
- return this.workspace;
16
+ return this.workspace || this.namespace || this.options[0]?.value;
15
17
  },
16
18
 
17
19
  set(value) {
@@ -23,17 +25,56 @@ export default {
23
25
  },
24
26
 
25
27
  options() {
26
- const out = this.allWorkspaces.map((obj) => {
28
+ if (this.allWorkspaces.length) {
29
+ const out = this.allWorkspaces.map((obj) => {
30
+ return {
31
+ label: obj.nameDisplay,
32
+ value: obj.id,
33
+ };
34
+ });
35
+
36
+ return out;
37
+ }
38
+
39
+ // If doesn't have workspaces (e.g. no permissions)
40
+ // Then find the workspaces from the annotation.
41
+ return this.allNamespaces.filter((item) => {
42
+ return item.metadata.annotations[WORKSPACE_ANNOTATION] === WORKSPACE;
43
+ }).map((obj) => {
27
44
  return {
28
45
  label: obj.nameDisplay,
29
46
  value: obj.id,
30
47
  };
31
48
  });
49
+ },
50
+ },
51
+
52
+ watch: {
53
+ options(curr, prev) {
54
+ if (curr.length === 0) {
55
+ this.value = '';
56
+ }
32
57
 
33
- return out;
58
+ const currentExists = curr.find(item => item.value === this.value);
59
+
60
+ if (curr.length && !currentExists) {
61
+ this.value = curr[0]?.value;
62
+ }
34
63
  },
35
64
  },
36
65
 
66
+ created() {
67
+ // in fleet standard user with just the project owner and global git repo permissions
68
+ // returns 'default'
69
+ const initValue = !this.workspace ? this.$store.getters['prefs/get'](LAST_NAMESPACE) : '';
70
+
71
+ this.value = (initValue === 'default' || initValue === '') && this.options.length ? this.options[0].value : initValue;
72
+ },
73
+
74
+ data() {
75
+ return { namespace: this.$store.getters['prefs/get'](LAST_NAMESPACE) };
76
+ },
77
+
37
78
  methods: {
38
79
  focus() {
39
80
  this.$refs.select.$refs.search.focus();