dashboard-shell-shell 1.0.122 → 1.0.1000000081

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 (372) hide show
  1. package/.DS_Store +0 -0
  2. package/assets/brand/harvester/favicon.png +0 -0
  3. package/assets/brand/suse/favicon.png +0 -0
  4. package/assets/icons/iconfont.css +19 -3
  5. package/assets/icons/iconfont.js +1 -1
  6. package/assets/icons/iconfont.json +28 -0
  7. package/assets/icons/iconfont.ttf +0 -0
  8. package/assets/icons/iconfont.woff +0 -0
  9. package/assets/icons/iconfont.woff2 +0 -0
  10. package/assets/images/pl/half-logo.svg +2 -23
  11. package/assets/styles/base/_functions.scss +0 -0
  12. package/assets/styles/base/_mixins.scss +0 -0
  13. package/assets/styles/base/_variables.scss +1 -1
  14. package/assets/styles/global/_labeled-input.scss +0 -1
  15. package/assets/styles/global/_layout.scss +1 -1
  16. package/assets/styles/global/_select.scss +4 -2
  17. package/assets/styles/global/_table.scss +5 -0
  18. package/assets/styles/vendor/vue-select.scss +2 -1
  19. package/assets/translations/en-us.yaml +1 -1
  20. package/assets/translations/zh-hans.yaml +25 -15
  21. package/chart/monitoring/index.vue +3 -1
  22. package/chart/monitoring/prometheus/index.vue +13 -10
  23. package/cloud-credential/aws.vue +2 -0
  24. package/components/ActionDropdown.vue +1 -1
  25. package/components/ActionDropdownShell.vue +71 -0
  26. package/components/ActionMenu.vue +2 -2
  27. package/components/ActionMenuShell.vue +3 -0
  28. package/components/AppModal.vue +84 -8
  29. package/components/AssignTo.vue +25 -11
  30. package/components/AsyncButton.vue +24 -7
  31. package/components/BannerGraphic.vue +1 -0
  32. package/components/ButtonDropdown.vue +26 -4
  33. package/components/ButtonGroup.vue +4 -0
  34. package/components/ButtonMultiAction.vue +1 -0
  35. package/components/CodeMirror.vue +19 -6
  36. package/components/CommunityLinks.vue +3 -3
  37. package/components/ConsumptionGauge.vue +24 -5
  38. package/components/CopyToClipboardText.vue +2 -1
  39. package/components/CruResource.vue +13 -7
  40. package/components/CruResourceFooter.vue +2 -2
  41. package/components/DashboardOptions.vue +29 -17
  42. package/components/DetailText.vue +5 -0
  43. package/components/DisableAuthProviderModal.vue +1 -0
  44. package/components/DotState.vue +84 -0
  45. package/components/ExplorerMembers.vue +1 -1
  46. package/components/ExplorerProjectsNamespaces.vue +89 -16
  47. package/components/FixedBanner.vue +19 -12
  48. package/components/GlobalRoleBindings.vue +5 -1
  49. package/components/GrafanaDashboard.vue +4 -4
  50. package/components/GrowlManager.vue +4 -1
  51. package/components/HardwareResourceGauge.vue +39 -3
  52. package/components/InfoBox.vue +3 -3
  53. package/components/InputOrDisplay.vue +28 -2
  54. package/components/LabelValue.vue +20 -1
  55. package/components/LandingPagePreference.vue +5 -3
  56. package/components/LocaleSelector.vue +39 -93
  57. package/components/ModalManager.vue +55 -0
  58. package/components/ModalWithCard.vue +13 -3
  59. package/components/MoveModal.vue +1 -0
  60. package/components/PodSecurityAdmission.vue +1 -1
  61. package/components/PromptChangePassword.vue +1 -1
  62. package/components/PromptModal.vue +16 -3
  63. package/components/PromptRemove.vue +29 -9
  64. package/components/PromptRestore.vue +1 -0
  65. package/components/ResourceCancelModal.vue +1 -0
  66. package/components/ResourceDetail/Masthead.vue +52 -17
  67. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  68. package/components/ResourceDetail/index.vue +54 -16
  69. package/components/ResourceList/Masthead.vue +9 -4
  70. package/components/ResourceList/index.vue +4 -3
  71. package/components/ResourceTable.vue +1 -0
  72. package/components/SideNav.vue +20 -15
  73. package/components/SlideInPanelManager.vue +126 -0
  74. package/components/SortableTable/THead.vue +10 -4
  75. package/components/SortableTable/actions.js +1 -1
  76. package/components/SortableTable/index.vue +540 -553
  77. package/components/SortableTable/selection.js +2 -13
  78. package/components/StatusBadge.vue +77 -0
  79. package/components/Tabbed/Tab.vue +3 -3
  80. package/components/Tabbed/index.vue +47 -29
  81. package/components/Wizard.vue +2 -2
  82. package/components/YamlEditor.vue +1 -1
  83. package/components/__tests__/AsyncButton.test.ts +2 -2
  84. package/components/__tests__/FixedBanner.test.ts +3 -3
  85. package/components/__tests__/ModalManager.spec.ts +176 -0
  86. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  87. package/components/auth/Principal.vue +10 -3
  88. package/components/auth/RoleDetailEdit.vue +1 -1
  89. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  90. package/components/form/ArrayList.vue +123 -85
  91. package/components/form/ArrayListGrouped.vue +10 -2
  92. package/components/form/ArrayListSelect.vue +1 -1
  93. package/components/form/Command.vue +6 -15
  94. package/components/form/EnvVars.vue +16 -8
  95. package/components/form/Footer.vue +10 -7
  96. package/components/form/HealthCheck.vue +3 -3
  97. package/components/form/HookOption.vue +11 -16
  98. package/components/form/InputWithSelect.vue +6 -5
  99. package/components/form/KeyValue.vue +39 -10
  100. package/components/form/LabeledSelect.vue +73 -77
  101. package/components/form/Labels.vue +6 -3
  102. package/components/form/LifecycleHooks.vue +3 -3
  103. package/components/form/MatchExpressions.vue +42 -17
  104. package/components/form/NameNsDescription.vue +163 -116
  105. package/components/form/Networking.vue +20 -12
  106. package/components/form/NodeAffinity.vue +31 -23
  107. package/components/form/NodeScheduling.vue +13 -3
  108. package/components/form/Password.vue +11 -5
  109. package/components/form/PodAffinity.vue +47 -48
  110. package/components/form/Probe.vue +68 -66
  111. package/components/form/ResourceQuota/Namespace.vue +4 -4
  112. package/components/form/ResourceQuota/NamespaceRow.vue +5 -7
  113. package/components/form/ResourceQuota/Project.vue +9 -5
  114. package/components/form/ResourceQuota/ProjectRow.vue +4 -6
  115. package/components/form/ResourceSelector.vue +7 -9
  116. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
  117. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
  118. package/components/form/SSHKnownHosts/index.vue +16 -2
  119. package/components/form/Security.vue +54 -56
  120. package/components/form/Select.vue +44 -7
  121. package/components/form/ShellInput.vue +5 -1
  122. package/components/form/SimpleSecretSelector.vue +29 -9
  123. package/components/form/Tolerations.vue +5 -1
  124. package/components/form/UnitInput.vue +10 -5
  125. package/components/form/ValueFromResource.vue +134 -121
  126. package/components/form/WorkloadPorts.vue +18 -18
  127. package/components/form/__tests__/ArrayList.test.ts +5 -2
  128. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  129. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  130. package/components/form/__tests__/Probe.test.ts +12 -8
  131. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
  132. package/components/form/__tests__/Select.test.ts +37 -0
  133. package/components/form/__tests__/UnitInput.test.ts +4 -5
  134. package/components/formatter/BadgeStateFormatter.vue +8 -5
  135. package/components/formatter/InternalExternalIP.vue +2 -0
  136. package/components/formatter/LiveDate.vue +3 -3
  137. package/components/formatter/SecretData.vue +20 -7
  138. package/components/nav/Favorite.vue +5 -1
  139. package/components/nav/Group.vue +18 -4
  140. package/components/nav/Header.vue +39 -13
  141. package/components/nav/Jump.vue +7 -0
  142. package/components/nav/NamespaceFilter.vue +21 -11
  143. package/components/nav/Pinned.vue +1 -1
  144. package/components/nav/TopLevelMenu.vue +5 -17
  145. package/components/nav/Type.vue +30 -33
  146. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
  147. package/components/rancherResourceDetail/Masthead.vue +769 -0
  148. package/components/rancherResourceDetail/__tests__/Masthead.test.ts +65 -0
  149. package/components/rancherResourceDetail/index.vue +591 -0
  150. package/components/rancherResourceList/Masthead-btn.vue +225 -0
  151. package/components/rancherResourceList/Masthead.vue +375 -0
  152. package/components/rancherResourceList/ResourceLoadingIndicator.vue +140 -0
  153. package/components/rancherResourceList/index.vue +307 -0
  154. package/components/rancherResourceList/resource-list.config.js +7 -0
  155. package/components/rancherResourceTable.vue +783 -0
  156. package/components/rancherSortableTable/THead.vue +561 -0
  157. package/components/rancherSortableTable/actions.js +153 -0
  158. package/components/rancherSortableTable/advanced-filtering.js +272 -0
  159. package/components/rancherSortableTable/debug.js +117 -0
  160. package/components/rancherSortableTable/filtering.js +290 -0
  161. package/components/rancherSortableTable/grouping.js +48 -0
  162. package/components/rancherSortableTable/index.vue +2712 -0
  163. package/components/rancherSortableTable/paging.js +155 -0
  164. package/components/rancherSortableTable/selection.js +629 -0
  165. package/components/rancherSortableTable/sortable-config.ts +4 -0
  166. package/components/rancherSortableTable/sorting.js +129 -0
  167. package/components/templates/blank.vue +4 -1
  168. package/components/templates/default.vue +8 -0
  169. package/components/templates/home.vue +10 -1
  170. package/components/templates/plain.vue +10 -1
  171. package/composables/focusTrap.ts +11 -3
  172. package/composables/useRuntimeFlag.ts +29 -0
  173. package/config/private-label.js +15 -10
  174. package/config/router/routes.js +21 -13
  175. package/config/store.js +4 -0
  176. package/config/table-headers.js +3 -2
  177. package/config/uiplugins.js +5 -1
  178. package/core/plugin-routes.ts +5 -115
  179. package/core/plugins.js +1 -1
  180. package/core/types.ts +23 -2
  181. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +84 -23
  182. package/detail/autoscaling.horizontalpodautoscaler/index.vue +13 -3
  183. package/detail/provisioning.cattle.io.cluster.vue +72 -6
  184. package/dialog/AddCustomBadgeDialog.vue +1 -0
  185. package/dialog/DeactivateDriverDialog.vue +5 -4
  186. package/dialog/ForceMachineRemoveDialog.vue +6 -3
  187. package/dialog/GitRepoForceUpdateDialog.vue +1 -1
  188. package/dialog/ScalePoolDownDialog.vue +2 -2
  189. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
  190. package/edit/auth/__tests__/oidc.test.ts +162 -88
  191. package/edit/auth/azuread.vue +2 -1
  192. package/edit/auth/github.vue +1 -1
  193. package/edit/auth/googleoauth.vue +5 -1
  194. package/edit/auth/ldap/__tests__/config.test.ts +0 -14
  195. package/edit/auth/ldap/config.vue +0 -24
  196. package/edit/auth/ldap/index.vue +1 -1
  197. package/edit/auth/oidc.vue +39 -6
  198. package/edit/auth/saml.vue +1 -1
  199. package/edit/autoscaling.horizontalpodautoscaler/metric-identifier.vue +5 -2
  200. package/edit/cloudcredential.vue +24 -9
  201. package/edit/fleet.cattle.io.clustergroup.vue +5 -3
  202. package/edit/fleet.cattle.io.gitrepo.vue +2 -0
  203. package/edit/logging-flow/Match.vue +1 -1
  204. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
  205. package/edit/management.cattle.io.user.vue +28 -3
  206. package/edit/monitoring.coreos.com.alertmanagerconfig/auth.vue +19 -19
  207. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +31 -31
  208. package/edit/monitoring.coreos.com.alertmanagerconfig/routeConfig.vue +36 -12
  209. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +6 -6
  210. package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +10 -10
  211. package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +4 -4
  212. package/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue +4 -4
  213. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +1 -1
  214. package/edit/monitoring.coreos.com.receiver/auth.vue +29 -29
  215. package/edit/monitoring.coreos.com.receiver/types/email.vue +6 -6
  216. package/edit/monitoring.coreos.com.receiver/types/opsgenie.vue +10 -10
  217. package/edit/monitoring.coreos.com.receiver/types/pagerduty.vue +5 -5
  218. package/edit/monitoring.coreos.com.receiver/types/slack.vue +4 -4
  219. package/edit/namespace.vue +1 -2
  220. package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
  221. package/edit/networking.k8s.io.ingress/RulePath.vue +1 -1
  222. package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
  223. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
  224. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
  225. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -9
  226. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -10
  227. package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -40
  228. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +5 -2
  229. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
  230. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +33 -2
  231. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -3
  232. package/edit/service.vue +0 -3
  233. package/edit/token.vue +32 -11
  234. package/edit/workload/Job.vue +6 -6
  235. package/edit/workload/__tests__/Job.test.ts +0 -1
  236. package/edit/workload/index.vue +1 -0
  237. package/edit/workload/mixins/workload.js +3 -3
  238. package/initialize/install-plugins.js +2 -1
  239. package/list/harvesterhci.io.management.cluster.vue +4 -1
  240. package/list/management.cattle.io.feature.vue +1 -0
  241. package/list/namespace.vue +3 -1
  242. package/list/provisioning.cattle.io.cluster.vue +20 -12
  243. package/list/workload.vue +7 -6
  244. package/machine-config/__tests__/vmwarevsphere.test.ts +48 -3
  245. package/machine-config/azure.vue +16 -4
  246. package/machine-config/vmwarevsphere.vue +16 -0
  247. package/mixins/resource-fetch.js +2 -1
  248. package/models/__tests__/logging.banzaicloud.io.flow.test.ts +88 -0
  249. package/models/__tests__/namespace.test.ts +25 -1
  250. package/models/cloudcredential.js +5 -0
  251. package/models/kontainerdriver.js +6 -3
  252. package/models/logging.banzaicloud.io.flow.js +2 -1
  253. package/models/management.cattle.io.node.js +3 -3
  254. package/models/management.cattle.io.setting.js +2 -1
  255. package/models/namespace.js +4 -5
  256. package/models/nodedriver.js +6 -3
  257. package/models/storage.k8s.io.storageclass.js +2 -2
  258. package/models/workload.js +4 -1
  259. package/package.json +1 -1
  260. package/pages/about.vue +16 -8
  261. package/pages/account/index.vue +80 -24
  262. package/pages/account/pri.vue +229 -0
  263. package/pages/auth/login.vue +195 -44
  264. package/pages/auth/logout.vue +4 -1
  265. package/pages/auth/setup.vue +144 -19
  266. package/pages/auth/verify.vue +13 -8
  267. package/pages/auth copy/login.vue +595 -0
  268. package/pages/auth copy/logout.vue +47 -0
  269. package/pages/auth copy/setup.vue +523 -0
  270. package/pages/auth copy/verify.vue +203 -0
  271. package/pages/c/_cluster/_product/namespaces.vue +5 -5
  272. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  273. package/pages/c/_cluster/apps/charts/install.vue +26 -26
  274. package/pages/c/_cluster/auth/config/index.vue +10 -12
  275. package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
  276. package/pages/c/_cluster/explorer/index.vue +17 -15
  277. package/pages/c/_cluster/istio/index.vue +2 -2
  278. package/pages/c/_cluster/longhorn/index.vue +1 -1
  279. package/pages/c/_cluster/monitoring/index.vue +1 -1
  280. package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
  281. package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
  282. package/pages/c/_cluster/monitoring/monitor/index.vue +2 -2
  283. package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
  284. package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
  285. package/pages/c/_cluster/neuvector/index.vue +1 -1
  286. package/pages/c/_cluster/settings/brand.vue +3 -3
  287. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
  288. package/pages/diagnostic.vue +59 -11
  289. package/pages/fail-whale.vue +14 -8
  290. package/pages/home.vue +24 -18
  291. package/pages/prefs.vue +9 -7
  292. package/pages/support/index.vue +4 -1
  293. package/pkg/tsconfig.json +9 -9
  294. package/pkg/vue.config.js +1 -1
  295. package/plugins/dashboard-store/normalize.js +3 -1
  296. package/plugins/dashboard-store/resource-class.js +31 -29
  297. package/plugins/internal-api/index.ts +37 -0
  298. package/plugins/internal-api/shared/base-api.ts +13 -0
  299. package/plugins/internal-api/shell/shell.api.ts +108 -0
  300. package/promptRemove/management.cattle.io.fleetworkspace.vue +1 -1
  301. package/promptRemove/management.cattle.io.globalrole.vue +1 -1
  302. package/promptRemove/management.cattle.io.project.vue +2 -2
  303. package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
  304. package/promptRemove/pod.vue +1 -1
  305. package/public/index.html +2 -1
  306. package/rancher-components/BadgeState/BadgeState.vue +5 -1
  307. package/rancher-components/Banner/Banner.vue +8 -2
  308. package/rancher-components/Card/Card.vue +3 -6
  309. package/rancher-components/Form/Checkbox/Checkbox.vue +4 -0
  310. package/rancher-components/Form/LabeledInput/LabeledInput.vue +5 -2
  311. package/rancher-components/Form/Radio/RadioButton.vue +3 -3
  312. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -5
  313. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
  314. package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -2
  315. package/rancher-components/RcDropdown/RcDropdownMenu.vue +7 -3
  316. package/rancher-components/RcDropdown/types.ts +1 -0
  317. package/scripts/clean +0 -0
  318. package/scripts/extension/bundle +20 -0
  319. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
  320. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
  321. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  322. package/scripts/extension/helm/scripts/package +0 -0
  323. package/scripts/extension/helm/scripts/patch +0 -0
  324. package/scripts/extension/helm/scripts/version +0 -0
  325. package/scripts/extension/helmpatch +44 -31
  326. package/scripts/extension/parse-tag-name +0 -0
  327. package/scripts/extension/publish +12 -12
  328. package/scripts/publish-shell.sh +18 -23
  329. package/scripts/serve-pkgs +0 -0
  330. package/scripts/sync-shell-deps +0 -0
  331. package/scripts/test-plugins-build.sh +4 -6
  332. package/scripts/typegen.sh +28 -46
  333. package/server/har-file.js +25 -3
  334. package/static/favicon.ico +0 -0
  335. package/static/favicon.png +0 -0
  336. package/static/loading-indicator.html +2 -2
  337. package/store/aws.js +9 -2
  338. package/store/features.js +2 -1
  339. package/store/i18n.js +3 -3
  340. package/store/modal.ts +71 -0
  341. package/store/slideInPanel.ts +47 -0
  342. package/store/type-map.js +2 -1
  343. package/types/cloud-shell/index.d.ts +11014 -0
  344. package/types/global-vue.d.ts +5 -0
  345. package/types/internal-api/shell/growl.d.ts +25 -0
  346. package/types/internal-api/shell/modal.d.ts +77 -0
  347. package/types/internal-api/shell/slideIn.d.ts +15 -0
  348. package/types/shell/index.d.ts +118 -128
  349. package/types/vue-shim.d.ts +4 -1
  350. package/utils/__tests__/object.test.ts +38 -4
  351. package/utils/__tests__/string.test.ts +2 -2
  352. package/utils/auth.js +1 -0
  353. package/utils/banners.js +0 -45
  354. package/utils/cluster.js +35 -0
  355. package/utils/color.js +9 -8
  356. package/utils/error.js +61 -3
  357. package/utils/errorTranslate.json +450 -30
  358. package/utils/object.js +46 -6
  359. package/utils/router.js +22 -1
  360. package/utils/select.js +26 -3
  361. package/utils/string.js +9 -8
  362. package/utils/title.ts +1 -1
  363. package/utils/validators/machine-pool.ts +20 -0
  364. package/vue.config.js +7 -2
  365. package/components/formatter/ExtensionCache.vue +0 -74
  366. package/components/formatter/Port.vue +0 -24
  367. package/components/formatter/SecretType.vue +0 -41
  368. package/types/resources/fleet.d.ts +0 -57
  369. package/types/resources/pod-security-admission.ts +0 -36
  370. package/types/resources/settings.d.ts +0 -93
  371. package/types/resources/userPreferences.d.ts +0 -13
  372. package/types/vue-shim.d +0 -20
@@ -0,0 +1,166 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { createStore, Store } from 'vuex';
3
+ import { nextTick } from 'vue';
4
+ import SlideInPanelManager from '@shell/components/SlideInPanelManager.vue';
5
+
6
+ const MockComponent = {
7
+ template: '<div data-testid="slide-in-panel-component">Mock Panel Content</div>',
8
+ props: ['width', 'title', 'extraProp']
9
+ };
10
+
11
+ describe('slideInPanelManager.vue with Teleport', () => {
12
+ let store: Store<any>;
13
+ let getters: Record<string, () => any>;
14
+ let slidesDiv: HTMLDivElement;
15
+
16
+ beforeEach(() => {
17
+ // Create teleport target container
18
+ slidesDiv = document.createElement('div');
19
+ slidesDiv.setAttribute('id', 'slides');
20
+ document.body.appendChild(slidesDiv);
21
+
22
+ getters = {
23
+ 'slideInPanel/isOpen': () => true,
24
+ 'slideInPanel/component': () => MockComponent,
25
+ 'slideInPanel/componentProps': () => ({
26
+ width: '40%', title: 'Test Title', extraProp: 'extra'
27
+ })
28
+ };
29
+
30
+ store = createStore({
31
+ getters,
32
+ mutations: { 'slideInPanel/close': jest.fn() }
33
+ });
34
+ });
35
+
36
+ afterEach(() => {
37
+ // Clean up the teleport container
38
+ document.body.removeChild(slidesDiv);
39
+ });
40
+
41
+ const factory = () => {
42
+ return mount(SlideInPanelManager, {
43
+ attachTo: document.body, // attach to document so Teleport renders
44
+ global: { plugins: [store] }
45
+ });
46
+ };
47
+
48
+ it('renders slide in panel with proper style when open', async() => {
49
+ factory();
50
+ await nextTick();
51
+
52
+ const slidePanel = document.querySelector('#slides .slide-in') as HTMLElement;
53
+ const slideGlass = document.querySelector('[data-testid="slide-in-glass"]') as HTMLElement;
54
+ const slideComponent = document.querySelector('[data-testid="slide-in-panel-component"]') as HTMLElement;
55
+ const headerTitle = document.querySelector('#slides .slide-in .header .title') as HTMLElement;
56
+
57
+ expect(slidePanel).toBeTruthy();
58
+ expect(slideGlass).toBeTruthy();
59
+ expect(slideComponent).toBeTruthy();
60
+ expect(headerTitle.textContent?.trim()).toBe('Test Title');
61
+
62
+ const styleAttr = slidePanel.getAttribute('style') || '';
63
+
64
+ expect(styleAttr).toContain('width: 40%');
65
+ expect(styleAttr).toContain('top: 55px');
66
+ expect(styleAttr).toContain('height: calc(100vh - 55px)');
67
+ expect(styleAttr).toContain('right: 0');
68
+ });
69
+
70
+ it('renders default panel title when no title is provided', async() => {
71
+ // Update getter so that no title is provided
72
+ getters['slideInPanel/componentProps'] = () => ({ width: '40%' });
73
+ store = createStore({
74
+ getters,
75
+ mutations: { 'slideInPanel/close': jest.fn() }
76
+ });
77
+ factory();
78
+ await nextTick();
79
+
80
+ const headerTitle = document.querySelector('#slides #slide-in-panel-manager .header .title') as HTMLElement;
81
+
82
+ expect(headerTitle.textContent?.trim()).toBe('Details');
83
+ });
84
+
85
+ it('computes panelTop correctly when a banner exists', async() => {
86
+ // Create a banner element with a simulated clientHeight.
87
+ const banner = document.createElement('div');
88
+
89
+ banner.setAttribute('id', 'banner-header');
90
+ document.body.appendChild(banner);
91
+ // Simulate a banner with a clientHeight of 100.
92
+ Object.defineProperty(banner, 'clientHeight', { value: 100, configurable: true });
93
+
94
+ factory();
95
+ await nextTick();
96
+
97
+ const slidePanel = document.querySelector('#slides .slide-in') as HTMLElement;
98
+ const styleAttr = slidePanel.getAttribute('style') || '';
99
+
100
+ // Expected panelTop = HEADER_HEIGHT (55) + banner.clientHeight (100) = "155px"
101
+ expect(styleAttr).toContain('top: 155px');
102
+ expect(styleAttr).toContain('height: calc(100vh - 155px)');
103
+
104
+ document.body.removeChild(banner);
105
+ });
106
+
107
+ it('renders slide in glass as hidden and panel with negative right when closed', async() => {
108
+ // Set isOpen to false.
109
+ getters['slideInPanel/isOpen'] = () => false;
110
+ store = createStore({
111
+ getters,
112
+ mutations: { 'slideInPanel/close': jest.fn() }
113
+ });
114
+ factory();
115
+ await nextTick();
116
+
117
+ const slideGlass = document.querySelector('[data-testid="slide-in-glass"]') as HTMLElement;
118
+
119
+ expect(slideGlass).toBeTruthy();
120
+ expect(slideGlass.style.display).toBe('none');
121
+
122
+ const slidePanel = document.querySelector('#slides .slide-in') as HTMLElement;
123
+ const styleAttr = slidePanel.getAttribute('style') || '';
124
+
125
+ // With currentProps width "40%", panelRight should be "-40%" when closed.
126
+ expect(styleAttr).toContain('right: -40%');
127
+ });
128
+
129
+ it('calls store commit when clicking on the slide-in glass overlay', async() => {
130
+ const closeMutation = jest.fn();
131
+
132
+ getters['slideInPanel/isOpen'] = () => true;
133
+ store = createStore({
134
+ getters,
135
+ mutations: { 'slideInPanel/close': closeMutation }
136
+ });
137
+ factory();
138
+ await nextTick();
139
+
140
+ const slideGlass = document.querySelector('[data-testid="slide-in-glass"]') as HTMLElement;
141
+
142
+ slideGlass.click();
143
+ await nextTick();
144
+
145
+ expect(closeMutation).toHaveBeenCalledWith({}, undefined);
146
+ });
147
+
148
+ it('calls store commit when clicking on the slide-in close icon', async() => {
149
+ const closeMutation = jest.fn();
150
+
151
+ getters['slideInPanel/isOpen'] = () => true;
152
+ store = createStore({
153
+ getters,
154
+ mutations: { 'slideInPanel/close': closeMutation }
155
+ });
156
+ factory();
157
+ await nextTick();
158
+
159
+ const closeIcon = document.querySelector('[data-testid="slide-in-close"]') as HTMLElement;
160
+
161
+ closeIcon.click();
162
+ await nextTick();
163
+
164
+ expect(closeMutation).toHaveBeenCalledWith({}, undefined);
165
+ });
166
+ });
@@ -90,6 +90,7 @@ export default {
90
90
  <img
91
91
  :src="principal.avatarSrc"
92
92
  :class="{'round': principal.roundAvatar}"
93
+ :alt="t('principal.alt.avatar')"
93
94
  >
94
95
  </div>
95
96
  <div
@@ -98,9 +99,9 @@ export default {
98
99
  >
99
100
  <table>
100
101
  <tbody>
101
- <tr><td>{{ t('principal.name') }}: </td><td>{{ principal.name || principal.loginName }}</td></tr>
102
- <tr><td>{{ t('principal.loginName') }}: </td><td>{{ principal.loginName }}</td></tr>
103
- <tr><td>{{ t('principal.type') }}: </td><td>{{ principal.displayType }}</td></tr>
102
+ <tr><th>{{ t('principal.name') }}: </th><td>{{ principal.name || principal.loginName }}</td></tr>
103
+ <tr><th>{{ t('principal.loginName') }}: </th><td>{{ principal.loginName }}</td></tr>
104
+ <tr><th>{{ t('principal.type') }}: </th><td>{{ principal.displayType }}</td></tr>
104
105
  </tbody>
105
106
  </table>
106
107
  </div>
@@ -164,6 +165,12 @@ export default {
164
165
  grid-template-rows: auto math.div($size, 2);
165
166
  column-gap: 10px;
166
167
 
168
+ th {
169
+ text-align: left;
170
+ font-weight: normal;
171
+ padding-right: 10px;
172
+ }
173
+
167
174
  &.showLabels {
168
175
  grid-template-areas:
169
176
  "avatar name";
@@ -801,7 +801,7 @@ export default {
801
801
  .columns {
802
802
  .col > .unlabeled-select:not(.taggable) {
803
803
  // override the odd padding-top from shell/assets/styles/global/_select.scss
804
- padding: $unlabaled-select-padding
804
+ /* padding: $unlabaled-select-padding */
805
805
  }
806
806
  }
807
807
  }
@@ -51,8 +51,9 @@ describe('component: RoleDetailEdit', () => {
51
51
  const wrapper = mount(RoleDetailEdit, {
52
52
  props: {
53
53
  value: {
54
- rules: [{ verbs }],
55
- subtype: 'GLOBAL'
54
+ rules: [{ verbs }],
55
+ subtype: 'GLOBAL',
56
+ metadata: { name: 'global-role-with-inherited' },
56
57
  },
57
58
  },
58
59
 
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { ref, watch, computed } from 'vue';
2
3
  import debounce from 'lodash/debounce';
3
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
4
5
  import { removeAt } from '@shell/utils/array';
@@ -94,22 +95,87 @@ export default {
94
95
  // we only want functions in the rules array
95
96
  validator: (rules) => rules.every((rule) => ['function'].includes(typeof rule))
96
97
  },
98
+ a11yLabel: {
99
+ type: String,
100
+ default: '',
101
+ },
102
+ componentTestid: {
103
+ type: String,
104
+ default: 'array-list',
105
+ }
97
106
  },
98
- data() {
99
- const input = (Array.isArray(this.value) ? this.value : []).slice();
100
- const rows = [];
107
+
108
+ setup(props, { emit }) {
109
+ const input = (Array.isArray(props.value) ? props.value : []).slice();
110
+ const rows = ref([]);
101
111
 
102
112
  for ( const value of input ) {
103
- rows.push({ value });
113
+ rows.value.push({ value });
104
114
  }
105
- if ( !rows.length && this.initialEmptyRow ) {
106
- const value = this.defaultAddValue ? clone(this.defaultAddValue) : '';
115
+ if ( !rows.value.length && props.initialEmptyRow ) {
116
+ const value = props.defaultAddValue ? clone(props.defaultAddValue) : '';
107
117
 
108
- rows.push({ value });
118
+ rows.value.push({ value });
109
119
  }
110
120
 
111
- return { rows, lastUpdateWasFromValue: false };
121
+ const isView = computed(() => {
122
+ return props.mode === _VIEW;
123
+ });
124
+
125
+ /**
126
+ * Cleanup rows and emit input
127
+ */
128
+ const update = () => {
129
+ if ( isView.value ) {
130
+ return;
131
+ }
132
+ const out = [];
133
+
134
+ for ( const row of rows.value ) {
135
+ const trim = !props.valueMultiline && (typeof row.value === 'string');
136
+ const value = trim ? row.value.trim() : row.value;
137
+
138
+ if ( typeof value !== 'undefined' ) {
139
+ out.push(value);
140
+ }
141
+ }
142
+ emit('update:value', out);
143
+ };
144
+
145
+ const lastUpdateWasFromValue = ref(false);
146
+ const queueUpdate = debounce(update, 50);
147
+
148
+ watch(
149
+ rows,
150
+ () => {
151
+ // lastUpdateWasFromValue is used to break a cycle where when rows are updated
152
+ // this was called which then forced rows to updated again
153
+ if (!lastUpdateWasFromValue.value) {
154
+ queueUpdate();
155
+ }
156
+ lastUpdateWasFromValue.value = false;
157
+ },
158
+ { deep: true }
159
+ );
160
+
161
+ watch(
162
+ () => props.value,
163
+ () => {
164
+ lastUpdateWasFromValue.value = true;
165
+ rows.value = (props.value || []).map((v) => ({ value: v }));
166
+ },
167
+ { deep: true }
168
+ );
169
+
170
+ return {
171
+ rows,
172
+ lastUpdateWasFromValue,
173
+ queueUpdate,
174
+ isView,
175
+ update,
176
+ };
112
177
  },
178
+
113
179
  computed: {
114
180
  _addLabel() {
115
181
  return this.addLabel || this.t('generic.add');
@@ -117,10 +183,6 @@ export default {
117
183
  _removeLabel() {
118
184
  return this.removeLabel || this.t('generic.remove');
119
185
  },
120
-
121
- isView() {
122
- return this.mode === _VIEW;
123
- },
124
186
  showAdd() {
125
187
  return this.addAllowed;
126
188
  },
@@ -141,29 +203,7 @@ export default {
141
203
  return !this.valueMultiline && this.protip;
142
204
  }
143
205
  },
144
- watch: {
145
- value: {
146
- deep: true,
147
- handler() {
148
- this.lastUpdateWasFromValue = true;
149
- this.rows = (this.value || []).map((v) => ({ value: v }));
150
- }
151
- },
152
-
153
- rows: {
154
- deep: true,
155
- handler(newValue, oldValue) {
156
- // lastUpdateWasFromValue is used to break a cycle where when rows are updated
157
- // this was called which then forced rows to updated again
158
- if (!this.lastUpdateWasFromValue) {
159
- this.queueUpdate();
160
- }
161
- this.lastUpdateWasFromValue = false;
162
- }
163
- }
164
- },
165
206
  created() {
166
- this.queueUpdate = debounce(this.update, 50);
167
207
  },
168
208
  methods: {
169
209
  add() {
@@ -189,26 +229,6 @@ export default {
189
229
  this.queueUpdate();
190
230
  },
191
231
 
192
- /**
193
- * Cleanup rows and emit input
194
- */
195
- update() {
196
- if ( this.isView ) {
197
- return;
198
- }
199
- const out = [];
200
-
201
- for ( const row of this.rows ) {
202
- const trim = !this.valueMultiline && (typeof row.value === 'string');
203
- const value = trim ? row.value.trim() : row.value;
204
-
205
- if ( typeof value !== 'undefined' ) {
206
- out.push(value);
207
- }
208
- }
209
- this.$emit('update:value', out);
210
- },
211
-
212
232
  /**
213
233
  * Handle paste event, e.g. split multiple lines in rows
214
234
  */
@@ -254,7 +274,32 @@ export default {
254
274
  </h3>
255
275
  </slot>
256
276
  </div>
257
-
277
+ <div
278
+ v-if="showAdd && !isView"
279
+ class="footer"
280
+ >
281
+ <slot
282
+ v-if="showAdd"
283
+ name="add"
284
+ :add="add"
285
+ >
286
+ <button
287
+ type="button"
288
+ class="btn role-primary add"
289
+ :disabled="loading || disableAdd"
290
+ :data-testid="`${componentTestid}-button`"
291
+ :aria-label="_addLabel"
292
+ role="button"
293
+ @click="add()"
294
+ >
295
+ <i
296
+ class="mr-5 icon"
297
+ :class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
298
+ />
299
+ {{ _addLabel }}
300
+ </button>
301
+ </slot>
302
+ </div>
258
303
  <template v-if="rows.length">
259
304
  <div v-if="showHeader">
260
305
  <slot name="column-headers">
@@ -266,7 +311,7 @@ export default {
266
311
  <div
267
312
  v-for="(row, idx) in rows"
268
313
  :key="idx"
269
- :data-testid="`array-list-box${ idx }`"
314
+ :data-testid="`${componentTestid}-box${ idx }`"
270
315
  class="box"
271
316
  >
272
317
  <slot
@@ -290,7 +335,7 @@ export default {
290
335
  v-if="valueMultiline"
291
336
  ref="value"
292
337
  v-model:value="row.value"
293
- :data-testid="`textarea-${idx}`"
338
+ :data-testid="`${componentTestid}-textarea-${idx}`"
294
339
  :placeholder="valuePlaceholder"
295
340
  :mode="mode"
296
341
  :disabled="disabled"
@@ -301,7 +346,7 @@ export default {
301
346
  v-else-if="rules.length > 0"
302
347
  ref="value"
303
348
  v-model:value="row.value"
304
- :data-testid="`labeled-input-${idx}`"
349
+ :data-testid="`${componentTestid}-labeled-input-${idx}`"
305
350
  :placeholder="valuePlaceholder"
306
351
  :disabled="isView || disabled"
307
352
  :rules="rules"
@@ -313,9 +358,10 @@ export default {
313
358
  v-else
314
359
  ref="value"
315
360
  v-model="row.value"
316
- :data-testid="`input-${idx}`"
361
+ :data-testid="`${componentTestid}-input-${idx}`"
317
362
  :placeholder="valuePlaceholder"
318
363
  :disabled="isView || disabled"
364
+ :aria-label="a11yLabel ? a11yLabel : undefined"
319
365
  @paste="onPaste(idx, $event)"
320
366
  >
321
367
  </slot>
@@ -335,7 +381,9 @@ export default {
335
381
  type="button"
336
382
  :disabled="isView"
337
383
  class="btn role-link"
338
- :data-testid="`remove-item-${idx}`"
384
+ :data-testid="`${componentTestid}-remove-item-${idx}`"
385
+ :aria-label="`${_removeLabel} ${idx + 1}`"
386
+ role="button"
339
387
  @click="remove(row, idx)"
340
388
  >
341
389
  {{ _removeLabel }}
@@ -354,30 +402,7 @@ export default {
354
402
  </div>
355
403
  </slot>
356
404
  </div>
357
- <div
358
- v-if="showAdd && !isView"
359
- class="footer mt-20"
360
- >
361
- <slot
362
- v-if="showAdd"
363
- name="add"
364
- :add="add"
365
- >
366
- <button
367
- type="button"
368
- class="btn role-tertiary add"
369
- :disabled="loading || disableAdd"
370
- data-testid="array-list-button"
371
- @click="add()"
372
- >
373
- <i
374
- class="mr-5 icon"
375
- :class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
376
- />
377
- {{ _addLabel }}
378
- </button>
379
- </slot>
380
- </div>
405
+
381
406
  </div>
382
407
  </template>
383
408
 
@@ -398,7 +423,12 @@ export default {
398
423
  .value {
399
424
  flex: 1;
400
425
  INPUT {
401
- height: $unlabeled-input-height;
426
+ height: $input-height;
427
+ border: solid var(--border-width) var(--input-border);
428
+ padding: 4px 11px;
429
+ &:hover{
430
+ box-shadow: 0 4px 6px 0 var(--input-border-box-shadow);
431
+ }
402
432
  }
403
433
  }
404
434
  }
@@ -406,6 +436,7 @@ export default {
406
436
  text-align: right;
407
437
  }
408
438
  .footer {
439
+ margin-bottom: 24px;
409
440
  .protip {
410
441
  float: right;
411
442
  padding: 5px 0;
@@ -415,4 +446,11 @@ export default {
415
446
  .required {
416
447
  color: var(--error);
417
448
  }
449
+ :deep() .labeled-input.compact-input{
450
+ padding: 0px;
451
+ }
452
+ :deep() .box{
453
+ margin-bottom: 10px;
454
+ }
455
+
418
456
  </style>
@@ -127,8 +127,16 @@ export default {
127
127
  & > .remove {
128
128
  position: absolute;
129
129
 
130
- top: 0;
131
- right: 0;
130
+ top: 10px;
131
+ right: 10px;
132
+ & > .close{
133
+ width: 32px;
134
+ min-width: 32px !important;
135
+ color: var(--body-text);
136
+ &:hover{
137
+ color: var(--link);
138
+ }
139
+ }
132
140
  }
133
141
 
134
142
  & > .info-box {
@@ -98,6 +98,6 @@ export default {
98
98
 
99
99
  <style lang="scss" scoped>
100
100
  :deep() .unlabeled-select {
101
- height: 61px;
101
+ height: 30px;
102
102
  }
103
103
  </style>
@@ -43,23 +43,14 @@ export default {
43
43
  },
44
44
 
45
45
  data() {
46
- const {
47
- command,
48
- args,
49
- workingDir,
50
- stdin = false,
51
- stdinOnce = false,
52
- tty = false,
53
- } = this.value;
54
-
55
46
  return {
56
- args,
57
- command,
47
+ args: this.value.args,
48
+ command: this.value.command,
58
49
  commandOptions: ['No', 'Once', 'Yes'],
59
- stdin,
60
- stdinOnce,
61
- tty,
62
- workingDir,
50
+ stdin: this.value.stdin || false,
51
+ stdinOnce: this.value.stdin || false,
52
+ tty: this.value.tty || false,
53
+ workingDir: this.value.workingDir,
63
54
  };
64
55
  },
65
56
 
@@ -39,14 +39,10 @@ export default {
39
39
  },
40
40
 
41
41
  data() {
42
- const { env = [], envFrom = [] } = this.value;
43
-
44
- const allEnv = [...env, ...envFrom].map((row) => {
45
- return { value: row, id: randomStr(4) };
46
- });
47
-
48
42
  return {
49
- env, envFrom, allEnv
43
+ env: [],
44
+ envFrom: [],
45
+ allEnv: [],
50
46
  };
51
47
  },
52
48
 
@@ -63,7 +59,18 @@ export default {
63
59
  }
64
60
  }
65
61
  },
62
+
66
63
  created() {
64
+ const { env = [], envFrom = [] } = this.value;
65
+
66
+ const allEnv = [...env, ...envFrom].map((row) => {
67
+ return { value: row, id: randomStr(4) };
68
+ });
69
+
70
+ this.env = env;
71
+ this.envFrom = envFrom;
72
+ this.allEnv = allEnv;
73
+
67
74
  this.queueUpdate = debounce(this.update, 500);
68
75
  },
69
76
 
@@ -107,7 +114,8 @@ export default {
107
114
  <div :style="{'width':'100%'}">
108
115
  <div
109
116
  v-for="(row, i) in allEnv"
110
- :key="i"
117
+ :key="row.id"
118
+ :data-testid="`env-var-row-${i}`"
111
119
  >
112
120
  <ValueFromResource
113
121
  v-model:value="row.value"
@@ -51,7 +51,7 @@ export default defineComponent({
51
51
  <div v-if="!isView">
52
52
  <div class="spacer-small" />
53
53
 
54
- <div
54
+ <!-- <div
55
55
  v-for="(err,idx) in errors"
56
56
  :key="idx"
57
57
  >
@@ -59,7 +59,7 @@ export default defineComponent({
59
59
  color="error"
60
60
  :label="err"
61
61
  />
62
- </div>
62
+ </div> -->
63
63
  <div class="buttons">
64
64
  <div class="left">
65
65
  <slot name="left" />
@@ -91,9 +91,10 @@ export default defineComponent({
91
91
 
92
92
  <style lang='scss'>
93
93
  .buttons {
94
- display: grid;
94
+ /* display: grid;
95
95
  grid-template-areas: "left right";
96
- grid-template-columns: "min-content auto";
96
+ grid-template-columns: "min-content auto"; */
97
+ display: flex;
97
98
 
98
99
  .left {
99
100
  grid-area: left;
@@ -105,11 +106,13 @@ export default defineComponent({
105
106
  }
106
107
 
107
108
  .right {
108
- grid-area: right;
109
- text-align: right;
109
+ /* grid-area: right;
110
+ text-align: right; */
111
+ display: flex;
110
112
 
111
113
  .btn, button {
112
- margin: 0 0 0 $column-gutter;
114
+ /* margin: 0 0 0 $column-gutter; */
115
+ margin: 0 10px 0 0px;
113
116
  }
114
117
  }
115
118
  }