@rancher/shell 3.0.8-rc.8 → 3.0.8

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 (260) hide show
  1. package/apis/impl/apis.ts +61 -0
  2. package/apis/index.ts +40 -0
  3. package/apis/intf/modal.ts +90 -0
  4. package/apis/intf/shell.ts +36 -0
  5. package/apis/intf/slide-in.ts +98 -0
  6. package/apis/intf/system.ts +41 -0
  7. package/apis/shell/__tests__/modal.test.ts +80 -0
  8. package/apis/shell/__tests__/notifications.test.ts +71 -0
  9. package/apis/shell/__tests__/slide-in.test.ts +54 -0
  10. package/apis/shell/__tests__/system.test.ts +129 -0
  11. package/apis/shell/index.ts +38 -0
  12. package/apis/shell/modal.ts +41 -0
  13. package/apis/shell/notifications.ts +65 -0
  14. package/apis/shell/slide-in.ts +33 -0
  15. package/apis/shell/system.ts +65 -0
  16. package/apis/vue-shim.d.ts +11 -0
  17. package/assets/brand/suse/dark/rancher-logo.svg +1 -64
  18. package/assets/styles/global/_tooltip.scss +6 -1
  19. package/assets/translations/en-us.yaml +14 -1
  20. package/components/ActionMenuShell.vue +3 -1
  21. package/components/BackLink.vue +8 -0
  22. package/components/BannerGraphic.vue +1 -5
  23. package/components/BrandImage.vue +17 -6
  24. package/components/Cron/CronExpressionEditor.vue +1 -1
  25. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  26. package/components/CruResource.vue +8 -1
  27. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +1 -0
  28. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +50 -1
  29. package/components/Drawer/ResourceDetailDrawer/composables.ts +19 -0
  30. package/components/Drawer/ResourceDetailDrawer/index.vue +4 -1
  31. package/components/Drawer/ResourceDetailDrawer/types.ts +2 -1
  32. package/components/LocaleSelector.vue +2 -2
  33. package/components/ModalManager.vue +11 -1
  34. package/components/Questions/__tests__/Yaml.test.ts +1 -1
  35. package/components/Questions/__tests__/index.test.ts +159 -0
  36. package/components/RelatedResources.vue +5 -0
  37. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  38. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  39. package/components/Resource/Detail/Metadata/index.vue +3 -3
  40. package/components/Resource/Detail/ResourcePopover/index.vue +5 -1
  41. package/components/Resource/Detail/composables.ts +2 -2
  42. package/components/ResourceDetail/Masthead/latest.vue +23 -21
  43. package/components/ResourceDetail/index.vue +3 -0
  44. package/components/ResourceTable.vue +54 -21
  45. package/components/SlideInPanelManager.vue +16 -11
  46. package/components/SortableTable/THead.vue +2 -1
  47. package/components/SortableTable/index.vue +20 -2
  48. package/components/Tabbed/__tests__/index.test.ts +86 -0
  49. package/components/Tabbed/index.vue +37 -2
  50. package/components/__tests__/NamespaceFilter.test.ts +49 -0
  51. package/components/auth/SelectPrincipal.vue +28 -6
  52. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  53. package/components/auth/login/ldap.vue +3 -3
  54. package/components/fleet/FleetSecretSelector.vue +1 -1
  55. package/components/form/KeyValue.vue +1 -1
  56. package/components/form/NameNsDescription.vue +1 -1
  57. package/components/form/NodeScheduling.vue +2 -2
  58. package/components/form/ResourceTabs/composable.ts +2 -2
  59. package/components/form/ResourceTabs/index.vue +0 -2
  60. package/components/form/__tests__/NameNsDescription.test.ts +42 -0
  61. package/components/formatter/InternalExternalIP.vue +4 -1
  62. package/components/formatter/LinkName.vue +5 -0
  63. package/components/formatter/__tests__/InternalExternalIP.test.ts +1 -1
  64. package/components/nav/Group.vue +25 -7
  65. package/components/nav/Header.vue +1 -1
  66. package/components/nav/NamespaceFilter.vue +1 -0
  67. package/components/nav/Type.vue +17 -6
  68. package/components/nav/WindowManager/panels/TabBodyContainer.vue +1 -1
  69. package/components/nav/__tests__/Type.test.ts +59 -0
  70. package/components/templates/standalone.vue +1 -1
  71. package/composables/cruResource.ts +27 -0
  72. package/composables/focusTrap.ts +3 -1
  73. package/composables/resourceDetail.ts +15 -0
  74. package/composables/useI18n.ts +10 -1
  75. package/composables/useLabeledFormElement.ts +3 -4
  76. package/config/__test__/uiplugins.test.ts +309 -0
  77. package/config/labels-annotations.js +1 -0
  78. package/config/product/explorer.js +3 -1
  79. package/config/product/fleet.js +1 -1
  80. package/config/router/navigation-guards/clusters.js +3 -3
  81. package/config/router/navigation-guards/products.js +1 -1
  82. package/config/router/routes.js +7 -7
  83. package/config/types.js +7 -0
  84. package/config/uiplugins.js +46 -2
  85. package/core/__tests__/extension-manager-impl.test.js +437 -0
  86. package/core/extension-manager-impl.js +21 -25
  87. package/core/plugin-helpers.ts +2 -2
  88. package/core/plugin.ts +9 -1
  89. package/core/plugins-loader.js +2 -2
  90. package/core/types-provisioning.ts +5 -1
  91. package/core/types.ts +35 -0
  92. package/detail/provisioning.cattle.io.cluster.vue +9 -6
  93. package/dialog/DeveloperLoadExtensionDialog.vue +13 -4
  94. package/dialog/MoveNamespaceDialog.vue +20 -4
  95. package/dialog/RollbackWorkloadDialog.vue +2 -5
  96. package/dialog/SearchDialog.vue +1 -0
  97. package/dialog/__tests__/MoveNamespaceDialog.test.ts +249 -0
  98. package/directives/__tests__/clean-tooltip.test.ts +298 -0
  99. package/directives/clean-tooltip.ts +234 -0
  100. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -2
  101. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +100 -3
  102. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  103. package/edit/configmap.vue +1 -0
  104. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  105. package/edit/fleet.cattle.io.helmop.vue +11 -6
  106. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  107. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  108. package/edit/logging-flow/index.vue +1 -0
  109. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  110. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  111. package/edit/management.cattle.io.project.vue +1 -0
  112. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  113. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  114. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  115. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  116. package/edit/monitoring.coreos.com.route.vue +1 -1
  117. package/edit/namespace.vue +1 -0
  118. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  119. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  120. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  121. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  122. package/edit/node.vue +1 -0
  123. package/edit/persistentvolume/index.vue +27 -22
  124. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  125. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  126. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  127. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  128. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  129. package/edit/persistentvolume/plugins/csi.vue +18 -16
  130. package/edit/persistentvolume/plugins/fc.vue +13 -14
  131. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  132. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  133. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  134. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  135. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  136. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  137. package/edit/persistentvolume/plugins/local.vue +1 -3
  138. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  139. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  140. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  141. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  142. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  143. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  144. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  145. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  146. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  147. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
  148. package/edit/provisioning.cattle.io.cluster/index.vue +5 -5
  149. package/edit/provisioning.cattle.io.cluster/rke2.vue +9 -8
  150. package/edit/resources.cattle.io.restore.vue +1 -1
  151. package/edit/secret/index.vue +1 -1
  152. package/edit/service.vue +1 -0
  153. package/edit/serviceaccount.vue +1 -0
  154. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  155. package/edit/workload/Job.vue +2 -2
  156. package/edit/workload/index.vue +2 -1
  157. package/edit/workload/mixins/workload.js +1 -1
  158. package/initialize/App.vue +4 -4
  159. package/initialize/install-plugins.js +19 -5
  160. package/machine-config/azure.vue +1 -1
  161. package/machine-config/components/GCEImage.vue +1 -1
  162. package/mixins/__tests__/brand.spec.ts +2 -2
  163. package/mixins/brand.js +1 -7
  164. package/mixins/create-edit-view/index.js +5 -0
  165. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +128 -5
  166. package/models/chart.js +70 -74
  167. package/models/management.cattle.io.cluster.js +21 -3
  168. package/models/provisioning.cattle.io.cluster.js +31 -11
  169. package/package.json +11 -10
  170. package/pages/auth/login.vue +4 -6
  171. package/pages/auth/setup.vue +1 -1
  172. package/pages/auth/verify.vue +3 -3
  173. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  174. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  175. package/pages/c/_cluster/apps/charts/index.vue +122 -24
  176. package/pages/c/_cluster/apps/charts/install.vue +33 -0
  177. package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
  178. package/pages/c/_cluster/explorer/index.vue +8 -6
  179. package/pages/c/_cluster/fleet/index.vue +4 -7
  180. package/pages/c/_cluster/manager/hostedprovider/index.vue +12 -6
  181. package/pages/c/_cluster/settings/brand.vue +1 -1
  182. package/pages/c/_cluster/settings/index.vue +5 -0
  183. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  184. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  185. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  186. package/pkg/auto-import.js +3 -3
  187. package/pkg/dynamic-importer.lib.js +1 -1
  188. package/pkg/import.js +1 -1
  189. package/plugins/__tests__/mutations.tests.ts +179 -0
  190. package/plugins/dashboard-client-init.js +3 -0
  191. package/plugins/dashboard-store/getters.js +19 -2
  192. package/plugins/dashboard-store/model-loader.js +1 -1
  193. package/plugins/dashboard-store/mutations.js +23 -2
  194. package/plugins/dashboard-store/resource-class.js +11 -5
  195. package/plugins/i18n.js +8 -0
  196. package/plugins/plugin.js +2 -2
  197. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +506 -0
  198. package/plugins/steve/steve-class.js +1 -1
  199. package/plugins/steve/steve-pagination-utils.ts +131 -47
  200. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  201. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  202. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -42
  203. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  204. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  205. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  206. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  207. package/rancher-components/Pill/types.ts +0 -1
  208. package/rancher-components/RcDropdown/useDropdownContext.ts +2 -4
  209. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  210. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  211. package/rancher-components/RcIcon/index.ts +1 -0
  212. package/rancher-components/RcIcon/types.ts +160 -0
  213. package/rancher-components/RcItemCard/RcItemCard.vue +1 -1
  214. package/rancher-components/utils/status.test.ts +67 -0
  215. package/rancher-components/utils/status.ts +77 -0
  216. package/scripts/publish-shell.sh +25 -0
  217. package/scripts/typegen.sh +1 -0
  218. package/store/__tests__/catalog.test.ts +1 -1
  219. package/store/__tests__/type-map.test.ts +164 -2
  220. package/store/action-menu.js +8 -0
  221. package/store/auth.js +25 -13
  222. package/store/catalog.js +6 -0
  223. package/store/i18n.js +3 -3
  224. package/store/index.js +8 -6
  225. package/store/notifications.ts +2 -0
  226. package/store/prefs.js +6 -7
  227. package/store/type-map.js +17 -7
  228. package/store/wm.ts +4 -4
  229. package/types/internal-api/shell/modal.d.ts +6 -6
  230. package/types/notifications/index.ts +126 -15
  231. package/types/rancher/index.d.ts +9 -0
  232. package/types/shell/index.d.ts +54 -3
  233. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  234. package/types/store/pagination.types.ts +157 -9
  235. package/types/vue-shim.d.ts +5 -4
  236. package/utils/__tests__/provider.test.ts +98 -0
  237. package/utils/__tests__/router.test.js +238 -0
  238. package/utils/__tests__/selector-typed.test.ts +263 -0
  239. package/utils/cluster.js +4 -1
  240. package/utils/color.js +1 -1
  241. package/utils/dynamic-content/__tests__/info.test.ts +6 -0
  242. package/utils/dynamic-content/info.ts +43 -0
  243. package/utils/favicon.js +4 -4
  244. package/utils/fleet.ts +8 -1
  245. package/utils/pagination-utils.ts +2 -2
  246. package/utils/pagination-wrapper.ts +1 -1
  247. package/utils/provider.ts +14 -0
  248. package/utils/router.js +50 -0
  249. package/utils/selector-typed.ts +6 -2
  250. package/utils/unit-tests/pagination-utils.spec.ts +8 -8
  251. package/vue.config.js +3 -3
  252. package/composables/useExtensionManager.ts +0 -17
  253. package/core/plugins.js +0 -38
  254. package/directives/clean-tooltip.js +0 -32
  255. package/plugins/internal-api/index.ts +0 -37
  256. package/plugins/internal-api/shared/base-api.ts +0 -13
  257. package/plugins/internal-api/shell/shell.api.ts +0 -108
  258. package/plugins/nuxt-client-init.js +0 -3
  259. package/types/internal-api/shell/growl.d.ts +0 -25
  260. package/types/internal-api/shell/slideIn.d.ts +0 -15
@@ -0,0 +1,61 @@
1
+ import { throttle } from 'lodash';
2
+ import { createExtensionManager } from '@shell/core/extension-manager-impl';
3
+ import { ShellApiImpl } from '@shell/apis/shell';
4
+
5
+ /**
6
+ * Initialise the APIs that are available in the shell
7
+ *
8
+ * This is loaded during app startiup in `initialize/index.js`
9
+ */
10
+ export function initUiApis(context: any, inject: any, vueApp: any) {
11
+ // ======================================================================================================================
12
+ // Extension Manager
13
+ // ======================================================================================================================
14
+ const extensionManager = createExtensionManager(context);
15
+ const deprecationMessage = '[DEPRECATED] `this.$plugin` is deprecated and will be removed in a future version. Use `this.$extension` instead.';
16
+
17
+ registerApi('plugin', deprecationProxy(extensionManager, deprecationMessage), inject, vueApp);
18
+ registerApi('extension', extensionManager, inject, vueApp);
19
+
20
+ // ======================================================================================================================
21
+ // Shell API
22
+ // ======================================================================================================================
23
+ registerApi('shell', new ShellApiImpl(context.store), inject, vueApp);
24
+ }
25
+
26
+ // ======================================================================================================================
27
+ // Helpers
28
+ // ======================================================================================================================
29
+
30
+ function registerApi(name: string, api: any, inject: any, vueApp: any) {
31
+ inject(name, api);
32
+ vueApp.provide(`$${ name }`, api);
33
+ }
34
+
35
+ /**
36
+ * Proxy to log a deprecation warning when target is accessed. Only prints
37
+ * deprecation warnings in dev builds.
38
+ * @param {*} target the object to proxy
39
+ * @param {*} message the deprecation warning to print to the console
40
+ * @returns The proxied target that prints a deprecation warning when target is
41
+ * accessed
42
+ */
43
+ const deprecationProxy = (target: any, message: string) => {
44
+ const logWarning = throttle(() => {
45
+ // eslint-disable-next-line no-console
46
+ console.warn(message);
47
+ }, 150);
48
+
49
+ const deprecationHandler = {
50
+ get(target: any, prop: any) {
51
+ logWarning();
52
+
53
+ return Reflect.get(target, prop);
54
+ }
55
+ };
56
+
57
+ // an empty handler allows the proxy to behave just like the original target
58
+ const proxyHandler = !!process.env.dev ? deprecationHandler : {};
59
+
60
+ return new Proxy(target, proxyHandler);
61
+ };
package/apis/index.ts ADDED
@@ -0,0 +1,40 @@
1
+ // Main export for APIs, particularly for the composition API
2
+
3
+ import { inject } from 'vue';
4
+ import { ExtensionManager } from '@shell/types/extension-manager';
5
+ import { ShellApi as ShellApiImport } from '@shell/apis/intf/shell';
6
+
7
+ // Re-export the types for the APIs, so they appear in this module
8
+ export type ShellApi = ShellApiImport;
9
+ export type ExtensionManagerApi = ExtensionManager;
10
+
11
+ /**
12
+ * Returns an object that can be used to access the registered extension manager instance.
13
+ *
14
+ * @returns Returns an object that can be used to access the registered extension manager instance.
15
+ */
16
+ export const useExtensionManager = (): ExtensionManagerApi => {
17
+ return getApi<ExtensionManagerApi>('$extension', 'useExtensionManager');
18
+ };
19
+
20
+ /**
21
+ * Returns an object that implements the ShellApi interface
22
+ *
23
+ * @returns Returns an object that implements the ShellApi interface
24
+ */
25
+ export const useShell = (): ShellApi => {
26
+ return getApi<ShellApi>('$shell', 'useShell');
27
+ };
28
+
29
+ // =================================================================================================================
30
+ // Internal helper to get any API by key with error handling
31
+ // =================================================================================================================
32
+ function getApi<T>(key: string, name: string): T {
33
+ const api = inject<T>(key);
34
+
35
+ if (!api) {
36
+ throw new Error(`${ name } must only be called after ${ key } has been initialized`);
37
+ }
38
+
39
+ return api as T;
40
+ }
@@ -0,0 +1,90 @@
1
+ import { Component } from 'vue';
2
+
3
+ /**
4
+ * Configuration object for opening a modal.
5
+ */
6
+ export interface ModalConfig {
7
+ /**
8
+ * Props to pass directly to the component rendered inside the modal.
9
+ *
10
+ * Example:
11
+ * ```ts
12
+ * props: { title: 'Hello Modal', isVisible: true }
13
+ * ```
14
+ */
15
+ props?: Record<string, any>;
16
+
17
+ /**
18
+ * Array of resources that the modal component might need.
19
+ * These are passed directly into the modal's `resources` prop.
20
+ *
21
+ * Example:
22
+ * ```ts
23
+ * resources: [myResource, anotherResource]
24
+ * ```
25
+ */
26
+ resources?: any[];
27
+
28
+ /**
29
+ * Custom width for the modal. Defaults to `600px`.
30
+ * The width can be specified as a string with a valid unit (`px`, `%`, `rem`, etc.).
31
+ *
32
+ * Examples:
33
+ * ```ts
34
+ * width: '800px' // Width in pixels
35
+ * width: '75%' // Width as a percentage
36
+ * ```
37
+ */
38
+ width?: string;
39
+
40
+ /**
41
+ * Determines if clicking outside the modal will close it. Defaults to `true`.
42
+ * Set this to `false` to prevent closing via outside clicks.
43
+ *
44
+ * Example:
45
+ * ```ts
46
+ * closeOnClickOutside: false
47
+ * ```
48
+ */
49
+ closeOnClickOutside?: boolean;
50
+
51
+ /**
52
+ * If true, the modal is considered "sticky" and may not close automatically
53
+ * on certain user interactions. Defaults to `false`.
54
+ *
55
+ * Example:
56
+ * ```ts
57
+ * modalSticky: true
58
+ * ```
59
+ */
60
+ // modalSticky?: boolean; // Not implemented yet
61
+ }
62
+
63
+ /**
64
+ * API for displaying modals in Rancher UI. Here's what a Modal looks like in Rancher UI:
65
+ * * ![modal Example](/img/modal.png)
66
+ */
67
+ export interface ModalApi {
68
+ /**
69
+ * Opens a modal dialog in Rancher UI
70
+ *
71
+ * Example:
72
+ * ```ts
73
+ * import MyCustomModal from '@/components/MyCustomModal.vue';
74
+ *
75
+ * this.$shell.modal.open(MyCustomModal, {
76
+ * props: { title: 'Hello Modal' }
77
+ * });
78
+ * ```
79
+ * For usage with the Composition API check usage guide [here](../../shell-api#using-composition-api-in-vue).
80
+ *
81
+ * @param component
82
+ * The Vue component to be displayed inside the modal.
83
+ * This can be any SFC (Single-File Component) imported and passed in as a `Component`.
84
+ *
85
+ *
86
+ * @param config Modal configuration object
87
+ *
88
+ */
89
+ open(component: Component, config?: ModalConfig): void;
90
+ }
@@ -0,0 +1,36 @@
1
+
2
+ import { NotificationApi } from '@shell/types/notifications';
3
+ import { ModalApi } from '@shell/apis/intf/modal';
4
+ import { SlideInApi } from '@shell/apis/intf/slide-in';
5
+ import { SystemApi } from '@shell/apis/intf/system';
6
+
7
+ export * from '@shell/types/notifications';
8
+ export * from '@shell/apis/intf/modal';
9
+ export * from '@shell/apis/intf/slide-in';
10
+ export * from '@shell/apis/intf/system';
11
+
12
+ /**
13
+ * @internal
14
+ * Available "API's" inside Shell API
15
+ */
16
+ export interface ShellApi {
17
+ /**
18
+ * Provides access to the Modal API which can be used for displaying modals in Rancher UI
19
+ */
20
+ get modal(): ModalApi;
21
+
22
+ /**
23
+ * Provides access to the Slide-In API which can be used for displaying Slide-In panels in Rancher UI
24
+ */
25
+ get slideIn(): SlideInApi;
26
+
27
+ /**
28
+ * Provides access to the Notification Center API which can be used for notifications in the Rancher UI Notification Center
29
+ */
30
+ get notification(): NotificationApi;
31
+
32
+ /**
33
+ * Provides access to the system API which providers information about the current system
34
+ */
35
+ get system(): SystemApi;
36
+ }
@@ -0,0 +1,98 @@
1
+ import { Component } from 'vue';
2
+
3
+ /**
4
+ *
5
+ * Configuration object for opening a Slide-In panel. Here's what a Slide-In looks like in Rancher UI:
6
+ *
7
+ */
8
+ export interface SlideInConfig {
9
+ /**
10
+ *
11
+ * Width of the Slide-In panel in percentage, related to the window width. Defaults to `33%`
12
+ *
13
+ */
14
+ width?: string;
15
+ /**
16
+ *
17
+ * Height of the Slide-In panel. Can be percentage or vh. Defaults to (window - header) height.
18
+ * Can be set as `33%` or `80vh`
19
+ *
20
+ */
21
+ height?: string;
22
+ /**
23
+ *
24
+ * CSS Top position for the Slide-In panel, string using px, as `0px` or `20px`. Default is right below header height
25
+ *
26
+ */
27
+ top?: string;
28
+ /**
29
+ *
30
+ * title for the Slide-In panel
31
+ *
32
+ */
33
+ title?: string;
34
+ /**
35
+ *
36
+ * Wether Slide-In header is displayed or not
37
+ *
38
+ */
39
+ showHeader?: boolean;
40
+ /**
41
+ *
42
+ * Array of props to watch out for in route, when they change, closes Slide-In
43
+ * @ignore
44
+ *
45
+ */
46
+ closeOnRouteChange?: [string];
47
+ /**
48
+ *
49
+ * Return focus selector for focus trap
50
+ * @ignore
51
+ *
52
+ */
53
+ returnFocusSelector?: string;
54
+ /**
55
+ *
56
+ * We can pass variable (value) to "force" focus trap to initialize "on-demand"
57
+ * @ignore
58
+ *
59
+ */
60
+ focusTrapWatcherBasedVariable?: boolean;
61
+ /**
62
+ *
63
+ * Vue Props to pass directly to the component rendered inside the slide in panel in an object format as "props=..."
64
+ *
65
+ * Useful for passing additional information or context to the component rendered inside the Slide-In window
66
+ *
67
+ */
68
+ [key: string]: any;
69
+ }
70
+
71
+ /**
72
+ * API for displaying Slide-In panels in Rancher UI
73
+ * * ![slidein Example](/img/slidein.png)
74
+ */
75
+ export interface SlideInApi {
76
+ /**
77
+ * Opens a slide in panel in Rancher UI
78
+ *
79
+ * Example:
80
+ * ```ts
81
+ * import MyCustomSlideIn from '@/components/MyCustomSlideIn.vue';
82
+ *
83
+ * this.$shell.slideIn.open(MyCustomSlideIn, {
84
+ * title: 'Hello from SlideIn panel!'
85
+ * });
86
+ * ```
87
+ *
88
+ * For usage with the Composition API check usage guide [here](../../shell-api#using-composition-api-in-vue).
89
+ *
90
+ * @param component
91
+ * The Vue component to be displayed inside the slide in panel.
92
+ * This can be any SFC (Single-File Component) imported and passed in as a `Component`.
93
+ *
94
+ * @param config Slide-In configuration object
95
+ *
96
+ */
97
+ open(component: Component, config?: SlideInConfig): void;
98
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * system API which providers information about the current system
3
+ * * ![system Example](/img/system.png)
4
+ *
5
+ * Usage example:
6
+ * ```ts
7
+ * const rancherVersion = this.$shell.system.rancherVersion;
8
+ * console.log('Rancher Version:', rancherVersion);
9
+ * ```
10
+ *
11
+ */
12
+ export interface SystemApi {
13
+ /**
14
+ * Rancher version
15
+ */
16
+ rancherVersion: string;
17
+ /**
18
+ * Rancher UI version
19
+ */
20
+ uiVersion: string;
21
+ /**
22
+ * If Rancher system running is Prime
23
+ */
24
+ isRancherPrime: boolean;
25
+ /**
26
+ * Git Commit for Rancher system running
27
+ */
28
+ gitCommit: string;
29
+ /**
30
+ * Rancher Kubernetes version
31
+ */
32
+ kubernetesVersion: string;
33
+ /**
34
+ * If Rancher system is a Dev build
35
+ */
36
+ isDevBuild: boolean;
37
+ /**
38
+ * If Rancher system is a Pre-Release build/version
39
+ */
40
+ isPrereleaseVersion: boolean;
41
+ }
@@ -0,0 +1,80 @@
1
+ // modal.test.ts
2
+
3
+ import {
4
+ describe, it, expect, jest, beforeEach
5
+ } from '@jest/globals';
6
+ import { ModalApiImpl } from '../modal'; // Adjust path as needed
7
+ import { Store } from 'vuex';
8
+
9
+ // A mock component to use in tests
10
+ const MockComponent = { template: '<div>Mock</div>' };
11
+
12
+ describe('modalApiImpl', () => {
13
+ let mockStore: Store<any>;
14
+ let modalApi: ModalApiImpl;
15
+ let mockCommit: jest.Mock;
16
+
17
+ beforeEach(() => {
18
+ // 1. Arrange: Create a mock commit function
19
+ mockCommit = jest.fn() as any;
20
+
21
+ // Create a mock store object
22
+ mockStore = { commit: mockCommit } as any;
23
+
24
+ // 2. Arrange: Instantiate the class with the mock store
25
+ modalApi = new ModalApiImpl(mockStore);
26
+ });
27
+
28
+ it('should open a modal with all default values', () => {
29
+ // 3. Act: Call the method with only the required component
30
+ modalApi.open(MockComponent);
31
+
32
+ // 4. Assert: Check if the store's commit was called correctly
33
+ expect(mockCommit).toHaveBeenCalledTimes(1);
34
+ expect(mockCommit).toHaveBeenCalledWith('modal/openModal', {
35
+ component: MockComponent,
36
+ componentProps: {},
37
+ resources: [],
38
+ modalWidth: '600px',
39
+ closeOnClickOutside: true,
40
+ });
41
+ });
42
+
43
+ it('should open a modal with custom configuration', () => {
44
+ const config = {
45
+ props: { title: 'Hello' },
46
+ resources: [{ id: 1, type: 'node' }],
47
+ width: '800px',
48
+ closeOnClickOutside: false,
49
+ };
50
+
51
+ // 3. Act: Call the method with a config
52
+ modalApi.open(MockComponent, config);
53
+
54
+ // 4. Assert: Check if the config values override the defaults
55
+ expect(mockCommit).toHaveBeenCalledTimes(1);
56
+ expect(mockCommit).toHaveBeenCalledWith('modal/openModal', {
57
+ component: MockComponent,
58
+ componentProps: config.props,
59
+ resources: config.resources,
60
+ modalWidth: config.width,
61
+ closeOnClickOutside: config.closeOnClickOutside,
62
+ });
63
+ });
64
+
65
+ it('should correctly merge a partial config with defaults', () => {
66
+ const config = { props: { id: '123' } };
67
+
68
+ // 3. Act
69
+ modalApi.open(MockComponent, config);
70
+
71
+ // 4. Assert
72
+ expect(mockCommit).toHaveBeenCalledWith('modal/openModal', {
73
+ component: MockComponent,
74
+ componentProps: config.props, // Custom
75
+ resources: [], // Default
76
+ modalWidth: '600px', // Default
77
+ closeOnClickOutside: true, // Default
78
+ });
79
+ });
80
+ });
@@ -0,0 +1,71 @@
1
+ // notifications.test.ts
2
+
3
+ import {
4
+ describe, it, expect, jest, beforeEach
5
+ } from '@jest/globals';
6
+ import { NotificationApiImpl } from '../notifications';
7
+ import { Store } from 'vuex';
8
+ import { NotificationLevel } from '@shell/types/notifications'; // Assuming this path
9
+
10
+ describe('notificationApiImpl', () => {
11
+ let mockStore: Store<any>;
12
+ let notificationApi: NotificationApiImpl;
13
+ let mockDispatch: jest.Mock;
14
+
15
+ beforeEach(() => {
16
+ // 1. Arrange
17
+ mockDispatch = jest.fn() as any;
18
+ mockStore = { dispatch: mockDispatch } as any;
19
+
20
+ // 2. Arrange
21
+ notificationApi = new NotificationApiImpl(mockStore);
22
+ });
23
+
24
+ it('should send a notification and return its ID', async() => {
25
+ const mockNotificationId = 'notif-12345';
26
+ const config = { progress: 80 };
27
+
28
+ // Arrange: Mock the dispatch to return a promise resolving to the ID
29
+ mockDispatch.mockResolvedValue(mockNotificationId);
30
+
31
+ // 3. Act: Call the async method
32
+ const result = await notificationApi.send(
33
+ NotificationLevel.Success,
34
+ 'Test Title',
35
+ 'Test Message',
36
+ config
37
+ );
38
+
39
+ // 4. Assert
40
+ expect(mockDispatch).toHaveBeenCalledTimes(1);
41
+ expect(mockDispatch).toHaveBeenCalledWith(
42
+ 'notifications/add',
43
+ {
44
+ level: NotificationLevel.Success,
45
+ title: 'Test Title',
46
+ message: 'Test Message',
47
+ progress: 80,
48
+ },
49
+ { root: true }
50
+ );
51
+
52
+ // Assert the return value
53
+ expect(result).toBe(mockNotificationId);
54
+ });
55
+
56
+ it('should update notification progress', () => {
57
+ // 3. Act
58
+ notificationApi.updateProgress('notif-abc', 75);
59
+
60
+ // 4. Assert
61
+ expect(mockDispatch).toHaveBeenCalledTimes(1);
62
+ expect(mockDispatch).toHaveBeenCalledWith(
63
+ 'notifications/update',
64
+ {
65
+ id: 'notif-abc',
66
+ progress: 75,
67
+ },
68
+ { root: true }
69
+ );
70
+ });
71
+ });
@@ -0,0 +1,54 @@
1
+ // slide-in.test.ts
2
+
3
+ import {
4
+ describe, it, expect, jest, beforeEach
5
+ } from '@jest/globals';
6
+ import { SlideInApiImpl } from '../slide-in'; // Adjust path as needed
7
+ import { Store } from 'vuex';
8
+
9
+ // A mock component to use in tests
10
+ const MockComponent = { template: '<div>Mock</div>' };
11
+
12
+ describe('slideInApiImpl', () => {
13
+ let mockStore: Store<any>;
14
+ let slideInApi: SlideInApiImpl;
15
+ let mockCommit: jest.Mock;
16
+
17
+ beforeEach(() => {
18
+ // 1. Arrange
19
+ mockCommit = jest.fn() as any;
20
+ mockStore = { commit: mockCommit } as any;
21
+
22
+ // 2. Arrange
23
+ slideInApi = new SlideInApiImpl(mockStore);
24
+ });
25
+
26
+ it('should open a slide-in panel with no config', () => {
27
+ // 3. Act
28
+ slideInApi.open(MockComponent);
29
+
30
+ // 4. Assert
31
+ expect(mockCommit).toHaveBeenCalledTimes(1);
32
+ expect(mockCommit).toHaveBeenCalledWith('slideInPanel/open', {
33
+ component: MockComponent,
34
+ componentProps: {},
35
+ });
36
+ });
37
+
38
+ it('should open a slide-in panel with a config', () => {
39
+ const config = {
40
+ title: 'Test Panel',
41
+ width: '50%',
42
+ };
43
+
44
+ // 3. Act
45
+ slideInApi.open(MockComponent, config);
46
+
47
+ // 4. Assert
48
+ expect(mockCommit).toHaveBeenCalledTimes(1);
49
+ expect(mockCommit).toHaveBeenCalledWith('slideInPanel/open', {
50
+ component: MockComponent,
51
+ componentProps: { ...config }, // The implementation spreads the config
52
+ });
53
+ });
54
+ });