diff --git a/package.json b/package.json
index 2d74f684a1f..59ac7a5d553 100644
--- a/package.json
+++ b/package.json
@@ -205,5 +205,6 @@
},
"resolutions": {
"html-webpack-plugin": "^5.0.0"
- }
+ },
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
diff --git a/shell/components/GrowlManager.vue b/shell/components/GrowlManager.vue
index f992716cdd1..287cff7266f 100644
--- a/shell/components/GrowlManager.vue
+++ b/shell/components/GrowlManager.vue
@@ -103,7 +103,10 @@ export default {
class="close hand icon icon-close"
@click="close(growl)"
/>
-
+
{{ growl.title }}
diff --git a/shell/plugins/rancher-api/index.ts b/shell/plugins/rancher-api/index.ts
index d88ed659607..ae58959ee99 100644
--- a/shell/plugins/rancher-api/index.ts
+++ b/shell/plugins/rancher-api/index.ts
@@ -1,5 +1,3 @@
-// shell/plugins/rancher-api/index.ts
-
import { Store } from 'vuex';
import { ApiPrototype } from '@shell/types/rancher-api';
// import RancherApi from './rancher-api-class';
@@ -12,7 +10,7 @@ interface PluginContext {
[key: string]: any;
}
-export default function (context: PluginContext, inject: (key: string, value: any) => void) {
+export default function(context: PluginContext, inject: (key: string, value: any) => void) {
const { store } = context;
/**
diff --git a/shell/plugins/rancher-api/shell-api-class.ts b/shell/plugins/rancher-api/shell-api-class.ts
index 0ec80e3d236..28e5a6d2356 100644
--- a/shell/plugins/rancher-api/shell-api-class.ts
+++ b/shell/plugins/rancher-api/shell-api-class.ts
@@ -1,6 +1,7 @@
import { Store } from 'vuex';
-import { GrowlConfig, handleGrowl } from '@shell/utils/growl';
+import { GrowlConfig } from '@shell/types/rancher-api/growl';
+import { ModalConfig } from '@shell/types/rancher-api/modal';
interface ShellApiOptions {
store: Store;
@@ -14,27 +15,69 @@ export default class ShellApi {
}
/**
- * Dispatches a growl notification based on the provided configuration.
+ * Dispatches a growl notification.
*
* @param config - Configuration for the growl notification.
+ * - If `message` is a string, it is treated as the main content of the notification.
+ * - If `message` is a `DetailedMessage` object, `title` and `description` are extracted.
*
- * The `config` parameter is an object of type `GrowlConfig`, which includes:
- * - `error`: An `ErrorMessage` object containing the details of the error to be displayed.
- * This object can have an optional `data` property with `_statusText` and `message`,
- * or these properties can be directly on the `error` object.
- * - `store`: A parameter representing the Vuex store used to dispatch actions.
- * This is where the growl notification action will be dispatched.
- * - `type`: An optional string representing the type of notification (e.g., 'success', 'info', 'warning', 'error').
- * If not provided, defaults to 'error'.
- * - `timeout`: An optional number representing the duration in milliseconds
- * for which the notification should be displayed. Defaults to 5000 milliseconds if not provided.
- *
- * The action payload includes:
- * - `title`: The error status text.
- * - `message`: The detailed error message.
- * - `timeout`: The specified or default timeout duration.
+ * Example:
+ * ```
+ * this.$shell.growl({ message: 'Operation successful!', type: 'success' });
+ * this.$shell.growl({ message: { title: 'Warning', description: 'Check your input.' }, type: 'warning' });
+ * ```
*/
growl(config: GrowlConfig): void {
- handleGrowl(config);
+ const { type = 'error', timeout = 5000 } = config;
+
+ let title = '';
+ let description = '';
+
+ if (typeof config.message === 'string') {
+ description = config.message;
+ } else {
+ title = config.message.title || '';
+ description = config.message.description;
+ }
+
+ this.$store.dispatch(
+ `growl/${ type }`,
+ {
+ title,
+ message: description,
+ timeout,
+ },
+ { root: true }
+ );
+ }
+
+ /**
+ * Opens a modal by committing to the Vuex store.
+ *
+ * This method updates the store's `action-menu` module to show a modal with the
+ * specified configuration. The modal is rendered using the `PromptModal` component,
+ * and its content is dynamically loaded based on the `component` field in the configuration.
+ *
+ * @param config A `ModalConfig` object defining the modal’s content and behavior.
+ *
+ * Example:
+ * ```
+ * this.$shell.modal({
+ * component: 'MyCustomDialog',
+ * componentProps: { title: 'Hello Modal' },
+ * resources: [someResource],
+ * modalWidth: '800px',
+ * closeOnClickOutside: false
+ * });
+ * ```
+ */
+ modal(config: ModalConfig): void {
+ this.$store.commit('action-menu/togglePromptModal', {
+ component: config.component,
+ componentProps: config.componentProps || {},
+ resources: config.resources || [],
+ modalWidth: config.modalWidth || '600px',
+ closeOnClickOutside: config.closeOnClickOutside ?? true,
+ });
}
}
diff --git a/shell/types/rancher-api/cluster.d.ts b/shell/types/rancher-api/cluster.d.ts
new file mode 100644
index 00000000000..36a6c70a443
--- /dev/null
+++ b/shell/types/rancher-api/cluster.d.ts
@@ -0,0 +1,35 @@
+/**
+ * TODO: Update @shell/plugins/dashboard-store/resource-class to TS.
+ */
+export interface SteveResource {
+ save(): Promise,
+ remove(): Promise,
+}
+
+export interface ResourceFetchOptions {
+ id?: string,
+ namespace?: string,
+ selector?: string,
+ force?: boolean
+}
+
+export interface ResourceFetchRequest {
+ type: string,
+ options?: ResourceFetchOptions
+}
+
+export interface ResourceManageOptions {
+ metadata: {
+ name: string,
+ namespace?: string,
+ labels?: {[key: string]: string},
+ annotations?: {[key: string]: string}
+ },
+ spec?: any
+}
+
+export interface ResourceManageRequest {
+ type: string,
+ options: ResourceManageOptions,
+ resource?: SteveResource
+}
diff --git a/shell/types/rancher-api/growl.d.ts b/shell/types/rancher-api/growl.d.ts
new file mode 100644
index 00000000000..def12827a65
--- /dev/null
+++ b/shell/types/rancher-api/growl.d.ts
@@ -0,0 +1,25 @@
+export interface DetailedMessage {
+ title?: string;
+ description: string;
+}
+
+export interface GrowlConfig {
+ /**
+ * The content of the notification message.
+ * Either a simple string or an object with `title` and `description` for detailed notifications.
+ */
+ message: string | DetailedMessage;
+
+ /**
+ * Optional type of the growl notification.
+ * Determines the visual style of the notification.
+ * Defaults to `'error'` if not provided.
+ */
+ type?: 'success' | 'info' | 'warning' | 'error';
+
+ /**
+ * Optional duration (in milliseconds) for which the notification should be displayed.
+ * Defaults to `5000` milliseconds. A value of `0` keeps the notification indefinitely.
+ */
+ timeout?: number;
+}
diff --git a/shell/types/rancher-api/modal.d.ts b/shell/types/rancher-api/modal.d.ts
new file mode 100644
index 00000000000..87b481b1581
--- /dev/null
+++ b/shell/types/rancher-api/modal.d.ts
@@ -0,0 +1,82 @@
+/**
+ * Configuration object for opening a modal.
+ */
+export interface ModalConfig {
+ /**
+ * TODO: Understand how this works with extensions
+ *
+ * The name of the component to be displayed inside the modal.
+ *
+ * The component must reside in the `dialog` directory, depending on the environment:
+ *
+ * 1. **When Using the Shell as Part of the Core Project**:
+ * - Components must live in the `@shell/dialog` directory.
+ * - Example:
+ * ```
+ * shell/dialog/MyCustomDialog.vue
+ * ```
+ *
+ * 2. **When Using the Shell as a Library (Extensions)**:
+ * - Components must live in the `pkg//dialog` directory within the extension.
+ * - Example, in an extension named `my-extension`:
+ * ```
+ * /pkg/my-extension/dialog/MyCustomDialog.vue
+ * ```
+ *
+ * - The `component` value should still match the file name without the `.vue` extension.
+ * - Example:
+ * ```typescript
+ * component: 'MyCustomDialog' // Dynamically imports MyCustomDialog.vue
+ * ```
+ *
+ */
+ component: string;
+
+ /**
+ * Optional props to pass directly to the component rendered inside the modal.
+ * This can be a record of key-value pairs where keys are the prop names, and
+ * values are the corresponding prop values for the component.
+ *
+ * Example:
+ * ```
+ * componentProps: { title: 'Hello Modal', isVisible: true }
+ * ```
+ */
+ componentProps?: Record;
+
+ /**
+ * Optional array of resources that the modal component might need.
+ * These resources are passed directly to the modal's `resources` prop.
+ *
+ * Example:
+ * ```
+ * resources: [myResource, anotherResource]
+ * ```
+ */
+ resources?: any[];
+
+ /**
+ * Custom width for the modal. Defaults to `600px`.
+ * The width can be specified as a number (pixels) or as a string
+ * with a valid unit, such as `px` or `%`.
+ *
+ * Example:
+ * ```
+ * modalWidth: '800px' // Width in pixels
+ * modalWidth: '75%' // Width as a percentage
+ * ```
+ */
+ modalWidth?: string;
+
+ /**
+ * If true, clicking outside the modal will close it. Defaults to `true`.
+ * Set this to `false` if you want the modal to remain open until the user
+ * explicitly closes it.
+ *
+ * Example:
+ * ```
+ * closeOnClickOutside: false
+ * ```
+ */
+ closeOnClickOutside?: boolean;
+}
diff --git a/shell/utils/growl.ts b/shell/utils/growl.ts
deleted file mode 100644
index 1898760cff1..00000000000
--- a/shell/utils/growl.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { Store } from 'vuex';
-
-export interface Message {
- data?: {
- _statusText: string,
- message: string
- }
- _statusText?: string,
- message?: string
-}
-
-export interface GrowlConfig {
- message: Message,
- store: Store,
- type?: string,
- timeout?: number
-}
-
-/**
- * Dispatches a growl notification based on the provided configuration.
- *
- * @param config - Configuration for the growl notification.
- *
- * The `config` parameter is an object of type `GrowlConfig`, which includes:
- * - `message`: An `Message` object containing the details of the error to be displayed.
- * This object can have an optional `data` property with `_statusText` and `message`,
- * or these properties can be directly on the `error` object.
- * - `store`: A parameter representing the Vuex store used to dispatch actions.
- * This is where the growl notification action will be dispatched.
- * - `type`: An optional string representing the type of notification (e.g., 'success', 'info', 'warning', 'error').
- * If not provided, defaults to 'error'.
- * - `timeout`: An optional number representing the duration in milliseconds
- * for which the notification should be displayed. Defaults to 5000 milliseconds if not provided.
- *
- * The function extracts error details either from `config.error.data` or `config.error`
- * (if `data` is not present), and dispatches a growl notification action to the store.
- * The action dispatched is of the form `growl/[type]` where `[type]` is either
- * the provided type in the config or 'error' by default.
- *
- * The action payload includes:
- * - `title`: The error status text.
- * - `message`: The detailed error message.
- * - `timeout`: The specified or default timeout duration.
- */
-export function handleGrowl(config: GrowlConfig): void {
- const message = config.message?.data || config.message;
-
- config.store.dispatch(`growl/${ config.type || 'error' }`, {
- title: message._statusText,
- message: message.message,
- timeout: config.timeout || 5000,
- }, { root: true });
-}