Skip to content

Commit

Permalink
Simplify growl hook - add hook for prompt modal
Browse files Browse the repository at this point in the history
lint
  • Loading branch information
jordojordo committed Dec 5, 2024
1 parent b9f976e commit a5cfc9d
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 76 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,6 @@
},
"resolutions": {
"html-webpack-plugin": "^5.0.0"
}
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
5 changes: 4 additions & 1 deletion shell/components/GrowlManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ export default {
class="close hand icon icon-close"
@click="close(growl)"
/>
<div class="growl-text-title">
<div
v-if="growl.title"
class="growl-text-title"
>
{{ growl.title }}
</div>
<p v-if="growl.message">
Expand Down
4 changes: 1 addition & 3 deletions shell/plugins/rancher-api/index.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;

/**
Expand Down
79 changes: 61 additions & 18 deletions shell/plugins/rancher-api/shell-api-class.ts
Original file line number Diff line number Diff line change
@@ -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<any>;
Expand All @@ -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,
});
}
}
35 changes: 35 additions & 0 deletions shell/types/rancher-api/cluster.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* TODO: Update @shell/plugins/dashboard-store/resource-class to TS.
*/
export interface SteveResource {
save(): Promise<any>,
remove(): Promise<any>,
}

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
}
25 changes: 25 additions & 0 deletions shell/types/rancher-api/growl.d.ts
Original file line number Diff line number Diff line change
@@ -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;
}
82 changes: 82 additions & 0 deletions shell/types/rancher-api/modal.d.ts
Original file line number Diff line number Diff line change
@@ -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/<extension-pkg>/dialog` directory within the extension.
* - Example, in an extension named `my-extension`:
* ```
* <extension-root>/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<string, any>;

/**
* 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;
}
53 changes: 0 additions & 53 deletions shell/utils/growl.ts

This file was deleted.

0 comments on commit a5cfc9d

Please sign in to comment.