@rancher/shell 0.3.29 → 0.5.0

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 (301) hide show
  1. package/assets/images/providers/ovhcloudmks.svg +122 -0
  2. package/assets/images/providers/ovhcloudpubliccloud.svg +122 -0
  3. package/assets/styles/global/_layout.scss +99 -0
  4. package/assets/translations/en-us.yaml +31 -6
  5. package/assets/translations/zh-hans.yaml +2 -2
  6. package/babel.config.js +7 -1
  7. package/chart/monitoring/alerting/index.vue +7 -21
  8. package/chart/monitoring/grafana/index.vue +55 -0
  9. package/chart/monitoring/index.vue +51 -17
  10. package/chart/monitoring/prometheus/index.vue +37 -43
  11. package/chart/rancher-backup/index.vue +2 -1
  12. package/cloud-credential/azure.vue +4 -17
  13. package/components/AsyncButton.vue +17 -5
  14. package/components/Certificates.vue +164 -0
  15. package/components/CodeMirror.vue +19 -21
  16. package/components/CopyCode.vue +6 -2
  17. package/components/CopyToClipboard.vue +2 -1
  18. package/components/CopyToClipboardText.vue +14 -9
  19. package/components/CruResource.vue +1 -0
  20. package/components/DraggableZone.vue +2 -2
  21. package/components/EtcdInfoBanner.vue +5 -5
  22. package/components/ExplorerProjectsNamespaces.vue +25 -1
  23. package/components/IconOrSvg.vue +1 -1
  24. package/components/LandingPagePreference.vue +1 -4
  25. package/components/Markdown.vue +16 -12
  26. package/components/PodSecurityAdmission.vue +2 -2
  27. package/components/Questions/index.vue +1 -1
  28. package/components/ResourceDetail/Masthead.vue +25 -9
  29. package/components/ResourceTable.vue +14 -2
  30. package/components/ResourceYaml.vue +5 -0
  31. package/components/SideNav.vue +1 -1
  32. package/components/SingleClusterInfo.vue +1 -4
  33. package/components/StatusTable.vue +5 -1
  34. package/components/Tabbed/index.vue +12 -0
  35. package/components/__tests__/CopyCode.test.ts +5 -4
  36. package/components/fleet/FleetBundles.vue +5 -11
  37. package/components/fleet/FleetRepos.vue +62 -27
  38. package/components/fleet/FleetResources.vue +6 -1
  39. package/components/fleet/FleetSummary.vue +3 -3
  40. package/components/fleet/__tests__/FleetSummary.test.ts +316 -0
  41. package/components/form/ArrayListSelect.vue +10 -0
  42. package/components/form/Error.vue +3 -3
  43. package/components/form/Footer.vue +2 -2
  44. package/components/form/GitPicker.vue +83 -38
  45. package/components/form/KeyValue.vue +4 -0
  46. package/components/form/LabeledSelect.vue +4 -0
  47. package/components/form/Password.vue +3 -1
  48. package/components/formatter/Checked.vue +11 -3
  49. package/components/formatter/FleetClusterSummaryGraph.vue +27 -0
  50. package/components/formatter/FleetSummaryGraph.vue +23 -11
  51. package/components/formatter/LiveDuration.vue +1 -1
  52. package/components/formatter/PercentageBar.vue +1 -1
  53. package/components/formatter/__tests__/Checked.test.ts +19 -0
  54. package/components/nav/Group.vue +2 -2
  55. package/components/nav/Header.vue +1 -2
  56. package/components/nav/TopLevelMenu.vue +36 -6
  57. package/components/nav/Type.vue +1 -3
  58. package/components/nav/WindowManager/ContainerLogs.vue +101 -3
  59. package/components/nav/WindowManager/ContainerShell.vue +6 -1
  60. package/components/nav/WindowManager/__tests__/ContainerLogs.test.ts +186 -0
  61. package/components/nav/WindowManager/index.vue +11 -10
  62. package/components/nav/__tests__/TopLevelMenu.test.ts +33 -0
  63. package/components/nav/__tests__/Type.test.ts +1 -1
  64. package/components/nuxt/nuxt-child.js +14 -78
  65. package/components/nuxt/nuxt.js +1 -1
  66. package/{layouts → components/templates}/blank.vue +1 -1
  67. package/{layouts → components/templates}/default.vue +8 -98
  68. package/{layouts → components/templates}/error.vue +10 -19
  69. package/{layouts → components/templates}/home.vue +4 -1
  70. package/{layouts → components/templates}/plain.vue +4 -1
  71. package/{layouts → components/templates}/standalone.vue +1 -1
  72. package/{layouts → components/templates}/unauthenticated.vue +1 -1
  73. package/composables/useCompactInput.test.ts +36 -0
  74. package/composables/useCompactInput.ts +20 -0
  75. package/composables/useLabeledFormElement.test.ts +135 -0
  76. package/composables/useLabeledFormElement.ts +138 -0
  77. package/config/harvester-manager-types.js +2 -0
  78. package/config/home-links.js +1 -1
  79. package/config/private-label.js +22 -0
  80. package/config/product/explorer.js +3 -0
  81. package/config/product/fleet.js +6 -1
  82. package/config/product/manager.js +8 -2
  83. package/config/query-params.js +1 -0
  84. package/config/router.js +385 -364
  85. package/config/settings.ts +1 -0
  86. package/config/store.js +1 -1
  87. package/config/system-namespaces.js +3 -0
  88. package/config/table-headers.js +47 -0
  89. package/core/plugin-helpers.js +3 -5
  90. package/core/plugin-routes.ts +56 -114
  91. package/core/plugin.ts +16 -10
  92. package/core/plugins-loader.js +7 -9
  93. package/core/plugins.js +0 -3
  94. package/creators/app/files/.gitlab-ci.yml +14 -0
  95. package/creators/app/init +19 -0
  96. package/detail/fleet.cattle.io.cluster.vue +11 -1
  97. package/detail/provisioning.cattle.io.cluster.vue +4 -3
  98. package/dialog/ScaleMachineDownDialog.vue +34 -17
  99. package/edit/__tests__/service.test.ts +89 -0
  100. package/edit/auth/googleoauth.vue +1 -5
  101. package/edit/cloudcredential.vue +2 -0
  102. package/edit/configmap.vue +2 -1
  103. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +2 -2
  104. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +12 -3
  105. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +2 -1
  106. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +1 -1
  107. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +15 -7
  108. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +112 -0
  109. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +473 -0
  110. package/edit/provisioning.cattle.io.cluster/__tests__/{CustomCommand.tests.ts → CustomCommand.test.ts} +6 -0
  111. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +1 -1
  112. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +73 -0
  113. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +7 -1
  114. package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +386 -0
  115. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  116. package/edit/provisioning.cattle.io.cluster/index.vue +92 -36
  117. package/edit/provisioning.cattle.io.cluster/rke2.vue +171 -583
  118. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +137 -0
  119. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +157 -0
  120. package/edit/provisioning.cattle.io.cluster/{Basics.vue → tabs/Basics.vue} +94 -19
  121. package/edit/provisioning.cattle.io.cluster/{MachinePool.vue → tabs/MachinePool.vue} +1 -0
  122. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +135 -0
  123. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +189 -0
  124. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +144 -0
  125. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/index.vue +76 -0
  126. package/edit/service.vue +12 -0
  127. package/edit/workload/Upgrading.vue +3 -2
  128. package/edit/workload/mixins/workload.js +1 -1
  129. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +2 -1
  130. package/initialize/App.js +25 -71
  131. package/initialize/client.js +21 -162
  132. package/initialize/index.js +47 -124
  133. package/list/management.cattle.io.feature.vue +1 -7
  134. package/list/node.vue +1 -0
  135. package/machine-config/__tests__/vmwarevsphere.test.ts +100 -21
  136. package/machine-config/vmwarevsphere.vue +73 -51
  137. package/middleware/authenticated.js +10 -17
  138. package/mixins/auth-config.js +2 -7
  139. package/mixins/brand.js +29 -41
  140. package/mixins/create-edit-view/index.js +2 -2
  141. package/mixins/labeled-form-element.ts +6 -1
  142. package/models/__tests__/management.cattle.io.cluster.test.ts +4 -0
  143. package/models/__tests__/management.cattle.io.node.ts +85 -0
  144. package/models/__tests__/management.cattle.io.nodepool.ts +83 -0
  145. package/models/__tests__/namespace.test.ts +49 -9
  146. package/models/__tests__/workload.test.ts +91 -0
  147. package/models/cluster/node.js +4 -4
  148. package/models/cluster.x-k8s.io.machinedeployment.js +14 -0
  149. package/models/fleet.cattle.io.cluster.js +4 -0
  150. package/models/fleet.cattle.io.gitrepo.js +56 -13
  151. package/models/management.cattle.io.cluster.js +7 -3
  152. package/models/management.cattle.io.kontainerdriver.js +1 -1
  153. package/models/management.cattle.io.node.js +18 -14
  154. package/models/management.cattle.io.nodepool.js +17 -0
  155. package/models/namespace.js +1 -1
  156. package/models/pod.js +20 -0
  157. package/models/provisioning.cattle.io.cluster.js +39 -4
  158. package/models/secret.js +117 -18
  159. package/models/workload.js +16 -0
  160. package/models/workload.service.js +18 -0
  161. package/package.json +11 -10
  162. package/pages/about.vue +0 -1
  163. package/pages/account/create-key.vue +0 -1
  164. package/pages/account/index.vue +0 -1
  165. package/pages/auth/login.vue +0 -1
  166. package/pages/auth/logout.vue +0 -2
  167. package/pages/auth/setup.vue +0 -4
  168. package/pages/auth/verify.vue +14 -8
  169. package/pages/c/_cluster/apps/charts/index.vue +64 -43
  170. package/pages/c/_cluster/apps/charts/install.vue +4 -4
  171. package/pages/c/_cluster/apps/index.vue +0 -2
  172. package/pages/c/_cluster/auth/index.vue +0 -2
  173. package/pages/c/_cluster/ecm/index.vue +0 -2
  174. package/pages/c/_cluster/explorer/index.vue +28 -2
  175. package/pages/c/_cluster/fleet/index.vue +1 -1
  176. package/pages/c/_cluster/index.vue +0 -2
  177. package/pages/c/_cluster/settings/banners.vue +0 -2
  178. package/pages/c/_cluster/settings/brand.vue +0 -2
  179. package/pages/c/_cluster/settings/index.vue +0 -2
  180. package/pages/c/_cluster/settings/links.vue +0 -1
  181. package/pages/c/_cluster/settings/performance.vue +0 -1
  182. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +2 -1
  183. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +10 -46
  184. package/pages/c/_cluster/uiplugins/index.vue +0 -2
  185. package/pages/diagnostic.vue +1 -2
  186. package/pages/fail-whale.vue +0 -1
  187. package/pages/prefs.vue +0 -1
  188. package/pages/support/index.vue +2 -8
  189. package/pkg/auto-import.js +1 -1
  190. package/plugins/axios.js +0 -36
  191. package/plugins/back-button.js +3 -5
  192. package/plugins/clean-html-directive.js +1 -19
  193. package/plugins/clean-html.js +53 -0
  194. package/plugins/clean-tooltip-directive.js +1 -1
  195. package/plugins/codemirror-loader.js +1 -1
  196. package/plugins/codemirror.js +41 -0
  197. package/plugins/dashboard-store/__tests__/{mutations.spec.ts → mutations.test.ts} +1 -1
  198. package/plugins/dashboard-store/__tests__/resource-class.test.ts +49 -0
  199. package/plugins/dashboard-store/__tests__/utils/store-mocks.ts +7 -0
  200. package/plugins/dashboard-store/actions.js +30 -4
  201. package/plugins/dashboard-store/classify.js +1 -18
  202. package/plugins/dashboard-store/getters.js +10 -5
  203. package/plugins/dashboard-store/index.js +0 -12
  204. package/plugins/dashboard-store/mutations.js +0 -4
  205. package/plugins/dashboard-store/resource-class.js +59 -18
  206. package/plugins/index.js +11 -0
  207. package/plugins/steve/__tests__/steve-class.spec.ts +59 -0
  208. package/plugins/steve/__tests__/utils/steve-mocks.ts +31 -0
  209. package/plugins/steve/getters.js +4 -1
  210. package/plugins/steve/norman-class.js +19 -0
  211. package/plugins/steve/steve-class.js +22 -0
  212. package/plugins/steve/subscribe.js +4 -10
  213. package/rancher-components/Accordion/Accordion.test.ts +45 -0
  214. package/rancher-components/Accordion/Accordion.vue +86 -0
  215. package/rancher-components/Accordion/index.ts +1 -0
  216. package/rancher-components/BadgeState/BadgeState.vue +3 -3
  217. package/rancher-components/Banner/Banner.vue +2 -2
  218. package/rancher-components/Card/Card.vue +3 -3
  219. package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
  220. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
  221. package/rancher-components/Form/LabeledInput/LabeledInput.vue +65 -24
  222. package/rancher-components/Form/Radio/RadioButton.test.ts +7 -3
  223. package/rancher-components/Form/Radio/RadioButton.vue +13 -7
  224. package/rancher-components/Form/Radio/RadioGroup.test.ts +30 -0
  225. package/rancher-components/Form/Radio/RadioGroup.vue +8 -3
  226. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -4
  227. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  228. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
  229. package/rancher-components/StringList/StringList.test.ts +270 -0
  230. package/rancher-components/StringList/StringList.vue +65 -26
  231. package/rancher-components/components/Accordion/Accordion.test.ts +45 -0
  232. package/rancher-components/components/Accordion/Accordion.vue +86 -0
  233. package/rancher-components/components/Accordion/index.ts +1 -0
  234. package/rancher-components/components/BadgeState/BadgeState.vue +3 -3
  235. package/rancher-components/components/Banner/Banner.vue +2 -2
  236. package/rancher-components/components/Card/Card.vue +3 -3
  237. package/rancher-components/components/Form/Checkbox/Checkbox.vue +3 -3
  238. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +18 -1
  239. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +57 -24
  240. package/rancher-components/components/Form/Radio/RadioButton.vue +13 -7
  241. package/rancher-components/components/Form/Radio/RadioGroup.vue +4 -3
  242. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +6 -4
  243. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  244. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +9 -4
  245. package/rancher-components/components/StringList/StringList.vue +8 -8
  246. package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +50 -0
  247. package/scripts/extension/bundle +19 -7
  248. package/scripts/extension/helm/scripts/package +11 -3
  249. package/scripts/extension/parse-tag-name +2 -2
  250. package/scripts/extension/publish +20 -9
  251. package/scripts/publish-shell.sh +10 -0
  252. package/scripts/test-plugins-build.sh +85 -9
  253. package/server/har-file.js +183 -0
  254. package/store/catalog.js +1 -1
  255. package/store/features.js +1 -0
  256. package/store/i18n.js +11 -0
  257. package/store/index.js +13 -15
  258. package/store/prefs.js +33 -35
  259. package/store/type-map.js +8 -7
  260. package/tsconfig.json +35 -9
  261. package/tsconfig.paths.json +21 -0
  262. package/types/shell/index.d.ts +433 -234
  263. package/types/vue-shim.d.ts +42 -0
  264. package/utils/__tests__/create-yaml.test.ts +60 -0
  265. package/utils/axios.js +0 -19
  266. package/utils/azure.js +24 -0
  267. package/utils/clipboard.js +5 -0
  268. package/utils/create-yaml.js +17 -10
  269. package/utils/git.ts +1 -1
  270. package/utils/monitoring.js +1 -1
  271. package/utils/nuxt.js +18 -39
  272. package/utils/object.js +14 -0
  273. package/utils/router.scrollBehavior.js +12 -14
  274. package/utils/time.js +1 -1
  275. package/utils/url.ts +1 -1
  276. package/vue.config.js +23 -2
  277. package/.DS_Store +0 -0
  278. package/assets/images/providers/aks-black.svg +0 -28
  279. package/assets/images/providers/aks.svg +0 -31
  280. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +0 -234
  281. package/initialize/layouts.ts +0 -26
  282. package/mixins/fetch.server.js +0 -73
  283. package/pages/c/index.vue +0 -9
  284. package/pages/rio/mesh.vue +0 -508
  285. package/plugins/transitions.js +0 -4
  286. package/plugins/vue-clipboard2.js +0 -4
  287. package/tsconfig.default.json +0 -46
  288. package/yarn-error.log +0 -200
  289. /package/components/form/__tests__/{NameNsDescription.ts → NameNsDescription.test.ts} +0 -0
  290. /package/edit/networking.k8s.io.networkpolicy/__tests__/utils/{selectors.ts → selectors.test.ts} +0 -0
  291. /package/edit/provisioning.cattle.io.cluster/{AgentConfiguration.vue → tabs/AgentConfiguration.vue} +0 -0
  292. /package/edit/provisioning.cattle.io.cluster/{MemberRoles.vue → tabs/MemberRoles.vue} +0 -0
  293. /package/edit/provisioning.cattle.io.cluster/{S3Config.vue → tabs/etcd/S3Config.vue} +0 -0
  294. /package/edit/provisioning.cattle.io.cluster/{ACE.vue → tabs/networking/ACE.vue} +0 -0
  295. /package/edit/provisioning.cattle.io.cluster/{RegistryConfigs.vue → tabs/registries/RegistryConfigs.vue} +0 -0
  296. /package/edit/provisioning.cattle.io.cluster/{RegistryMirrors.vue → tabs/registries/RegistryMirrors.vue} +0 -0
  297. /package/edit/provisioning.cattle.io.cluster/{DrainOptions.vue → tabs/upgrade/DrainOptions.vue} +0 -0
  298. /package/plugins/dashboard-store/__tests__/{actions.spec.ts → actions.test.ts} +0 -0
  299. /package/plugins/dashboard-store/__tests__/{getters.spec.ts → getters.test.ts} +0 -0
  300. /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
  301. /package/rancher-components/components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
@@ -0,0 +1,45 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import { Accordion } from './index';
3
+
4
+ describe('component: Accordion', () => {
5
+ it('is closed initially by default', () => {
6
+ const title = 'Test Title';
7
+
8
+ const wrapper = shallowMount(Accordion, { propsData: { title } });
9
+
10
+ expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(false);
11
+ expect(wrapper.find('[data-testid="accordion-header"]').text()).toBe(title);
12
+ });
13
+
14
+ it('is opened initially when openInitially prop is true', () => {
15
+ const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
16
+
17
+ expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(true);
18
+ });
19
+
20
+ it('when closed, opens when the header is clicked', async() => {
21
+ const wrapper = shallowMount(Accordion, { });
22
+
23
+ await wrapper.find('[data-testid="accordion-header"]').trigger('click');
24
+ expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(true);
25
+ });
26
+
27
+ it('when open, closes when the header is clicked', async() => {
28
+ const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
29
+
30
+ await wrapper.find('[data-testid="accordion-header"]').trigger('click');
31
+ expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(false);
32
+ });
33
+
34
+ it('displays a chevron when closed', async() => {
35
+ const wrapper = shallowMount(Accordion, { propsData: { } });
36
+
37
+ expect(wrapper.find('[data-testid="accordion-header"] .icon-chevron-up').exists()).toBe(true);
38
+ });
39
+
40
+ it('displays an inverted chevron when open', async() => {
41
+ const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
42
+
43
+ expect(wrapper.find('[data-testid="accordion-header"] .icon-chevron-down').exists()).toBe(true);
44
+ });
45
+ });
@@ -0,0 +1,86 @@
1
+ <script lang="ts">
2
+ import { defineComponent } from 'vue';
3
+ import { mapGetters } from 'vuex';
4
+
5
+ export default defineComponent({
6
+ props: {
7
+ title: {
8
+ type: String,
9
+ default: ''
10
+ },
11
+
12
+ titleKey: {
13
+ type: String,
14
+ default: null
15
+ },
16
+
17
+ openInitially: {
18
+ type: Boolean,
19
+ default: false
20
+ }
21
+ },
22
+
23
+ data() {
24
+ return { isOpen: this.openInitially };
25
+ },
26
+
27
+ computed: { ...mapGetters({ t: 'i18n/t' }) },
28
+
29
+ methods: {
30
+ toggle() {
31
+ this.isOpen = !this.isOpen;
32
+ }
33
+ }
34
+ });
35
+ </script>
36
+
37
+ <template>
38
+ <div class="accordion-container">
39
+ <div
40
+ class="accordion-header"
41
+ data-testid="accordion-header"
42
+ @click="toggle"
43
+ >
44
+ <i
45
+ class="icon text-primary"
46
+ :class="{'icon-chevron-down':isOpen, 'icon-chevron-up':!isOpen}"
47
+ data-testid="accordion-chevron"
48
+ />
49
+ <slot name="header">
50
+ <h4
51
+ data-testid="accordion-title-slot-content"
52
+ class="mb-0"
53
+ >
54
+ {{ titleKey ? t(titleKey) : title }}
55
+ </h4>
56
+ </slot>
57
+ </div>
58
+ <div
59
+ v-show="isOpen"
60
+ class="accordion-body"
61
+ data-testid="accordion-body"
62
+ >
63
+ <slot />
64
+ </div>
65
+ </div>
66
+ </template>
67
+
68
+ <style lang="scss" scoped>
69
+ .accordion-container {
70
+ border: 1px solid var(--border)
71
+ }
72
+ .accordion-header {
73
+ padding: 5px;
74
+ display: flex;
75
+ align-items: center;
76
+ &>*{
77
+ padding: 5px 0px 5px 0px;
78
+ }
79
+ I {
80
+ margin: 0px 10px 0px 10px;
81
+ }
82
+ }
83
+ .accordion-body {
84
+ padding: 10px;
85
+ }
86
+ </style>
@@ -0,0 +1 @@
1
+ export { default as Accordion } from './Accordion.vue';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import Vue, { PropType } from 'vue';
2
+ import { PropType, defineComponent } from 'vue';
3
3
 
4
4
  interface Badge {
5
5
  stateBackground: string;
@@ -11,7 +11,7 @@ interface Badge {
11
11
  * <p>Represents a badge whose label and color is either taken from the value property or
12
12
  * from the label and color properties. The state property takes precedence.</p>
13
13
  */
14
- export default Vue.extend({
14
+ export default defineComponent({
15
15
  props: {
16
16
  /**
17
17
  * A value having the properties `stateBackground` and `stateDisplay`
@@ -59,7 +59,7 @@ export default Vue.extend({
59
59
  </script>
60
60
 
61
61
  <template>
62
- <span :class="{'badge-state': true, [bg]: true}">
62
+ <span :class="['badge-state', bg]">
63
63
  <i
64
64
  v-if="icon"
65
65
  class="icon"
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import { defineComponent } from 'vue';
3
3
  import { nlToBr } from '@shell/utils/string';
4
4
  import { stringify } from '@shell/utils/error';
5
5
 
6
- export default Vue.extend({
6
+ export default defineComponent({
7
7
  props: {
8
8
  /**
9
9
  * A color class that represents the color of the banner.
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import { defineComponent, PropType } from 'vue';
3
3
 
4
- export default Vue.extend({
4
+ export default defineComponent({
5
5
  name: 'Card',
6
6
  props: {
7
7
  /**
@@ -22,7 +22,7 @@ export default Vue.extend({
22
22
  * The function to invoke when the default action button is clicked.
23
23
  */
24
24
  buttonAction: {
25
- type: Function,
25
+ type: Function as PropType<(event: MouseEvent) => void>,
26
26
  default: (): void => { }
27
27
  },
28
28
  /**
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">
2
- import Vue, { PropType } from 'vue';
2
+ import { PropType, defineComponent } from 'vue';
3
3
  import { _EDIT, _VIEW } from '@shell/config/query-params';
4
4
  import { addObject, removeObject } from '@shell/utils/array';
5
5
  import cloneDeep from 'lodash/cloneDeep';
6
6
 
7
- export default Vue.extend({
7
+ export default defineComponent({
8
8
  name: 'Checkbox',
9
9
 
10
10
  props: {
@@ -140,7 +140,7 @@ export default Vue.extend({
140
140
  /**
141
141
  * Toggles the checked state for the checkbox and emits an 'input' event.
142
142
  */
143
- clicked(event: MouseEvent): boolean | void {
143
+ clicked(event: MouseEvent | KeyboardEvent): boolean | void {
144
144
  if ((event.target as HTMLLinkElement).tagName === 'A' && (event.target as HTMLLinkElement).href) {
145
145
  // Ignore links inside the checkbox label so you can click them
146
146
  return true;
@@ -1,4 +1,3 @@
1
-
2
1
  import { mount } from '@vue/test-utils';
3
2
  import { LabeledInput } from './index';
4
3
 
@@ -20,4 +19,22 @@ describe('component: LabeledInput', () => {
20
19
  expect(wrapper.emitted('input')).toHaveLength(1);
21
20
  expect(wrapper.emitted('input')![0][0]).toBe(value);
22
21
  });
22
+
23
+ it('using mode "multiline" should emit input value correctly', () => {
24
+ const value = 'any-string';
25
+ const delay = 1;
26
+ const wrapper = mount(LabeledInput as any, {
27
+ propsData: { delay, multiline: true },
28
+ mocks: { $store: { getters: { 'i18n/t': jest.fn() } } }
29
+ });
30
+
31
+ jest.useFakeTimers();
32
+ wrapper.find('input').setValue('1');
33
+ wrapper.find('input').setValue(value);
34
+ jest.advanceTimersByTime(delay);
35
+ jest.useRealTimers();
36
+
37
+ expect(wrapper.emitted('input')).toHaveLength(1);
38
+ expect(wrapper.emitted('input')![0][0]).toBe(value);
39
+ });
23
40
  });
@@ -1,21 +1,27 @@
1
1
  <script lang="ts">
2
- import Vue, { VueConstructor } from 'vue';
3
- import CompactInput from '@shell/mixins/compact-input';
4
- import LabeledFormElement from '@shell/mixins/labeled-form-element';
2
+ import { defineComponent } from 'vue';
5
3
  import TextAreaAutoGrow from '@components/Form/TextArea/TextAreaAutoGrow.vue';
6
4
  import LabeledTooltip from '@components/LabeledTooltip/LabeledTooltip.vue';
7
5
  import { escapeHtml } from '@shell/utils/string';
8
6
  import cronstrue from 'cronstrue';
9
7
  import { isValidCron } from 'cron-validator';
10
8
  import { debounce } from 'lodash';
9
+ import { useLabeledFormElement, labeledFormElementProps } from '@shell/composables/useLabeledFormElement';
10
+ import { useCompactInput } from '@shell/composables/useCompactInput';
11
11
 
12
- export default (
13
- Vue as VueConstructor<Vue & InstanceType<typeof LabeledFormElement> & InstanceType<typeof CompactInput>>
14
- ).extend({
12
+ declare module 'vue/types/vue' {
13
+ interface Vue {
14
+ onInput: (event: Event) => void | ((event: Event) => void);
15
+ }
16
+ }
17
+
18
+ export default defineComponent({
15
19
  components: { LabeledTooltip, TextAreaAutoGrow },
16
- mixins: [LabeledFormElement, CompactInput],
20
+
21
+ inheritAttrs: false,
17
22
 
18
23
  props: {
24
+ ...labeledFormElementProps,
19
25
  /**
20
26
  * The type of the Labeled Input.
21
27
  * @values text, cron, multiline, multiline-password
@@ -90,24 +96,39 @@ export default (
90
96
  delay: {
91
97
  type: Number,
92
98
  default: 0
93
- }
99
+ },
100
+ },
101
+
102
+ setup(props, { emit }) {
103
+ const {
104
+ focused,
105
+ onFocusLabeled,
106
+ onBlurLabeled,
107
+ isDisabled,
108
+ validationMessage,
109
+ requiredField
110
+ } = useLabeledFormElement(props, emit);
111
+ const { isCompact } = useCompactInput(props);
112
+
113
+ return {
114
+ focused,
115
+ onFocusLabeled,
116
+ onBlurLabeled,
117
+ isDisabled,
118
+ validationMessage,
119
+ requiredField,
120
+ isCompact,
121
+ };
94
122
  },
95
123
 
96
124
  data() {
97
125
  return {
98
126
  updated: false,
99
- validationErrors: ''
127
+ validationErrors: '',
100
128
  };
101
129
  },
102
130
 
103
131
  computed: {
104
- /**
105
- * Determines if the Labeled Input @input event should be debounced.
106
- */
107
- onInput(): ((value: string) => void) | void {
108
- return this.delay ? debounce(this.delayInput, this.delay) : this.delayInput;
109
- },
110
-
111
132
  /**
112
133
  * Determines if the Labeled Input should display a label.
113
134
  */
@@ -122,7 +143,7 @@ export default (
122
143
  return !!this.tooltip || !!this.tooltipKey;
123
144
  },
124
145
 
125
- tooltipValue(): string | undefined {
146
+ tooltipValue(): string | Record<string, unknown> | undefined {
126
147
  if (this.hasTooltip) {
127
148
  return this.tooltipKey ? this.t(this.tooltipKey) : this.tooltip;
128
149
  }
@@ -144,7 +165,7 @@ export default (
144
165
  if (this.type !== 'cron' || !this.value) {
145
166
  return;
146
167
  }
147
- if (!isValidCron(this.value)) {
168
+ if (typeof this.value === 'string' && !isValidCron(this.value)) {
148
169
  return this.t('generic.invalidCron');
149
170
  }
150
171
  try {
@@ -173,15 +194,22 @@ export default (
173
194
  /**
174
195
  * The max length for the Labeled Input.
175
196
  */
176
- _maxlength(): number | null {
197
+ _maxlength(): number | undefined {
177
198
  if (this.type === 'text' && this.maxlength) {
178
199
  return this.maxlength;
179
200
  }
180
201
 
181
- return null;
202
+ return undefined;
182
203
  },
183
204
  },
184
205
 
206
+ created() {
207
+ /**
208
+ * Determines if the Labeled Input @input event should be debounced.
209
+ */
210
+ this.onInput = this.delay ? debounce(this.delayInput, this.delay) : this.delayInput;
211
+ },
212
+
185
213
  methods: {
186
214
  /**
187
215
  * Attempts to give the Labeled Input focus.
@@ -216,8 +244,13 @@ export default (
216
244
  /**
217
245
  * Emit on input with delay. Note: Arrow function is avoided due context
218
246
  * binding.
247
+ *
248
+ * NOTE: In multiline, TextAreaAutoGrow emits a string with the value
249
+ * https://github.com/rancher/dashboard/issues/10249
219
250
  */
220
- delayInput(value: string): void {
251
+ delayInput(val: string | Event): void {
252
+ const value = typeof val === 'string' ? val : (val?.target as HTMLInputElement)?.value;
253
+
221
254
  this.$emit('input', value);
222
255
  },
223
256
 
@@ -234,7 +267,7 @@ export default (
234
267
  * event.
235
268
  * @see labeled-form-element.ts mixin for onBlurLabeled()
236
269
  */
237
- onBlur(event: string): void {
270
+ onBlur(event: string | FocusEvent): void {
238
271
  this.$emit('blur', event);
239
272
  this.onBlurLabeled();
240
273
  },
@@ -286,7 +319,7 @@ export default (
286
319
  :placeholder="_placeholder"
287
320
  autocapitalize="off"
288
321
  :class="{ conceal: type === 'multiline-password' }"
289
- @input="onInput($event)"
322
+ @input="onInput"
290
323
  @focus="onFocus"
291
324
  @blur="onBlur"
292
325
  />
@@ -303,7 +336,7 @@ export default (
303
336
  autocomplete="off"
304
337
  autocapitalize="off"
305
338
  :data-lpignore="ignorePasswordManagers"
306
- @input="onInput($event.target.value)"
339
+ @input="onInput"
307
340
  @focus="onFocus"
308
341
  @blur="onBlur"
309
342
  @change="onChange"
@@ -1,8 +1,9 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import { defineComponent } from 'vue';
3
3
  import { _VIEW } from '@shell/config/query-params';
4
+ import { randomStr } from '@shell/utils/string';
4
5
 
5
- export default Vue.extend({
6
+ export default defineComponent({
6
7
  props: {
7
8
  /**
8
9
  * The name of the input, for grouping.
@@ -71,7 +72,10 @@ export default Vue.extend({
71
72
  },
72
73
 
73
74
  data() {
74
- return { isChecked: this.value === this.val };
75
+ return {
76
+ isChecked: this.value === this.val,
77
+ randomString: `${ randomStr() }-radio`,
78
+ };
75
79
  },
76
80
 
77
81
  computed: {
@@ -115,13 +119,15 @@ export default Vue.extend({
115
119
  /**
116
120
  * Emits the input event.
117
121
  */
118
- clicked({ target }: { target?: HTMLElement }) {
119
- if (this.isDisabled || target?.tagName === 'A') {
122
+ clicked(event: MouseEvent | KeyboardEvent) {
123
+ const target = event.target;
124
+
125
+ if (this.isDisabled || (target instanceof HTMLElement && target.tagName === 'A')) {
120
126
  return;
121
127
  }
122
128
 
123
129
  this.$emit('input', this.val);
124
- }
130
+ },
125
131
  }
126
132
  });
127
133
  </script>
@@ -134,7 +140,7 @@ export default Vue.extend({
134
140
  @click.stop="clicked($event)"
135
141
  >
136
142
  <input
137
- :id="_uid+'-radio'"
143
+ :id="randomString"
138
144
  :disabled="isDisabled"
139
145
  :name="name"
140
146
  :value="''+val"
@@ -1,14 +1,15 @@
1
1
  <script lang="ts">
2
- import Vue, { PropType } from 'vue';
2
+ import { PropType, defineComponent } from 'vue';
3
3
  import { _VIEW } from '@shell/config/query-params';
4
4
  import RadioButton from '@components/Form/Radio/RadioButton.vue';
5
5
 
6
6
  interface Option {
7
7
  value: unknown,
8
- label: string
8
+ label: string,
9
+ description?: string,
9
10
  }
10
11
 
11
- export default Vue.extend({
12
+ export default defineComponent({
12
13
  components: { RadioButton },
13
14
  props: {
14
15
  /**
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import { defineComponent } from 'vue';
3
3
  import debounce from 'lodash/debounce';
4
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
5
5
 
@@ -10,7 +10,7 @@ declare module 'vue/types/vue' {
10
10
  }
11
11
  }
12
12
 
13
- export default Vue.extend({
13
+ export default defineComponent({
14
14
  inheritAttrs: false,
15
15
 
16
16
  props: {
@@ -115,7 +115,9 @@ export default Vue.extend({
115
115
  /**
116
116
  * Emits the input event and resizes the Text Area.
117
117
  */
118
- onInput(val: string): void {
118
+ onInput(event: Event): void {
119
+ const val = (event?.target as HTMLInputElement)?.value;
120
+
119
121
  this.$emit('input', val);
120
122
  this.queueResize();
121
123
  },
@@ -163,7 +165,7 @@ export default Vue.extend({
163
165
  v-bind="$attrs"
164
166
  :spellcheck="spellcheck"
165
167
  @paste="$emit('paste', $event)"
166
- @input="onInput($event.target.value)"
168
+ @input="onInput($event)"
167
169
  @focus="$emit('focus', $event)"
168
170
  @blur="$emit('blur', $event)"
169
171
  />
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
3
- export default Vue.extend({
2
+ import { defineComponent } from 'vue';
3
+
4
+ type StateType = boolean | 'true' | 'false' | undefined;
5
+
6
+ export default defineComponent({
4
7
  props: {
5
8
  value: {
6
9
  type: [Boolean, String, Number],
@@ -28,7 +31,7 @@ export default Vue.extend({
28
31
  },
29
32
  },
30
33
  data() {
31
- return { state: false as boolean | string | number };
34
+ return { state: false as StateType };
32
35
  },
33
36
 
34
37
  watch: {
@@ -41,7 +44,7 @@ export default Vue.extend({
41
44
  },
42
45
 
43
46
  methods: {
44
- toggle(neu: boolean | string | number) {
47
+ toggle(neu: StateType | null) {
45
48
  this.state = neu === null ? !this.state : neu;
46
49
  this.$emit('input', this.state ? this.onValue : this.offValue);
47
50
  }
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import { defineComponent } from 'vue';
3
3
 
4
- export default Vue.extend({
4
+ export default defineComponent({
5
5
  props: {
6
6
  /**
7
7
  * The Labeled Tooltip value.
@@ -29,9 +29,14 @@ export default Vue.extend({
29
29
  }
30
30
  },
31
31
  computed: {
32
- iconClass() {
32
+ iconClass(): string {
33
33
  return this.status === 'error' ? 'icon-warning' : 'icon-info';
34
34
  }
35
+ },
36
+ methods: {
37
+ isObject(value: string | Record<string, unknown>): value is Record<string, unknown> {
38
+ return typeof value === 'object' && value !== null && !!value.content;
39
+ }
35
40
  }
36
41
  });
37
42
  </script>
@@ -44,7 +49,7 @@ export default Vue.extend({
44
49
  >
45
50
  <template v-if="hover">
46
51
  <i
47
- v-clean-tooltip="value.content ? { ...{content: value.content, classes: [`tooltip-${status}`]}, ...value } : value"
52
+ v-clean-tooltip="isObject(value) ? { ...{content: value.content, classes: [`tooltip-${status}`]}, ...value } : value"
48
53
  :class="{'hover':!value, [iconClass]: true}"
49
54
  class="icon status-icon"
50
55
  />
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import Vue, { PropType } from 'vue';
2
+ import Vue, { PropType, defineComponent } from 'vue';
3
3
 
4
4
  import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue';
5
5
  import { findStringIndex, hasDuplicatedStrings } from '@shell/utils/array';
@@ -29,7 +29,7 @@ const CLASS = {
29
29
  /**
30
30
  * Manage a list of strings
31
31
  */
32
- export default Vue.extend({
32
+ export default defineComponent({
33
33
 
34
34
  name: 'StringList',
35
35
  components: { LabeledInput },
@@ -92,9 +92,9 @@ export default Vue.extend({
92
92
  },
93
93
  data() {
94
94
  return {
95
- value: null as string | null,
95
+ value: undefined as string | undefined,
96
96
  selected: null as string | null,
97
- editedItem: null as string | null,
97
+ editedItem: undefined as string | undefined,
98
98
  isCreateItem: false,
99
99
  errors: { duplicate: false } as Record<Error, boolean>
100
100
  };
@@ -281,7 +281,7 @@ export default Vue.extend({
281
281
  this.isCreateItem = true;
282
282
  this.setFocus(INPUT.create);
283
283
  } else {
284
- this.value = null;
284
+ this.value = undefined;
285
285
  this.toggleError('duplicate', false);
286
286
  this.onSelectLeave();
287
287
 
@@ -303,11 +303,11 @@ export default Vue.extend({
303
303
  this.editedItem = item || '';
304
304
  this.setFocus(INPUT.edit);
305
305
  } else {
306
- this.value = null;
306
+ this.value = undefined;
307
307
  this.toggleError('duplicate', false);
308
308
  this.onSelectLeave();
309
309
 
310
- this.editedItem = null;
310
+ this.editedItem = undefined;
311
311
  }
312
312
  },
313
313
 
@@ -502,7 +502,7 @@ export default Vue.extend({
502
502
  <button
503
503
  data-testid="button-add"
504
504
  class="btn btn-sm role-tertiary add-button"
505
- :disabled="isCreateItem || editedItem"
505
+ :disabled="!!isCreateItem || !!editedItem"
506
506
  @click.prevent="onClickPlusButton"
507
507
  >
508
508
  <span class="icon icon-plus icon-sm" />