@rancher/shell 3.0.4 → 3.0.5-rc.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 (270) hide show
  1. package/assets/images/providers/sks.svg +1 -0
  2. package/assets/styles/base/_basic.scss +6 -0
  3. package/assets/styles/base/_helpers.scss +4 -0
  4. package/assets/styles/base/_variables.scss +1 -0
  5. package/assets/styles/global/_button.scss +1 -0
  6. package/assets/translations/en-us.yaml +65 -15
  7. package/assets/translations/zh-hans.yaml +4 -3
  8. package/chart/monitoring/index.vue +3 -1
  9. package/cloud-credential/aws.vue +2 -0
  10. package/components/ActionDropdownShell.vue +71 -0
  11. package/components/AppModal.vue +18 -4
  12. package/components/AsyncButton.vue +24 -7
  13. package/components/BannerGraphic.vue +1 -0
  14. package/components/CommunityLinks.vue +4 -59
  15. package/components/CopyToClipboardText.vue +2 -1
  16. package/components/CruResource.vue +6 -1
  17. package/components/DetailText.vue +5 -0
  18. package/components/ExplorerMembers.vue +1 -1
  19. package/components/ExplorerProjectsNamespaces.vue +68 -18
  20. package/components/GlobalRoleBindings.vue +5 -1
  21. package/components/GrowlManager.vue +1 -0
  22. package/components/LandingPagePreference.vue +7 -3
  23. package/components/LocaleSelector.vue +39 -95
  24. package/components/ModalManager.vue +55 -0
  25. package/components/ModalWithCard.vue +1 -0
  26. package/components/PromptModal.vue +47 -8
  27. package/components/PromptRemove.vue +1 -0
  28. package/components/PromptRestore.vue +1 -0
  29. package/components/ResourceCancelModal.vue +1 -0
  30. package/components/ResourceDetail/Masthead.vue +38 -12
  31. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  32. package/components/ResourceDetail/index.vue +47 -12
  33. package/components/ResourceTable.vue +54 -19
  34. package/components/SideNav.vue +5 -1
  35. package/components/SlideInPanelManager.vue +126 -0
  36. package/components/SortableTable/THead.vue +5 -2
  37. package/components/SortableTable/actions.js +1 -1
  38. package/components/SortableTable/index.vue +64 -51
  39. package/components/SortableTable/paging.js +16 -19
  40. package/components/SortableTable/selection.js +0 -11
  41. package/components/Wizard.vue +2 -2
  42. package/components/__tests__/AsyncButton.test.ts +2 -2
  43. package/components/__tests__/ModalManager.spec.ts +176 -0
  44. package/components/__tests__/PromptModal.test.ts +148 -0
  45. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  46. package/components/auth/AuthBanner.vue +13 -11
  47. package/components/auth/Principal.vue +1 -0
  48. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  49. package/components/auth/login/ldap.vue +1 -1
  50. package/components/fleet/FleetResources.vue +21 -6
  51. package/components/form/ArrayList.vue +76 -60
  52. package/components/form/BannerSettings.vue +17 -2
  53. package/components/form/ColorInput.vue +35 -6
  54. package/components/form/Command.vue +6 -15
  55. package/components/form/EnvVars.vue +16 -8
  56. package/components/form/HealthCheck.vue +3 -3
  57. package/components/form/HookOption.vue +11 -16
  58. package/components/form/LabeledSelect.vue +18 -22
  59. package/components/form/LifecycleHooks.vue +3 -3
  60. package/components/form/MatchExpressions.vue +14 -8
  61. package/components/form/NameNsDescription.vue +128 -104
  62. package/components/form/Networking.vue +20 -12
  63. package/components/form/NodeAffinity.vue +31 -23
  64. package/components/form/NodeScheduling.vue +13 -3
  65. package/components/form/NotificationSettings.vue +15 -1
  66. package/components/form/Password.vue +1 -0
  67. package/components/form/PodAffinity.vue +43 -43
  68. package/components/form/Probe.vue +68 -66
  69. package/components/form/ResourceQuota/Project.vue +5 -1
  70. package/components/form/ResourceSelector.vue +7 -9
  71. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +16 -24
  72. package/components/form/SSHKnownHosts/index.vue +30 -13
  73. package/components/form/Security.vue +54 -56
  74. package/components/form/Select.vue +32 -21
  75. package/components/form/ShellInput.vue +5 -1
  76. package/components/form/Tolerations.vue +5 -1
  77. package/components/form/ValueFromResource.vue +134 -121
  78. package/components/form/WorkloadPorts.vue +18 -18
  79. package/components/form/__tests__/ArrayList.test.ts +5 -2
  80. package/components/form/__tests__/ColorInput.test.ts +35 -0
  81. package/components/form/__tests__/LabeledSelect.test.ts +40 -0
  82. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  83. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  84. package/components/form/__tests__/Probe.test.ts +12 -8
  85. package/components/form/__tests__/SSHKnownHosts.test.ts +22 -2
  86. package/components/form/__tests__/Select.test.ts +37 -0
  87. package/components/formatter/InternalExternalIP.vue +2 -0
  88. package/components/formatter/SecretData.vue +20 -7
  89. package/components/nav/Group.vue +27 -5
  90. package/components/nav/Header.vue +17 -43
  91. package/components/nav/NamespaceFilter.vue +134 -86
  92. package/components/nav/TopLevelMenu.vue +4 -5
  93. package/components/nav/Type.vue +12 -1
  94. package/components/nav/WindowManager/ContainerLogs.vue +87 -61
  95. package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
  96. package/components/templates/blank.vue +4 -1
  97. package/components/templates/default.vue +8 -3
  98. package/components/templates/home.vue +10 -1
  99. package/components/templates/plain.vue +10 -4
  100. package/composables/focusTrap.ts +12 -4
  101. package/composables/useRuntimeFlag.ts +29 -0
  102. package/config/router/routes.js +20 -13
  103. package/config/store.js +4 -0
  104. package/config/uiplugins.js +5 -1
  105. package/core/types.ts +12 -6
  106. package/detail/catalog.cattle.io.app.vue +6 -1
  107. package/detail/fleet.cattle.io.bundle.vue +70 -6
  108. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  109. package/detail/namespace.vue +0 -3
  110. package/detail/node.vue +17 -13
  111. package/detail/provisioning.cattle.io.cluster.vue +72 -6
  112. package/dialog/AddCustomBadgeDialog.vue +1 -1
  113. package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
  114. package/{components/AssignTo.vue → dialog/AssignToDialog.vue} +71 -80
  115. package/dialog/ChangePasswordDialog.vue +106 -0
  116. package/dialog/DeactivateDriverDialog.vue +1 -0
  117. package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
  118. package/dialog/DisableAuthProviderDialog.vue +101 -0
  119. package/dialog/DrainNode.vue +1 -1
  120. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
  121. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
  122. package/dialog/FeatureFlagListDialog.vue +288 -0
  123. package/dialog/ForceMachineRemoveDialog.vue +5 -2
  124. package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
  125. package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
  126. package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -59
  127. package/dialog/MoveNamespaceDialog.vue +157 -0
  128. package/dialog/ScalePoolDownDialog.vue +1 -1
  129. package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
  130. package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
  131. package/dialog/WechatDialog.vue +57 -0
  132. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
  133. package/edit/auth/__tests__/oidc.test.ts +152 -109
  134. package/edit/auth/azuread.vue +2 -1
  135. package/edit/auth/github.vue +1 -1
  136. package/edit/auth/googleoauth.vue +5 -1
  137. package/edit/auth/ldap/index.vue +1 -1
  138. package/edit/auth/oidc.vue +38 -5
  139. package/edit/auth/saml.vue +1 -1
  140. package/edit/cloudcredential.vue +24 -9
  141. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
  142. package/edit/management.cattle.io.user.vue +28 -3
  143. package/edit/namespace.vue +1 -4
  144. package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
  145. package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
  146. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
  147. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
  148. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -9
  149. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
  150. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
  151. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
  152. package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
  153. package/edit/provisioning.cattle.io.cluster/rke2.vue +49 -41
  154. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
  155. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
  156. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +33 -2
  157. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
  158. package/edit/token.vue +2 -0
  159. package/edit/workload/index.vue +1 -0
  160. package/edit/workload/mixins/workload.js +0 -2
  161. package/initialize/install-plugins.js +2 -1
  162. package/list/harvesterhci.io.management.cluster.vue +4 -1
  163. package/list/management.cattle.io.feature.vue +4 -287
  164. package/list/provisioning.cattle.io.cluster.vue +20 -12
  165. package/machine-config/azure.vue +16 -4
  166. package/mixins/vue-select-overrides.js +0 -4
  167. package/models/__tests__/namespace.test.ts +25 -1
  168. package/models/cloudcredential.js +5 -0
  169. package/models/fleet.cattle.io.cluster.js +8 -2
  170. package/models/fleet.cattle.io.gitrepo.js +8 -34
  171. package/models/kontainerdriver.js +6 -3
  172. package/models/management.cattle.io.feature.js +7 -1
  173. package/models/management.cattle.io.node.js +3 -3
  174. package/models/namespace.js +11 -6
  175. package/models/nodedriver.js +6 -3
  176. package/models/workload.js +4 -1
  177. package/package.json +3 -3
  178. package/pages/about.vue +13 -3
  179. package/pages/account/index.vue +16 -6
  180. package/pages/auth/login.vue +18 -7
  181. package/pages/auth/logout.vue +4 -1
  182. package/pages/auth/setup.vue +2 -0
  183. package/pages/auth/verify.vue +13 -8
  184. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  185. package/pages/c/_cluster/apps/charts/install.vue +26 -26
  186. package/pages/c/_cluster/auth/config/index.vue +10 -12
  187. package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
  188. package/pages/c/_cluster/explorer/index.vue +17 -15
  189. package/pages/c/_cluster/istio/index.vue +2 -2
  190. package/pages/c/_cluster/longhorn/index.vue +1 -1
  191. package/pages/c/_cluster/monitoring/index.vue +1 -1
  192. package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
  193. package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
  194. package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
  195. package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
  196. package/pages/c/_cluster/neuvector/index.vue +1 -1
  197. package/pages/c/_cluster/settings/banners.vue +4 -3
  198. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
  199. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +98 -55
  201. package/pages/diagnostic.vue +59 -11
  202. package/pages/fail-whale.vue +14 -8
  203. package/pages/home.vue +24 -18
  204. package/pages/prefs.vue +7 -6
  205. package/pages/support/index.vue +4 -1
  206. package/plugins/internal-api/index.ts +37 -0
  207. package/plugins/internal-api/shared/base-api.ts +13 -0
  208. package/plugins/internal-api/shell/shell.api.ts +108 -0
  209. package/plugins/steve/actions.js +0 -12
  210. package/public/index.html +1 -0
  211. package/rancher-components/Card/Card.vue +1 -1
  212. package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
  213. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
  214. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
  215. package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
  216. package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
  217. package/rancher-components/Form/Radio/RadioButton.vue +20 -4
  218. package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
  219. package/rancher-components/Form/Radio/RadioGroup.vue +52 -10
  220. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
  221. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
  222. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
  223. package/rancher-components/RcButton/RcButton.vue +2 -1
  224. package/rancher-components/RcButton/types.ts +1 -0
  225. package/rancher-components/RcDropdown/RcDropdown.vue +18 -6
  226. package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
  227. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
  228. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
  229. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
  230. package/rancher-components/RcDropdown/index.ts +2 -0
  231. package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
  232. package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
  233. package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
  234. package/scripts/extension/bundle +20 -0
  235. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
  236. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  237. package/scripts/extension/helmpatch +44 -31
  238. package/scripts/extension/publish +12 -12
  239. package/scripts/typegen.sh +2 -4
  240. package/server/har-file.js +25 -3
  241. package/store/action-menu.js +26 -56
  242. package/store/features.js +2 -1
  243. package/store/index.js +5 -0
  244. package/store/modal.ts +71 -0
  245. package/store/slideInPanel.ts +47 -0
  246. package/store/type-map.js +12 -1
  247. package/store/type-map.utils.ts +4 -4
  248. package/types/global-vue.d.ts +5 -0
  249. package/types/internal-api/shell/growl.d.ts +25 -0
  250. package/types/internal-api/shell/modal.d.ts +77 -0
  251. package/types/internal-api/shell/slideIn.d.ts +15 -0
  252. package/types/resources/fleet.d.ts +0 -14
  253. package/types/shell/index.d.ts +43 -24
  254. package/types/vue-shim.d.ts +4 -1
  255. package/utils/__mocks__/tabbable.js +13 -0
  256. package/utils/__tests__/object.test.ts +38 -4
  257. package/utils/cluster.js +35 -0
  258. package/utils/fleet.ts +15 -73
  259. package/utils/object.js +48 -5
  260. package/utils/validators/formRules/__tests__/index.test.ts +10 -1
  261. package/utils/validators/formRules/index.ts +27 -3
  262. package/utils/validators/machine-pool.ts +20 -0
  263. package/components/DisableAuthProviderModal.vue +0 -114
  264. package/components/MoveModal.vue +0 -166
  265. package/components/PromptChangePassword.vue +0 -123
  266. package/components/fleet/FleetBundleResources.vue +0 -86
  267. package/components/formatter/ExtensionCache.vue +0 -74
  268. package/components/formatter/Port.vue +0 -24
  269. package/components/formatter/SecretType.vue +0 -41
  270. package/types/vue-shim.d +0 -20
@@ -43,23 +43,14 @@ export default {
43
43
  },
44
44
 
45
45
  data() {
46
- const {
47
- command,
48
- args,
49
- workingDir,
50
- stdin = false,
51
- stdinOnce = false,
52
- tty = false,
53
- } = this.value;
54
-
55
46
  return {
56
- args,
57
- command,
47
+ args: this.value.args,
48
+ command: this.value.command,
58
49
  commandOptions: ['No', 'Once', 'Yes'],
59
- stdin,
60
- stdinOnce,
61
- tty,
62
- workingDir,
50
+ stdin: this.value.stdin || false,
51
+ stdinOnce: this.value.stdin || false,
52
+ tty: this.value.tty || false,
53
+ workingDir: this.value.workingDir,
63
54
  };
64
55
  },
65
56
 
@@ -39,14 +39,10 @@ export default {
39
39
  },
40
40
 
41
41
  data() {
42
- const { env = [], envFrom = [] } = this.value;
43
-
44
- const allEnv = [...env, ...envFrom].map((row) => {
45
- return { value: row, id: randomStr(4) };
46
- });
47
-
48
42
  return {
49
- env, envFrom, allEnv
43
+ env: [],
44
+ envFrom: [],
45
+ allEnv: [],
50
46
  };
51
47
  },
52
48
 
@@ -63,7 +59,18 @@ export default {
63
59
  }
64
60
  }
65
61
  },
62
+
66
63
  created() {
64
+ const { env = [], envFrom = [] } = this.value;
65
+
66
+ const allEnv = [...env, ...envFrom].map((row) => {
67
+ return { value: row, id: randomStr(4) };
68
+ });
69
+
70
+ this.env = env;
71
+ this.envFrom = envFrom;
72
+ this.allEnv = allEnv;
73
+
67
74
  this.queueUpdate = debounce(this.update, 500);
68
75
  },
69
76
 
@@ -107,7 +114,8 @@ export default {
107
114
  <div :style="{'width':'100%'}">
108
115
  <div
109
116
  v-for="(row, i) in allEnv"
110
- :key="i"
117
+ :key="row.id"
118
+ :data-testid="`env-var-row-${i}`"
111
119
  >
112
120
  <ValueFromResource
113
121
  v-model:value="row.value"
@@ -18,10 +18,10 @@ export default {
18
18
  },
19
19
 
20
20
  data() {
21
- const { readinessProbe, livenessProbe, startupProbe } = this.value;
22
-
23
21
  return {
24
- readinessProbe, livenessProbe, startupProbe
22
+ readinessProbe: this.value.readinessProbe,
23
+ livenessProbe: this.value.livenessProbe,
24
+ startupProbe: this.value.startupProbe,
25
25
  };
26
26
  },
27
27
 
@@ -28,23 +28,18 @@ export default {
28
28
  },
29
29
 
30
30
  data() {
31
- const selectHook = null;
32
-
33
- const defaultExec = { exec: { command: [] } };
34
- const defaultHttpGet = {
35
- httpGet: {
36
- host: '',
37
- path: '',
38
- port: null,
39
- scheme: '',
40
- httpHeaders: null
41
- }
42
- };
43
-
44
31
  return {
45
- selectHook,
46
- defaultExec,
47
- defaultHttpGet,
32
+ selectHook: null,
33
+ defaultExec: { exec: { command: [] } },
34
+ defaultHttpGet: {
35
+ httpGet: {
36
+ host: '',
37
+ path: '',
38
+ port: null,
39
+ scheme: '',
40
+ httpHeaders: null
41
+ }
42
+ },
48
43
  schemeOptions: ['HTTP', 'HTTPS']
49
44
  };
50
45
  },
@@ -116,9 +116,11 @@ export default {
116
116
 
117
117
  data() {
118
118
  return {
119
- selectedVisibility: 'visible',
120
- shouldOpen: true,
121
- uid: generateRandomAlphaString(10)
119
+ selectedVisibility: 'visible',
120
+ shouldOpen: true,
121
+ labeledSelectLabelId: `ls-label-id-${ generateRandomAlphaString(12) }`,
122
+ isOpen: false,
123
+ generatedUid: `ls-uid-${ generateRandomAlphaString(12) }`
122
124
  };
123
125
  },
124
126
 
@@ -160,21 +162,6 @@ export default {
160
162
  return;
161
163
  }
162
164
 
163
- // we need this override as in a "closeOnSelect" type of component
164
- // if we don't have this override, it would open again
165
- if (this.overridesMixinPreventDoubleTriggerKeysOpen) {
166
- this.$nextTick(() => {
167
- const el = this.$refs['select'];
168
-
169
- if ( el ) {
170
- el.focus();
171
- }
172
-
173
- this.overridesMixinPreventDoubleTriggerKeysOpen = false;
174
- });
175
-
176
- return;
177
- }
178
165
  this.$refs['select-input'].open = true;
179
166
 
180
167
  this.$nextTick(() => {
@@ -197,11 +184,13 @@ export default {
197
184
  },
198
185
 
199
186
  onOpen() {
187
+ this.isOpen = true;
200
188
  this.$emit('on-open');
201
189
  this.resizeHandler();
202
190
  },
203
191
 
204
192
  onClose() {
193
+ this.isOpen = false;
205
194
  this.$emit('on-close');
206
195
  },
207
196
 
@@ -279,6 +268,7 @@ export default {
279
268
 
280
269
  <template>
281
270
  <div
271
+ :id="hasLabel ? labeledSelectLabelId : undefined"
282
272
  ref="select"
283
273
  class="labeled-select"
284
274
  :class="[
@@ -296,6 +286,10 @@ export default {
296
286
  }
297
287
  ]"
298
288
  :tabindex="isView || disabled ? -1 : 0"
289
+ role="combobox"
290
+ :aria-expanded="isOpen"
291
+ :aria-describedby="$attrs['aria-describedby'] || undefined"
292
+ :aria-required="requiredField"
299
293
  @click="focusSearch"
300
294
  @keydown.enter="focusSearch"
301
295
  @keydown.down.prevent="focusSearch"
@@ -307,7 +301,7 @@ export default {
307
301
  >
308
302
  <label
309
303
  v-if="hasLabel"
310
- :id="`labeled-select-uid-${uid}`"
304
+ :for="labeledSelectLabelId"
311
305
  >
312
306
  <t
313
307
  v-if="labelKey"
@@ -318,12 +312,12 @@ export default {
318
312
  <span
319
313
  v-if="requiredField"
320
314
  class="required"
315
+ :aria-hidden="true"
321
316
  >*</span>
322
317
  </label>
323
318
  </div>
324
319
  <v-select
325
320
  ref="select-input"
326
- :aria-labelledby="hasLabel ? `labeled-select-uid-${uid}` : ''"
327
321
  v-bind="filteredAttrs"
328
322
  class="inline"
329
323
  :append-to-body="appendToBody"
@@ -344,7 +338,8 @@ export default {
344
338
  :modelValue="value != null && !loading ? value : ''"
345
339
  :dropdown-should-open="dropdownShouldOpen"
346
340
  :tabindex="-1"
347
- role="listbox"
341
+ :uid="generatedUid"
342
+ :aria-label="'-'"
348
343
  @update:modelValue="$emit('selecting', $event); $emit('update:value', $event)"
349
344
  @search:blur="onBlur"
350
345
  @search:focus="onFocus"
@@ -353,6 +348,7 @@ export default {
353
348
  @close="onClose"
354
349
  @option:selecting="$emit('selecting', $event)"
355
350
  @option:deselecting="$emit('deselecting', $event)"
351
+ @keydown.enter.stop
356
352
  >
357
353
  <template #option="option">
358
354
  <template v-if="showTagPrompts">
@@ -374,7 +370,7 @@ export default {
374
370
  </div>
375
371
  </template>
376
372
  <template v-else-if="option.kind === 'divider'">
377
- <hr>
373
+ <hr role="none">
378
374
  </template>
379
375
  <template v-else-if="option.kind === 'highlighted'">
380
376
  <div class="option-kind-highlighted">
@@ -24,10 +24,10 @@ export default {
24
24
  },
25
25
 
26
26
  data() {
27
- const { postStart, preStop } = this.value;
28
-
29
27
  return {
30
- postStart, preStop, hookOptions: ['postStart', 'preStop']
28
+ postStart: this.value.postStart,
29
+ preStop: this.value.preStop,
30
+ hookOptions: ['postStart', 'preStop']
31
31
  };
32
32
  },
33
33
 
@@ -70,6 +70,14 @@ export default {
70
70
  },
71
71
 
72
72
  data() {
73
+ return {
74
+ ops: [],
75
+ rules: [],
76
+ custom: []
77
+ };
78
+ },
79
+
80
+ created() {
73
81
  const t = this.$store.getters['i18n/t'];
74
82
 
75
83
  const podOptions = [
@@ -88,8 +96,6 @@ export default {
88
96
  { label: t('workload.scheduling.affinity.matchExpressions.greaterThan'), value: 'Gt' },
89
97
  ];
90
98
 
91
- const ops = this.type === NODE ? nodeOptions : podOptions;
92
-
93
99
  let rules;
94
100
 
95
101
  // special case for matchFields and matchExpressions
@@ -127,11 +133,8 @@ export default {
127
133
  rules.push(newRule);
128
134
  }
129
135
 
130
- return {
131
- ops,
132
- rules,
133
- custom: []
134
- };
136
+ this.rules = rules;
137
+ this.ops = this.type === NODE ? nodeOptions : podOptions;
135
138
  },
136
139
 
137
140
  computed: {
@@ -210,7 +213,10 @@ export default {
210
213
  update() {
211
214
  this.$nextTick(() => {
212
215
  const out = this.rules.map((rule) => {
213
- const expression = { key: rule.key, operator: rule.operator };
216
+ const expression = {
217
+ key: rule.key.trim(),
218
+ operator: rule.operator
219
+ };
214
220
 
215
221
  if (this.matchingSelectorDisplay) {
216
222
  expression.matching = rule.matching;
@@ -1,5 +1,7 @@
1
1
  <script>
2
- import { mapGetters, mapActions } from 'vuex';
2
+ import { computed, ref, toRef, watch } from 'vue';
3
+ import { mapActions, useStore } from 'vuex';
4
+
3
5
  import { get, set } from '@shell/utils/object';
4
6
  import { sortBy } from '@shell/utils/sort';
5
7
  import { NAMESPACE } from '@shell/config/types';
@@ -8,6 +10,7 @@ import { _VIEW, _EDIT, _CREATE } from '@shell/config/query-params';
8
10
  import { LabeledInput } from '@components/Form/LabeledInput';
9
11
  import LabeledSelect from '@shell/components/form/LabeledSelect';
10
12
  import { normalizeName } from '@shell/utils/kube';
13
+ import { useI18n } from '@shell/composables/useI18n';
11
14
 
12
15
  export default {
13
16
  name: 'NameNsDescription',
@@ -28,6 +31,10 @@ export default {
28
31
  type: String,
29
32
  required: true,
30
33
  },
34
+ nameHidden: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
31
38
  nameNsHidden: {
32
39
  type: Boolean,
33
40
  default: false,
@@ -169,81 +176,74 @@ export default {
169
176
  },
170
177
 
171
178
  data() {
172
- const v = this.value;
173
- const metadata = v.metadata;
174
- let namespace, name, description;
179
+ return { createNamespace: false };
180
+ },
175
181
 
176
- if (this.nameKey) {
177
- name = get(v, this.nameKey);
178
- } else {
179
- name = metadata?.name;
180
- }
182
+ setup(props, { emit }) {
183
+ const v = toRef(props.value);
184
+ const metadata = v.value.metadata;
185
+ const namespace = ref(null);
186
+ const name = ref(null);
187
+ const description = ref(null);
181
188
 
182
- if (this.namespaced) {
183
- if (this.forceNamespace) {
184
- namespace = this.forceNamespace;
185
- this.updateNamespace(namespace);
186
- } else if (this.namespaceKey) {
187
- namespace = get(v, this.namespaceKey);
188
- } else {
189
- namespace = metadata?.namespace;
189
+ watch(name, (val) => {
190
+ if (props.normalizeName) {
191
+ val = normalizeName(val);
190
192
  }
191
193
 
192
- if (!namespace && !this.noDefaultNamespace) {
193
- namespace = this.$store.getters['defaultNamespace'];
194
- if (metadata) {
195
- metadata.namespace = namespace;
196
- }
194
+ if (props.nameKey) {
195
+ set(props.value, props.nameKey, val);
196
+ } else {
197
+ props.value.metadata['name'] = val;
197
198
  }
198
- }
199
+ emit('update:value', props.value);
200
+ });
199
201
 
200
- if (this.descriptionKey) {
201
- description = get(v, this.descriptionKey);
202
+ if (props.nameKey) {
203
+ name.value = get(v.value, props.nameKey);
202
204
  } else {
203
- description = metadata?.annotations?.[DESCRIPTION];
205
+ name.value = metadata?.name || '';
204
206
  }
205
207
 
206
- const inStore = this.$store.getters['currentStore']();
207
- const nsSchema = this.$store.getters[`${ inStore }/schemaFor`](NAMESPACE);
208
+ const isCreate = computed(() => {
209
+ return props.mode === _CREATE;
210
+ });
208
211
 
209
- return {
210
- namespace,
211
- name,
212
- description,
213
- createNamespace: false,
214
- nsSchema
215
- };
216
- },
212
+ const store = useStore();
213
+ const { t } = useI18n(store);
214
+ const allowedNamespaces = computed(() => store.getters.allowedNamespaces());
215
+ const storeNamespaces = computed(() => store.getters.namespaces());
216
+ const currentCluster = computed(() => store.getters.currentCluster);
217
217
 
218
- computed: {
219
- ...mapGetters(['currentProduct', 'currentCluster', 'namespaces', 'allowedNamespaces']),
220
- ...mapActions('cru-resource', ['setCreateNamespace']),
221
- namespaceReallyDisabled() {
222
- return (
223
- !!this.forceNamespace || this.namespaceDisabled || this.mode === _EDIT
224
- ); // namespace is never editable
225
- },
218
+ const inStore = computed(() => {
219
+ return store.getters['currentStore']();
220
+ });
226
221
 
227
- nameReallyDisabled() {
228
- return this.nameDisabled || (this.mode === _EDIT && !this.nameEditable);
229
- },
222
+ const nsSchema = computed(() => {
223
+ return store.getters[`${ inStore.value }/schemaFor`](NAMESPACE);
224
+ });
225
+
226
+ const canCreateNamespace = computed(() => {
227
+ // Check if user can push to namespaces... and as the ns is outside of a project restrict to admins and cluster owners
228
+ return (nsSchema.value?.collectionMethods || []).includes('POST') && currentCluster.value?.canUpdate;
229
+ });
230
230
 
231
231
  /**
232
232
  * Map namespaces from the store to options, adding divider and create button
233
233
  */
234
- options() {
234
+ const options = computed(() => {
235
235
  let namespaces;
236
236
 
237
- if (this.namespacesOverride) {
237
+ if (props.namespacesOverride) {
238
238
  // Use the resources provided
239
- namespaces = this.namespacesOverride;
239
+ namespaces = props.namespacesOverride;
240
240
  } else {
241
- if (this.namespaceOptions) {
241
+ if (props.namespaceOptions) {
242
242
  // Use the namespaces provided
243
- namespaces = (this.namespaceOptions.map((ns) => ns.name) || []).sort();
243
+ namespaces = (props.namespaceOptions.map((ns) => ns.name) || []).sort();
244
244
  } else {
245
245
  // Determine the namespaces
246
- const namespaceObjs = this.isCreate ? this.allowedNamespaces() : this.namespaces();
246
+ const namespaceObjs = isCreate.value ? allowedNamespaces.value : storeNamespaces.value;
247
247
 
248
248
  namespaces = Object.keys(namespaceObjs);
249
249
  }
@@ -251,22 +251,22 @@ export default {
251
251
 
252
252
  const options = namespaces
253
253
  .map((namespace) => ({ nameDisplay: namespace, id: namespace }))
254
- .map(this.namespaceMapper || ((obj) => ({
254
+ .map(props.namespaceMapper || ((obj) => ({
255
255
  label: obj.nameDisplay,
256
256
  value: obj.id,
257
257
  })));
258
258
 
259
259
  const sortedByLabel = sortBy(options, 'label');
260
260
 
261
- if (this.forceNamespace) {
261
+ if (props.forceNamespace) {
262
262
  sortedByLabel.unshift({
263
- label: this.forceNamespace,
264
- value: this.forceNamespace,
263
+ label: props.forceNamespace,
264
+ value: props.forceNamespace,
265
265
  });
266
266
  }
267
267
 
268
268
  const createButton = {
269
- label: this.t('namespace.createNamespace'),
269
+ label: t('namespace.createNamespace'),
270
270
  value: '',
271
271
  kind: 'highlighted'
272
272
  };
@@ -276,20 +276,78 @@ export default {
276
276
  kind: 'divider'
277
277
  };
278
278
 
279
- const createOverhead = this.canCreateNamespace || this.createNamespaceOverride ? [createButton, divider] : [];
279
+ const createOverhead = canCreateNamespace.value || props.createNamespaceOverride ? [createButton, divider] : [];
280
280
 
281
281
  return [
282
282
  ...createOverhead,
283
283
  ...sortedByLabel
284
284
  ];
285
+ });
286
+
287
+ const updateNamespace = (val) => {
288
+ if (props.forceNamespace) {
289
+ val = props.forceNamespace;
290
+ }
291
+
292
+ if (props.namespaced) {
293
+ emit('isNamespaceNew', !val || (options.value && !options.value.find((n) => n.value === val)));
294
+ }
295
+
296
+ if (props.namespaceKey) {
297
+ set(props.value, props.namespaceKey, val);
298
+ } else {
299
+ props.value.metadata.namespace = val;
300
+ }
301
+ };
302
+
303
+ if (props.namespaced) {
304
+ if (props.forceNamespace) {
305
+ namespace.value = toRef(props.forceNamespace);
306
+ updateNamespace(namespace);
307
+ } else if (props.namespaceKey) {
308
+ namespace.value = get(v, props.namespaceKey);
309
+ } else {
310
+ namespace.value = metadata?.namespace;
311
+ }
312
+
313
+ if (!namespace.value && !props.noDefaultNamespace) {
314
+ namespace.value = store.getters['defaultNamespace'];
315
+ if (metadata) {
316
+ metadata.namespace = namespace;
317
+ }
318
+ }
319
+ }
320
+
321
+ if (props.descriptionKey) {
322
+ description.value = get(v, props.descriptionKey);
323
+ } else {
324
+ description.value = metadata?.annotations?.[DESCRIPTION];
325
+ }
326
+
327
+ return {
328
+ namespace,
329
+ name,
330
+ description,
331
+ isCreate,
332
+ options,
333
+ updateNamespace,
334
+ };
335
+ },
336
+
337
+ computed: {
338
+ ...mapActions('cru-resource', ['setCreateNamespace']),
339
+ namespaceReallyDisabled() {
340
+ return (
341
+ !!this.forceNamespace || this.namespaceDisabled || this.mode === _EDIT
342
+ ); // namespace is never editable
285
343
  },
286
344
 
287
- isView() {
288
- return this.mode === _VIEW;
345
+ nameReallyDisabled() {
346
+ return this.nameDisabled || (this.mode === _EDIT && !this.nameEditable);
289
347
  },
290
348
 
291
- isCreate() {
292
- return this.mode === _CREATE;
349
+ isView() {
350
+ return this.mode === _VIEW;
293
351
  },
294
352
 
295
353
  showCustomize() {
@@ -308,27 +366,9 @@ export default {
308
366
 
309
367
  return `span-${ span }`;
310
368
  },
311
-
312
- canCreateNamespace() {
313
- // Check if user can push to namespaces... and as the ns is outside of a project restrict to admins and cluster owners
314
- return (this.nsSchema?.collectionMethods || []).includes('POST') && this.currentCluster?.canUpdate;
315
- }
316
369
  },
317
370
 
318
371
  watch: {
319
- name(val) {
320
- if (this.normalizeName) {
321
- val = normalizeName(val);
322
- }
323
-
324
- if (this.nameKey) {
325
- set(this.value, this.nameKey, val);
326
- } else {
327
- this.value.metadata['name'] = val;
328
- }
329
- this.$emit('update:value', this.value);
330
- },
331
-
332
372
  namespace(val) {
333
373
  this.updateNamespace(val);
334
374
  this.$emit('update:value', this.value);
@@ -346,29 +386,13 @@ export default {
346
386
 
347
387
  mounted() {
348
388
  this.$nextTick(() => {
349
- if (this.$refs.name) {
350
- this.$refs.name.focus();
389
+ if (this.$refs.nameInput) {
390
+ this.$refs.nameInput.focus();
351
391
  }
352
392
  });
353
393
  },
354
394
 
355
395
  methods: {
356
- updateNamespace(val) {
357
- if (this.forceNamespace) {
358
- val = this.forceNamespace;
359
- }
360
-
361
- if (this.namespaced) {
362
- this.$emit('isNamespaceNew', !val || (this.options && !this.options.find((n) => n.value === val)));
363
- }
364
-
365
- if (this.namespaceKey) {
366
- set(this.value, this.namespaceKey, val);
367
- } else {
368
- this.value.metadata.namespace = val;
369
- }
370
- },
371
-
372
396
  changeNameAndNamespace(e) {
373
397
  this.name = (e.text || '').toLowerCase();
374
398
  this.namespace = e.selected;
@@ -389,7 +413,7 @@ export default {
389
413
  true,
390
414
  );
391
415
  this.$emit('isNamespaceNew', true);
392
- this.$nextTick(() => this.$refs.namespace.focus());
416
+ this.$nextTick(() => this.$refs.namespaceInput.focus());
393
417
  } else {
394
418
  this.createNamespace = false;
395
419
  this.$store.dispatch(
@@ -411,7 +435,7 @@ export default {
411
435
  class="col span-3"
412
436
  >
413
437
  <LabeledInput
414
- ref="namespace"
438
+ ref="namespaceInput"
415
439
  v-model:value="namespace"
416
440
  :label="t('namespace.label')"
417
441
  :placeholder="t('namespace.createNamespace')"
@@ -454,14 +478,15 @@ export default {
454
478
  </div>
455
479
 
456
480
  <div
457
- v-if="!nameNsHidden"
481
+ v-if="!nameHidden && !nameNsHidden"
458
482
  :data-testid="componentTestid + '-name'"
459
483
  class="col span-3"
460
484
  >
461
485
  <LabeledInput
462
- ref="name"
486
+ ref="nameInput"
463
487
  key="name"
464
488
  v-model:value="name"
489
+ data-testid="NameNsDescriptionNameInput"
465
490
  :label="t(nameLabel)"
466
491
  :placeholder="t(namePlaceholder)"
467
492
  :disabled="nameReallyDisabled"
@@ -473,7 +498,6 @@ export default {
473
498
  </div>
474
499
 
475
500
  <slot name="customize" />
476
- <!-- // TODO: here goes the custom component -->
477
501
  <div
478
502
  v-show="!descriptionHidden"
479
503
  :data-testid="componentTestid + '-description'"