@rancher/shell 0.3.0 → 0.3.1

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 (322) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_layout.scss +1 -2
  4. package/assets/styles/global/_select.scss +1 -4
  5. package/assets/styles/themes/_dark.scss +4 -4
  6. package/assets/styles/themes/_light.scss +4 -3
  7. package/assets/styles/themes/_suse.scss +1 -1
  8. package/assets/styles/vendor/vue-select.scss +4 -3
  9. package/assets/translations/en-us.yaml +669 -73
  10. package/assets/translations/zh-hans.yaml +547 -165
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/cloud-credential/azure.vue +23 -0
  13. package/cloud-credential/harvester.vue +25 -62
  14. package/cloud-credential/pnap.vue +80 -0
  15. package/components/.DS_Store +0 -0
  16. package/components/AdvancedSection.vue +9 -2
  17. package/components/Alert.vue +2 -2
  18. package/components/ButtonDropdown.vue +0 -2
  19. package/components/ButtonGroup.vue +1 -0
  20. package/components/CollapsibleCard.vue +0 -1
  21. package/components/CruResource.vue +41 -4
  22. package/components/DetailTop.vue +58 -3
  23. package/components/DisableAuthProviderModal.vue +106 -0
  24. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  25. package/components/ExplorerMembers.vue +253 -30
  26. package/components/ExplorerProjectsNamespaces.vue +77 -33
  27. package/components/GrowlManager.vue +3 -3
  28. package/components/IconOrSvg.vue +149 -0
  29. package/components/LogItem.vue +69 -0
  30. package/components/PodSecurityAdmission.vue +302 -0
  31. package/components/PromptModal.vue +1 -0
  32. package/components/ResourceDetail/Masthead.vue +54 -2
  33. package/components/ResourceDetail/index.vue +12 -5
  34. package/components/ResourceList/Masthead.vue +11 -1
  35. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  36. package/components/ResourceList/index.vue +53 -12
  37. package/components/ResourceList/resource-list.config.js +7 -0
  38. package/components/ResourceTable.vue +31 -6
  39. package/components/SimpleBox.vue +1 -1
  40. package/components/SortableTable/THead.vue +15 -5
  41. package/components/SortableTable/index.vue +21 -10
  42. package/components/Tabbed/index.vue +20 -15
  43. package/components/__tests__/.DS_Store +0 -0
  44. package/components/__tests__/AsyncButton.test.ts +140 -0
  45. package/components/__tests__/BackLink.test.ts +33 -0
  46. package/components/__tests__/ButtonGroup.test.ts +124 -0
  47. package/components/__tests__/ClusterBadge.test.ts +32 -0
  48. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  49. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  50. package/components/__tests__/CruResource.test.ts +3 -2
  51. package/components/__tests__/FixedBanner.test.ts +129 -0
  52. package/components/__tests__/GrowlManager.test.ts +147 -0
  53. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  54. package/components/__tests__/PercentageBar.test.ts +32 -0
  55. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  56. package/components/auth/AuthBanner.vue +20 -10
  57. package/components/auth/RoleDetailEdit.vue +26 -17
  58. package/components/auth/SelectPrincipal.vue +36 -5
  59. package/components/form/ArrayList.vue +3 -35
  60. package/components/form/ArrayListGrouped.vue +13 -4
  61. package/components/form/ArrayListSelect.vue +5 -5
  62. package/components/form/Error.vue +8 -0
  63. package/components/form/KeyValue.vue +39 -7
  64. package/components/form/LabeledSelect.vue +5 -2
  65. package/components/form/Labels.vue +46 -16
  66. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  67. package/components/form/Members/MembershipEditor.vue +12 -12
  68. package/components/form/NameNsDescription.vue +1 -1
  69. package/components/form/NodeScheduling.vue +1 -1
  70. package/components/form/Probe.vue +3 -3
  71. package/components/form/ResourceQuota/Project.vue +6 -6
  72. package/components/form/ResourceTabs/index.vue +1 -6
  73. package/components/form/Security.vue +7 -6
  74. package/components/form/Select.vue +3 -2
  75. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  76. package/components/form/ServicePorts.vue +8 -0
  77. package/components/form/WorkloadPorts.vue +7 -1
  78. package/components/form/__tests__/ArrayList.test.ts +74 -0
  79. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  80. package/components/formatter/Checked.vue +1 -1
  81. package/components/formatter/ClusterLink.vue +5 -0
  82. package/components/formatter/IconIsDefault.vue +2 -2
  83. package/components/formatter/InternalExternalIP.vue +11 -8
  84. package/components/formatter/LiveDuration.vue +78 -0
  85. package/components/formatter/WorkloadHealthScale.vue +5 -3
  86. package/components/nav/Header.vue +6 -3
  87. package/components/nav/NamespaceFilter.vue +146 -63
  88. package/components/nav/TopLevelMenu.vue +22 -19
  89. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  90. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  91. package/components/nav/WindowManager/Window.vue +2 -0
  92. package/components/nav/WindowManager/index.vue +10 -0
  93. package/config/elemental-types.js +9 -0
  94. package/config/features.js +2 -0
  95. package/config/home-links.js +4 -1
  96. package/config/pod-security-admission.ts +82 -0
  97. package/config/product/apps.js +1 -1
  98. package/config/product/auth.js +6 -5
  99. package/config/product/explorer.js +6 -6
  100. package/config/product/fleet.js +1 -1
  101. package/config/product/manager.js +6 -2
  102. package/config/secret.js +0 -1
  103. package/config/settings.ts +26 -9
  104. package/config/table-headers.js +22 -11
  105. package/config/types.js +4 -1
  106. package/content/docs/zh-hans/getting-started.md +113 -137
  107. package/content/docs/zh-hans/whats-new.md +8 -46
  108. package/creators/pkg/package-lock.json +37 -0
  109. package/creators/pkg/package.json +1 -1
  110. package/detail/catalog.cattle.io.app.vue +1 -1
  111. package/detail/pod.vue +1 -1
  112. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  113. package/detail/service.vue +2 -9
  114. package/detail/workload/index.vue +0 -1
  115. package/dialog/AddClusterMemberDialog.vue +22 -28
  116. package/dialog/AddProjectMemberDialog.vue +53 -9
  117. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  118. package/dialog/DrainNode.vue +44 -48
  119. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  120. package/dialog/GenericPrompt.vue +15 -20
  121. package/dialog/RollbackWorkloadDialog.vue +15 -46
  122. package/dialog/RotateCertificatesDialog.vue +5 -7
  123. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  124. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  125. package/dialog/ScaleMachineDownDialog.vue +1 -1
  126. package/dialog/ScalePoolDownDialog.vue +121 -0
  127. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  128. package/edit/auth/azuread.vue +16 -16
  129. package/edit/auth/github.vue +8 -0
  130. package/edit/auth/googleoauth.vue +10 -1
  131. package/edit/auth/ldap/index.vue +10 -0
  132. package/edit/auth/oidc.vue +10 -0
  133. package/edit/auth/saml.vue +10 -0
  134. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  135. package/edit/cloudcredential.vue +3 -7
  136. package/edit/logging-flow/Match.vue +39 -8
  137. package/edit/logging-flow/index.vue +27 -4
  138. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  139. package/edit/management.cattle.io.project.vue +8 -1
  140. package/edit/management.cattle.io.setting.vue +5 -2
  141. package/edit/management.cattle.io.user.vue +7 -1
  142. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
  143. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  144. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  145. package/edit/namespace.vue +18 -4
  146. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  147. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  148. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  149. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  150. package/edit/persistentvolume/index.vue +30 -27
  151. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  152. package/edit/persistentvolume/plugins/csi.vue +102 -62
  153. package/edit/persistentvolume/plugins/fc.vue +19 -19
  154. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  155. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  156. package/edit/persistentvolumeclaim.vue +78 -75
  157. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  158. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  159. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  160. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  161. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
  162. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  164. package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
  165. package/edit/secret/index.vue +3 -7
  166. package/edit/service.vue +3 -1
  167. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  168. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  169. package/edit/workload/__tests__/index.test.ts +98 -0
  170. package/edit/workload/index.vue +58 -8
  171. package/edit/workload/mixins/workload.js +107 -70
  172. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  173. package/edit/workload/storage/emptyDir.vue +88 -0
  174. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  175. package/edit/workload/storage/index.vue +8 -0
  176. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  177. package/layouts/default.vue +57 -44
  178. package/list/__tests__/workload.test.ts +5 -2
  179. package/list/catalog.cattle.io.app.vue +1 -0
  180. package/list/cis.cattle.io.clusterscan.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +5 -6
  182. package/list/fleet.cattle.io.cluster.vue +6 -3
  183. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  184. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  185. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  186. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  187. package/list/logging.banzaicloud.io.flow.vue +6 -5
  188. package/list/management.cattle.io.cluster.vue +1 -0
  189. package/list/management.cattle.io.feature.vue +3 -4
  190. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  191. package/list/management.cattle.io.setting.vue +2 -2
  192. package/list/management.cattle.io.user.vue +4 -10
  193. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  194. package/list/node.vue +8 -5
  195. package/list/persistentvolume.vue +3 -3
  196. package/list/persistentvolumeclaim.vue +3 -4
  197. package/list/provisioning.cattle.io.cluster.vue +18 -19
  198. package/list/service.vue +6 -14
  199. package/list/workload.vue +43 -38
  200. package/machine-config/azure.vue +429 -60
  201. package/machine-config/pnap.vue +288 -0
  202. package/mixins/auth-config.js +1 -3
  203. package/mixins/browser-tab-visibility.js +8 -14
  204. package/mixins/chart.js +1 -1
  205. package/mixins/create-edit-view/impl.js +4 -0
  206. package/mixins/create-edit-view/index.js +4 -2
  207. package/mixins/resource-fetch-namespaced.js +98 -0
  208. package/mixins/resource-fetch.js +79 -45
  209. package/mixins/resource-manager.js +1 -23
  210. package/models/apps.controllerrevision.js +7 -0
  211. package/models/apps.daemonset.js +18 -0
  212. package/models/apps.deployment.js +44 -0
  213. package/models/apps.replicaset.js +7 -0
  214. package/models/apps.statefulset.js +18 -0
  215. package/models/batch.job.js +7 -14
  216. package/models/cluster/node.js +10 -2
  217. package/models/cluster.x-k8s.io.machine.js +26 -4
  218. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  219. package/models/event.js +7 -0
  220. package/models/logging.banzaicloud.io.flow.js +4 -0
  221. package/models/management.cattle.io.cluster.js +1 -1
  222. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  223. package/models/management.cattle.io.globalrole.js +2 -2
  224. package/models/management.cattle.io.node.js +37 -2
  225. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  226. package/models/management.cattle.io.project.js +30 -11
  227. package/models/management.cattle.io.setting.js +1 -1
  228. package/models/management.cattle.io.user.js +37 -1
  229. package/models/namespace.js +42 -5
  230. package/models/persistentvolume.js +14 -2
  231. package/models/pod.js +15 -0
  232. package/models/projectroletemplatebinding.js +7 -0
  233. package/models/provisioning.cattle.io.cluster.js +61 -10
  234. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  235. package/models/service.js +14 -13
  236. package/models/storage.k8s.io.storageclass.js +33 -18
  237. package/models/workload.js +38 -7
  238. package/nuxt.config.js +27 -17
  239. package/package.json +7 -7
  240. package/pages/about.vue +14 -2
  241. package/pages/c/_cluster/apps/charts/index.vue +4 -3
  242. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  243. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  244. package/pages/c/_cluster/auth/config/index.vue +8 -6
  245. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  246. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  247. package/pages/c/_cluster/explorer/index.vue +12 -6
  248. package/pages/c/_cluster/longhorn/index.vue +1 -1
  249. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  250. package/pages/c/_cluster/monitoring/index.vue +1 -1
  251. package/pages/c/_cluster/neuvector/index.vue +1 -1
  252. package/pages/c/_cluster/settings/performance.vue +48 -2
  253. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
  254. package/pages/c/_cluster/uiplugins/index.vue +28 -2
  255. package/pages/diagnostic.vue +5 -4
  256. package/pages/home.vue +105 -30
  257. package/pages/prefs.vue +23 -12
  258. package/pages/rio/mesh.vue +1 -1
  259. package/pkg/dynamic-importer.lib.js +8 -0
  260. package/pkg/vue.config.js +4 -0
  261. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  262. package/plugins/dashboard-store/actions.js +32 -25
  263. package/plugins/dashboard-store/getters.js +50 -33
  264. package/plugins/dashboard-store/mutations.js +134 -28
  265. package/plugins/dashboard-store/resource-class.js +21 -41
  266. package/plugins/steve/actions.js +30 -0
  267. package/plugins/steve/caches/resourceCache.js +60 -0
  268. package/plugins/steve/getters.js +44 -1
  269. package/plugins/steve/mutations.js +97 -36
  270. package/plugins/steve/resourceWatcher.js +277 -0
  271. package/plugins/steve/schema.utils.js +25 -0
  272. package/plugins/steve/subscribe.js +288 -115
  273. package/plugins/steve/worker/index.js +17 -0
  274. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  275. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  276. package/rancher-components/Card/Card.vue +3 -3
  277. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  278. package/rancher-components/StringList/StringList.test.ts +45 -420
  279. package/rancher-components/StringList/StringList.vue +1 -10
  280. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  281. package/rancher-components/components/Banner/Banner.vue +129 -61
  282. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  283. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  284. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  285. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  286. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  287. package/rancher-components/components/StringList/StringList.vue +21 -15
  288. package/scripts/test-plugins-build.sh +8 -0
  289. package/static/loading-indicator.html +1 -1
  290. package/store/index.js +54 -3
  291. package/store/plugins.js +0 -17
  292. package/store/pnap.js +128 -0
  293. package/store/prefs.js +4 -2
  294. package/store/type-map.js +55 -13
  295. package/types/pod-security-admission.ts +36 -0
  296. package/types/shell/index.d.ts +496 -396
  297. package/utils/__tests__/object.test.ts +17 -1
  298. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  299. package/utils/async.ts +36 -0
  300. package/utils/color.js +45 -0
  301. package/utils/crypto/browserHashUtils.js +18 -0
  302. package/utils/dynamic-importer.js +8 -0
  303. package/utils/install-redirect.js +1 -1
  304. package/utils/object.js +24 -0
  305. package/utils/pod-security-admission.ts +39 -0
  306. package/utils/socket.js +61 -24
  307. package/utils/string.js +2 -0
  308. package/utils/svg-filter.js +301 -0
  309. package/utils/time.js +49 -0
  310. package/utils/validators/cidr.js +4 -0
  311. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  312. package/utils/validators/formRules/index.ts +14 -0
  313. package/config/product/harvester-manager.js +0 -162
  314. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  315. package/list/harvesterhci.io.management.cluster.vue +0 -241
  316. package/machine-config/harvester.vue +0 -693
  317. package/models/harvesterhci.io.management.cluster.js +0 -228
  318. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  319. package/rancher-components/Card/Card.test.ts +0 -39
  320. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  321. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  322. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -380,28 +380,27 @@ export default {
380
380
  // - resourceNames
381
381
  // - resources
382
382
  // - verbs
383
- const value = event.label ? event.label : event;
384
383
 
385
384
  switch (key) {
386
385
  case 'apiGroups':
387
386
 
388
- if (value || (value === '')) {
389
- this.$set(rule, 'apiGroups', [value]);
387
+ if (event || (event === '')) {
388
+ this.$set(rule, 'apiGroups', [event]);
390
389
  }
391
390
 
392
391
  break;
393
392
 
394
393
  case 'verbs':
395
394
 
396
- if (value) {
397
- this.$set(rule, 'verbs', [value]);
395
+ if (event) {
396
+ this.$set(rule, 'verbs', [event]);
398
397
  } else {
399
398
  this.$set(rule, 'verbs', []);
400
399
  }
401
400
  break;
402
401
 
403
402
  case 'resources':
404
- if (event.resourceName) {
403
+ if (event?.resourceName) {
405
404
  // If we are updating the resources defined in a rule,
406
405
  // the event will be an object with the
407
406
  // properties apiGroupValue and resourceName.
@@ -409,7 +408,7 @@ export default {
409
408
  // Automatically fill in the API group of the
410
409
  // selected resource.
411
410
  this.$set(rule, 'apiGroups', [event.apiGroupValue]);
412
- } else if (event.label) {
411
+ } else if (event?.label) {
413
412
  // When the user creates a new resource name in the resource
414
413
  // field instead of selecting an existing one,
415
414
  // we have to treat that differently because the incoming event
@@ -424,8 +423,8 @@ export default {
424
423
  break;
425
424
 
426
425
  case 'nonResourceURLs':
427
- if (value) {
428
- this.$set(rule, 'nonResourceURLs', [value]);
426
+ if (event) {
427
+ this.$set(rule, 'nonResourceURLs', [event]);
429
428
  } else {
430
429
  this.$set(rule, 'nonResourceURLs', []);
431
430
  }
@@ -447,6 +446,21 @@ export default {
447
446
  this.done();
448
447
  },
449
448
  async actuallySave(url) {
449
+ // Go through all of the grules and replace double quote apiGroups
450
+ // k8S documentation shows using empty rules as "" - we change this to empty string when used
451
+ this.value.rules?.forEach((rule) => {
452
+ if (rule.apiGroups) {
453
+ rule.apiGroups = rule.apiGroups.map((group) => {
454
+ // If the group is two double quotes ("") replace if with empty string
455
+ if (group.trim() === '\"\"') {
456
+ group = '';
457
+ }
458
+
459
+ return group;
460
+ });
461
+ }
462
+ });
463
+
450
464
  if ( this.isCreate ) {
451
465
  url = url || this.schema.linkFor('collection');
452
466
  await this.value.save({ url, redirectUnauthorized: false });
@@ -623,12 +637,7 @@ export default {
623
637
  </span>
624
638
  </div>
625
639
  <div :class="ruleClass">
626
- <span class="text-label">{{ t('rbac.roletemplate.tabs.grantResources.tableHeaders.apiGroups') }}
627
- <span
628
- v-if="isNamespaced"
629
- class="required"
630
- >*</span>
631
- </span>
640
+ <span class="text-label">{{ t('rbac.roletemplate.tabs.grantResources.tableHeaders.apiGroups') }}</span>
632
641
  </div>
633
642
  <div
634
643
  v-if="!isNamespaced"
@@ -670,7 +679,7 @@ export default {
670
679
  :value="getRule('apiGroups', props.row.value)"
671
680
  :disabled="isBuiltin"
672
681
  :mode="mode"
673
- @input="setRule('apiGroups', props.row.value, $event)"
682
+ @input="setRule('apiGroups', props.row.value, $event.target.value)"
674
683
  >
675
684
  </div>
676
685
  <div
@@ -681,7 +690,7 @@ export default {
681
690
  :value="getRule('nonResourceURLs', props.row.value)"
682
691
  :disabled="isBuiltin"
683
692
  :mode="mode"
684
- @input="setRule('nonResourceURLs', props.row.value, $event)"
693
+ @input="setRule('nonResourceURLs', props.row.value, $event.target.value)"
685
694
  >
686
695
  </div>
687
696
  </div>
@@ -40,7 +40,7 @@ export default {
40
40
  project: {
41
41
  type: Boolean,
42
42
  default: false
43
- },
43
+ }
44
44
  },
45
45
 
46
46
  async fetch() {
@@ -54,10 +54,11 @@ export default {
54
54
 
55
55
  data() {
56
56
  return {
57
- principals: null,
58
- searchStr: '',
59
- options: [],
60
- newValue: '',
57
+ principals: null,
58
+ searchStr: '',
59
+ options: [],
60
+ newValue: '',
61
+ tooltipContent: null,
61
62
  };
62
63
  },
63
64
 
@@ -94,6 +95,24 @@ export default {
94
95
  },
95
96
 
96
97
  methods: {
98
+ setTooltipContent() {
99
+ if (!this.retainSelection) {
100
+ return;
101
+ }
102
+ if (this.principals) {
103
+ const selected = this.principals.find(p => p.id === this.newValue);
104
+
105
+ this.tooltipContent = selected?.name;
106
+ } else {
107
+ this.tooltipContent = null;
108
+ }
109
+ },
110
+ resetTooltipContent() {
111
+ if (!this.retainSelection) {
112
+ return;
113
+ }
114
+ this.tooltipContent = null;
115
+ },
97
116
  add(id) {
98
117
  if (!id) {
99
118
  // Ignore attempts to select an invalid principal
@@ -156,6 +175,11 @@ export default {
156
175
  <LabeledSelect
157
176
  ref="labeled-select"
158
177
  v-model="newValue"
178
+ v-tooltip="{
179
+ content: tooltipContent,
180
+ placement: 'bottom',
181
+ classes: ['select-principal-tooltip']
182
+ }"
159
183
  :mode="mode"
160
184
  :label="label"
161
185
  :placeholder="placeholder"
@@ -166,6 +190,8 @@ export default {
166
190
  :class="{'retain-selection': retainSelection}"
167
191
  @input="add"
168
192
  @search="onSearch"
193
+ @on-open="resetTooltipContent()"
194
+ @on-close="setTooltipContent()"
169
195
  >
170
196
  <template v-slot:no-options="{ searching }">
171
197
  <template v-if="searching">
@@ -226,4 +252,9 @@ export default {
226
252
  text-overflow: ellipsis;
227
253
  }
228
254
  }
255
+
256
+ .select-principal-tooltip {
257
+ max-width: 580px;
258
+ word-wrap: break-word;
259
+ }
229
260
  </style>
@@ -5,13 +5,11 @@ import { removeAt } from '@shell/utils/array';
5
5
  import { TextAreaAutoGrow } from '@components/Form/TextArea';
6
6
  import { clone } from '@shell/utils/object';
7
7
  import { LabeledInput } from '@components/Form/LabeledInput';
8
-
9
8
  const DEFAULT_PROTIP = 'Tip: Paste lines into any list field for easy bulk entry';
10
9
 
11
10
  export default {
12
11
  components: { TextAreaAutoGrow, LabeledInput },
13
-
14
- props: {
12
+ props: {
15
13
  value: {
16
14
  type: Array,
17
15
  default: null,
@@ -24,7 +22,6 @@ export default {
24
22
  type: Boolean,
25
23
  default: false,
26
24
  },
27
-
28
25
  title: {
29
26
  type: String,
30
27
  default: ''
@@ -37,7 +34,6 @@ export default {
37
34
  type: Boolean,
38
35
  default: false,
39
36
  },
40
-
41
37
  valueLabel: {
42
38
  type: String,
43
39
  default: 'Value',
@@ -50,7 +46,6 @@ export default {
50
46
  type: Boolean,
51
47
  default: false,
52
48
  },
53
-
54
49
  addLabel: {
55
50
  type: String,
56
51
  default() {
@@ -61,7 +56,6 @@ export default {
61
56
  type: Boolean,
62
57
  default: true,
63
58
  },
64
-
65
59
  removeLabel: {
66
60
  type: String,
67
61
  default() {
@@ -72,22 +66,18 @@ export default {
72
66
  type: Boolean,
73
67
  default: true,
74
68
  },
75
-
76
69
  defaultAddValue: {
77
70
  type: [String, Number, Object, Array],
78
71
  default: ''
79
72
  },
80
-
81
73
  loading: {
82
74
  type: Boolean,
83
75
  default: false
84
76
  },
85
-
86
77
  disabled: {
87
78
  type: Boolean,
88
79
  default: false,
89
80
  },
90
-
91
81
  rules: {
92
82
  default: () => [],
93
83
  type: Array,
@@ -95,7 +85,6 @@ export default {
95
85
  validator: rules => rules.every(rule => ['function'].includes(typeof rule))
96
86
  }
97
87
  },
98
-
99
88
  data() {
100
89
  const input = (this.value || []).slice();
101
90
  const rows = [];
@@ -103,7 +92,6 @@ export default {
103
92
  for ( const value of input ) {
104
93
  rows.push({ value });
105
94
  }
106
-
107
95
  if ( !rows.length && this.initialEmptyRow ) {
108
96
  const value = this.defaultAddValue ? clone(this.defaultAddValue) : '';
109
97
 
@@ -112,24 +100,19 @@ export default {
112
100
 
113
101
  return { rows, lastUpdateWasFromValue: false };
114
102
  },
115
-
116
103
  computed: {
117
104
  isView() {
118
105
  return this.mode === _VIEW;
119
106
  },
120
-
121
107
  showAdd() {
122
108
  return this.addAllowed;
123
109
  },
124
-
125
110
  showRemove() {
126
111
  return this.removeAllowed;
127
112
  },
128
-
129
113
  isDefaultProtip() {
130
114
  return this.protip === DEFAULT_PROTIP;
131
115
  },
132
-
133
116
  showProtip() {
134
117
  if (this.protip && !this.isDefaultProtip) {
135
118
  return true;
@@ -138,7 +121,6 @@ export default {
138
121
  return !this.valueMultiline && this.protip;
139
122
  }
140
123
  },
141
-
142
124
  watch: {
143
125
  value() {
144
126
  this.lastUpdateWasFromValue = true;
@@ -156,29 +138,24 @@ export default {
156
138
  }
157
139
  }
158
140
  },
159
-
160
141
  created() {
161
142
  this.queueUpdate = debounce(this.update, 50);
162
143
  },
163
-
164
144
  methods: {
165
145
  add() {
166
146
  this.rows.push({ value: clone(this.defaultAddValue) });
167
147
  if (this.defaultAddValue) {
168
148
  this.queueUpdate();
169
149
  }
170
-
171
150
  this.$nextTick(() => {
172
151
  const inputs = this.$refs.value;
173
152
 
174
153
  if ( inputs && inputs.length > 0 ) {
175
154
  inputs[inputs.length - 1].focus();
176
155
  }
177
-
178
156
  this.$emit('add');
179
157
  });
180
158
  },
181
-
182
159
  /**
183
160
  * Remove item and emits removed row and its own index value
184
161
  */
@@ -187,12 +164,10 @@ export default {
187
164
  removeAt(this.rows, index);
188
165
  this.queueUpdate();
189
166
  },
190
-
191
167
  update() {
192
168
  if ( this.isView ) {
193
169
  return;
194
170
  }
195
-
196
171
  const out = [];
197
172
 
198
173
  for ( const row of this.rows ) {
@@ -203,15 +178,12 @@ export default {
203
178
  out.push(value);
204
179
  }
205
180
  }
206
-
207
181
  this.$emit('input', out);
208
182
  },
209
-
210
183
  onPaste(index, event) {
211
184
  if (this.valueMultiline) {
212
185
  return;
213
186
  }
214
-
215
187
  event.preventDefault();
216
188
  const text = event.clipboardData.getData('text/plain');
217
189
  const split = text.split('\n').map(value => ({ value }));
@@ -252,6 +224,7 @@ export default {
252
224
  <div
253
225
  v-for="(row, idx) in rows"
254
226
  :key="idx"
227
+ data-testid="array-list-box"
255
228
  class="box"
256
229
  >
257
230
  <slot
@@ -349,7 +322,7 @@ export default {
349
322
  type="button"
350
323
  class="btn role-tertiary add"
351
324
  :disabled="loading"
352
- data-testid="add-item"
325
+ data-testid="array-list-button"
353
326
  @click="add()"
354
327
  >
355
328
  <i
@@ -366,14 +339,11 @@ export default {
366
339
  <style lang="scss" scoped>
367
340
  .title {
368
341
  margin-bottom: 10px;
369
-
370
342
  }
371
-
372
343
  .box {
373
344
  display: grid;
374
345
  grid-template-columns: auto $array-list-remove-margin;
375
346
  align-items: center;
376
-
377
347
  margin-bottom: 10px;
378
348
  .value {
379
349
  flex: 1;
@@ -382,11 +352,9 @@ export default {
382
352
  }
383
353
  }
384
354
  }
385
-
386
355
  .remove {
387
356
  text-align: right;
388
357
  }
389
-
390
358
  .footer {
391
359
  .protip {
392
360
  float: right;
@@ -4,6 +4,7 @@ import InfoBox from '@shell/components/InfoBox';
4
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
5
5
 
6
6
  export default {
7
+ name: 'ArrayListGrouped',
7
8
  components: { ArrayList, InfoBox },
8
9
  props: {
9
10
  /**
@@ -21,6 +22,13 @@ export default {
21
22
  type: Boolean,
22
23
  default: true,
23
24
  },
25
+ /**
26
+ * Start with empty row
27
+ */
28
+ initialEmptyRow: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
24
32
 
25
33
  /**
26
34
  * Form mode for the component
@@ -51,7 +59,7 @@ export default {
51
59
  }
52
60
 
53
61
  return this.canRemove;
54
- }
62
+ },
55
63
  }
56
64
  };
57
65
  </script>
@@ -62,6 +70,7 @@ export default {
62
70
  v-bind="$attrs"
63
71
  :add-allowed="canAdd && !isView"
64
72
  :mode="mode"
73
+ :initial-empty-row="initialEmptyRow"
65
74
  @input="$emit('input', $event)"
66
75
  @add="$emit('add')"
67
76
  @remove="$emit('remove', $event)"
@@ -79,7 +88,7 @@ export default {
79
88
  :data-testid="`remove-item-${scope.i}`"
80
89
  @click="scope.remove"
81
90
  >
82
- <i class="icon icon-2x icon-x" />
91
+ <i class="icon icon-x" />
83
92
  </button>
84
93
  <span v-else />
85
94
  </template>
@@ -105,15 +114,15 @@ export default {
105
114
  & > .remove {
106
115
  position: absolute;
107
116
 
108
- padding: 0px;
109
-
110
117
  top: 0;
111
118
  right: 0;
112
119
  }
113
120
 
114
121
  & > .info-box {
115
122
  margin-bottom: 0;
123
+ padding-right: 25px;
116
124
  }
117
125
  }
118
126
  }
127
+
119
128
  </style>
@@ -65,11 +65,11 @@ export default {
65
65
  @input="$emit('input', $event)"
66
66
  >
67
67
  <template v-slot:columns="scope">
68
- <Select
69
- :value="scope.row.value"
70
- v-bind="selectProps"
71
- :options="calculateOptions(scope.row.value)"
72
- @input="updateRow(scope.i, $event)"
68
+ <Select
69
+ :value="scope.row.value"
70
+ v-bind="selectProps"
71
+ :options="calculateOptions(scope.row.value)"
72
+ @input="updateRow(scope.i, $event)"
73
73
  />
74
74
  </template>
75
75
  </ArrayList>
@@ -15,6 +15,13 @@ export default Vue.extend<any, any, any, any>({
15
15
  default: () => [],
16
16
  type: Array as PropType<Rule[]>,
17
17
  },
18
+ /**
19
+ * Add icon for the banner
20
+ */
21
+ icon: {
22
+ type: String,
23
+ default: null
24
+ },
18
25
  asBanner: {
19
26
  default: false,
20
27
  type: Boolean
@@ -49,6 +56,7 @@ export default Vue.extend<any, any, any, any>({
49
56
  v-if="!!asBanner && !!validationMessage"
50
57
  color="error"
51
58
  :label="validationMessage"
59
+ :icon="icon"
52
60
  />
53
61
  <span
54
62
  v-else-if="!!validationMessage"
@@ -96,6 +96,20 @@ export default {
96
96
  return this.$store.getters['i18n/t']('keyValue.keyPlaceholder');
97
97
  },
98
98
  },
99
+ /**
100
+ * List of keys which needs to be disabled and hidden based on toggler
101
+ */
102
+ protectedKeys: {
103
+ type: Array,
104
+ default: () => [],
105
+ },
106
+ /**
107
+ * Conditionally display protected keys, if any
108
+ */
109
+ toggleFilter: {
110
+ type: Boolean,
111
+ default: false,
112
+ },
99
113
  separatorLabel: {
100
114
  type: String,
101
115
  default: '',
@@ -235,7 +249,6 @@ export default {
235
249
  },
236
250
 
237
251
  computed: {
238
-
239
252
  isView() {
240
253
  return this.mode === _VIEW;
241
254
  },
@@ -261,6 +274,12 @@ export default {
261
274
  */
262
275
  canRemove() {
263
276
  return !this.isView && this.removeAllowed;
277
+ },
278
+ /**
279
+ * Filter rows based on toggler, keeping to still emit all the values
280
+ */
281
+ filteredRows() {
282
+ return this.rows.filter(row => !(this.isProtected(row.key) && !this.toggleFilter));
264
283
  }
265
284
  },
266
285
  created() {
@@ -275,6 +294,10 @@ export default {
275
294
  }
276
295
  },
277
296
  methods: {
297
+ isProtected(key) {
298
+ return this.protectedKeys && this.protectedKeys.includes(key);
299
+ },
300
+
278
301
  getRows(value) {
279
302
  const rows = [];
280
303
 
@@ -325,7 +348,7 @@ export default {
325
348
  rows.push(entry);
326
349
  }
327
350
  }
328
- if ( !rows.length && this.initialEmptyRow ) {
351
+ if ( rows && !rows.length && this.initialEmptyRow ) {
329
352
  rows.push({
330
353
  [this.keyName]: '',
331
354
  [this.valueName]: '',
@@ -389,6 +412,10 @@ export default {
389
412
  this.add(key, value);
390
413
  }
391
414
  });
415
+
416
+ if (lines.length > 0) {
417
+ this.removeEmptyRows();
418
+ }
392
419
  }
393
420
  },
394
421
  download(idx, ev) {
@@ -550,9 +577,10 @@ export default {
550
577
  </div>
551
578
  </template>
552
579
  <template
553
- v-for="(row,i) in rows"
580
+ v-for="(row,i) in filteredRows"
554
581
  v-else
555
582
  >
583
+ <!-- Key -->
556
584
  <div
557
585
  :key="i+'key'"
558
586
  class="kv-item key"
@@ -570,6 +598,7 @@ export default {
570
598
  ref="key"
571
599
  v-model="row[keyName]"
572
600
  :searchable="true"
601
+ :disabled="isProtected(row.key)"
573
602
  :clearable="false"
574
603
  :taggable="keyTaggable"
575
604
  :options="calculateOptions(row[keyName])"
@@ -579,13 +608,15 @@ export default {
579
608
  v-else
580
609
  ref="key"
581
610
  v-model="row[keyName]"
582
- :disabled="isView || !keyEditable"
611
+ :disabled="isView || !keyEditable || isProtected(row.key)"
583
612
  :placeholder="keyPlaceholder"
584
613
  @input="queueUpdate"
585
614
  @paste="onPaste(i, $event)"
586
615
  >
587
616
  </slot>
588
617
  </div>
618
+
619
+ <!-- Value -->
589
620
  <div
590
621
  :key="i+'value'"
591
622
  class="kv-item value"
@@ -608,6 +639,7 @@ export default {
608
639
  v-else-if="valueMultiline"
609
640
  v-model="row[valueName]"
610
641
  :class="{'conceal': valueConcealed}"
642
+ :disabled="isProtected(row.key)"
611
643
  :mode="mode"
612
644
  :placeholder="valuePlaceholder"
613
645
  :min-height="40"
@@ -617,7 +649,7 @@ export default {
617
649
  <input
618
650
  v-else
619
651
  v-model="row[valueName]"
620
- :disabled="isView"
652
+ :disabled="isView || isProtected(row.key)"
621
653
  :type="valueConcealed ? 'password' : 'text'"
622
654
  :placeholder="valuePlaceholder"
623
655
  autocorrect="off"
@@ -652,7 +684,7 @@ export default {
652
684
  >
653
685
  <button
654
686
  type="button"
655
- :disabled="isView"
687
+ :disabled="isView || isProtected(row.key)"
656
688
  class="btn role-link"
657
689
  @click="remove(i)"
658
690
  >
@@ -664,7 +696,7 @@ export default {
664
696
  </div>
665
697
  <div
666
698
  v-if="(addAllowed || readAllowed) && !isView"
667
- class="footer"
699
+ class="footer mt-20"
668
700
  >
669
701
  <slot
670
702
  name="add"
@@ -150,6 +150,10 @@ export default {
150
150
  this.resizeHandler();
151
151
  },
152
152
 
153
+ onClose() {
154
+ this.$emit('on-close');
155
+ },
156
+
153
157
  getOptionLabel(option) {
154
158
  if (!option) {
155
159
  return;
@@ -277,6 +281,7 @@ export default {
277
281
  @search:focus="onFocus"
278
282
  @search="onSearch"
279
283
  @open="onOpen"
284
+ @close="onClose"
280
285
  @option:selected="$emit('selecting', $event)"
281
286
  >
282
287
  <template #option="option">
@@ -456,9 +461,7 @@ export default {
456
461
 
457
462
  ::v-deep .vs__actions {
458
463
  &:after {
459
- line-height: 1.85rem;
460
464
  position: relative;
461
- right: 3px;
462
465
  top: -10px;
463
466
  }
464
467
  }