@rancher/shell 3.0.2-rc.5 → 3.0.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 (219) hide show
  1. package/assets/images/providers/nutanix.svg +12 -1
  2. package/assets/styles/base/_basic.scss +2 -1
  3. package/assets/styles/base/_helpers.scss +4 -0
  4. package/assets/styles/base/_variables.scss +2 -0
  5. package/assets/styles/global/_labeled-input.scss +5 -13
  6. package/assets/styles/global/_layout.scss +4 -1
  7. package/assets/styles/global/_select.scss +5 -0
  8. package/assets/styles/themes/_dark.scss +1 -3
  9. package/assets/styles/themes/_light.scss +5 -1
  10. package/assets/translations/en-us.yaml +130 -23
  11. package/assets/translations/zh-hans.yaml +0 -3
  12. package/cloud-credential/azure.vue +1 -1
  13. package/components/ActionMenuShell.vue +105 -0
  14. package/components/AppModal.vue +2 -2
  15. package/components/AsyncButton.vue +2 -0
  16. package/components/ButtonGroup.vue +9 -2
  17. package/components/ClusterBadge.vue +1 -0
  18. package/components/ClusterIconMenu.vue +3 -0
  19. package/components/ClusterProviderIcon.vue +14 -1
  20. package/components/CodeMirror.vue +96 -5
  21. package/components/Collapse.vue +16 -3
  22. package/components/CruResource.vue +9 -0
  23. package/components/CruResourceFooter.vue +1 -1
  24. package/components/ExplorerMembers.vue +2 -1
  25. package/components/FixedBanner.vue +19 -12
  26. package/components/Import.vue +14 -1
  27. package/components/LandingPagePreference.vue +4 -2
  28. package/components/PodSecurityAdmission.vue +8 -6
  29. package/components/PromptChangePassword.vue +1 -0
  30. package/components/PromptRemove.vue +23 -21
  31. package/components/ResourceDetail/Masthead.vue +30 -11
  32. package/components/ResourceDetail/__tests__/Masthead.test.ts +61 -0
  33. package/components/ResourceDetail/index.vue +6 -0
  34. package/components/ResourceTable.vue +6 -1
  35. package/components/ResourceYaml.vue +1 -0
  36. package/components/Setting.vue +115 -0
  37. package/components/SortableTable/THead.vue +2 -0
  38. package/components/SortableTable/index.vue +7 -12
  39. package/components/StatusBadge.vue +71 -0
  40. package/components/Tabbed/index.vue +16 -15
  41. package/components/Wizard.vue +108 -104
  42. package/components/YamlEditor.vue +12 -2
  43. package/components/__tests__/Collapse.test.ts +2 -2
  44. package/components/__tests__/FixedBanner.test.ts +3 -3
  45. package/components/auth/Principal.vue +29 -17
  46. package/components/auth/__tests__/Principal.test.ts +40 -0
  47. package/components/auth/login/ldap.vue +7 -0
  48. package/components/fleet/FleetBundles.vue +1 -1
  49. package/components/fleet/FleetRepos.vue +1 -1
  50. package/components/fleet/FleetResources.vue +0 -2
  51. package/components/fleet/FleetSummary.vue +60 -65
  52. package/components/fleet/ForceDirectedTreeChart/index.vue +5 -1
  53. package/components/fleet/__tests__/FleetSummary.test.ts +49 -9
  54. package/components/form/ArrayList.vue +6 -2
  55. package/components/form/ColorInput.vue +1 -0
  56. package/components/form/KeyValue.vue +11 -12
  57. package/components/form/LabeledSelect.vue +15 -3
  58. package/components/form/Labels.vue +8 -1
  59. package/components/form/Members/MembershipEditor.vue +230 -222
  60. package/components/form/Members/__tests__/MembershipEditor.test.ts +62 -0
  61. package/components/form/Password.vue +3 -0
  62. package/components/form/ProjectMemberEditor.vue +6 -3
  63. package/components/form/ResourceTabs/index.vue +15 -13
  64. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +5 -4
  65. package/components/form/SchedulingCustomization.vue +85 -0
  66. package/components/form/Select.vue +3 -2
  67. package/components/form/SelectOrCreateAuthSecret.vue +2 -1
  68. package/components/form/UnitInput.vue +3 -4
  69. package/components/form/__tests__/ArrayList.test.ts +9 -6
  70. package/components/form/__tests__/LabeledSelect.test.ts +37 -0
  71. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +34 -0
  72. package/components/form/__tests__/UnitInput.test.ts +4 -5
  73. package/components/formatter/LiveDate.vue +3 -1
  74. package/components/formatter/ServiceType.vue +12 -4
  75. package/components/formatter/WorkloadHealthScale.vue +2 -1
  76. package/components/nav/Header.vue +35 -2
  77. package/components/nav/HeaderPageActionMenu.vue +11 -40
  78. package/components/nav/Jump.vue +8 -2
  79. package/components/nav/NamespaceFilter.vue +5 -4
  80. package/components/nav/Pinned.vue +1 -1
  81. package/components/nav/TopLevelMenu.helper.ts +5 -5
  82. package/components/nav/TopLevelMenu.vue +1 -12
  83. package/components/nav/WindowManager/ContainerLogs.vue +96 -58
  84. package/components/nav/WindowManager/ContainerShell.vue +99 -18
  85. package/components/nav/WindowManager/index.vue +74 -6
  86. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
  87. package/components/templates/default.vue +2 -47
  88. package/config/features.js +1 -0
  89. package/config/labels-annotations.js +11 -1
  90. package/config/router/navigation-guards/index.js +2 -1
  91. package/config/router/navigation-guards/record-last-route.js +24 -0
  92. package/config/settings.ts +66 -98
  93. package/config/version.js +1 -1
  94. package/core/types-provisioning.ts +7 -0
  95. package/detail/fleet.cattle.io.bundle.vue +7 -0
  96. package/detail/fleet.cattle.io.cluster.vue +0 -3
  97. package/detail/fleet.cattle.io.gitrepo.vue +8 -15
  98. package/detail/provisioning.cattle.io.cluster.vue +8 -2
  99. package/dialog/DeactivateDriverDialog.vue +5 -5
  100. package/dialog/GitRepoForceUpdateDialog.vue +132 -0
  101. package/directives/strip-html-aria-label.js +19 -0
  102. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +87 -0
  103. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +217 -37
  104. package/edit/auth/__tests__/oidc.test.ts +60 -12
  105. package/edit/auth/ldap/__tests__/config.test.ts +40 -0
  106. package/edit/auth/ldap/config.vue +67 -89
  107. package/edit/auth/oidc.vue +16 -2
  108. package/edit/catalog.cattle.io.clusterrepo.vue +12 -8
  109. package/edit/cis.cattle.io.clusterscan.vue +13 -1
  110. package/edit/fleet.cattle.io.gitrepo.vue +198 -72
  111. package/edit/logging-flow/Match.vue +0 -21
  112. package/edit/management.cattle.io.project.vue +1 -1
  113. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +10 -3
  114. package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +5 -1
  115. package/edit/monitoring.coreos.com.prometheusrule/index.vue +5 -2
  116. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +8 -1
  117. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -0
  118. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -2
  119. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +55 -15
  120. package/edit/provisioning.cattle.io.cluster/index.vue +28 -30
  121. package/edit/provisioning.cattle.io.cluster/rke2.vue +64 -13
  122. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +37 -2
  123. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -2
  124. package/edit/resources.cattle.io.backup.vue +150 -15
  125. package/edit/secret/__tests__/ssh.test.ts +79 -0
  126. package/edit/secret/ssh.vue +7 -1
  127. package/edit/service.vue +0 -3
  128. package/edit/workload/Job.vue +8 -8
  129. package/edit/workload/__tests__/Job.test.ts +0 -1
  130. package/edit/workload/index.vue +3 -1
  131. package/initialize/install-directives.js +2 -0
  132. package/initialize/install-plugins.js +6 -1
  133. package/list/catalog.cattle.io.app.vue +21 -4
  134. package/list/fleet.cattle.io.bundle.vue +1 -1
  135. package/list/management.cattle.io.setting.vue +34 -132
  136. package/list/provisioning.cattle.io.cluster.vue +11 -3
  137. package/machine-config/vmwarevsphere.vue +15 -8
  138. package/mixins/__tests__/auth-config.test.ts +74 -0
  139. package/mixins/__tests__/chart.test.ts +5 -4
  140. package/mixins/__tests__/create-edit-view.test.ts +38 -0
  141. package/mixins/auth-config.js +8 -0
  142. package/mixins/chart.js +2 -2
  143. package/mixins/create-edit-view/impl.js +4 -1
  144. package/mixins/vue-select-overrides.js +10 -0
  145. package/models/__tests__/catalog.cattle.io.app.test.ts +148 -0
  146. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +157 -0
  147. package/models/__tests__/secret.test.ts +56 -13
  148. package/models/catalog.cattle.io.app.js +112 -37
  149. package/models/cluster.js +11 -0
  150. package/models/fleet.cattle.io.bundle.js +40 -2
  151. package/models/fleet.cattle.io.gitrepo.js +169 -109
  152. package/models/management.cattle.io.fleetworkspace.js +4 -0
  153. package/models/management.cattle.io.kontainerdriver.js +7 -0
  154. package/models/nodedriver.js +4 -1
  155. package/models/provisioning.cattle.io.cluster.js +24 -0
  156. package/models/secret.js +1 -1
  157. package/package.json +5 -5
  158. package/pages/auth/login.vue +5 -11
  159. package/pages/auth/verify.vue +11 -1
  160. package/pages/c/_cluster/apps/charts/index.vue +6 -4
  161. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  162. package/pages/c/_cluster/explorer/ConfigBadge.vue +3 -5
  163. package/pages/c/_cluster/explorer/EventsTable.vue +3 -2
  164. package/pages/c/_cluster/explorer/__tests__/index.test.ts +9 -9
  165. package/pages/c/_cluster/explorer/index.vue +33 -35
  166. package/pages/c/_cluster/explorer/tools/index.vue +3 -3
  167. package/pages/c/_cluster/fleet/index.vue +0 -5
  168. package/pages/c/_cluster/legacy/project/index.vue +1 -1
  169. package/pages/c/_cluster/settings/performance.vue +52 -53
  170. package/pages/c/_cluster/uiplugins/index.vue +19 -22
  171. package/pages/home.vue +17 -12
  172. package/pages/prefs.vue +5 -1
  173. package/plugins/shortkey.js +10 -1
  174. package/plugins/steve/steve-pagination-utils.ts +58 -8
  175. package/promptRemove/management.cattle.io.fleetworkspace.vue +98 -0
  176. package/promptRemove/management.cattle.io.globalrole.vue +1 -1
  177. package/promptRemove/management.cattle.io.project.vue +2 -8
  178. package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
  179. package/promptRemove/mixin/roleDeletionCheck.js +1 -7
  180. package/promptRemove/pod.vue +7 -28
  181. package/rancher-components/Card/Card.vue +9 -1
  182. package/rancher-components/Form/Checkbox/Checkbox.vue +42 -6
  183. package/rancher-components/Form/LabeledInput/LabeledInput.vue +30 -3
  184. package/rancher-components/Form/Radio/RadioButton.vue +18 -3
  185. package/rancher-components/Form/Radio/RadioGroup.vue +39 -5
  186. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +13 -1
  187. package/rancher-components/RcButton/RcButton.test.ts +97 -0
  188. package/rancher-components/RcButton/RcButton.vue +14 -9
  189. package/rancher-components/RcDropdown/RcDropdown.vue +3 -1
  190. package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -2
  191. package/rancher-components/RcDropdown/RcDropdownMenu.vue +66 -0
  192. package/rancher-components/RcDropdown/index.ts +1 -0
  193. package/rancher-components/RcDropdown/types.ts +27 -0
  194. package/rancher-components/RcDropdown/useDropdownContext.ts +5 -2
  195. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
  196. package/scripts/typegen.sh +1 -0
  197. package/store/__tests__/auth.test.ts +120 -0
  198. package/store/action-menu.js +13 -3
  199. package/store/auth.js +14 -9
  200. package/store/aws.js +9 -2
  201. package/store/catalog.js +14 -7
  202. package/store/features.js +1 -0
  203. package/store/prefs.js +9 -28
  204. package/store/type-map.utils.ts +4 -0
  205. package/types/resources/settings.d.ts +27 -20
  206. package/types/shell/index.d.ts +18 -12
  207. package/utils/__tests__/array.test.ts +13 -1
  208. package/utils/__tests__/string.test.ts +80 -1
  209. package/utils/array.ts +13 -0
  210. package/utils/auth.js +4 -0
  211. package/utils/banners.js +0 -45
  212. package/utils/cluster.js +1 -1
  213. package/{edit/monitoring.coreos.com.prometheusrule → utils}/duration.js +5 -3
  214. package/utils/object.js +0 -3
  215. package/utils/pagination-utils.ts +15 -2
  216. package/utils/string.js +31 -7
  217. package/utils/validators/formRules/__tests__/index.test.ts +27 -0
  218. package/utils/validators/formRules/index.ts +16 -0
  219. package/edit/provisioning.cattle.io.cluster/import.vue +0 -198
@@ -229,17 +229,17 @@ export default defineComponent({
229
229
  @update:value="updateLabels()"
230
230
  />
231
231
  <p v-else>
232
- <t :k="`podSecurityAdmission.labels.${level}`" />
232
+ <t
233
+ :id="`psa-label-for-level-${ level }`"
234
+ :k="`podSecurityAdmission.labels.${level}`"
235
+ />
233
236
  </p>
234
237
  </span>
235
238
 
236
- <span
237
- class="
238
- col
239
- span-4"
240
- >
239
+ <span class="col span-4">
241
240
  <LabeledSelect
242
241
  v-model:value="psaControl.level"
242
+ :aria-labelledby="`psa-label-for-level-${ level }`"
243
243
  :data-testid="componentTestid + '--psaControl-' + i + '-level'"
244
244
  :disabled="isPsaControlDisabled(psaControl.active)"
245
245
  :options="options"
@@ -256,6 +256,7 @@ export default defineComponent({
256
256
  :options="options"
257
257
  :placeholder="t('podSecurityAdmission.version.placeholder', { psaControl: mode })"
258
258
  :mode="mode"
259
+ :aria-label="`${t(`podSecurityAdmission.labels.${level}`)} - ${t('podSecurityAdmission.version.placeholder', { psaControl: mode })}`"
259
260
  @update:value="updateLabels()"
260
261
  />
261
262
  </span>
@@ -295,6 +296,7 @@ export default defineComponent({
295
296
  :options="options"
296
297
  :placeholder="t('podSecurityAdmission.exemptions.placeholder', { psaExemptionsControl: dimension })"
297
298
  :mode="mode"
299
+ :aria-label="`${t(`podSecurityAdmission.labels.${ dimension }`)} - ${t('podSecurityAdmission.exemptions.placeholder', { psaExemptionsControl: dimension })}`"
298
300
  @update:value="updateExemptions()"
299
301
  />
300
302
  </span>
@@ -40,6 +40,7 @@ export default {
40
40
  <app-modal
41
41
  v-if="showModal"
42
42
  custom-class="change-password-modal"
43
+ data-testid="change-password__modal"
43
44
  name="password-modal"
44
45
  :width="500"
45
46
  :height="465"
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { shallowRef } from 'vue';
2
3
  import { mapState, mapGetters } from 'vuex';
3
4
  import { get, isEmpty } from '@shell/utils/object';
4
5
  import { escapeHtml, resourceNames } from '@shell/utils/string';
@@ -38,7 +39,7 @@ export default {
38
39
  error: '',
39
40
  warning: '',
40
41
  preventDelete: false,
41
- removeComponent: this.$store.getters['type-map/importCustomPromptRemove'](resource),
42
+ removeComponent: shallowRef(this.$store.getters['type-map/importCustomPromptRemove'](resource)),
42
43
  chartsToRemoveIsApp: false,
43
44
  chartsDeleteCrd: false,
44
45
  showModal: false,
@@ -46,7 +47,7 @@ export default {
46
47
  },
47
48
  computed: {
48
49
  names() {
49
- return this.toRemove.map((obj) => obj.nameDisplay).slice(0, 5);
50
+ return this.toRemove.map((obj) => obj.nameDisplay);
50
51
  },
51
52
 
52
53
  nameToMatchPosition() {
@@ -92,12 +93,6 @@ export default {
92
93
  return first?.confirmRemove;
93
94
  },
94
95
 
95
- plusMore() {
96
- const remaining = this.toRemove.length - this.names.length;
97
-
98
- return this.t('promptRemove.andOthers', { count: remaining });
99
- },
100
-
101
96
  // if the current route ends with the ID of the resource being deleted, whatever page this is wont be valid after successful deletion: navigate away
102
97
  doneLocation() {
103
98
  // if deleting more than one resource, this is happening in list view and shouldn't redirect anywhere
@@ -167,7 +162,7 @@ export default {
167
162
  if (show) {
168
163
  const selected = this.toRemove[0];
169
164
 
170
- if (this.currentRouter?.currentRoute?.name === 'c-cluster-explorer-tools' &&
165
+ if (this.currentRouter?.currentRoute?.value?.name === 'c-cluster-explorer-tools' &&
171
166
  selected.type === CATALOG.APP &&
172
167
  selected.spec?.chart?.metadata?.annotations[CATALOG_ANNOTATIONS.AUTO_INSTALL]) {
173
168
  this.chartsToRemoveIsApp = true;
@@ -183,7 +178,7 @@ export default {
183
178
 
184
179
  this.hasCustomRemove = this.$store.getters['type-map/hasCustomPromptRemove'](resource);
185
180
 
186
- this.removeComponent = this.$store.getters['type-map/importCustomPromptRemove'](resource);
181
+ this.removeComponent = shallowRef(this.$store.getters['type-map/importCustomPromptRemove'](resource));
187
182
  } else {
188
183
  this.showModal = false;
189
184
  }
@@ -359,7 +354,7 @@ export default {
359
354
  <div class="mb-10">
360
355
  <template v-if="!hasCustomRemove">
361
356
  {{ t('promptRemove.attemptingToRemove', { type }) }} <span
362
- v-clean-html="resourceNames(names, plusMore, t)"
357
+ v-clean-html="resourceNames(names, t)"
363
358
  />
364
359
  </template>
365
360
 
@@ -368,7 +363,7 @@ export default {
368
363
  v-if="hasCustomRemove"
369
364
  ref="customPrompt"
370
365
  v-model:value="toRemove"
371
- v-bind="_data"
366
+ v-bind="$data"
372
367
  :close="close"
373
368
  :needs-confirm="needsConfirm"
374
369
  :value="toRemove"
@@ -394,6 +389,7 @@ export default {
394
389
  v-focus
395
390
  :data-testid="componentTestid + '-input'"
396
391
  type="text"
392
+ :aria-label="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) })"
397
393
  >
398
394
  <div class="text-warning mb-10 mt-10">
399
395
  {{ warning }}
@@ -407,22 +403,28 @@ export default {
407
403
  >
408
404
  {{ protip }}
409
405
  </div>
410
- <Checkbox
411
- v-if="chartsToRemoveIsApp"
412
- v-model:value="chartsDeleteCrd"
413
- label-key="promptRemoveApp.removeCrd"
414
- class="mt-10 type"
415
- @update:value="chartAddCrdToRemove"
416
- />
417
406
  </LabeledInput>
418
407
  <div v-else-if="!hasCustomRemove">
419
- <div class="text-warning mb-10 mt-10">
408
+ <div
409
+ v-if="warning"
410
+ class="text-warning mb-10 mt-10"
411
+ >
420
412
  {{ warning }}
421
413
  </div>
422
- <div class="text-error mb-10 mt-10">
414
+ <div
415
+ v-if="error"
416
+ class="text-error mb-10 mt-10"
417
+ >
423
418
  {{ error }}
424
419
  </div>
425
420
  </div>
421
+ <Checkbox
422
+ v-if="chartsToRemoveIsApp"
423
+ v-model:value="chartsDeleteCrd"
424
+ label-key="promptRemoveApp.removeCrd"
425
+ class="mt-10 type"
426
+ @update:value="chartAddCrdToRemove"
427
+ />
426
428
  </template>
427
429
  <template #actions>
428
430
  <button
@@ -504,10 +504,32 @@ export default {
504
504
  {{ namespace }}
505
505
  </span>
506
506
  </span>
507
- <span v-if="parent.showAge">{{ t("resourceDetail.masthead.age") }}: <LiveDate
508
- class="live-date"
509
- :value="value.creationTimestamp"
510
- /></span>
507
+ <span v-if="parent.showAge">
508
+ {{ t("resourceDetail.masthead.age") }}:
509
+ <LiveDate
510
+ class="live-date"
511
+ :value="value.creationTimestamp"
512
+ />
513
+ </span>
514
+ <span
515
+ v-if="value.showCreatedBy"
516
+ data-testid="masthead-subheader-createdBy"
517
+ >
518
+ {{ t("resourceDetail.masthead.createdBy") }}:
519
+ <router-link
520
+ v-if="value.createdBy.location"
521
+ :to="value.createdBy.location"
522
+ data-testid="masthead-subheader-createdBy-link"
523
+ >
524
+ {{ value.createdBy.displayName }}
525
+ </router-link>
526
+ <span
527
+ v-else
528
+ data-testid="masthead-subheader-createdBy_plain-text"
529
+ >
530
+ {{ value.createdBy.displayName }}
531
+ </span>
532
+ </span>
511
533
  <span v-if="value.showPodRestarts">{{ t("resourceDetail.masthead.restartCount") }}:<span class="live-data"> {{ value.restartCount }}</span></span>
512
534
  </div>
513
535
  </div>
@@ -587,11 +609,8 @@ export default {
587
609
  }
588
610
 
589
611
  HEADER {
590
- margin: 0 0 0 -5px;
591
-
592
- .title {
593
- overflow-x: hidden;
594
- }
612
+ margin: 0;
613
+ grid-template-columns: minmax(0, 1fr) auto;
595
614
  }
596
615
 
597
616
  .primaryheader {
@@ -600,14 +619,13 @@ export default {
600
619
  align-items: center;
601
620
 
602
621
  h1 {
603
- margin: 0;
622
+ margin: 0 0 0 -5px;
604
623
  overflow-x: hidden;
605
624
  display: flex;
606
625
  flex-direction: row;
607
626
  align-items: center;
608
627
 
609
628
  .masthead-resource-title {
610
- padding: 0 8px;
611
629
  text-overflow: ellipsis;
612
630
  overflow: hidden;
613
631
  white-space: nowrap;
@@ -638,6 +656,7 @@ export default {
638
656
  }
639
657
 
640
658
  .masthead-state {
659
+ margin-left: 8px;
641
660
  font-size: initial;
642
661
  }
643
662
 
@@ -0,0 +1,61 @@
1
+ import { mount, RouterLinkStub } from '@vue/test-utils';
2
+ import { _VIEW } from '@shell/config/query-params';
3
+ import Masthead from '@shell/components/ResourceDetail/Masthead.vue';
4
+
5
+ const mockedStore = () => {
6
+ return {
7
+ getters: {
8
+ currentStore: () => 'current_store',
9
+ currentProduct: { inStore: 'cluster' },
10
+ isExplorer: false,
11
+ currentCluster: {},
12
+ 'type-map/labelFor': jest.fn(),
13
+ 'type-map/optionsFor': jest.fn(),
14
+ 'current_store/schemaFor': jest.fn(),
15
+ },
16
+ };
17
+ };
18
+
19
+ const requiredSetup = () => {
20
+ return {
21
+ stubs: {
22
+ 'router-link': RouterLinkStub,
23
+ LiveDate: true
24
+ },
25
+ mocks: { $store: mockedStore() }
26
+ };
27
+ };
28
+
29
+ describe('component: Masthead', () => {
30
+ it.each([
31
+ ['hidden', '', false, { displayName: 'admin', location: { id: 'resource-id' } }, false, false],
32
+ ['plain-text', 'admin', true, { displayName: 'admin', location: null }, false, true],
33
+ ['link', 'foo', true, { displayName: 'foo', location: { id: 'resource-id' } }, true, false],
34
+ ])('"Created By" should be %p, with text: %p', (
35
+ _,
36
+ text,
37
+ showCreatedBy,
38
+ createdBy,
39
+ showLink,
40
+ showPlainText,
41
+ ) => {
42
+ const wrapper = mount(Masthead, {
43
+ props: {
44
+ mode: _VIEW,
45
+ value: {
46
+ showCreatedBy,
47
+ createdBy,
48
+ },
49
+ },
50
+ global: { ...requiredSetup() }
51
+ });
52
+
53
+ const container = wrapper.find('[data-testid="masthead-subheader-createdBy"]');
54
+ const link = wrapper.find('[data-testid="masthead-subheader-createdBy-link"]');
55
+ const plainText = wrapper.find('[data-testid="masthead-subheader-createdBy_plain-text"]');
56
+
57
+ expect(link.exists()).toBe(showLink);
58
+ expect(plainText.exists()).toBe(showPlainText);
59
+ expect(showLink || showPlainText ? container.element.textContent : '').toContain(text);
60
+ });
61
+ });
@@ -71,6 +71,11 @@ export default {
71
71
  default: null,
72
72
  },
73
73
 
74
+ flexContent: {
75
+ type: Boolean,
76
+ default: false,
77
+ },
78
+
74
79
  /**
75
80
  * Inherited global identifier prefix for tests
76
81
  * Define a term based on the parent component to avoid conflicts on multiple components
@@ -484,6 +489,7 @@ export default {
484
489
  :initial-value="initialModel"
485
490
  :live-value="liveModel"
486
491
  :real-mode="realMode"
492
+ :class="{'flex-content': flexContent}"
487
493
  @update:value="$emit('input', $event)"
488
494
  @set-subtype="setSubtype"
489
495
  />
@@ -188,6 +188,11 @@ export default {
188
188
  type: Number,
189
189
  default: null, // Default comes from the user preference
190
190
  },
191
+
192
+ hideGroupingControls: {
193
+ type: Boolean,
194
+ default: false
195
+ }
191
196
  },
192
197
 
193
198
  data() {
@@ -591,7 +596,7 @@ export default {
591
596
  @enter="handleEnterKeyPress"
592
597
  >
593
598
  <template
594
- v-if="showGrouping"
599
+ v-if="!hideGroupingControls && showGrouping"
595
600
  #header-middle
596
601
  >
597
602
  <slot name="more-header-middle" />
@@ -298,6 +298,7 @@ export default {
298
298
  <YamlEditor
299
299
  ref="yamleditor"
300
300
  v-model:value="currentYaml"
301
+ :mode="mode"
301
302
  :initial-yaml-values="initialYaml"
302
303
  class="yaml-editor flex-content"
303
304
  :editor-mode="editorMode"
@@ -0,0 +1,115 @@
1
+ <script>
2
+ import ActionMenu from '@shell/components/ActionMenuShell.vue';
3
+ import { mapGetters } from 'vuex';
4
+ export default {
5
+ name: 'Setting',
6
+ components: { ActionMenu },
7
+ props: {
8
+ value: {
9
+ type: Object,
10
+ required: true,
11
+ },
12
+ },
13
+ computed: {
14
+ ...mapGetters({ t: 'i18n/t' }),
15
+ ...mapGetters({ options: 'action-menu/optionsArray' }),
16
+ },
17
+ };
18
+ </script>
19
+
20
+ <template>
21
+ <div
22
+ class="advanced-setting mb-20"
23
+ :data-testid="`advanced-setting__option-${value.id}`"
24
+ >
25
+ <div class="header">
26
+ <div class="title">
27
+ <h1>
28
+ {{ value.id }}
29
+ <span
30
+ v-if="value.fromEnv"
31
+ class="modified"
32
+ >{{ t('advancedSettings.setEnv') }}</span>
33
+ <span
34
+ v-else-if="value.customized"
35
+ class="modified"
36
+ >{{ t('advancedSettings.modified') }}</span>
37
+ </h1>
38
+ <h2>{{ t(`advancedSettings.descriptions.${value.id}`) }}</h2>
39
+ </div>
40
+ <div
41
+ v-if="value.hasActions"
42
+ class="action"
43
+ >
44
+ <action-menu
45
+ :resource="value.data"
46
+ :button-aria-label="t('advancedSettings.edit.label')"
47
+ data-testid="action-button"
48
+ button-role="tertiary"
49
+ />
50
+ </div>
51
+ </div>
52
+ <div value>
53
+ <div v-if="value.canHide">
54
+ <button
55
+ class="btn btn-sm role-primary"
56
+ role="button"
57
+ :aria-label="t('advancedSettings.hideShow')"
58
+ @click="value.hide = !value.hide"
59
+ >
60
+ {{ value.hide ? t('advancedSettings.show') : t('advancedSettings.hide') }} {{ value.id }}
61
+ </button>
62
+ </div>
63
+ <div
64
+ v-show="!value.canHide || (value.canHide && !value.hide)"
65
+ class="settings-value"
66
+ >
67
+ <pre v-if="value.kind === 'json'">{{ value.json }}</pre>
68
+ <pre v-else-if="value.kind === 'multiline'">{{ value.data.value || value.data.default }}</pre>
69
+ <pre v-else-if="value.kind === 'enum'">{{ t(value.enum) }}</pre>
70
+ <pre v-else-if="value.data.value || value.data.default">{{ value.data.value || value.data.default }}</pre>
71
+ <pre
72
+ v-else
73
+ class="text-muted"
74
+ >&lt;{{ t('advancedSettings.none') }}&gt;</pre>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </template>
79
+
80
+ <style lang='scss' scoped>
81
+ .settings-value pre {
82
+ margin: 0;
83
+ }
84
+ .advanced-setting {
85
+ border: 1px solid var(--border);
86
+ padding: 20px;
87
+ border-radius: var(--border-radius);
88
+
89
+ h1 {
90
+ font-size: 14px;
91
+ }
92
+ h2 {
93
+ font-size: 12px;
94
+ margin-bottom: 0;
95
+ opacity: 0.8;
96
+ }
97
+ }
98
+
99
+ .header {
100
+ display: flex;
101
+ margin-bottom: 20px;
102
+ }
103
+
104
+ .title {
105
+ flex: 1;
106
+ }
107
+
108
+ .modified {
109
+ margin-left: 10px;
110
+ border: 1px solid var(--primary);
111
+ border-radius: 5px;
112
+ padding: 2px 10px;
113
+ font-size: 12px;
114
+ }
115
+ </style>
@@ -230,6 +230,7 @@ export default {
230
230
  data-testid="sortable-table_check_select_all"
231
231
  :indeterminate="isIndeterminate"
232
232
  :disabled="noRows || noResults"
233
+ :alternate-label="t('sortableTable.genericGroupCheckbox')"
233
234
  />
234
235
  </th>
235
236
  <th
@@ -269,6 +270,7 @@ export default {
269
270
  <div
270
271
  v-if="col.sort"
271
272
  class="sort"
273
+ aria-hidden="true"
272
274
  >
273
275
  <i
274
276
  v-show="hasAdvancedFiltering && !col.isFilter"
@@ -23,6 +23,7 @@ import LabeledSelect from '@shell/components/form/LabeledSelect';
23
23
  import { getParent } from '@shell/utils/dom';
24
24
  import { FORMATTERS } from '@shell/components/SortableTable/sortable-config';
25
25
  import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
26
+ import ActionMenu from '@shell/components/ActionMenuShell.vue';
26
27
 
27
28
  // Uncomment for table performance debugging
28
29
  // import tableDebug from './debug';
@@ -58,6 +59,7 @@ export default {
58
59
  ActionDropdown,
59
60
  LabeledSelect,
60
61
  ButtonMultiAction,
62
+ ActionMenu,
61
63
  },
62
64
  mixins: [
63
65
  filtering,
@@ -1383,6 +1385,7 @@ export default {
1383
1385
  :data-node-id="row.key"
1384
1386
  :data-testid="componentTestid + '-' + i + '-checkbox'"
1385
1387
  :value="selectedRows.includes(row.row)"
1388
+ :alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
1386
1389
  />
1387
1390
  </td>
1388
1391
  <td
@@ -1468,23 +1471,16 @@ export default {
1468
1471
  </template>
1469
1472
  <td
1470
1473
  v-if="rowActions"
1471
- align="middle"
1472
1474
  >
1473
1475
  <slot
1474
1476
  name="row-actions"
1475
1477
  :row="row.row"
1478
+ :index="i"
1476
1479
  >
1477
- <ButtonMultiAction
1478
- :id="`actionButton+${i}+${(row.row && row.row.name) ? row.row.name : ''}`"
1479
- :ref="`actionButton${i}`"
1480
- aria-haspopup="true"
1481
- aria-expanded="false"
1482
- :aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1480
+ <ActionMenu
1481
+ :resource="row.row"
1483
1482
  :data-testid="componentTestid + '-' + i + '-action-button'"
1484
- :borderless="true"
1485
- @click="handleActionButtonClick(i, $event)"
1486
- @keyup.enter="handleActionButtonClick(i, $event)"
1487
- @keyup.space="handleActionButtonClick(i, $event)"
1483
+ :button-aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1488
1484
  />
1489
1485
  </slot>
1490
1486
  </td>
@@ -1782,7 +1778,6 @@ export default {
1782
1778
  min-width: 400px;
1783
1779
  border-radius: 5px 5px 0 0;
1784
1780
  outline: 1px solid var(--border);
1785
- overflow: hidden;
1786
1781
  background: var(--sortable-table-bg);
1787
1782
  border-radius: 4px;
1788
1783
 
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+
3
+ const STATUS = {
4
+ success: {
5
+ color: 'text-success',
6
+ icon: 'icon-checkmark'
7
+ },
8
+ warning: {
9
+ color: 'text-warning',
10
+ icon: 'icon-warning'
11
+ },
12
+ info: {
13
+ color: 'text-info',
14
+ icon: 'icon-info'
15
+ },
16
+ error: {
17
+ color: 'text-error',
18
+ icon: 'icon-error'
19
+ }
20
+ };
21
+
22
+ const { status = 'success', label } = defineProps<{
23
+ status?: 'success' | 'warning' | 'info' | 'error',
24
+ label?: string
25
+ }>();
26
+
27
+ </script>
28
+ <template>
29
+ <div
30
+ class="status-badge"
31
+ >
32
+ <i
33
+ class="status-badge__icon icon"
34
+ :class="{
35
+ [STATUS[status].icon]: true,
36
+ [STATUS[status].color]: true
37
+ }"
38
+ />
39
+ <div
40
+ v-if="label"
41
+ class="status-badge__label"
42
+ >
43
+ {{ label }}
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <style lang="scss" scoped>
49
+ .status-badge {
50
+ align-items: center;
51
+ display: inline-flex;
52
+ border: 1px solid;
53
+ border-color: var(--border);
54
+ margin-top: 20px;
55
+
56
+ & + & {
57
+ margin-left: 20px;
58
+ }
59
+
60
+ &__label {
61
+ border-left: 1px solid var(--border);
62
+ padding: 5px 20px;
63
+ color: var(--body-text);
64
+ }
65
+
66
+ &__icon {
67
+ text-align: center;
68
+ padding: 5px 10px;
69
+ }
70
+ }
71
+ </style>