@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.
- package/apis/impl/apis.ts +61 -0
- package/apis/index.ts +40 -0
- package/apis/intf/modal.ts +90 -0
- package/apis/intf/shell.ts +36 -0
- package/apis/intf/slide-in.ts +98 -0
- package/apis/intf/system.ts +41 -0
- package/apis/shell/__tests__/modal.test.ts +80 -0
- package/apis/shell/__tests__/notifications.test.ts +71 -0
- package/apis/shell/__tests__/slide-in.test.ts +54 -0
- package/apis/shell/__tests__/system.test.ts +129 -0
- package/apis/shell/index.ts +38 -0
- package/apis/shell/modal.ts +41 -0
- package/apis/shell/notifications.ts +65 -0
- package/apis/shell/slide-in.ts +33 -0
- package/apis/shell/system.ts +65 -0
- package/apis/vue-shim.d.ts +11 -0
- package/assets/brand/suse/dark/rancher-logo.svg +1 -64
- package/assets/styles/global/_tooltip.scss +6 -1
- package/assets/translations/en-us.yaml +14 -1
- package/components/ActionMenuShell.vue +3 -1
- package/components/BackLink.vue +8 -0
- package/components/BannerGraphic.vue +1 -5
- package/components/BrandImage.vue +17 -6
- package/components/Cron/CronExpressionEditor.vue +1 -1
- package/components/Cron/CronExpressionEditorModal.vue +1 -1
- package/components/CruResource.vue +8 -1
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +1 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +50 -1
- package/components/Drawer/ResourceDetailDrawer/composables.ts +19 -0
- package/components/Drawer/ResourceDetailDrawer/index.vue +4 -1
- package/components/Drawer/ResourceDetailDrawer/types.ts +2 -1
- package/components/LocaleSelector.vue +2 -2
- package/components/ModalManager.vue +11 -1
- package/components/Questions/__tests__/Yaml.test.ts +1 -1
- package/components/Questions/__tests__/index.test.ts +159 -0
- package/components/RelatedResources.vue +5 -0
- package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
- package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
- package/components/Resource/Detail/Metadata/index.vue +3 -3
- package/components/Resource/Detail/ResourcePopover/index.vue +5 -1
- package/components/Resource/Detail/composables.ts +2 -2
- package/components/ResourceDetail/Masthead/latest.vue +23 -21
- package/components/ResourceDetail/index.vue +3 -0
- package/components/ResourceTable.vue +54 -21
- package/components/SlideInPanelManager.vue +16 -11
- package/components/SortableTable/THead.vue +2 -1
- package/components/SortableTable/index.vue +20 -2
- package/components/Tabbed/__tests__/index.test.ts +86 -0
- package/components/Tabbed/index.vue +37 -2
- package/components/__tests__/NamespaceFilter.test.ts +49 -0
- package/components/auth/SelectPrincipal.vue +28 -6
- package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
- package/components/auth/login/ldap.vue +3 -3
- package/components/fleet/FleetSecretSelector.vue +1 -1
- package/components/form/KeyValue.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/NodeScheduling.vue +2 -2
- package/components/form/ResourceTabs/composable.ts +2 -2
- package/components/form/ResourceTabs/index.vue +0 -2
- package/components/form/__tests__/NameNsDescription.test.ts +42 -0
- package/components/formatter/InternalExternalIP.vue +4 -1
- package/components/formatter/LinkName.vue +5 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +1 -1
- package/components/nav/Group.vue +25 -7
- package/components/nav/Header.vue +1 -1
- package/components/nav/NamespaceFilter.vue +1 -0
- package/components/nav/Type.vue +17 -6
- package/components/nav/WindowManager/panels/TabBodyContainer.vue +1 -1
- package/components/nav/__tests__/Type.test.ts +59 -0
- package/components/templates/standalone.vue +1 -1
- package/composables/cruResource.ts +27 -0
- package/composables/focusTrap.ts +3 -1
- package/composables/resourceDetail.ts +15 -0
- package/composables/useI18n.ts +10 -1
- package/composables/useLabeledFormElement.ts +3 -4
- package/config/__test__/uiplugins.test.ts +309 -0
- package/config/labels-annotations.js +1 -0
- package/config/product/explorer.js +3 -1
- package/config/product/fleet.js +1 -1
- package/config/router/navigation-guards/clusters.js +3 -3
- package/config/router/navigation-guards/products.js +1 -1
- package/config/router/routes.js +7 -7
- package/config/types.js +7 -0
- package/config/uiplugins.js +46 -2
- package/core/__tests__/extension-manager-impl.test.js +437 -0
- package/core/extension-manager-impl.js +21 -25
- package/core/plugin-helpers.ts +2 -2
- package/core/plugin.ts +9 -1
- package/core/plugins-loader.js +2 -2
- package/core/types-provisioning.ts +5 -1
- package/core/types.ts +35 -0
- package/detail/provisioning.cattle.io.cluster.vue +9 -6
- package/dialog/DeveloperLoadExtensionDialog.vue +13 -4
- package/dialog/MoveNamespaceDialog.vue +20 -4
- package/dialog/RollbackWorkloadDialog.vue +2 -5
- package/dialog/SearchDialog.vue +1 -0
- package/dialog/__tests__/MoveNamespaceDialog.test.ts +249 -0
- package/directives/__tests__/clean-tooltip.test.ts +298 -0
- package/directives/clean-tooltip.ts +234 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -2
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +100 -3
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
- package/edit/configmap.vue +1 -0
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.helmop.vue +11 -6
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
- package/edit/logging-flow/index.vue +1 -0
- package/edit/logging.banzaicloud.io.output/index.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +1 -1
- package/edit/management.cattle.io.project.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
- package/edit/monitoring.coreos.com.route.vue +1 -1
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +1 -0
- package/edit/networking.k8s.io.ingress/index.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +27 -22
- package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
- package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
- package/edit/persistentvolume/plugins/azureFile.vue +15 -14
- package/edit/persistentvolume/plugins/cephfs.vue +15 -14
- package/edit/persistentvolume/plugins/cinder.vue +15 -14
- package/edit/persistentvolume/plugins/csi.vue +18 -16
- package/edit/persistentvolume/plugins/fc.vue +13 -14
- package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
- package/edit/persistentvolume/plugins/flocker.vue +1 -3
- package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
- package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
- package/edit/persistentvolume/plugins/hostPath.vue +40 -39
- package/edit/persistentvolume/plugins/iscsi.vue +13 -14
- package/edit/persistentvolume/plugins/local.vue +1 -3
- package/edit/persistentvolume/plugins/longhorn.vue +23 -22
- package/edit/persistentvolume/plugins/nfs.vue +15 -14
- package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
- package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
- package/edit/persistentvolume/plugins/quobyte.vue +15 -14
- package/edit/persistentvolume/plugins/rbd.vue +15 -14
- package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
- package/edit/persistentvolume/plugins/storageos.vue +15 -14
- package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
- package/edit/provisioning.cattle.io.cluster/index.vue +5 -5
- package/edit/provisioning.cattle.io.cluster/rke2.vue +9 -8
- package/edit/resources.cattle.io.restore.vue +1 -1
- package/edit/secret/index.vue +1 -1
- package/edit/service.vue +1 -0
- package/edit/serviceaccount.vue +1 -0
- package/edit/storage.k8s.io.storageclass/index.vue +1 -0
- package/edit/workload/Job.vue +2 -2
- package/edit/workload/index.vue +2 -1
- package/edit/workload/mixins/workload.js +1 -1
- package/initialize/App.vue +4 -4
- package/initialize/install-plugins.js +19 -5
- package/machine-config/azure.vue +1 -1
- package/machine-config/components/GCEImage.vue +1 -1
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/brand.js +1 -7
- package/mixins/create-edit-view/index.js +5 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +128 -5
- package/models/chart.js +70 -74
- package/models/management.cattle.io.cluster.js +21 -3
- package/models/provisioning.cattle.io.cluster.js +31 -11
- package/package.json +11 -10
- package/pages/auth/login.vue +4 -6
- package/pages/auth/setup.vue +1 -1
- package/pages/auth/verify.vue +3 -3
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
- package/pages/c/_cluster/apps/charts/chart.vue +33 -15
- package/pages/c/_cluster/apps/charts/index.vue +122 -24
- package/pages/c/_cluster/apps/charts/install.vue +33 -0
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
- package/pages/c/_cluster/explorer/index.vue +8 -6
- package/pages/c/_cluster/fleet/index.vue +4 -7
- package/pages/c/_cluster/manager/hostedprovider/index.vue +12 -6
- package/pages/c/_cluster/settings/brand.vue +1 -1
- package/pages/c/_cluster/settings/index.vue +5 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
- package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
- package/pages/c/_cluster/uiplugins/index.vue +126 -184
- package/pkg/auto-import.js +3 -3
- package/pkg/dynamic-importer.lib.js +1 -1
- package/pkg/import.js +1 -1
- package/plugins/__tests__/mutations.tests.ts +179 -0
- package/plugins/dashboard-client-init.js +3 -0
- package/plugins/dashboard-store/getters.js +19 -2
- package/plugins/dashboard-store/model-loader.js +1 -1
- package/plugins/dashboard-store/mutations.js +23 -2
- package/plugins/dashboard-store/resource-class.js +11 -5
- package/plugins/i18n.js +8 -0
- package/plugins/plugin.js +2 -2
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +506 -0
- package/plugins/steve/steve-class.js +1 -1
- package/plugins/steve/steve-pagination-utils.ts +131 -47
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -42
- package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
- package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
- package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
- package/rancher-components/Pill/types.ts +0 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +2 -4
- package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
- package/rancher-components/RcIcon/RcIcon.vue +46 -0
- package/rancher-components/RcIcon/index.ts +1 -0
- package/rancher-components/RcIcon/types.ts +160 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +1 -1
- package/rancher-components/utils/status.test.ts +67 -0
- package/rancher-components/utils/status.ts +77 -0
- package/scripts/publish-shell.sh +25 -0
- package/scripts/typegen.sh +1 -0
- package/store/__tests__/catalog.test.ts +1 -1
- package/store/__tests__/type-map.test.ts +164 -2
- package/store/action-menu.js +8 -0
- package/store/auth.js +25 -13
- package/store/catalog.js +6 -0
- package/store/i18n.js +3 -3
- package/store/index.js +8 -6
- package/store/notifications.ts +2 -0
- package/store/prefs.js +6 -7
- package/store/type-map.js +17 -7
- package/store/wm.ts +4 -4
- package/types/internal-api/shell/modal.d.ts +6 -6
- package/types/notifications/index.ts +126 -15
- package/types/rancher/index.d.ts +9 -0
- package/types/shell/index.d.ts +54 -3
- package/types/store/__tests__/pagination.types.spec.ts +137 -0
- package/types/store/pagination.types.ts +157 -9
- package/types/vue-shim.d.ts +5 -4
- package/utils/__tests__/provider.test.ts +98 -0
- package/utils/__tests__/router.test.js +238 -0
- package/utils/__tests__/selector-typed.test.ts +263 -0
- package/utils/cluster.js +4 -1
- package/utils/color.js +1 -1
- package/utils/dynamic-content/__tests__/info.test.ts +6 -0
- package/utils/dynamic-content/info.ts +43 -0
- package/utils/favicon.js +4 -4
- package/utils/fleet.ts +8 -1
- package/utils/pagination-utils.ts +2 -2
- package/utils/pagination-wrapper.ts +1 -1
- package/utils/provider.ts +14 -0
- package/utils/router.js +50 -0
- package/utils/selector-typed.ts +6 -2
- package/utils/unit-tests/pagination-utils.spec.ts +8 -8
- package/vue.config.js +3 -3
- package/composables/useExtensionManager.ts +0 -17
- package/core/plugins.js +0 -38
- package/directives/clean-tooltip.js +0 -32
- package/plugins/internal-api/index.ts +0 -37
- package/plugins/internal-api/shared/base-api.ts +0 -13
- package/plugins/internal-api/shell/shell.api.ts +0 -108
- package/plugins/nuxt-client-init.js +0 -3
- package/types/internal-api/shell/growl.d.ts +0 -25
- 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
|
+
* * 
|
|
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
|
+
* * 
|
|
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
|
+
* * 
|
|
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
|
+
});
|