@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
@@ -224,7 +224,7 @@ export default {
224
224
 
225
225
  if (nxt >= tabsLength) {
226
226
  return 0;
227
- } else if (nxt <= 0) {
227
+ } else if (nxt < 0) {
228
228
  return tabsLength - 1;
229
229
  } else {
230
230
  return nxt;
@@ -259,11 +259,13 @@ export default {
259
259
  class="tabs"
260
260
  :class="{'clearfix':!sideTabs, 'vertical': sideTabs, 'horizontal': !sideTabs}"
261
261
  data-testid="tabbed-block"
262
+ tabindex="0"
262
263
  @keydown.right.prevent="selectNext(1)"
263
264
  @keydown.left.prevent="selectNext(-1)"
264
265
  @keydown.down.prevent="selectNext(1)"
265
266
  @keydown.up.prevent="selectNext(-1)"
266
267
  >
268
+ <!-- This is the tabs link... tabs appear here because they are injected from the "Tab" component -->
267
269
  <li
268
270
  v-for="tab in sortedTabs"
269
271
  :id="tab.name"
@@ -278,7 +280,6 @@ export default {
278
280
  :aria-selected="tab.active"
279
281
  :aria-label="tab.labelDisplay || ''"
280
282
  role="tab"
281
- tabindex="0"
282
283
  @click.prevent="select(tab.name, $event)"
283
284
  @keyup.enter.space="select(tab.name, $event)"
284
285
  >
@@ -336,8 +337,9 @@ export default {
336
337
  'tab-container--flat': !!flat,
337
338
  }"
338
339
  >
340
+ <!-- This is where "normal" tab content goes... -->
339
341
  <slot />
340
- <!-- Extension tabs -->
342
+ <!-- Extension tabs content goes here... -->
341
343
  <Tab
342
344
  v-for="tab, i in extensionTabs"
343
345
  :key="`${tab.name}${i}`"
@@ -365,6 +367,15 @@ export default {
365
367
  margin: 0;
366
368
  padding: 0;
367
369
 
370
+ &:focus-visible {
371
+ outline: none;
372
+
373
+ .tab.active {
374
+ @include focus-outline;
375
+ outline-offset: -2px;
376
+ }
377
+ }
378
+
368
379
  &.horizontal {
369
380
  border: solid thin var(--border);
370
381
  border-bottom: 0;
@@ -380,12 +391,8 @@ export default {
380
391
  }
381
392
  }
382
393
 
383
- &:focus {
384
- outline: none;
385
-
386
- & .tab.active a span {
387
- text-decoration: underline;
388
- }
394
+ &:focus .tab.active a span {
395
+ text-decoration: underline;
389
396
  }
390
397
 
391
398
  .tab {
@@ -405,12 +412,6 @@ export default {
405
412
  text-decoration: underline;
406
413
  }
407
414
  }
408
-
409
- &:focus-visible {
410
- @include focus-outline;
411
- outline-offset: -4px;
412
- text-decoration: none;
413
- }
414
415
  }
415
416
 
416
417
  .conditions-alert-icon {
@@ -154,7 +154,9 @@ export default {
154
154
  },
155
155
 
156
156
  canNext() {
157
- return (this.activeStepIndex < this.visibleSteps.length - 1) && this.activeStep.ready;
157
+ const activeStep = this.visibleSteps[this.activeStepIndex];
158
+
159
+ return (this.activeStepIndex < this.visibleSteps.length - 1) && activeStep.ready;
158
160
  },
159
161
 
160
162
  readySteps() {
@@ -277,124 +279,126 @@ export default {
277
279
  class="outer-container"
278
280
  :class="{'hide': !stepsLoaded}"
279
281
  >
280
- <div class="header">
281
- <div class="title">
282
- <div
283
- v-if="showBanner"
284
- class="top choice-banner"
285
- >
286
- <slot
287
- v-if="!!bannerImage || !!bannerTitle"
288
- name="bannerTitle"
282
+ <div>
283
+ <div class="header">
284
+ <div class="title">
285
+ <div
286
+ v-if="showBanner"
287
+ class="top choice-banner"
289
288
  >
290
- <div
291
- v-show="initialTitle || activeStepIndex > 0"
292
- class="title"
289
+ <slot
290
+ v-if="!!bannerImage || !!bannerTitle"
291
+ name="bannerTitle"
293
292
  >
294
- <!-- Logo -->
295
- <slot name="bannerTitleImage">
296
- <div
297
- v-if="bannerImage"
298
- class="round-image"
299
- >
300
- <LazyImage
301
- :src="bannerImage"
302
- class="logo"
303
- />
293
+ <div
294
+ v-show="initialTitle || activeStepIndex > 0"
295
+ class="title"
296
+ >
297
+ <!-- Logo -->
298
+ <slot name="bannerTitleImage">
299
+ <div
300
+ v-if="bannerImage"
301
+ class="round-image"
302
+ >
303
+ <LazyImage
304
+ :src="bannerImage"
305
+ class="logo"
306
+ />
307
+ </div>
308
+ </slot>
309
+ <!-- Title with subtext -->
310
+ <div class="subtitle">
311
+ <h2 v-if="bannerTitle">
312
+ {{ bannerTitle }}
313
+ </h2>
314
+ <span
315
+ v-if="bannerTitleSubtext"
316
+ class="subtext"
317
+ >{{ bannerTitleSubtext }}</span>
304
318
  </div>
305
- </slot>
306
- <!-- Title with subtext -->
307
- <div class="subtitle">
308
- <h2 v-if="bannerTitle">
309
- {{ bannerTitle }}
310
- </h2>
319
+ </div>
320
+ </slot>
321
+ <!-- Step number with subtext -->
322
+ <div
323
+ v-if="activeStep && showSteps"
324
+ class="subtitle"
325
+ >
326
+ <h2>{{ !!headerMode ? t(`wizard.${headerMode}`) : t(`asyncButton.${finishMode}.action`) }}: {{ t('wizard.step', {number:activeStepIndex+1}) }}</h2>
327
+ <slot name="bannerSubtext">
311
328
  <span
312
- v-if="bannerTitleSubtext"
329
+ v-if="activeStep.subtext !== null"
313
330
  class="subtext"
314
- >{{ bannerTitleSubtext }}</span>
315
- </div>
331
+ >{{ activeStep.subtext || activeStep.label }}</span>
332
+ </slot>
316
333
  </div>
317
- </slot>
318
- <!-- Step number with subtext -->
319
- <div
320
- v-if="activeStep && showSteps"
321
- class="subtitle"
322
- >
323
- <h2>{{ !!headerMode ? t(`wizard.${headerMode}`) : t(`asyncButton.${finishMode}.action`) }}: {{ t('wizard.step', {number:activeStepIndex+1}) }}</h2>
324
- <slot name="bannerSubtext">
325
- <span
326
- v-if="activeStep.subtext !== null"
327
- class="subtext"
328
- >{{ activeStep.subtext || activeStep.label }}</span>
329
- </slot>
330
334
  </div>
331
- </div>
332
- <div class="step-sequence">
333
- <ul
334
- v-if="showSteps"
335
- class="steps"
336
- tabindex="0"
337
- @keyup.right.stop="selectNext(1)"
338
- @keyup.left.stop="selectNext(-1)"
339
- >
340
- <template
341
- v-for="(step, idx ) in visibleSteps"
342
- :key="idx"
335
+ <div class="step-sequence">
336
+ <ul
337
+ v-if="showSteps"
338
+ class="steps"
339
+ tabindex="0"
340
+ @keyup.right.stop="selectNext(1)"
341
+ @keyup.left.stop="selectNext(-1)"
343
342
  >
344
- <li
345
-
346
- :id="step.name"
347
- :class="{step: true, active: step.name === activeStep.name, disabled: !isAvailable(step)}"
348
- role="presentation"
343
+ <template
344
+ v-for="(step, idx ) in visibleSteps"
345
+ :key="idx"
349
346
  >
350
- <span
351
- :aria-controls="'step' + idx+1"
352
- :aria-selected="step.name === activeStep.name"
353
- role="tab"
354
- class="controls"
355
- @click.prevent="goToStep(idx+1, true)"
347
+ <li
348
+
349
+ :id="step.name"
350
+ :class="{step: true, active: step.name === activeStep.name, disabled: !isAvailable(step)}"
351
+ role="presentation"
356
352
  >
357
353
  <span
358
- class="icon icon-lg"
359
- :class="{'icon-dot': step.name === activeStep.name, 'icon-dot-open':step.name !== activeStep.name}"
360
- />
361
- <span>
362
- {{ step.label }}
354
+ :aria-controls="'step' + idx+1"
355
+ :aria-selected="step.name === activeStep.name"
356
+ role="tab"
357
+ class="controls"
358
+ @click.prevent="goToStep(idx+1, true)"
359
+ >
360
+ <span
361
+ class="icon icon-lg"
362
+ :class="{'icon-dot': step.name === activeStep.name, 'icon-dot-open':step.name !== activeStep.name}"
363
+ />
364
+ <span>
365
+ {{ step.label }}
366
+ </span>
363
367
  </span>
364
- </span>
365
- </li>
366
- <div
367
- v-if="idx!==visibleSteps.length-1"
368
- :key="step.name"
369
- class="divider"
370
- />
371
- </template>
372
- </ul>
368
+ </li>
369
+ <div
370
+ v-if="idx!==visibleSteps.length-1"
371
+ :key="step.name"
372
+ class="divider"
373
+ />
374
+ </template>
375
+ </ul>
376
+ </div>
373
377
  </div>
374
378
  </div>
375
- </div>
376
- <slot
377
- class="step-container"
378
- name="stepContainer"
379
- :activeStep="activeStep"
380
- >
381
- <template
382
- v-for="(step, i) in steps"
383
- :key="i"
379
+ <slot
380
+ class="step-container"
381
+ name="stepContainer"
382
+ :activeStep="activeStep"
384
383
  >
385
- <div
386
- v-if="step.name === activeStep.name || step.hidden"
387
- :key="step.name"
388
- class="step-container__step"
389
- :class="{'hide': step.name !== activeStep.name && step.hidden}"
384
+ <template
385
+ v-for="(step, i) in steps"
386
+ :key="i"
390
387
  >
391
- <slot
392
- :step="step"
393
- :name="step.name"
394
- />
395
- </div>
396
- </template>
397
- </slot>
388
+ <div
389
+ v-if="step.name === activeStep.name || step.hidden"
390
+ :key="step.name"
391
+ class="step-container__step"
392
+ :class="{'hide': step.name !== activeStep.name && step.hidden}"
393
+ >
394
+ <slot
395
+ :step="step"
396
+ :name="step.name"
397
+ />
398
+ </div>
399
+ </template>
400
+ </slot>
401
+ </div>
398
402
  <slot
399
403
  name="controlsContainer"
400
404
  :showPrevious="showPrevious"
@@ -491,7 +495,7 @@ $spacer: 10px;
491
495
  flex-direction: column;
492
496
  flex: 1;
493
497
  padding: 0;
494
- justify-content: flex-start;
498
+ justify-content: space-between;
495
499
  }
496
500
 
497
501
  .header {
@@ -28,6 +28,11 @@ export default {
28
28
  }
29
29
  },
30
30
 
31
+ mode: {
32
+ type: String,
33
+ default: '',
34
+ },
35
+
31
36
  asObject: {
32
37
  type: Boolean,
33
38
  default: false,
@@ -213,17 +218,21 @@ export default {
213
218
  class="btn-group btn-sm diff-mode"
214
219
  >
215
220
  <button
221
+ role="button"
222
+ :aria-label="t('generic.unified')"
216
223
  type="button"
217
224
  class="btn btn-sm bg-default"
218
225
  :class="{'active': diffMode !== 'split'}"
219
226
  @click="diffMode='unified'"
220
- >Unified</button>
227
+ >{{ t('generic.unified') }}</button>
221
228
  <button
229
+ role="button"
230
+ :aria-label="t('generic.split')"
222
231
  type="button"
223
232
  class="btn btn-sm bg-default"
224
233
  :class="{'active': diffMode === 'split'}"
225
234
  @click="diffMode='split'"
226
- >Split</button>
235
+ >{{ t('generic.split') }}</button>
227
236
  </span>
228
237
  </div>
229
238
  <CodeMirror
@@ -234,6 +243,7 @@ export default {
234
243
  :options="codeMirrorOptions"
235
244
  :showKeyMapBox="true"
236
245
  :data-testid="componentTestid + '-code-mirror'"
246
+ :mode="mode"
237
247
  @onInput="onInput"
238
248
  @onReady="onReady"
239
249
  @onChanges="onChanges"
@@ -21,13 +21,13 @@ describe('component: Collapse.vue', () => {
21
21
  describe('collapsed', () => {
22
22
  const wrapper = mount(Collapse, { props: { open: true } });
23
23
 
24
- it('is collapse', () => {
24
+ it('is collapsed', () => {
25
25
  const content = wrapper.find(`[data-testid="collapse-content"]`);
26
26
 
27
27
  expect(content.element).toBeDefined();
28
28
  });
29
29
 
30
- it('icon should is chevron down', () => {
30
+ it('icon is chevron down', () => {
31
31
  const icon = wrapper.find(`[data-testid="collapse-icon-down"]`);
32
32
 
33
33
  expect(icon.element).toBeDefined();
@@ -40,7 +40,7 @@ describe('component: FixedBanner', () => {
40
40
  expect(wrapper.vm.showHeader).toStrictEqual(true);
41
41
 
42
42
  const bannerElem = wrapper.find('.banner');
43
- const noArrayTextElem = wrapper.find('.banner > p');
43
+ const noArrayTextElem = wrapper.find('.banner .single-row');
44
44
 
45
45
  expect(bannerElem.exists()).toBe(true);
46
46
  expect(bannerElem.classes()).not.toContain('banner-consent');
@@ -60,7 +60,7 @@ describe('component: FixedBanner', () => {
60
60
  expect(wrapper.vm.showFooter).toStrictEqual(true);
61
61
 
62
62
  const bannerElem = wrapper.find('.banner');
63
- const noArrayTextElem = wrapper.find('.banner > p');
63
+ const noArrayTextElem = wrapper.find('.banner .single-row');
64
64
 
65
65
  expect(bannerElem.exists()).toBe(true);
66
66
  expect(bannerElem.classes()).not.toContain('banner-consent');
@@ -84,7 +84,7 @@ describe('component: FixedBanner', () => {
84
84
  const bannerDialogElem = wrapper.find('.banner-dialog');
85
85
  const bannerDialogFrameElem = wrapper.find('.banner-dialog-frame');
86
86
  const buttonDialog = wrapper.find('.banner-dialog button');
87
- const noArrayTextElem = wrapper.find('.banner > p');
87
+ const noArrayTextElem = wrapper.find('.banner .single-row');
88
88
 
89
89
  expect(bannerElem.exists()).toBe(true);
90
90
  expect(bannerDialogGlassElem.exists()).toBe(true);
@@ -20,23 +20,7 @@ export default {
20
20
  },
21
21
 
22
22
  async fetch() {
23
- this.principal = this.$store.getters['rancher/byId'](NORMAN.PRINCIPAL, this.value);
24
-
25
- if ( this.principal ) {
26
- return;
27
- }
28
-
29
- const principalId = escape(this.value).replace(/\//g, '%2F');
30
-
31
- try {
32
- this.principal = await this.$store.dispatch('rancher/find', {
33
- type: NORMAN.PRINCIPAL,
34
- id: this.value,
35
- opt: { url: `/v3/principals/${ principalId }` }
36
- });
37
- } catch (e) {
38
- console.error('Failed to fetch principal', this.value, principalId); // eslint-disable-line no-console
39
- }
23
+ this.loadData();
40
24
  },
41
25
 
42
26
  data() {
@@ -51,6 +35,34 @@ export default {
51
35
  return p.name && p.loginName && p.name.trim().toLowerCase() !== p.loginName.trim().toLowerCase();
52
36
  }
53
37
  },
38
+
39
+ methods: {
40
+ async loadData() {
41
+ this.principal = this.$store.getters['rancher/byId'](NORMAN.PRINCIPAL, this.value);
42
+
43
+ if ( this.principal ) {
44
+ return;
45
+ }
46
+
47
+ const principalId = escape(this.value).replace(/\//g, '%2F');
48
+
49
+ try {
50
+ this.principal = await this.$store.dispatch('rancher/find', {
51
+ type: NORMAN.PRINCIPAL,
52
+ id: this.value,
53
+ opt: { url: `/v3/principals/${ principalId }` }
54
+ });
55
+ } catch (e) {
56
+ console.error('Failed to fetch principal', this.value, principalId); // eslint-disable-line no-console
57
+ }
58
+ }
59
+ },
60
+
61
+ watch: {
62
+ value() {
63
+ this.loadData();
64
+ }
65
+ },
54
66
  };
55
67
  </script>
56
68
 
@@ -0,0 +1,40 @@
1
+ import { mount, type VueWrapper } from '@vue/test-utils';
2
+ import Principal from '@shell/components/auth/Principal.vue';
3
+
4
+ describe('component: Principal', () => {
5
+ it('should render the component', () => {
6
+ const wrapper = mount(Principal, {
7
+ props: { value: 'whatever' },
8
+ global: { mocks: { $fetchState: { pending: false } } },
9
+ });
10
+
11
+ expect(wrapper.exists()).toBe(true);
12
+ });
13
+
14
+ it('should update principal displayed properties on value change', async() => {
15
+ const wrapper: VueWrapper<any, any> = mount(Principal, {
16
+ props: { value: 'whatever' },
17
+ global: {
18
+ mocks: {
19
+ $fetchState: { pending: false },
20
+ $store: {
21
+ getters: {
22
+ 'rancher/byId': (_: any, id: 'first' | 'second') => {
23
+ const options = {
24
+ first: { name: 'first name' },
25
+ second: { name: 'second name' }
26
+ };
27
+
28
+ return options[id];
29
+ }
30
+ }
31
+ },
32
+ },
33
+ },
34
+ });
35
+
36
+ await wrapper.setProps({ value: 'second' });
37
+
38
+ expect(wrapper.vm.principal.name).toStrictEqual('second name');
39
+ });
40
+ });
@@ -2,6 +2,7 @@
2
2
  import { LabeledInput } from '@components/Form/LabeledInput';
3
3
  import AsyncButton from '@shell/components/AsyncButton';
4
4
  import Login from '@shell/mixins/login';
5
+ import loadPlugins from '@shell/plugins/plugin';
5
6
 
6
7
  export default {
7
8
  emits: ['error', 'showInputs'],
@@ -32,6 +33,12 @@ export default {
32
33
  }
33
34
  });
34
35
 
36
+ await loadPlugins({
37
+ app: this.$store.app,
38
+ store: this.$store,
39
+ $plugin: this.$store.$plugin
40
+ });
41
+
35
42
  buttonCb(true);
36
43
  this.$router.replace('/');
37
44
  } catch (err) {
@@ -126,7 +126,7 @@ export default {
126
126
  v-if="displayWarning(row)"
127
127
  class="text-warning"
128
128
  >
129
- {{ row.status.summary.ready }}/{{ row.status.summary.desiredReady }}</span>
129
+ {{ row.status.summary.ready || 0 }}/{{ row.status.summary.desiredReady }}</span>
130
130
  <span v-else-if="row.status && row.status.summary">{{ row.status.summary.desiredReady }}</span>
131
131
  <span v-else>-</span>
132
132
  </template>
@@ -120,7 +120,7 @@ export default {
120
120
  <template #cell:repo="{ row }">
121
121
  <Link
122
122
  :row="row"
123
- :value="row.spec.repo"
123
+ :value="row.spec.repo || ''"
124
124
  label-key="repoDisplay"
125
125
  before-icon-key="repoIcon"
126
126
  url-key="spec.repo"
@@ -1,6 +1,5 @@
1
1
  <script>
2
2
  import SortableTable from '@shell/components/SortableTable';
3
- import { AGE } from '@shell/config/table-headers';
4
3
 
5
4
  export default {
6
5
  name: 'FleetResources',
@@ -65,7 +64,6 @@ export default {
65
64
  sort: 'namespace',
66
65
  label: 'Namespace',
67
66
  },
68
- { ...AGE }
69
67
  ];
70
68
  },
71
69
  }