@rancher/shell 0.3.4 → 0.3.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 (246) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +14 -1
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-routes.ts +23 -0
  86. package/creators/app/app.package.json +2 -1
  87. package/creators/app/files/.eslintrc.js +1 -1
  88. package/creators/app/files/babel.config.js +1 -18
  89. package/creators/app/files/vue.config.js +7 -0
  90. package/creators/app/init +5 -5
  91. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  92. package/creators/pkg/init +35 -4
  93. package/creators/update/init +1 -1
  94. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  95. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  96. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  97. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  98. package/detail/workload/index.vue +3 -3
  99. package/dialog/AddClusterMemberDialog.vue +1 -1
  100. package/dialog/AddProjectMemberDialog.vue +2 -2
  101. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  102. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  103. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  104. package/dialog/GenericPrompt.vue +18 -6
  105. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  106. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  107. package/dialog/ScaleMachineDownDialog.vue +1 -1
  108. package/edit/auth/github.vue +8 -8
  109. package/edit/auth/googleoauth.vue +5 -5
  110. package/edit/auth/ldap/index.vue +1 -1
  111. package/edit/auth/oidc.vue +1 -1
  112. package/edit/auth/saml.vue +1 -1
  113. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  114. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  115. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  116. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  117. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  118. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  119. package/edit/management.cattle.io.setting.vue +1 -1
  120. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  121. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  122. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  124. package/edit/namespace.vue +2 -2
  125. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  126. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  127. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  128. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  129. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  130. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  131. package/edit/resources.cattle.io.backup.vue +1 -1
  132. package/edit/service.vue +1 -1
  133. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  134. package/edit/workload/__tests__/Job.test.ts +3 -1
  135. package/edit/workload/index.vue +8 -3
  136. package/edit/workload/mixins/workload.js +16 -0
  137. package/layouts/default.vue +7 -3
  138. package/list/fleet.cattle.io.bundle.vue +6 -3
  139. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  140. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  141. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  142. package/list/node.vue +69 -16
  143. package/list/provisioning.cattle.io.cluster.vue +30 -1
  144. package/machine-config/azure.vue +97 -38
  145. package/middleware/authenticated.js +34 -0
  146. package/mixins/chart.js +73 -2
  147. package/mixins/resource-fetch.js +2 -2
  148. package/models/apps.statefulset.js +28 -0
  149. package/models/cluster/node.js +23 -2
  150. package/models/cluster.x-k8s.io.machine.js +4 -2
  151. package/models/clusterroletemplatebinding.js +7 -0
  152. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  153. package/models/fleet.cattle.io.cluster.js +19 -10
  154. package/models/fleet.cattle.io.gitrepo.js +7 -2
  155. package/models/management.cattle.io.cluster.js +1 -1
  156. package/models/management.cattle.io.fleetworkspace.js +12 -0
  157. package/models/management.cattle.io.gitreporestriction.js +5 -0
  158. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  159. package/models/provisioning.cattle.io.cluster.js +7 -5
  160. package/nuxt/App.js +210 -0
  161. package/nuxt/axios.js +186 -0
  162. package/nuxt/client.js +817 -0
  163. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  164. package/nuxt/components/nuxt-child.js +122 -0
  165. package/nuxt/components/nuxt-error.vue +98 -0
  166. package/nuxt/components/nuxt-link.client.js +98 -0
  167. package/nuxt/components/nuxt-link.server.js +16 -0
  168. package/nuxt/components/nuxt-loading.vue +154 -0
  169. package/nuxt/components/nuxt.js +101 -0
  170. package/nuxt/cookie-universal-nuxt.js +9 -0
  171. package/nuxt/empty.js +1 -0
  172. package/nuxt/index.js +365 -0
  173. package/nuxt/jsonp.js +82 -0
  174. package/nuxt/loading.html +39 -0
  175. package/nuxt/middleware.js +12 -0
  176. package/nuxt/mixins/fetch.client.js +90 -0
  177. package/nuxt/mixins/fetch.server.js +69 -0
  178. package/nuxt/portal-vue.js +4 -0
  179. package/nuxt/server.js +312 -0
  180. package/nuxt/store.js +178 -0
  181. package/nuxt/utils.js +630 -0
  182. package/nuxt/views/app.template.html +9 -0
  183. package/nuxt/views/error.html +23 -0
  184. package/package.json +5 -9
  185. package/pages/auth/setup.vue +2 -2
  186. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  187. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  188. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  189. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  190. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  191. package/pages/c/_cluster/explorer/index.vue +29 -25
  192. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  193. package/pages/c/_cluster/fleet/index.vue +95 -34
  194. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  195. package/pages/c/_cluster/istio/index.vue +5 -5
  196. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  197. package/pages/c/_cluster/monitoring/index.vue +7 -0
  198. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  199. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  201. package/pages/home.vue +9 -4
  202. package/pages/index.vue +10 -1
  203. package/plugins/clean-html-directive.js +31 -0
  204. package/plugins/dashboard-store/actions.js +32 -9
  205. package/plugins/dashboard-store/mutations.js +5 -2
  206. package/plugins/dashboard-store/resource-class.js +8 -1
  207. package/plugins/steve/mutations.js +3 -2
  208. package/plugins/steve/steve-description-class.js +5 -1
  209. package/plugins/steve/subscribe.js +63 -54
  210. package/plugins/steve-create-worker.js +14 -0
  211. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  212. package/promptRemove/management.cattle.io.project.vue +2 -2
  213. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  214. package/promptRemove/pod.vue +1 -1
  215. package/public/index.html +65 -0
  216. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  217. package/rancher-components/components/Banner/Banner.vue +1 -1
  218. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  219. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  220. package/scripts/build-pkg.sh +1 -0
  221. package/scripts/clean +6 -0
  222. package/scripts/extension/bundle +58 -0
  223. package/scripts/extension/helmpatch +89 -0
  224. package/scripts/extension/publish +314 -0
  225. package/scripts/test-plugins-build.sh +4 -0
  226. package/store/__tests__/index.test.ts +110 -0
  227. package/store/index.js +145 -58
  228. package/store/type-map.js +5 -1
  229. package/tsconfig.default.json +36 -0
  230. package/tsconfig.json +24 -0
  231. package/types/shell/index.d.ts +420 -343
  232. package/utils/__tests__/string.test.ts +12 -0
  233. package/utils/auth.js +65 -0
  234. package/utils/monitoring.js +2 -1
  235. package/utils/position.js +5 -8
  236. package/utils/router.scrollBehavior.js +80 -0
  237. package/utils/select.js +1 -3
  238. package/utils/socket.js +1 -0
  239. package/utils/string.js +13 -0
  240. package/utils/time.js +9 -0
  241. package/vue.config.js +679 -0
  242. package/chart/rancher-alerting-drivers.vue +0 -53
  243. package/chart/rancher-gatekeeper.vue +0 -37
  244. package/creators/app/files/nuxt.config.js +0 -6
  245. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  246. package/nuxt.config.js +0 -798
@@ -0,0 +1,75 @@
1
+ import { shallowMount, mount } from '@vue/test-utils';
2
+ import ChartPsp from '@shell/components/ChartPsp.vue';
3
+
4
+ describe('component: ChartPsp', () => {
5
+ it.each([
6
+ true, false
7
+ ])('should render checkbox referencing value.global.cattle.psp.enabled as %p', (value) => {
8
+ const version = 'v1.24.11+rke2r1';
9
+ const wrapper = shallowMount(ChartPsp, {
10
+ propsData: {
11
+ value: { global: { cattle: { psp: { enabled: value } } } },
12
+ cluster: { kubernetesVersion: version }
13
+ }
14
+ });
15
+
16
+ expect(wrapper.findComponent({ name: 'Checkbox' }).props().value).toBe(value);
17
+ });
18
+
19
+ it.each([
20
+ ['v1.24.11+rke2r1'],
21
+ ])('should display the checkbox for cluster with k8s version %p', (version) => {
22
+ const wrapper = shallowMount(ChartPsp, {
23
+ propsData: {
24
+ value: { global: { cattle: { psp: { enabled: false } } } },
25
+ cluster: { kubernetesVersion: version }
26
+ }
27
+ });
28
+
29
+ const input = wrapper.find(`[data-testid="psp-checkbox"]`).element as HTMLInputElement;
30
+
31
+ expect(input).toBeDefined();
32
+ });
33
+
34
+ it.each([
35
+ ['v1.25.11+rke2r1'],
36
+ ])('should not display the checkbox for cluster with k8s version %p', (version) => {
37
+ const wrapper = shallowMount(ChartPsp, {
38
+ propsData: {
39
+ value: { global: { cattle: { psp: { enabled: false } } } },
40
+ cluster: { kubernetesVersion: version }
41
+ }
42
+ });
43
+
44
+ const input = wrapper.find(`[data-testid="psp-checkbox"]`).element as HTMLInputElement;
45
+
46
+ expect(input).toBeUndefined();
47
+ });
48
+
49
+ it('should update value.global.cattle.psp.enabled when checkbox is toggled', async() => {
50
+ const chartValues = { global: {} } as any;
51
+ const version = 'v1.24.11+rke2r1';
52
+ const wrapper = mount(ChartPsp, {
53
+ propsData: {
54
+ value: chartValues,
55
+ cluster: { kubernetesVersion: version }
56
+ }
57
+ });
58
+
59
+ await wrapper.find('.checkbox-container').trigger('click');
60
+
61
+ expect(chartValues.global.cattle.psp.enabled).toBe(true);
62
+
63
+ await wrapper.find('.checkbox-container').trigger('click');
64
+ expect(chartValues.global.cattle.psp.enabled).toBe(false);
65
+ });
66
+
67
+ it.each([
68
+ { global: {} } as any,
69
+ { global: { cattle: {} } } as any,
70
+ ])('should define cattle.psp.enabled and set to false', (chartValues) => {
71
+ shallowMount(ChartPsp, { propsData: { value: chartValues } });
72
+
73
+ expect(chartValues.global.cattle.psp.enabled).toBe(false);
74
+ });
75
+ });
@@ -1,6 +1,7 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import CruResource from '@shell/components/CruResource.vue';
3
3
  import { _EDIT, _YAML } from '@shell/config/query-params';
4
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
4
5
 
5
6
  describe('component: CruResource', () => {
6
7
  it('should hide Cancel button', () => {
@@ -33,7 +34,8 @@ describe('component: CruResource', () => {
33
34
  it('should display multiple errors', () => {
34
35
  const errors = ['mistake!', 'BiG MiStAke11'];
35
36
  const wrapper = mount(CruResource, {
36
- propsData: {
37
+ directives: { cleanHtmlDirective },
38
+ propsData: {
37
39
  canYaml: false,
38
40
  mode: _EDIT,
39
41
  resource: {},
@@ -66,9 +66,9 @@ export default {
66
66
  </div>
67
67
  </div>
68
68
  <div
69
+ v-clean-html="t('principal.loading', null, true)"
69
70
  class="name"
70
71
  :class="{'text-muted': useMuted}"
71
- v-html="t('principal.loading', null, true)"
72
72
  />
73
73
  <div class="description" />
74
74
  </template>
@@ -26,7 +26,9 @@ export default {
26
26
  },
27
27
 
28
28
  async fetch() {
29
- this.allFleet = await this.$store.getters['management/all'](FLEET.CLUSTER);
29
+ if (this.$store.getters['management/schemaFor']( FLEET.CLUSTER )) {
30
+ this.allFleet = await this.$store.getters['management/all'](FLEET.CLUSTER);
31
+ }
30
32
  },
31
33
 
32
34
  data() {
@@ -71,8 +71,7 @@ export default {
71
71
  },
72
72
 
73
73
  pagingParams() {
74
- const inStore = this.$store.getters['currentStore'](FLEET.CLUSTER);
75
- const schema = this.$store.getters[`${ inStore }/schemaFor`](FLEET.CLUSTER);
74
+ const schema = this.$store.getters[`management/schemaFor`](FLEET.CLUSTER);
76
75
 
77
76
  return {
78
77
  singularLabel: this.$store.getters['type-map/labelFor'](schema),
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import { AS, _YAML } from '@shell/config/query-params';
3
+ import { FLEET } from '@shell/config/types';
3
4
 
4
5
  export default {
5
6
 
@@ -18,10 +19,14 @@ export default {
18
19
  query: { [AS]: _YAML },
19
20
  };
20
21
 
22
+ const gitRepoSchema = this.$store.getters['management/schemaFor'](FLEET.GIT_REPO);
23
+ const canCreateRepos = gitRepoSchema && gitRepoSchema.resourceMethods.includes('PUT');
24
+
21
25
  return {
22
26
  formRoute,
23
27
  yamlRoute,
24
28
  hasEditComponent,
29
+ canCreateRepos
25
30
  };
26
31
  },
27
32
  };
@@ -32,7 +37,10 @@ export default {
32
37
  <div class="title">
33
38
  {{ t('fleet.gitRepo.repo.noRepos') }}
34
39
  </div>
35
- <div class="actions">
40
+ <div
41
+ v-if="canCreateRepos"
42
+ class="actions"
43
+ >
36
44
  <n-link
37
45
  :to="formRoute"
38
46
  class="btn role-secondary"
@@ -0,0 +1,62 @@
1
+
2
+ <script>
3
+ import { FLEET } from '@shell/config/types';
4
+ import { NAME } from '@shell/config/product/fleet';
5
+ export default {
6
+ name: 'NoWorkspaces',
7
+
8
+ props: {
9
+ canView: {
10
+ type: Boolean,
11
+ default: false,
12
+ },
13
+ },
14
+ data() {
15
+ const formRoute = {
16
+ name: `c-cluster-product-resource-create`,
17
+ params: { resource: FLEET.WORKSPACE, product: NAME }
18
+ };
19
+
20
+ return { hasWorkspaces: false, formRoute };
21
+ },
22
+ };
23
+ </script>
24
+ <template>
25
+ <div class="intro-box">
26
+ <i class="icon icon-repository" />
27
+ <div class="title">
28
+ <span v-clean-html="t('fleet.gitRepo.repo.noWorkspaces', null, true)" />
29
+ </div>
30
+ <div
31
+ v-if="canView"
32
+ class="actions"
33
+ >
34
+ <n-link
35
+ :to="formRoute"
36
+ class="btn role-secondary"
37
+ >
38
+ {{ t('fleet.gitRepo.workspace.addWorkspace') }}
39
+ </n-link>
40
+ </div>
41
+ </div>
42
+ </template>
43
+ <style lang="scss" scoped>
44
+ .intro-box {
45
+ height: calc(100vh - var(--header-height)*2);
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ flex-direction: column;
50
+ }
51
+
52
+ .title {
53
+ margin-bottom: 15px;
54
+ font-size: $font-size-h2;
55
+ text-align: center;
56
+ max-width: 600px;
57
+ }
58
+ .icon-repository {
59
+ font-size: 96px;
60
+ margin-bottom: 32px;
61
+ }
62
+ </style>
@@ -80,7 +80,12 @@ export default {
80
80
  },
81
81
 
82
82
  bundleCounts() {
83
- const resources = this.bundles.filter(item => item.metadata.name.startsWith(`${ this.repoName }-`)) || [];
83
+ const resources = this.bundles.filter(item => item.metadata.name.startsWith(`${ this.repoName }-`));
84
+
85
+ if (!resources.length) {
86
+ return [];
87
+ }
88
+
84
89
  const out = { ...getResourceDefaultState(this.$store.getters['i18n/withFallback'], this.stateKey) };
85
90
 
86
91
  resources.forEach(({ status, metadata }) => {
@@ -176,6 +181,7 @@ export default {
176
181
  <template>
177
182
  <div class="row flexwrap">
178
183
  <FleetStatus
184
+ v-if="bundleCounts.length"
179
185
  title="Bundles"
180
186
  :values="bundleCounts"
181
187
  value-key="count"
@@ -1,11 +1,11 @@
1
1
  <script>
2
2
  import CompactInput from '@shell/mixins/compact-input';
3
3
  import LabeledFormElement from '@shell/mixins/labeled-form-element';
4
- import { findBy } from '@shell/utils/array';
5
4
  import { get } from '@shell/utils/object';
6
5
  import { LabeledTooltip } from '@components/LabeledTooltip';
7
6
  import VueSelectOverrides from '@shell/mixins/vue-select-overrides';
8
7
  import { onClickOption, calculatePosition } from '@shell/utils/select';
8
+ import isEqual from 'lodash/isEqual';
9
9
 
10
10
  export default {
11
11
  name: 'LabeledSelect',
@@ -105,16 +105,6 @@ export default {
105
105
  hasLabel() {
106
106
  return this.isCompact ? false : !!this.label || !!this.labelKey || !!this.$slots.label;
107
107
  },
108
-
109
- currentLabel() {
110
- const entry = findBy(this.options || [], 'value', this.value);
111
-
112
- if (entry) {
113
- return entry.label;
114
- }
115
-
116
- return this.getOptionLabel(this.value);
117
- },
118
108
  },
119
109
 
120
110
  methods: {
@@ -159,6 +149,19 @@ export default {
159
149
  return;
160
150
  }
161
151
 
152
+ // Force to update the option label if prop has been changed
153
+ const isOutdated = !this.options.find(opt => option[this.optionLabel] === opt[this.optionLabel]);
154
+
155
+ if (isOutdated && this.options) {
156
+ const newOption = this.options.find(opt => isEqual(this.reduce(option), this.reduce(opt)));
157
+
158
+ if (newOption) {
159
+ const label = get(newOption, this.optionLabel);
160
+
161
+ return this.localizedLabel ? this.$store.getters['i18n/t'](label) || label : label;
162
+ }
163
+ }
164
+
162
165
  if (this.$attrs['get-option-label']) {
163
166
  return this.$attrs['get-option-label'](option);
164
167
  }
@@ -35,6 +35,18 @@ export default {
35
35
  default: false,
36
36
  },
37
37
 
38
+ // whether or not to show add rule button at bottom
39
+ showAddButton: {
40
+ type: Boolean,
41
+ default: true
42
+ },
43
+
44
+ // whether or not to show remove rule button right side of the rule
45
+ showRemoveButton: {
46
+ type: Boolean,
47
+ default: true
48
+ },
49
+
38
50
  // whether or not to show remove button in upper right
39
51
  showRemove: {
40
52
  type: Boolean,
@@ -257,7 +269,10 @@ export default {
257
269
  @input="update"
258
270
  >
259
271
  </div>
260
- <div class="remove-container">
272
+ <div
273
+ v-if="showRemoveButton"
274
+ class="remove-container"
275
+ >
261
276
  <button
262
277
  v-if="!isView"
263
278
  type="button"
@@ -272,7 +287,7 @@ export default {
272
287
  </div>
273
288
  </div>
274
289
  <div
275
- v-if="!isView"
290
+ v-if="!isView && showAddButton"
276
291
  class="mt-20"
277
292
  >
278
293
  <button
@@ -20,7 +20,7 @@ export function normalizeName(str) {
20
20
  }
21
21
 
22
22
  export default {
23
- name: 'NameNsDescripiton',
23
+ name: 'NameNsDescription',
24
24
  components: {
25
25
  LabeledInput,
26
26
  LabeledSelect
@@ -169,7 +169,7 @@ export default {
169
169
  if (this.nameKey) {
170
170
  name = get(v, this.nameKey);
171
171
  } else {
172
- name = metadata.name;
172
+ name = metadata?.name;
173
173
  }
174
174
 
175
175
  if (this.namespaced) {
@@ -209,7 +209,7 @@ export default {
209
209
  },
210
210
 
211
211
  computed: {
212
- ...mapGetters(['currentProduct', 'currentCluster']),
212
+ ...mapGetters(['currentProduct', 'currentCluster', 'namespaces', 'allowedNamespaces']),
213
213
  namespaceReallyDisabled() {
214
214
  return (
215
215
  !!this.forceNamespace || this.namespaceDisabled || this.mode === _EDIT
@@ -220,36 +220,18 @@ export default {
220
220
  return this.nameDisabled || (this.mode === _EDIT && !this.nameEditable);
221
221
  },
222
222
 
223
- namespaces() {
224
- const currentStore = this.$store.getters['currentStore'](this.namespaceType);
225
- const namespaces = this.namespacesOverride || this.$store.getters[`${ currentStore }/all`](this.namespaceType);
226
-
227
- const filtered = namespaces.filter( this.namespaceFilter || ((namespace) => {
228
- // By default, include the namespace in the dropdown.
229
- let out = true;
230
-
231
- if (this.currentProduct?.hideSystemResources) {
232
- // Filter out the namespace
233
- // if it is a system namespace or if it is managed by
234
- // Fleet.
235
- out = !namespace.isSystem && !namespace.isFleetManaged;
236
- }
237
-
238
- if (this.mode === _CREATE) {
239
- out = out && !!namespace.links.update;
240
- }
241
-
242
- return out;
243
- }));
244
-
245
- const withLabels = filtered.map(this.namespaceMapper || ((obj) => {
246
- return {
223
+ /**
224
+ * Map namespaces from the store to options, adding divider and create button
225
+ */
226
+ options() {
227
+ const options = Object.keys(this.isCreate ? this.allowedNamespaces() : this.namespaces())
228
+ .map(namespace => ({ nameDisplay: namespace, id: namespace }))
229
+ .map(this.namespaceMapper || (obj => ({
247
230
  label: obj.nameDisplay,
248
231
  value: obj.id,
249
- };
250
- }));
232
+ })));
251
233
 
252
- const sortedByLabel = sortBy(withLabels, 'label');
234
+ const sortedByLabel = sortBy(options, 'label');
253
235
 
254
236
  if (this.forceNamespace) {
255
237
  sortedByLabel.unshift({
@@ -258,29 +240,33 @@ export default {
258
240
  });
259
241
  }
260
242
 
261
- const out = [];
262
-
263
- if (this.canCreateNamespace) {
264
- out.push({
265
- label: this.t('namespace.createNamespace'),
266
- value: '',
267
- kind: 'highlighted'
268
- });
269
- }
270
- out.push({
243
+ const createButton = {
244
+ label: this.t('namespace.createNamespace'),
245
+ value: '',
246
+ kind: 'highlighted'
247
+ };
248
+ const divider = {
271
249
  label: 'divider',
272
250
  disabled: true,
273
251
  kind: 'divider'
274
- },
275
- ...sortedByLabel);
252
+ };
276
253
 
277
- return out;
254
+ const createOverhead = this.canCreateNamespace ? [createButton, divider] : [];
255
+
256
+ return [
257
+ ...createOverhead,
258
+ ...sortedByLabel
259
+ ];
278
260
  },
279
261
 
280
262
  isView() {
281
263
  return this.mode === _VIEW;
282
264
  },
283
265
 
266
+ isCreate() {
267
+ return this.mode === _CREATE;
268
+ },
269
+
284
270
  colSpan() {
285
271
  if (!this.horizontal) {
286
272
  return `span-8`;
@@ -296,7 +282,7 @@ export default {
296
282
 
297
283
  canCreateNamespace() {
298
284
  // Check if user can push to namespaces... and as the ns is outside of a project restrict to admins and cluster owners
299
- return (this.nsSchema?.collectionMethods || []).includes('POST') && this.currentCluster.canUpdate;
285
+ return (this.nsSchema?.collectionMethods || []).includes('POST') && this.currentCluster?.canUpdate;
300
286
  }
301
287
  },
302
288
 
@@ -418,7 +404,7 @@ export default {
418
404
  v-show="!createNamespace"
419
405
  v-model="namespace"
420
406
  :clearable="true"
421
- :options="namespaces"
407
+ :options="options"
422
408
  :disabled="namespaceReallyDisabled"
423
409
  :searchable="true"
424
410
  :mode="mode"
@@ -124,7 +124,7 @@ export default {
124
124
  <div class="row">
125
125
  <div class="col span-12">
126
126
  <Banner :color="(matchingResources.none ? 'warning' : 'success')">
127
- <span v-html="t('generic.selectors.matchingResources.matchesSome', matchingResources)" />
127
+ <span v-clean-html="t('generic.selectors.matchingResources.matchesSome', matchingResources)" />
128
128
  </Banner>
129
129
  </div>
130
130
  </div>
@@ -55,6 +55,10 @@ export default {
55
55
  mode: {
56
56
  type: String,
57
57
  default: _EDIT
58
+ },
59
+ inStore: {
60
+ type: String,
61
+ default: 'cluster',
58
62
  }
59
63
  },
60
64
 
@@ -86,7 +90,7 @@ export default {
86
90
  }
87
91
  },
88
92
  secrets() {
89
- const allSecrets = this.$store.getters['cluster/all'](SECRET);
93
+ const allSecrets = this.$store.getters[`${ this.inStore }/all`](SECRET);
90
94
 
91
95
  return allSecrets
92
96
  .filter(secret => this.types.includes(secret._type) && secret.namespace === this.namespace);
@@ -154,8 +154,8 @@ export default {
154
154
  <template v-if="serviceNameNew">
155
155
  <div class="row span-6">
156
156
  <Banner
157
+ v-clean-html="t('workload.serviceAccountName.createMessage', { name: serviceName }) "
157
158
  color="info"
158
- v-html="t('workload.serviceAccountName.createMessage', { name: serviceName }) "
159
159
  />
160
160
  </div>
161
161
  </template>
@@ -107,18 +107,18 @@ export default {
107
107
  },
108
108
 
109
109
  methods: {
110
- updateSecretName(value) {
111
- if (value === this.none) {
110
+ updateSecretName(e) {
111
+ if (e.value === this.none) {
112
112
  // The key should appear blank if the secret name is cleared
113
113
  this.key = '';
114
114
  }
115
- if (value) {
116
- this.$emit('updateSecretName', value);
115
+ if (e.value) {
116
+ this.$emit('updateSecretName', e.value);
117
117
  }
118
118
  },
119
- updateSecretKey(value) {
120
- if (value) {
121
- this.$emit('updateSecretKey', value);
119
+ updateSecretKey(e) {
120
+ if (e.value) {
121
+ this.$emit('updateSecretKey', e.value);
122
122
  }
123
123
  }
124
124
  }
@@ -135,7 +135,7 @@ export default {
135
135
  :options="secretNames"
136
136
  :label="secretNameLabel"
137
137
  :mode="mode"
138
- @selecting="updateSecretName(name)"
138
+ @selecting="updateSecretName"
139
139
  />
140
140
  <LabeledSelect
141
141
  v-model="key"
@@ -144,7 +144,7 @@ export default {
144
144
  :options="keys"
145
145
  :label="keyNameLabel"
146
146
  :mode="mode"
147
- @selecting="updateSecretKey(key)"
147
+ @selecting="updateSecretKey"
148
148
  />
149
149
  </div>
150
150
  </div>