@rancher/shell 3.0.12-rc.3 → 3.0.12-rc.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 (315) hide show
  1. package/assets/styles/global/_button.scss +1 -1
  2. package/assets/styles/global/_layout.scss +4 -0
  3. package/assets/translations/en-us.yaml +183 -51
  4. package/assets/translations/zh-hans.yaml +1 -7
  5. package/chart/monitoring/ClusterSelector.vue +0 -21
  6. package/chart/monitoring/prometheus/index.vue +6 -3
  7. package/components/ActionDropdownShell.vue +5 -3
  8. package/components/ButtonGroup.vue +26 -1
  9. package/components/CruResource.vue +212 -16
  10. package/components/ExplorerMembers.vue +8 -4
  11. package/components/ExplorerProjectsNamespaces.vue +10 -6
  12. package/components/GrowlManager.vue +4 -0
  13. package/components/MgmtNodeList.vue +184 -0
  14. package/components/PromptRestore.vue +93 -32
  15. package/components/Questions/index.vue +1 -0
  16. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
  17. package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
  18. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
  19. package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
  20. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +2 -0
  21. package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
  22. package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
  23. package/components/ResourceDetail/index.vue +1 -1
  24. package/components/ResourceList/Masthead.vue +7 -1
  25. package/components/ResourceList/index.vue +82 -1
  26. package/components/ResourceTable.vue +1 -0
  27. package/components/RichTranslation.vue +5 -2
  28. package/components/Setting.vue +1 -0
  29. package/components/SortableTable/index.vue +4 -3
  30. package/components/SubtleLink.vue +31 -6
  31. package/components/Tabbed/Tab.vue +29 -3
  32. package/components/Tabbed/index.vue +25 -3
  33. package/components/TableOfContents/TableOfContents.vue +109 -0
  34. package/components/TableOfContents/composables.ts +258 -0
  35. package/components/Window/ContainerShell.vue +21 -11
  36. package/components/Window/__tests__/ContainerShell.test.ts +107 -37
  37. package/components/Wizard.vue +23 -5
  38. package/components/__tests__/ButtonGroup.test.ts +56 -0
  39. package/components/__tests__/PromptRestore.test.ts +169 -19
  40. package/components/fleet/AppCoChartGrid.vue +401 -0
  41. package/components/fleet/AppCoEmptyState.vue +127 -0
  42. package/components/fleet/AppCoPageHeader.vue +119 -0
  43. package/components/fleet/AppCoVersionSelect.vue +70 -0
  44. package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
  45. package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
  46. package/components/fleet/FleetClusterTargets/index.vue +189 -146
  47. package/components/fleet/FleetIntro.vue +7 -3
  48. package/components/fleet/FleetNoWorkspaces.vue +7 -3
  49. package/components/fleet/FleetSecretSelector.vue +5 -3
  50. package/components/fleet/FleetValuesFrom.vue +8 -2
  51. package/components/fleet/GitRepoAdvancedTab.vue +1 -0
  52. package/components/fleet/GitRepoMetadataTab.vue +5 -0
  53. package/components/fleet/GitRepoTargetTab.vue +0 -2
  54. package/components/fleet/HelmOpAdvancedTab.vue +19 -53
  55. package/components/fleet/HelmOpAppCoConfigTab.vue +597 -0
  56. package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
  57. package/components/fleet/HelmOpMetadataTab.vue +5 -0
  58. package/components/fleet/HelmOpResourcesSection.vue +82 -0
  59. package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
  60. package/components/fleet/HelmOpTargetTab.vue +64 -60
  61. package/components/fleet/HelmOpValuesTab.vue +129 -105
  62. package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
  63. package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
  64. package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
  65. package/components/fleet/__tests__/FleetClusterTargets.test.ts +253 -0
  66. package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
  67. package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
  68. package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
  69. package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
  70. package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
  71. package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
  72. package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
  73. package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
  74. package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
  75. package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
  76. package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
  77. package/components/fleet/dashboard/Empty.vue +8 -4
  78. package/components/fleet/dashboard/ResourceCard.vue +28 -0
  79. package/components/fleet/dashboard/ResourceDetails.vue +28 -0
  80. package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
  81. package/components/form/ArrayList.vue +61 -4
  82. package/components/form/FileSelector.vue +39 -1
  83. package/components/form/KeyValue.vue +23 -2
  84. package/components/form/LabeledSelect.vue +39 -1
  85. package/components/form/Labels.vue +22 -3
  86. package/components/form/NameNsDescription.vue +13 -5
  87. package/components/form/PrivateRegistry.constants.ts +7 -0
  88. package/components/form/PrivateRegistry.vue +253 -18
  89. package/components/form/ResourceTabs/index.vue +1 -0
  90. package/components/form/SelectOrCreateAuthSecret.vue +140 -17
  91. package/components/form/__tests__/FileSelector.test.ts +23 -0
  92. package/components/form/__tests__/NameNsDescription.test.ts +75 -0
  93. package/components/form/__tests__/PrivateRegistry.test.ts +463 -73
  94. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +122 -0
  95. package/components/formatter/EtcdSnapshotName.vue +73 -0
  96. package/components/formatter/InternalExternalIP.vue +10 -4
  97. package/components/formatter/ServiceTargets.vue +26 -7
  98. package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
  99. package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
  100. package/components/nav/Header.vue +12 -1
  101. package/components/nav/TopLevelMenu.vue +7 -2
  102. package/components/nav/__tests__/Header.test.ts +15 -0
  103. package/components/nav/__tests__/TopLevelMenu.test.ts +120 -2
  104. package/components/templates/default.vue +16 -4
  105. package/components/templates/home.vue +9 -4
  106. package/components/templates/plain.vue +9 -4
  107. package/composables/useHelmOpResources.test.ts +56 -0
  108. package/composables/useHelmOpResources.ts +32 -0
  109. package/composables/useStateColor.test.ts +325 -0
  110. package/composables/useStateColor.ts +128 -0
  111. package/config/features.js +1 -0
  112. package/config/home-links.js +1 -1
  113. package/config/labels-annotations.js +3 -0
  114. package/config/product/explorer.js +17 -4
  115. package/config/product/manager.js +8 -0
  116. package/config/router/index.js +16 -0
  117. package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
  118. package/config/router/navigation-guards/authentication.js +10 -4
  119. package/config/router/routes.js +20 -6
  120. package/config/secret.ts +10 -0
  121. package/config/settings.ts +6 -4
  122. package/config/table-headers.js +3 -4
  123. package/config/types.js +16 -0
  124. package/core/plugin-products-base.ts +3 -3
  125. package/core/plugin-types.ts +83 -30
  126. package/core/plugin.ts +3 -0
  127. package/core/types-provisioning.ts +34 -1
  128. package/core/types.ts +15 -2
  129. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
  130. package/detail/__tests__/workload.test.ts +3 -152
  131. package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
  132. package/detail/provisioning.cattle.io.cluster.vue +109 -7
  133. package/detail/workload/index.vue +12 -55
  134. package/dialog/RotateEncryptionKeyDialog.vue +33 -9
  135. package/dialog/__tests__/RotateEncryptionKeyDialog.test.ts +78 -0
  136. package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
  137. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +92 -0
  138. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +206 -0
  139. package/edit/__tests__/management.cattle.io.setting.test.ts +2 -1
  140. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  141. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
  142. package/edit/auth/__tests__/azuread.test.ts +34 -9
  143. package/edit/auth/__tests__/github.test.ts +234 -0
  144. package/edit/auth/__tests__/oidc.test.ts +26 -6
  145. package/edit/auth/__tests__/saml.test.ts +196 -0
  146. package/edit/auth/azuread.vue +128 -95
  147. package/edit/auth/github.vue +72 -13
  148. package/edit/auth/ldap/__tests__/index.test.ts +206 -0
  149. package/edit/auth/ldap/config.vue +8 -0
  150. package/edit/auth/ldap/index.vue +75 -1
  151. package/edit/auth/oidc.vue +119 -73
  152. package/edit/auth/saml.vue +76 -12
  153. package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
  154. package/edit/compliance.cattle.io.clusterscanprofile.vue +39 -41
  155. package/edit/fleet.cattle.io.gitrepo.vue +70 -16
  156. package/edit/fleet.cattle.io.helmop.vue +542 -141
  157. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  158. package/edit/{management.cattle.io.setting.vue → management.cattle.io.setting/index.vue} +32 -9
  159. package/edit/management.cattle.io.setting/system-default-registry-pull-secrets.vue +81 -0
  160. package/edit/management.cattle.io.user.vue +5 -2
  161. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -12
  162. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +18 -0
  163. package/edit/provisioning.cattle.io.cluster/rke2.vue +89 -11
  164. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
  165. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +0 -1
  166. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +14 -55
  167. package/list/group.principal.vue +5 -4
  168. package/list/harvesterhci.io.management.cluster.vue +8 -9
  169. package/list/management.cattle.io.user.vue +12 -9
  170. package/list/provisioning.cattle.io.cluster.vue +16 -10
  171. package/mixins/__tests__/auth-config.test.ts +90 -0
  172. package/mixins/__tests__/chart.test.ts +94 -0
  173. package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
  174. package/mixins/auth-config.js +7 -0
  175. package/mixins/chart.js +11 -2
  176. package/mixins/child-hook.js +12 -6
  177. package/mixins/create-edit-view/impl.js +5 -3
  178. package/mixins/resource-fetch-api-pagination.js +21 -1
  179. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
  180. package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
  181. package/models/__tests__/fleet-application.test.ts +175 -0
  182. package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
  183. package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
  184. package/models/__tests__/management.cattle.io.node.ts +22 -0
  185. package/models/__tests__/namespace.test.ts +36 -0
  186. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +205 -0
  187. package/models/__tests__/secret.test.ts +68 -1
  188. package/models/__tests__/workload.test.ts +401 -26
  189. package/models/catalog.cattle.io.clusterrepo.js +28 -4
  190. package/models/compliance.cattle.io.clusterscan.js +39 -4
  191. package/models/fleet-application.js +4 -0
  192. package/models/fleet.cattle.io.helmop.js +20 -1
  193. package/models/management.cattle.io.cluster.js +39 -5
  194. package/models/management.cattle.io.node.js +44 -3
  195. package/models/namespace.js +1 -1
  196. package/models/pod.js +46 -3
  197. package/models/provisioning.cattle.io.cluster.js +64 -14
  198. package/models/rke.cattle.io.etcdsnapshot.js +17 -9
  199. package/models/secret.js +19 -0
  200. package/models/workload.js +120 -20
  201. package/models/workload.service.js +5 -0
  202. package/package.json +14 -13
  203. package/pages/about.vue +5 -6
  204. package/pages/auth/login.vue +0 -35
  205. package/pages/auth/setup.vue +11 -0
  206. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
  207. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
  208. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
  209. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +485 -107
  210. package/pages/c/_cluster/apps/charts/chart.vue +2 -1
  211. package/pages/c/_cluster/apps/charts/index.vue +48 -10
  212. package/pages/c/_cluster/apps/charts/install.vue +236 -144
  213. package/pages/c/_cluster/auth/roles/index.vue +5 -4
  214. package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
  215. package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
  216. package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
  217. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
  218. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
  219. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
  220. package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
  221. package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
  222. package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
  223. package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
  224. package/pages/c/_cluster/fleet/application/create.vue +187 -136
  225. package/pages/c/_cluster/fleet/application/index.vue +5 -3
  226. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
  227. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
  228. package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
  229. package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
  230. package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
  231. package/pages/c/_cluster/fleet/index.vue +2 -2
  232. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +96 -0
  233. package/pages/c/_cluster/uiplugins/index.vue +15 -0
  234. package/pages/fail-whale.vue +16 -11
  235. package/pages/home.vue +16 -46
  236. package/pkg/require-asset.lib.js +25 -0
  237. package/pkg/vue.config.js +7 -0
  238. package/plugins/clean-html.d.ts +9 -0
  239. package/plugins/dashboard-store/__tests__/resource-class.test.ts +177 -0
  240. package/plugins/dashboard-store/getters.js +0 -1
  241. package/plugins/dashboard-store/resource-class.js +114 -19
  242. package/plugins/steve/__tests__/actions.test.ts +212 -0
  243. package/plugins/steve/actions.js +96 -0
  244. package/plugins/steve/steve-pagination-utils.ts +1 -1
  245. package/rancher-components/Accordion/Accordion.vue +53 -9
  246. package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
  247. package/rancher-components/Form/Radio/RadioButton.vue +17 -1
  248. package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
  249. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +30 -0
  250. package/rancher-components/Form/TextArea/__tests__/TextAreaAutoGrow.test.ts +95 -0
  251. package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
  252. package/rancher-components/RcButton/RcButton.test.ts +103 -0
  253. package/rancher-components/RcButton/RcButton.vue +94 -15
  254. package/rancher-components/RcButton/index.ts +1 -1
  255. package/rancher-components/RcButton/types.ts +3 -0
  256. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +6 -1
  257. package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
  258. package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
  259. package/rancher-components/RcSection/RcSection.vue +28 -3
  260. package/scripts/extension/helm/package/Dockerfile +1 -1
  261. package/scripts/test-plugins-build.sh +2 -1
  262. package/store/__tests__/features.test.ts +131 -0
  263. package/store/__tests__/growl.test.ts +374 -0
  264. package/store/__tests__/modal.test.ts +131 -0
  265. package/store/__tests__/notifications.test.ts +434 -0
  266. package/store/__tests__/slideInPanel.test.ts +88 -0
  267. package/store/__tests__/type-map.utils.test.ts +433 -0
  268. package/store/catalog.js +57 -0
  269. package/store/features.js +4 -0
  270. package/store/plugins.js +7 -4
  271. package/types/components/buttonGroup.ts +5 -0
  272. package/types/shell/index.d.ts +166 -70
  273. package/utils/__tests__/auth.test.ts +273 -0
  274. package/utils/__tests__/computed.test.ts +193 -0
  275. package/utils/__tests__/cspAdaptor.test.ts +163 -0
  276. package/utils/__tests__/dom.test.ts +81 -0
  277. package/utils/__tests__/duration.test.ts +37 -1
  278. package/utils/__tests__/dynamic-importer.test.ts +102 -0
  279. package/utils/__tests__/fleet-appco.test.ts +312 -0
  280. package/utils/__tests__/monitoring.test.ts +130 -0
  281. package/utils/__tests__/object.test.ts +22 -0
  282. package/utils/__tests__/operation-cr.test.ts +34 -0
  283. package/utils/__tests__/platform.test.ts +91 -0
  284. package/utils/__tests__/position.test.ts +237 -0
  285. package/utils/__tests__/provider.test.ts +51 -1
  286. package/utils/__tests__/queue.test.ts +232 -0
  287. package/utils/__tests__/release-notes.test.ts +221 -0
  288. package/utils/__tests__/router.test.js +254 -1
  289. package/utils/__tests__/select.test.ts +208 -0
  290. package/utils/__tests__/time.test.ts +265 -1
  291. package/utils/__tests__/title.test.ts +47 -0
  292. package/utils/__tests__/width.test.ts +53 -0
  293. package/utils/__tests__/window.test.ts +158 -0
  294. package/utils/__tests__/xccdf.test.ts +126 -6
  295. package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
  296. package/utils/crypto/__tests__/index.test.ts +144 -0
  297. package/utils/duration.ts +104 -0
  298. package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
  299. package/utils/dynamic-content/info.ts +2 -1
  300. package/utils/error.js +13 -0
  301. package/utils/fleet-appco.ts +323 -0
  302. package/utils/object.js +22 -2
  303. package/utils/operation-cr.js +19 -0
  304. package/utils/provider.ts +12 -0
  305. package/utils/require-asset.ts +7 -0
  306. package/utils/validators/__tests__/container-images.test.ts +104 -0
  307. package/utils/validators/__tests__/flow-output.test.ts +91 -0
  308. package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
  309. package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
  310. package/utils/validators/__tests__/private-registry.test.ts +27 -15
  311. package/utils/validators/private-registry.ts +15 -4
  312. package/utils/xccdf.ts +39 -42
  313. package/vue.config.js +1 -1
  314. package/pages/support/index.vue +0 -264
  315. package/utils/duration.js +0 -43
@@ -1,18 +1,22 @@
1
1
  <script>
2
- import { ref, watch, computed } from 'vue';
2
+ import { ref, watch, computed, toRef } from 'vue';
3
3
  import debounce from 'lodash/debounce';
4
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
5
5
  import { removeAt } from '@shell/utils/array';
6
6
  import { TextAreaAutoGrow } from '@components/Form/TextArea';
7
7
  import { clone } from '@shell/utils/object';
8
8
  import { LabeledInput } from '@components/Form/LabeledInput';
9
+ import Banner from '@components/Banner/Banner.vue';
10
+ import { useVeeValidateField } from '@shell/composables/useVeeValidateField';
9
11
  const DEFAULT_PROTIP = 'Tip: Paste lines into any list field for easy bulk entry';
10
12
 
11
13
  export default {
12
14
  emits: ['add', 'remove', 'update:value'],
13
15
 
14
- components: { TextAreaAutoGrow, LabeledInput },
15
- props: {
16
+ components: {
17
+ TextAreaAutoGrow, LabeledInput, Banner
18
+ },
19
+ props: {
16
20
  value: {
17
21
  type: Array,
18
22
  default: null,
@@ -106,7 +110,17 @@ export default {
106
110
  componentTestid: {
107
111
  type: String,
108
112
  default: 'array-list',
109
- }
113
+ },
114
+
115
+ /**
116
+ * Field name for vee-validate integration. When provided, the component
117
+ * registers with a parent form context for schema-level validation.
118
+ */
119
+ name: {
120
+ type: String,
121
+ default: null,
122
+ },
123
+
110
124
  },
111
125
 
112
126
  setup(props, { emit }) {
@@ -126,6 +140,26 @@ export default {
126
140
  return props.mode === _VIEW;
127
141
  });
128
142
 
143
+ // vee-validate integration: array-level validation via a parent form schema.
144
+ // Per-item validation continues to use the existing `rules` prop on
145
+ // LabeledInput.
146
+ const arrayValue = computed(() => props.value || []);
147
+ const { effectiveValidationMessage, veeHandleBlur, veeValidate } = useVeeValidateField({
148
+ name: toRef(props, 'name'),
149
+ rules: ref([]),
150
+ value: arrayValue,
151
+ validationMessage: ref(null),
152
+ });
153
+
154
+ // Only structural changes (add, delete, paste) mark trigger validation
155
+ // when invoking update()
156
+ const isStructuralChange = ref(false);
157
+
158
+ const validate = () => {
159
+ veeHandleBlur(undefined, false);
160
+ veeValidate();
161
+ };
162
+
129
163
  /**
130
164
  * Cleanup rows and emit input
131
165
  */
@@ -144,6 +178,10 @@ export default {
144
178
  }
145
179
  }
146
180
  emit('update:value', out);
181
+ if (isStructuralChange.value) {
182
+ validate();
183
+ isStructuralChange.value = false;
184
+ }
147
185
  };
148
186
 
149
187
  const lastUpdateWasFromValue = ref(false);
@@ -177,6 +215,9 @@ export default {
177
215
  queueUpdate,
178
216
  isView,
179
217
  update,
218
+ effectiveValidationMessage,
219
+ isStructuralChange,
220
+ validate,
180
221
  };
181
222
  },
182
223
 
@@ -211,6 +252,7 @@ export default {
211
252
  },
212
253
  methods: {
213
254
  add() {
255
+ this.isStructuralChange = true;
214
256
  this.rows.push({ value: clone(this.defaultAddValue) });
215
257
  if (this.defaultAddValue) {
216
258
  this.queueUpdate();
@@ -229,6 +271,7 @@ export default {
229
271
  */
230
272
  remove(row, index) {
231
273
  this.$emit('remove', { row, index });
274
+ this.isStructuralChange = true;
232
275
  removeAt(this.rows, index);
233
276
  this.queueUpdate();
234
277
  },
@@ -240,6 +283,7 @@ export default {
240
283
  event.preventDefault();
241
284
  const text = event.clipboardData.getData('text/plain');
242
285
 
286
+ this.isStructuralChange = true;
243
287
  if (this.valueMultiline) {
244
288
  // Allow to paste multiple lines
245
289
  this.rows[index].value = text;
@@ -285,6 +329,12 @@ export default {
285
329
  </h3>
286
330
  </slot>
287
331
  </div>
332
+ <Banner
333
+ v-if="effectiveValidationMessage"
334
+ class="validation-banner"
335
+ color="error"
336
+ :label="effectiveValidationMessage"
337
+ />
288
338
 
289
339
  <div>
290
340
  <template v-if="rows.length">
@@ -335,6 +385,7 @@ export default {
335
385
  :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
336
386
  @paste="onPaste(idx, $event)"
337
387
  @update:value="queueUpdate"
388
+ @blur="validate"
338
389
  />
339
390
  <LabeledInput
340
391
  v-else-if="rules.length > 0"
@@ -348,6 +399,7 @@ export default {
348
399
  :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
349
400
  @paste="onPaste(idx, $event)"
350
401
  @update:value="queueUpdate"
402
+ @blur="validate"
351
403
  />
352
404
  <input
353
405
  v-else
@@ -358,6 +410,7 @@ export default {
358
410
  :disabled="isView || disabled"
359
411
  :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
360
412
  @paste="onPaste(idx, $event)"
413
+ @blur="validate"
361
414
  >
362
415
  </slot>
363
416
  </div>
@@ -443,6 +496,10 @@ export default {
443
496
  color: var(--error);
444
497
  }
445
498
 
499
+ .validation-banner {
500
+ margin-top: 0;
501
+ }
502
+
446
503
  .box {
447
504
  display: grid;
448
505
  grid-template-columns: auto $array-list-remove-margin;
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import { _EDIT, _VIEW } from '@shell/config/query-params';
3
3
  import { set } from '@shell/utils/object';
4
+ import { RcButton } from '@components/RcButton';
4
5
 
5
6
  export function createOnSelected(field) {
6
7
  return function(contents) {
@@ -11,6 +12,8 @@ export function createOnSelected(field) {
11
12
  export default {
12
13
  emits: ['error', 'selected'],
13
14
 
15
+ components: { RcButton },
16
+
14
17
  props: {
15
18
  label: {
16
19
  type: String,
@@ -70,6 +73,15 @@ export default {
70
73
  class: {
71
74
  type: [String, Array],
72
75
  default: () => [],
76
+ },
77
+
78
+ /**
79
+ * Render the trigger as a small, secondary RcButton instead of the default
80
+ * plain button.
81
+ */
82
+ asRcButton: {
83
+ type: Boolean,
84
+ default: false,
73
85
  }
74
86
 
75
87
  },
@@ -82,6 +94,11 @@ export default {
82
94
  customClass() {
83
95
  return ['file-selector', 'btn', ...(Array.isArray(this.class) ? this.class : [this.class])];
84
96
  },
97
+
98
+ // RcButton provides its own `btn` class, so we omit it here to avoid clashing styles
99
+ rcButtonClass() {
100
+ return ['file-selector', ...(Array.isArray(this.class) ? this.class : [this.class])];
101
+ },
85
102
  },
86
103
 
87
104
  methods: {
@@ -154,8 +171,29 @@ export default {
154
171
  </script>
155
172
 
156
173
  <template>
174
+ <RcButton
175
+ v-if="!isView && asRcButton"
176
+ variant="secondary"
177
+ size="small"
178
+ :disabled="disabled"
179
+ :aria-label="label"
180
+ :class="rcButtonClass"
181
+ data-testid="file-selector__uploader-button"
182
+ @click="selectFile"
183
+ >
184
+ <span>{{ label }}</span>
185
+ <input
186
+ ref="uploader"
187
+ type="file"
188
+ class="hide"
189
+ :multiple="multiple"
190
+ :webkitdirectory="directory"
191
+ :accept="accept"
192
+ @change="fileChange"
193
+ >
194
+ </RcButton>
157
195
  <button
158
- v-if="!isView"
196
+ v-else-if="!isView"
159
197
  :disabled="disabled"
160
198
  :aria-label="label"
161
199
  type="button"
@@ -13,6 +13,7 @@ import { asciiLike } from '@shell/utils/string';
13
13
  import CodeMirror from '@shell/components/CodeMirror';
14
14
  import isEqual from 'lodash/isEqual';
15
15
  import { LabeledTooltip } from '@components/LabeledTooltip';
16
+ import { RcButton } from '@components/RcButton';
16
17
 
17
18
  export default {
18
19
  name: 'KeyValue',
@@ -24,7 +25,8 @@ export default {
24
25
  Select,
25
26
  TextAreaAutoGrow,
26
27
  FileSelector,
27
- LabeledTooltip
28
+ LabeledTooltip,
29
+ RcButton
28
30
  },
29
31
  props: {
30
32
  value: {
@@ -241,6 +243,10 @@ export default {
241
243
  keyErrors: {
242
244
  type: Object,
243
245
  default: () => ({})
246
+ },
247
+ useRcButton: {
248
+ type: Boolean,
249
+ default: false
244
250
  }
245
251
  },
246
252
  data() {
@@ -879,8 +885,23 @@ export default {
879
885
  name="add"
880
886
  :add="add"
881
887
  >
888
+ <RcButton
889
+ v-if="addAllowed && useRcButton"
890
+ size="small"
891
+ variant="secondary"
892
+ :class="[addClass]"
893
+ data-testid="add_row_item_button"
894
+ :disabled="loading || disabled || (keyOptions && filteredKeyOptions.length === 0)"
895
+ :aria-label="t('generic.ariaLabel.addKeyValue')"
896
+ @click="add()"
897
+ >
898
+ <i
899
+ class="mr-5 icon"
900
+ :class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
901
+ /> {{ _addLabel }}
902
+ </RcButton>
882
903
  <button
883
- v-if="addAllowed"
904
+ v-else-if="addAllowed"
884
905
  type="button"
885
906
  role="button"
886
907
  class="btn role-tertiary add"
@@ -117,6 +117,10 @@ export default {
117
117
  type: String,
118
118
  default: 'labelSelect.noOptions.empty'
119
119
  },
120
+ lockedOptions: {
121
+ type: Array,
122
+ default: () => []
123
+ },
120
124
 
121
125
  name: {
122
126
  type: String,
@@ -382,7 +386,17 @@ export default {
382
386
  }
383
387
 
384
388
  return this.getOptionLabel(opt);
385
- }
389
+ },
390
+
391
+ isOptionLocked(option) {
392
+ if (!this.lockedOptions.length) {
393
+ return false;
394
+ }
395
+
396
+ const label = this.getOptionLabel(option);
397
+
398
+ return this.lockedOptions.includes(typeof label === 'string' ? label.trim() : String(label));
399
+ },
386
400
  },
387
401
  };
388
402
  </script>
@@ -513,6 +527,14 @@ export default {
513
527
  />
514
528
  </div>
515
529
  </template>
530
+ <template
531
+ v-if="lockedOptions.length"
532
+ #selected-option="option"
533
+ >
534
+ <span :data-locked="isOptionLocked(option) || undefined">
535
+ {{ getOptionLabel(option) }}
536
+ </span>
537
+ </template>
516
538
  <!-- Pass down templates provided by the caller -->
517
539
  <template
518
540
  v-for="(_, slot) of $slots"
@@ -676,6 +698,14 @@ export default {
676
698
  min-height: unset !important;
677
699
  padding: 0 0 0 7px !important;
678
700
 
701
+ &:has([data-locked]) {
702
+ padding: 0 7px 0 7px !important;
703
+
704
+ .vs__deselect {
705
+ display: none;
706
+ }
707
+ }
708
+
679
709
  > button {
680
710
  height: 20px;
681
711
  line-height: 14px;
@@ -691,6 +721,14 @@ export default {
691
721
  }
692
722
  }
693
723
  }
724
+
725
+ :deep() .vs--disabled .vs__selected-options .vs__selected {
726
+ padding: 0 7px 0 7px !important;
727
+
728
+ .vs__deselect {
729
+ display: none;
730
+ }
731
+ }
694
732
  }
695
733
 
696
734
  :deep() .vs__selected-options {
@@ -126,6 +126,16 @@ export default {
126
126
  type: String,
127
127
  default: '',
128
128
  },
129
+
130
+ compact: {
131
+ type: Boolean,
132
+ default: false
133
+ },
134
+
135
+ useRcButton: {
136
+ type: Boolean,
137
+ default: false
138
+ }
129
139
  },
130
140
 
131
141
  data(): DataType {
@@ -162,9 +172,12 @@ export default {
162
172
  <div :class="defaultSectionClass">
163
173
  <div class="labels">
164
174
  <div class="labels__header">
165
- <h3 v-if="showLabelTitle">
175
+ <component
176
+ :is="!compact ? 'h3' : 'h4'"
177
+ v-if="showLabelTitle"
178
+ >
166
179
  <t k="labels.labels.title" />
167
- </h3>
180
+ </component>
168
181
  <ToggleSwitch
169
182
  v-if="showToggler"
170
183
  v-model:value="toggler"
@@ -186,13 +199,14 @@ export default {
186
199
  :read-allowed="false"
187
200
  :value-can-be-empty="true"
188
201
  :key-errors="labels.keyErrors"
202
+ :use-rc-button="useRcButton"
189
203
  @update:value="labels.update($event, (x) => value.setLabels(x))"
190
204
  />
191
205
  </slot>
192
206
  </div>
193
207
  </div>
194
208
  </div>
195
- <div class="spacer" />
209
+ <div :class="compact ? 'compact-spacer' : 'spacer'" />
196
210
  <div
197
211
  v-if="showAnnotations"
198
212
  :class="sectionClass"
@@ -208,6 +222,7 @@ export default {
208
222
  :read-allowed="false"
209
223
  :value-can-be-empty="true"
210
224
  :key-errors="annotations.keyErrors"
225
+ :use-rc-button="useRcButton"
211
226
  @update:value="annotations.update($event, (x) => value.setAnnotations(x))"
212
227
  />
213
228
  </div>
@@ -221,4 +236,8 @@ export default {
221
236
  justify-content: space-between;
222
237
  }
223
238
  }
239
+
240
+ .compact-spacer {
241
+ height: 24px;
242
+ }
224
243
  </style>
@@ -156,6 +156,14 @@ export default {
156
156
  type: Boolean,
157
157
  default: true,
158
158
  },
159
+ nameColSpan: {
160
+ type: Number,
161
+ default: 3,
162
+ },
163
+ noBottomMargin: {
164
+ type: Boolean,
165
+ default: false,
166
+ },
159
167
  rules: {
160
168
  default: () => ({
161
169
  namespace: [],
@@ -310,8 +318,8 @@ export default {
310
318
 
311
319
  if (props.namespaced) {
312
320
  if (props.forceNamespace) {
313
- namespace.value = toRef(props.forceNamespace);
314
- updateNamespace(namespace);
321
+ namespace.value = props.forceNamespace;
322
+ updateNamespace(namespace.value);
315
323
  } else if (props.namespaceKey) {
316
324
  namespace.value = get(v.value, props.namespaceKey);
317
325
  } else {
@@ -321,7 +329,7 @@ export default {
321
329
  if (!namespace.value && !props.noDefaultNamespace) {
322
330
  namespace.value = store.getters['defaultNamespace'];
323
331
  if (metadata) {
324
- metadata.namespace = namespace;
332
+ metadata.namespace = namespace.value;
325
333
  }
326
334
  }
327
335
  }
@@ -436,7 +444,7 @@ export default {
436
444
  </script>
437
445
 
438
446
  <template>
439
- <div class="row mb-20">
447
+ <div :class="['row', { 'mb-20': !noBottomMargin }]">
440
448
  <slot name="project-selector" />
441
449
  <div
442
450
  v-if="namespaced && !nameNsHidden && createNamespace"
@@ -491,7 +499,7 @@ export default {
491
499
  <div
492
500
  v-if="!nameHidden && !nameNsHidden"
493
501
  :data-testid="componentTestid + '-name'"
494
- class="col span-3"
502
+ :class="['col', `span-${nameColSpan}`]"
495
503
  >
496
504
  <LabeledInput
497
505
  ref="nameInput"
@@ -0,0 +1,7 @@
1
+ export const PRIVATE_REGISTRY_CONTEXT = {
2
+ PROVISIONING: 'provisioning',
3
+ IMPORTING: 'importing',
4
+ CHARTS: 'charts',
5
+ } as const;
6
+
7
+ export type PrivateRegistryContext = typeof PRIVATE_REGISTRY_CONTEXT[keyof typeof PRIVATE_REGISTRY_CONTEXT];