diff --git a/dev-docs.json b/dev-docs.json new file mode 100644 index 0000000000..379223a96b --- /dev/null +++ b/dev-docs.json @@ -0,0 +1,3 @@ +{ + "aiProvider": "aws" +} diff --git a/docusaurus/docs/cms/admin-panel-customization/extension.md b/docusaurus/docs/cms/admin-panel-customization/extension.md index 60ae7d42db..46b69125e7 100644 --- a/docusaurus/docs/cms/admin-panel-customization/extension.md +++ b/docusaurus/docs/cms/admin-panel-customization/extension.md @@ -5,9 +5,8 @@ displayed_sidebar: cmsSidebar sidebar_label: Extension toc_max_heading_level: 4 tags: -- admin panel -- admin panel customization - + - admin panel + - admin panel customization --- import HotReloading from '/docs/snippets/hot-reloading-admin-panel.md' @@ -28,6 +27,81 @@ There are 2 use cases where you might want to extend the admin panel: 👉 This can be done by directly updating the `/src/admin/app.[tsx|js]` file, which can import any file located in `/src/admin/extensions`. +## Widgets API + +The Widgets API allows you to create custom widgets that can be displayed in the admin panel dashboard. Widgets are React components that appear on the dashboard and can provide valuable information or functionality specific to your application. + +### Registering a widget + +To register a widget, use the `register` method from the Widgets class. Each widget requires specific properties: + +```typescript +// Example widget registration +strapi.admin.widgets.register({ + // Unique identifier for this widget + id: 'my-custom-widget', + // The icon displayed with the widget + icon: MyCustomIcon, + // The title displayed for the widget + title: { id: 'my-custom-widget.title', defaultMessage: 'My Custom Widget' }, + // Optional link to provide additional actions + link: { + label: { id: 'my-custom-widget.link', defaultMessage: 'Learn more' }, + href: '/some-path', + }, + // The React component to render (lazy loaded) + component: () => import('./components/MyCustomWidget'), + // Optional permissions to restrict who can see this widget + permissions: [ + { action: 'plugin::content-manager.explorer.read', subject: 'api::article.article' } + ], +}); +``` + +You can also register multiple widgets at once by passing an array: + +```typescript +strapi.admin.widgets.register([ + { + id: 'widget-1', + // ...other properties + }, + { + id: 'widget-2', + // ...other properties + } +]); +``` + +### Widget properties + +Each widget must have the following properties: + +| Property | Type | Description | +|----------|------|-------------| +| `id` | `string` | A unique identifier for the widget | +| `icon` | `React.ComponentType` | The icon component to display with the widget | +| `title` | `MessageDescriptor` | The title of the widget (internationalized) | +| `component` | `() => Promise<{ default: React.ComponentType }>` | The React component to render (lazy loaded) | +| `link` | `{ label: MessageDescriptor, href: To }` | Optional link providing additional context or actions | +| `permissions` | `Permission[]` | Optional array of permissions to restrict widget visibility | +| `pluginId` | `string` | Optional plugin identifier when the widget is provided by a plugin | + +### Widget UIDs + +When registering a widget, it's assigned a unique identifier (UID) based on its source: + +- For widgets from plugins: `plugin::{pluginId}.{id}` +- For global widgets: `global::{id}` + +### Retrieving registered widgets + +To get all registered widgets, use the `getAll` method: + +```typescript +const allWidgets = strapi.admin.widgets.getAll(); +``` + :::strapi Additional resources * If you're searching for ways of replacing the default WYSIWYG editor, please refer to the [corresponding page](/cms/admin-panel-customization/wysiwyg-editor). * The will also provide additional information on developing for Strapi's admin panel. diff --git a/docusaurus/docs/cms/admin-panel-customization/widgets.md b/docusaurus/docs/cms/admin-panel-customization/widgets.md new file mode 100644 index 0000000000..f59ffed429 --- /dev/null +++ b/docusaurus/docs/cms/admin-panel-customization/widgets.md @@ -0,0 +1,184 @@ +--- +title: Widgets API +description: Learn how to use the Widgets API to extend Strapi's admin panel with custom widgets. +displayed_sidebar: cmsSidebar +sidebar_label: Widgets +toc_max_heading_level: 4 +tags: +- admin panel +- admin panel customization +- widgets +--- + +# Widgets API + +Strapi's Widgets API allows you to extend the admin panel with custom widgets. Widgets are modular components that can be registered and displayed in specific areas of the admin interface. + +## Introduction + +Widgets are reusable UI components that can be added to the admin panel. They provide a way to extend the functionality of the admin panel without modifying its core code. Widgets can be used to display various types of information, provide shortcuts to frequently used functions, or integrate with external services. + +You can register widgets in two ways: +- As a plugin developer, you can register widgets that will be available whenever your plugin is installed +- As a Strapi developer, you can register widgets for a specific instance of a Strapi application + +## API Reference + +### Registering Widgets + +The Widgets API provides methods to register one or more widgets: + +```typescript +// Register a single widget +strapi.admin.widgets.register({ + id: 'my-widget', + component: () => import('./components/MyWidget'), + title: { id: 'myWidget.title', defaultMessage: 'My Widget' }, + icon: IconComponent, +}); + +// Register multiple widgets +strapi.admin.widgets.register([ + { + id: 'first-widget', + component: () => import('./components/FirstWidget'), + title: { id: 'firstWidget.title', defaultMessage: 'First Widget' }, + icon: FirstIconComponent, + }, + { + id: 'second-widget', + component: () => import('./components/SecondWidget'), + title: { id: 'secondWidget.title', defaultMessage: 'Second Widget' }, + icon: SecondIconComponent, + } +]); +``` + +### Getting All Registered Widgets + +You can retrieve all registered widgets using the `getAll` method: + +```typescript +const widgets = strapi.admin.widgets.getAll(); +``` + +## Widget Properties + +When registering a widget, you need to provide several properties: + +### Required Properties + +| Property | Type | Description | +|----------|------|-------------| +| `id` | `string` | A unique identifier for the widget | +| `component` | `() => Promise<{ default: React.ComponentType }>` | A function that returns a promise resolving to the widget component | +| `title` | `MessageDescriptor` | The title of the widget (supports internationalization) | +| `icon` | `React.ComponentType` | The icon component to display with the widget | + +### Optional Properties + +| Property | Type | Description | +|----------|------|-------------| +| `link` | `{ label: MessageDescriptor; href: To }` | A link to include in the widget | +| `pluginId` | `string` | The ID of the plugin registering the widget | +| `permissions` | `Permission[]` | Permissions required to view the widget | + +## Usage Examples + +### Basic Widget Registration + +```typescript +import { CheckCircle } from '@strapi/icons'; + +// In your plugin's admin/src/index.js or in src/admin/app.js +export default { + register(app) { + app.widgets.register({ + id: 'dashboard-welcome', + component: () => import('./components/DashboardWelcome'), + title: { + id: 'dashboard.welcome.title', + defaultMessage: 'Welcome to your dashboard', + }, + icon: CheckCircle, + }); + }, +}; +``` + +### Widget with a Link and Permissions + +```typescript +import { Heart } from '@strapi/icons'; + +export default { + register(app) { + app.widgets.register({ + id: 'content-metrics', + component: () => import('./components/ContentMetrics'), + title: { + id: 'metrics.content.title', + defaultMessage: 'Content Metrics', + }, + icon: Heart, + link: { + label: { + id: 'metrics.content.link', + defaultMessage: 'View all metrics', + }, + href: '/metrics', + }, + permissions: [ + { action: 'plugin::content-manager.read', subject: 'metrics' }, + ], + }); + }, +}; +``` + +### Plugin-specific Widget + +When registering a widget from a plugin, include the `pluginId` to properly namespace the widget: + +```typescript +export default { + register(app) { + app.widgets.register({ + id: 'analytics-summary', + pluginId: 'my-analytics-plugin', + component: () => import('./components/AnalyticsSummary'), + title: { + id: 'analytics.summary.title', + defaultMessage: 'Analytics Summary', + }, + icon: () => null, + }); + }, +}; +``` + +## Widget UID + +When widgets are registered, they are assigned a unique identifier (UID) based on their `id` and optional `pluginId`: + +- For global widgets: `global::{id}` +- For plugin widgets: `plugin::{pluginId}.{id}` + +This UID is used internally to track and manage registered widgets. + +```doc.dev +Need more information about where/how widgets are displayed in the admin panel UI. +The code reveals the registration mechanism but not how these widgets are rendered or where they appear in the interface. +Additional details about any widget-specific styling or layout considerations would also be helpful. +``` + +## Error Handling + +The Widgets API will throw errors if any required properties are missing when registering a widget: + +- If `id` is missing: "An id must be provided" +- If `component` is missing: "A component must be provided" +- If `title` is missing: "A title must be provided" +- If `icon` is missing: "An icon must be provided" + +Ensure all required properties are provided to avoid runtime errors. \ No newline at end of file