Ver Fonte

docs: Update ui extensions docs

Michael Bromley há 2 anos atrás
pai
commit
53440840d7

+ 3 - 8
docs/docs/guides/extending-the-admin-ui/add-actions-to-pages/index.md

@@ -8,7 +8,7 @@ weight: 5
 
 ## Adding ActionBar buttons
 
-It may not always make sense to navigate to your extension view from the main nav menu. For example, an "order invoice" extension that allows you to print invoices for orders. In this case, you can add new buttons to the "ActionBar", which is the horizontal section at the top of each screen containing the primary actions for that view. This is done using the [addActionBarItem function]({{< relref "add-action-bar-item" >}}).
+It may not always make sense to navigate to your extension view from the main nav menu. For example, an "order invoice" extension that allows you to print invoices for orders. In this case, you can add new buttons to the "ActionBar", which is the horizontal section at the top of each screen containing the primary actions for that view. This is done using the [addActionBarItem function](/reference/admin-ui-api/action-bar/add-action-bar-item/).
 
 ### ActionBar Example
 
@@ -36,7 +36,7 @@ export class SharedExtensionModule {}
 
 ![./ui-extensions-actionbar.webp](./ui-extensions-actionbar.webp)
 
-In each list or detail view in the app, the ActionBar has a unique `locationId` which is how the app knows in which view to place your button. The complete list of available locations into which you can add new ActionBar can be found in the [ActionBarLocationId docs]({{< relref "action-bar-location-id" >}}).
+In each list or detail view in the app, the ActionBar has a unique `locationId` which is how the app knows in which view to place your button. The complete list of available locations into which you can add new ActionBar can be found in the [ActionBarLocationId docs](/reference/admin-ui-api/action-bar/action-bar-location-id/).
 
 ### Adding onClick Actions to ActionBar buttons
 
@@ -91,7 +91,7 @@ Use cases for bulk actions include things like:
 
 ### Bulk Action Example
 
-A bulk action must be provided to a [ui-extension shared module]({{< relref "extending-the-admin-ui" >}}#lazy-vs-shared-modules) using the [`registerBulkAction` function]({{< relref "register-bulk-action" >}})
+A bulk action must be provided to a [ui-extension shared module](/guides/extending-the-admin-ui/introduction/#lazy-vs-shared-modules) using the [`registerBulkAction` function](/reference/admin-ui-api/bulk-actions/register-bulk-action/)
 
 ```ts
 import { NgModule } from '@angular/core';
@@ -156,8 +156,3 @@ registerBulkAction({
   // ...
 });
 ```
-
-Related API docs:
-
-- [`registerBulkAction`]({{< relref "register-bulk-action" >}})
-- [`BulkAction`]({{< relref "bulk-action" >}})

+ 1 - 1
docs/docs/guides/extending-the-admin-ui/adding-ui-translations/index.md

@@ -10,7 +10,7 @@ The Vendure Admin UI is fully localizable, allowing you to:
 * override existing translations
 * add complete translations for whole new languages
 
-{{< figure src="./ui-translations-01.webp" caption="The UI language is set from the User menu" >}}
+![The UI language is set from the User menu](./ui-translations-01.webp)
 
 ## Translation format
 

+ 1 - 1
docs/docs/guides/extending-the-admin-ui/creating-detail-views/index.md

@@ -15,7 +15,7 @@ Let's say you have a plugin which adds a new entity to the database called `Prod
 
 ### Extend the TypedBaseDetailComponent class
 
-The detail component itself is an Angular component which extends the [BaseDetailComponent]({{< relref "base-detail-component" >}}) or [TypedBaseDetailComponent]({{< relref "typed-base-detail-component" >}}) class.
+The detail component itself is an Angular component which extends the [BaseDetailComponent](/reference/admin-ui-api/list-detail-views/base-detail-component/) or [TypedBaseDetailComponent](/reference/admin-ui-api/list-detail-views/typed-base-detail-component) class.
 
 ```ts
 import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core';

+ 5 - 5
docs/docs/guides/extending-the-admin-ui/creating-list-views/index.md

@@ -15,7 +15,7 @@ Let's say you have a plugin which adds a new entity to the database called `Prod
 
 ### Use the PaginatedList interface
 
-To use the standardized list component, you need to make sure your plugin exposes this list in the GraphQL API following the [PaginatedList interface]({{< relref "paginated-list" >}}):
+To use the standardized list component, you need to make sure your plugin exposes this list in the GraphQL API following the [PaginatedList interface](/reference/typescript-api/common/paginated-list/):
 
 ```graphql
 type ProductReview implements Node {
@@ -36,11 +36,11 @@ type ProductReviewList implements PaginatedList {
 }
 ```
 
-See the [ListQueryBuilder docs]({{< relref "list-query-builder" >}}) for more information on how to implement this in your server plugin code.
+See the [ListQueryBuilder docs](/reference/typescript-api/data-access/list-query-builder/) for more information on how to implement this in your server plugin code.
 
 ### Create the list component
 
-The list component itself is an Angular component which extends the [BaseListComponent]({{< relref "base-list-component" >}}) or [TypedBaseListComponent]({{< relref "typed-base-list-component" >}}) class.
+The list component itself is an Angular component which extends the [BaseListComponent](/reference/admin-ui-api/list-detail-views/base-list-component/) or [TypedBaseListComponent](/reference/admin-ui-api/list-detail-views/typed-base-list-component) class.
 
 This example assumes you have set up your project to use [GraphQL Code Generator](https://the-guild.dev/graphql/codegen) with the [TypedDocumentNode plugin](https://the-guild.dev/graphql/codegen/plugins/typescript/typed-document-node).
 
@@ -139,7 +139,7 @@ export class ReviewListComponent extends TypedBaseListComponent<typeof GetReview
 
 ### Create the template
 
-This is the standard layout for any list view. The main functionality is provided by the [DataTable2Component]({{< relref "data-table2component" >}}).
+This is the standard layout for any list view. The main functionality is provided by the [DataTable2Component](/reference/admin-ui-api/components/data-table2component/).
 
 ```html
 <vdr-page-header>
@@ -232,4 +232,4 @@ This is the standard layout for any list view. The main functionality is provide
 
 ### Route config
 
-For an example of how the route config would look for this list view component, see the full example in the [Creating detail views guide]({{< relref "creating-detail-views" >}}#route-config).
+For an example of how the route config would look for this list view component, see the full example in the [Creating detail views guide](/guides/extending-the-admin-ui/creating-detail-views/#route-config).

+ 2 - 2
docs/docs/guides/extending-the-admin-ui/custom-detail-components/index.md

@@ -5,7 +5,7 @@ weight: 6
 
 # Custom Detail Components
 
-Most of the detail views can be extended with custom Angular components using the [registerCustomDetailComponent function]({{< relref "register-custom-detail-component" >}}).
+Most of the detail views can be extended with custom Angular components using the [registerCustomDetailComponent function](/reference/admin-ui-api/custom-detail-components/register-custom-detail-component/).
 
 Any components registered in this way will appear below the main detail form.
 
@@ -60,5 +60,5 @@ export class ProductInfoComponent implements CustomDetailComponent, OnInit {
 export class SharedExtensionModule {}
 ```
 
-The valid locations for embedding custom detail components can be found in the [CustomDetailComponentLocationId docs]({{< relref "custom-detail-component-location-id" >}}).
+The valid locations for embedding custom detail components can be found in the [CustomDetailComponentLocationId docs](/reference/admin-ui-api/custom-detail-components/custom-detail-component-location-id).
 

+ 67 - 68
docs/docs/guides/extending-the-admin-ui/custom-form-inputs/index.md

@@ -5,19 +5,17 @@ weight: 5
 
 # Custom Form Inputs
 
-Another way to extend the Admin UI app is to define custom form input components for manipulating any [Custom Fields]({{< ref "/reference/typescript-api/custom-fields" >}}) you have defined on your entities as well as [configurable args]({{< relref "config-args" >}}) used by custom [ConfigurableOperationDefs]({{< relref "configurable-operation-def" >}}).
+Another way to extend the Admin UI app is to define custom form input components for manipulating any [Custom Fields](/guides/developer-guide/custom-fields/) you have defined on your entities as well as [configurable args](/reference/typescript-api/configurable-operation-def/config-args/) used by custom [Configurable Operations](/guides/developer-guide/strategies-configurable-operations/#configurable-operations).
 
 ## For Custom Fields
 
 Let's say you define a custom "intensity" field on the Product entity:
 
-```ts
-// project/vendure-config.ts
-
+```ts title="src/vendure-config.ts"
 customFields: {
-  Product: [
-    { name: 'intensity', type: 'int', min: 0, max: 100, defaultValue: 0 },
-  ],
+    Product: [
+        {name: 'intensity', type: 'int', min: 0, max: 100, defaultValue: 0},
+    ],
 }
 ```
 
@@ -25,79 +23,78 @@ By default, the "intensity" field will be displayed as a number input:
 
 ![./ui-extensions-custom-field-default.webp](./ui-extensions-custom-field-default.webp)
 
-But let's say we want to display a range slider instead. Here's how we can do this using our shared extension module combined with the [registerFormInputComponent function]({{< relref "register-form-input-component" >}}):
+But let's say we want to display a range slider instead. Here's how we can do this using our shared extension module combined with the [registerFormInputComponent function](/reference/admin-ui-api/custom-input-components/register-form-input-component/):
 
-```ts
-// project/ui-extensions/shared.module.ts
+```ts title="src/ui-extensions/slider-form-input.component.ts"
 import { NgModule, Component } from '@angular/core';
 import { FormControl } from '@angular/forms';
-import { IntCustomFieldConfig ,SharedModule, FormInputComponent, registerFormInputComponent } from '@vendure/admin-ui/core';
+import { IntCustomFieldConfig, SharedModule, FormInputComponent, registerFormInputComponent } from '@vendure/admin-ui/core';
 
 @Component({
-  template: `
-    <input
-        type="range"
-        [min]="config.min || 0"
-        [max]="config.max || 100"
-        [formControl]="formControl" />
-    {{ formControl.value }}
+    template: `
+      <input
+          type="range"
+          [min]="config.min || 0"
+          [max]="config.max || 100"
+          [formControl]="formControl" />
+      {{ formControl.value }}
   `,
 })
 export class SliderControl implements FormInputComponent<IntCustomFieldConfig> {
-  readonly: boolean;
-  config: IntCustomFieldConfig;
-  formControl: FormControl;
+    readonly: boolean;
+    config: IntCustomFieldConfig;
+    formControl: FormControl;
 }
 
 @NgModule({
-  imports: [SharedModule],
-  declarations: [SliderControl],
-  providers: [
-    registerFormInputComponent('slider-form-input', SliderControl),
-  ]
+    imports: [SharedModule],
+    declarations: [SliderControl],
+    providers: [
+        registerFormInputComponent('slider-form-input', SliderControl),
+    ]
 })
-export class SharedExtensionModule {}
+export class SharedExtensionModule {
+}
 ```
-The `SharedExtensionModule` is then passed to the `compileUiExtensions()` function as described in the [UI Extensions With Angular guide]({{< relref "using-angular" >}}#4-pass-the-extension-to-the-compileuiextensions-function):
 
-```ts
-// project/vendure-config.ts
+The `SharedExtensionModule` is then passed to the `compileUiExtensions()` function as described in the [UI Extensions With Angular guide](/guides/extending-the-admin-ui/using-angular/#4-pass-the-extension-to-the-compileuiextensions-function):
+
+```ts title="src/vendure-config.ts"
 AdminUiPlugin.init({
-  port: 5001,
-  app: compileUiExtensions({
-    outputPath: path.join(__dirname, '../admin-ui'),
-    extensions: [{
-      extensionPath: path.join(__dirname, 'ui-extensions'),
-      ngModules: [{
-        type: 'shared',
-        ngModuleFileName: 'shared.module.ts',
-        ngModuleName: 'SharedExtensionModule',
-      }],
-    }],
-  }),
+    port: 5001,
+    app: compileUiExtensions({
+        outputPath: path.join(__dirname, '../admin-ui'),
+        extensions: [{
+            extensionPath: path.join(__dirname, 'ui-extensions'),
+            ngModules: [{
+                type: 'shared',
+                ngModuleFileName: 'shared.module.ts',
+                ngModuleName: 'SharedExtensionModule',
+            }],
+        }],
+    }),
 })
 ```
 
 Once registered, this new slider input can be used in our custom field config:
 
-```ts {hl_lines=[7]}
-// project/vendure-config.ts
-
+```ts title="src/vendure-config.ts"
 customFields: {
-  Product: [
-    { 
-      name: 'intensity', type: 'int', min: 0, max: 100, defaultValue: 0,
-      ui: { component: 'slider-form-input' }
-    },
-  ],
+    Product: [
+        {
+            name: 'intensity', type: 'int', min: 0, max: 100, defaultValue: 0,
+            // highlight-next-line
+            ui: {component: 'slider-form-input'}
+        },
+    ],
 }
 ```
 As we can see, adding the `ui` property to the custom field config allows us to specify our custom slider component.
 The component id _'slider-form-input'_ **must match** the string passed as the first argument to `registerFormInputComponent()`.
 
-{{% alert %}}
+:::info
 If we want, we can also pass any other arbitrary data in the `ui` object, which will then be available in our component as `this.config.ui.myField`. Note that only JSON-compatible data types are permitted, so no functions or class instances.
-{{< /alert >}}
+:::
 
 
 Re-compiling the Admin UI will result in our SliderControl now being used for the "intensity" custom field:
@@ -120,7 +117,7 @@ If you have a custom field of the `relation` type (which allows you to relate en
 
 Here is a simple example taken from the [real-world-vendure](https://github.com/vendure-ecommerce/real-world-vendure/blob/master/src/plugins/reviews/ui/components/featured-review-selector/featured-review-selector.component.ts) repo:
 
-```ts
+```ts title="src/plugins/reviews/ui/components/relation-review-input/relation-review-input.component.ts"
 import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
 import { FormControl } from '@angular/forms';
 import { ActivatedRoute } from '@angular/router';
@@ -181,27 +178,29 @@ export class RelationReviewInputComponent implements OnInit, FormInputComponent<
 
 ## For ConfigArgs
 
-[ConfigArgs]({{< relref "config-args" >}}) are used by classes which extend [ConfigurableOperationDef]({{< relref "configurable-operation-def" >}}) (such as ShippingCalculator or PaymentMethodHandler). These ConfigArgs allow user-input values to be passed to the operation's business logic.
+[ConfigArgs](/reference/typescript-api/configurable-operation-def/config-args/) are used by classes which extend [Configurable Operations](/guides/developer-guide/strategies-configurable-operations/#configurable-operations) (such as ShippingCalculator or PaymentMethodHandler). These ConfigArgs allow user-input values to be passed to the operation's business logic.
 
 They are configured in a very similar way to custom fields, and likewise can use custom form inputs by specifying the `ui` property. 
 
 Here's an example:
 
-```ts {hl_lines=[6,7,8]}
+```ts title="src/config/order-fixed-discount-action.ts"
 export const orderFixedDiscount = new PromotionOrderAction({
-  code: 'order_fixed_discount',
-  args: {
-    discount: {
-      type: 'int',
-      ui: {
-        component: 'currency-form-input',
-      },
+    code: 'order_fixed_discount',
+    args: {
+        discount: {
+            type: 'int',
+            // highlight-start
+            ui: {
+                component: 'currency-form-input',
+            },
+            // highlight-end
+        },
+    },
+    execute(ctx, order, args) {
+        return -args.discount;
     },
-  },
-  execute(ctx, order, args) {
-    return -args.discount;
-  },
-  description: [{ languageCode: LanguageCode.en, value: 'Discount order by fixed amount' }],
+    description: [{languageCode: LanguageCode.en, value: 'Discount order by fixed amount'}],
 });
 ```
 

+ 35 - 34
docs/docs/guides/extending-the-admin-ui/custom-timeline-components/index.md

@@ -5,29 +5,29 @@ weight: 6
 
 # Custom History Timeline Components
 
-The Order & Customer detail pages feature a timeline of history entries. Since v1.9.0 it is possible to define custom history entry types - see the [HistoryService docs]({{< relref "history-service" >}}) for an example.
+The Order & Customer detail pages feature a timeline of history entries. Since v1.9.0 it is possible to define custom history entry types - see the [HistoryService docs](0/reference/typescript-api/services/history-service/) for an example.
 
-You can also define a custom Angular component to render any timeline entry using the [registerHistoryEntryComponent function]({{< relref "register-history-entry-component" >}}).
+You can also define a custom Angular component to render any timeline entry using the [registerHistoryEntryComponent function](/reference/admin-ui-api/custom-history-entry-components/register-history-entry-component/).
 
 ![./timeline-entry.webp](./timeline-entry.webp)
 
 Following the example used in the HistoryService docs, we can define a component to render the tax ID verification
 entry in our Customer timeline:
 
-```ts
+```ts title="src/plugins/tax-id/ui/components/tax-id-history-entry/tax-id-history-entry.component.ts"
 import { Component, NgModule } from '@angular/core';
 import {
-  CustomerFragment,
-  CustomerHistoryEntryComponent,
-  registerHistoryEntryComponent,
-  SharedModule,
-  TimelineDisplayType,
-  TimelineHistoryEntry,
+    CustomerFragment,
+    CustomerHistoryEntryComponent,
+    registerHistoryEntryComponent,
+    SharedModule,
+    TimelineDisplayType,
+    TimelineHistoryEntry,
 } from '@vendure/admin-ui/core';
 
 @Component({
-  selector: 'tax-id-verification-component',
-  template: `
+    selector: 'tax-id-verification-component',
+    template: `
     <div *ngIf="entry.data.valid">
       Tax ID <strong>{{ entry.data.taxId }}</strong> was verified
       <vdr-history-entry-detail *ngIf="entry.data">
@@ -38,37 +38,38 @@ import {
   `,
 })
 class TaxIdHistoryEntryComponent implements CustomerHistoryEntryComponent {
-  entry: TimelineHistoryEntry;
-  customer: CustomerFragment;
+    entry: TimelineHistoryEntry;
+    customer: CustomerFragment;
 
-  getDisplayType(entry: TimelineHistoryEntry): TimelineDisplayType {
-    return entry.data.valid ? 'success' : 'error';
-  }
+    getDisplayType(entry: TimelineHistoryEntry): TimelineDisplayType {
+        return entry.data.valid ? 'success' : 'error';
+    }
 
-  getName(entry: TimelineHistoryEntry): string {
-    return 'Tax ID Verification Plugin';
-  }
+    getName(entry: TimelineHistoryEntry): string {
+        return 'Tax ID Verification Plugin';
+    }
 
-  isFeatured(entry: TimelineHistoryEntry): boolean {
-    return true;
-  }
+    isFeatured(entry: TimelineHistoryEntry): boolean {
+        return true;
+    }
 
-  getIconShape(entry: TimelineHistoryEntry) {
-    return entry.data.valid ? 'check-circle' : 'exclamation-circle';
-  }
+    getIconShape(entry: TimelineHistoryEntry) {
+        return entry.data.valid ? 'check-circle' : 'exclamation-circle';
+    }
 }
 
 @NgModule({
-  imports: [SharedModule],
-  declarations: [TaxIdHistoryEntryComponent],
-  providers: [
-    registerHistoryEntryComponent({
-      type: 'CUSTOMER_TAX_ID_VERIFICATION', 
-      component:TaxIdHistoryEntryComponent,
-    }),
-  ]
+    imports: [SharedModule],
+    declarations: [TaxIdHistoryEntryComponent],
+    providers: [
+        registerHistoryEntryComponent({
+            type: 'CUSTOMER_TAX_ID_VERIFICATION',
+            component: TaxIdHistoryEntryComponent,
+        }),
+    ]
 })
-export class SharedExtensionModule {}
+export class SharedExtensionModule {
+}
 ```
 
 

+ 53 - 46
docs/docs/guides/extending-the-admin-ui/dashboard-widgets/index.md

@@ -8,7 +8,7 @@ Dashboard widgets are components which can be added to the Admin UI dashboard. T
 
 The Admin UI comes with a handful of widgets, and you can also create your own widgets.
 
-{{< figure src="./dashboard-widgets.webp" caption="Dashboard widgets" >}}
+![Dashboard widgets](./dashboard-widgets.webp)
 
 ## Example: Reviews Widget
 
@@ -18,9 +18,9 @@ To notify administrators about new reviews that need approval, we'll create a da
 
 ### Create the widget
 
-A dashboard widget is an Angular component. This example features a simplified UI, just to illustrate the overall strucutre:
+A dashboard widget is an Angular component. This example features a simplified UI, just to illustrate the overall structure:
 
-```ts
+```ts title="src/plugins/reviews/ui/components/reviews-widget/reviews-widget.component.ts"
 import { Component, NgModule, OnInit } from '@angular/core';
 import { DataService, SharedModule } from '@vendure/admin-ui/core';
 import { Observable } from 'rxjs';
@@ -72,35 +72,38 @@ export class ReviewsWidgetComponent implements OnInit {
 export class ReviewsWidgetModule {}
 ```
 
-{{% alert %}}
-Note that we also need to define an `NgModule` for this component. This is because we will be lazy-loading the component at run-time, and the NgModule is required for us to use shared providers (e.g. `DataService`) and any shared components, directives or pipes defined in the `@vendure/admin-ui/core` package.
-{{% /alert %}}
+:::note
+We also need to define an `NgModule` for this component. This is because we will be lazy-loading the component at run-time, and the NgModule is required for us to use shared providers (e.g. `DataService`) and any shared components, directives or pipes defined in the `@vendure/admin-ui/core` package.
+:::
 
 ### Register the widget
 
-Our widget now needs to be registered as part of a [shared module]({{< relref "extending-the-admin-ui" >}}#lazy-vs-shared-modules):
+Our widget now needs to be registered as part of a [shared module](/guides/extending-the-admin-ui/introduction#lazy-vs-shared-modules):
 
-```ts
+```ts title="src/plugins/reviews/ui/shared-ui-extension.module.ts"
 import { NgModule } from '@angular/core';
 import { registerDashboardWidget } from '@vendure/admin-ui/core';
 import { reviewPermission } from '../constants';
 
 @NgModule({
-  imports: [],
-  declarations: [],
-  providers: [
-    registerDashboardWidget('reviews', {
-      title: 'Latest reviews',
-      supportedWidths: [4, 6, 8, 12],
-      requiresPermissions: [reviewPermission.Read],
-      loadComponent: () =>
-        import('./reviews-widget/reviews-widget.component').then(
-          m => m.ReviewsWidgetComponent,
-        ),
-    }),
-  ],
+    imports: [],
+    declarations: [],
+    providers: [
+        // highlight-start
+        registerDashboardWidget('reviews', {
+            title: 'Latest reviews',
+            supportedWidths: [4, 6, 8, 12],
+            requiresPermissions: [reviewPermission.Read],
+            loadComponent: () =>
+                import('./reviews-widget/reviews-widget.component').then(
+                    m => m.ReviewsWidgetComponent,
+                ),
+        }),
+        // highlight-end
+    ],
 })
-export class MySharedUiExtensionModule {}
+export class MySharedUiExtensionModule {
+}
 ```
 
 * **`title`** This is the title of the widget that will be displayed in the widget header.
@@ -114,25 +117,27 @@ Once registered, the reviews widget will be available to select by administrator
 
 While administrators can customize which widgets they want to display on the dashboard, and the layout of those widgets, you can also set a default layout:
 
-```ts
+```ts title="src/plugins/reviews/ui/shared-ui-extension.module.ts"
 import { NgModule } from '@angular/core';
 import { registerDashboardWidget, setDashboardWidgetLayout } from '@vendure/admin-ui/core';
 import { reviewPermission } from '../constants';
 
 @NgModule({
-  imports: [],
-  declarations: [],
-  providers: [
-    registerDashboardWidget('reviews', {
-      // omitted for brevity
-    }),
-    setDashboardWidgetLayout([
-      { id: 'welcome', width: 12 },
-      { id: 'orderSummary', width: 4 },
-      { id: 'latestOrders', width: 8 },
-      { id: 'reviews', width: 6 },
-    ]),
-  ],
+    imports: [],
+    declarations: [],
+    providers: [
+        registerDashboardWidget('reviews', {
+            // omitted for brevity
+        }),
+        // highlight-start
+        setDashboardWidgetLayout([
+            {id: 'welcome', width: 12},
+            {id: 'orderSummary', width: 4},
+            {id: 'latestOrders', width: 8},
+            {id: 'reviews', width: 6},
+        ]),
+        // highlight-end
+    ],
 })
 export class MySharedUiExtensionModule {}
 ```
@@ -148,21 +153,23 @@ Sometimes you may wish to alter the permissions settings of the default widgets
 For example, the "order summary" widget has a default permission requirement of "ReadOrder". If you want to limit the availability to e.g. the SuperAdmin role, you can do so
 by overriding the definition like this:
 
-```ts
+```ts title="src/plugins/reviews/ui/shared-ui-extension.module.ts"
 import { NgModule } from '@angular/core';
 import { registerDashboardWidget } from '@vendure/admin-ui/core';
 import { OrderSummaryWidgetComponent } from '@vendure/admin-ui/dashboard';
 
 @NgModule({
-  imports: [],
-  declarations: [],
-  providers: [
-    registerDashboardWidget('orderSummary', {
-      title: 'dashboard.orders-summary',
-      loadComponent: () => OrderSummaryWidgetComponent,
-      requiresPermissions: ['SuperAdmin'],
-    }),
-  ],
+    imports: [],
+    declarations: [],
+    providers: [
+        // highlight-start
+        registerDashboardWidget('orderSummary', {
+            title: 'dashboard.orders-summary',
+            loadComponent: () => OrderSummaryWidgetComponent,
+            requiresPermissions: ['SuperAdmin'],
+        }),
+        // highlight-end
+    ],
 })
 export class MySharedUiExtensionModule {}
 ```

+ 2 - 2
docs/docs/guides/extending-the-admin-ui/extending-the-admin-ui.md → docs/docs/guides/extending-the-admin-ui/introduction.md

@@ -1,8 +1,8 @@
 ---
-title: 'Extending the Admin UI'
+title: 'Introduction'
 ---
 
-# Extending the Admin UI
+# Extending the Admin UI: Introduction
 
 When creating a plugin, you may wish to extend the Admin UI in order to expose a graphical interface to the plugin's functionality.
 

+ 64 - 48
docs/docs/guides/extending-the-admin-ui/modifying-navigation-items/index.md

@@ -7,54 +7,70 @@ weight: 5
 
 ## Extending the NavMenu
 
-Once you have defined some custom routes in a lazy extension module, you need some way for the administrator to access them. For this you will use the [addNavMenuItem]({{< relref "add-nav-menu-item" >}}) and [addNavMenuSection]({{< relref "add-nav-menu-item" >}}) functions.
+Once you have defined some custom routes in a lazy extension module, you need some way for the administrator to access them. For this you will use the [addNavMenuItem](/reference/admin-ui-api/nav-menu/add-nav-menu-item/) and [addNavMenuSection](/reference/admin-ui-api/nav-menu/add-nav-menu-section) functions.
 
-Let's add a new section to the Admin UI main nav bar containing a link to the "greeter" module from the [Using Angular]({{< relref "../using-angular" >}}) example:
+Let's add a new section to the Admin UI main nav bar containing a link to the "greeter" module from the [Using Angular](/guides/extending-the-admin-ui/using-angular/) example:
 
-```ts
-// project/ui-extensions/greeter-shared.module.ts
+```ts title="src/plugins/greeter/ui/greeter-shared.module.ts"
 import { NgModule } from '@angular/core';
 import { SharedModule, addNavMenuSection } from '@vendure/admin-ui/core';
 
 @NgModule({
-  imports: [SharedModule],
-  providers: [
-    addNavMenuSection({
-      id: 'greeter',
-      label: 'My Extensions',
-      items: [{
-        id: 'greeter',
-        label: 'Greeter',
-        routerLink: ['/extensions/greet'],
-        // Icon can be any of https://clarity.design/icons
-        icon: 'cursor-hand-open',
-      }],
-    },
-    // Add this section before the "settings" section
-    'settings'),
-  ]
+    imports: [SharedModule],
+    providers: [
+        addNavMenuSection({
+                id: 'greeter',
+                label: 'My Extensions',
+                items: [{
+                    id: 'greeter',
+                    label: 'Greeter',
+                    routerLink: ['/extensions/greet'],
+                    // Icon can be any of https://clarity.design/icons
+                    icon: 'cursor-hand-open',
+                }],
+            },
+            // Add this section before the "settings" section
+            'settings'),
+    ]
 })
 export class GreeterSharedModule {}
 ```
 
 Now we must also register this new module with the compiler:
 
-```ts
-// project/vendure-config.ts
-
-ngModules: [
-  {
-    type: 'lazy',
-    route: 'greet',
-    ngModuleFileName: 'greeter.module.ts',
-    ngModuleName: 'GreeterModule',
-  },
-  {
-    type: 'shared',
-    ngModuleFileName: 'greeter-shared.module.ts',
-    ngModuleName: 'GreeterSharedModule',
-  }
-],
+```ts title="src/vendure-config.ts"
+import path from 'path';
+import { VendureConfig } from '@vendure/core';
+import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
+import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
+
+export const config: VendureConfig = {
+    // ...
+    plugins: [
+        AdminUiPlugin.init({
+            port: 3002,
+            app: compileUiExtensions({
+                outputPath: path.join(__dirname, '../admin-ui'),
+                extensions: [{
+                    extensionPath: path.join(__dirname, 'plugins/greeter/ui'),
+                    ngModules: [
+                        {
+                            type: 'lazy',
+                            route: 'greet',
+                            ngModuleFileName: 'greeter.module.ts',
+                            ngModuleName: 'GreeterModule',
+                        },
+                        {
+                            type: 'shared',
+                            ngModuleFileName: 'greeter-shared.module.ts',
+                            ngModuleName: 'GreeterSharedModule',
+                        }
+                    ],
+                }],
+            }),
+        }),
+    ],
+};
 ```
 
 Running the server will compile our new shared module into the app, and the result should look like this:
@@ -69,25 +85,25 @@ This is done by setting the `id` property to that of an existing nav menu sectio
 
 ## Adding page tabs
 
-You can add your own tabs to any of the Admin UI's list or detail pages using the [registerPageTab]({{< relref "register-page-tab" >}}) function. For example, to add a new tab to the product detail page for displaying product reviews:
+You can add your own tabs to any of the Admin UI's list or detail pages using the [registerPageTab](/reference/admin-ui-api/tabs/register-page-tab/) function. For example, to add a new tab to the product detail page for displaying product reviews:
 
-```ts
+```ts title="src/plugins/reviews/ui/shared-ui-extension.module.ts"
 import { NgModule } from '@angular/core';
 import { SharedModule, registerPageTab } from '@vendure/admin-ui/core';
 
 import { ReviewListComponent } from './components/review-list/review-list.component';
 
 @NgModule({
-  imports: [SharedModule],
-  providers: [
-    registerPageTab({
-      location: 'product-detail',
-      tab: 'Reviews',
-      route: 'reviews',
-      tabIcon: 'star',
-      component: ReviewListComponent,
-    }),
-  ]
+    imports: [SharedModule],
+    providers: [
+        registerPageTab({
+            location: 'product-detail',
+            tab: 'Reviews',
+            route: 'reviews',
+            tabIcon: 'star',
+            component: ReviewListComponent,
+        }),
+    ]
 })
 export class ReviewsSharedModule {}
 ```

+ 43 - 55
docs/docs/guides/extending-the-admin-ui/using-angular/index.md

@@ -7,9 +7,9 @@ weight: 0
 
 Writing your UI extensions with Angular results in the best-optimized and most seamless UI extensions, since you can re-use shared components exported by the `@vendure/admin-ui/core` library, and the Angular framework itself is already present in the app.
 
-{{< alert warning >}}
-**Note:** an understanding of [Angular](https://angular.io/) is necessary for successfully working with Angular-based UI extensions. Try [Angular's "Getting Started" guide](https://angular.io/start) to learn more.
-{{< /alert >}}
+:::note
+An understanding of [Angular](https://angular.io/) is necessary for successfully working with Angular-based UI extensions. Try [Angular's "Getting Started" guide](https://angular.io/start) to learn more.
+:::
 
 ## 1. Install `@vendure/ui-devkit`
 
@@ -27,16 +27,15 @@ npm install @vendure/ui-devkit
 
 Here's a very simple Angular component which displays a greeting:
 
-```ts
-// project/ui-extensions/greeter.component.ts
+```ts title="src/plugins/greeter/ui/components/greeter/greeter.component.ts"
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'greeter',
-  template: `<vdr-page-block><h1>{{ greeting }}</h1></vdr-page-block>`,
+    selector: 'greeter',
+    template: `<vdr-page-block><h1>{{ greeting }}</h1></vdr-page-block>`,
 })
 export class GreeterComponent {
-  greeting = 'Hello!';
+    greeting = 'Hello!';
 }
 ```
 
@@ -46,64 +45,62 @@ The `<vdr-page-block>` is just a wrapper that sets the layout and max width of y
 
 Next we need to declare an Angular module to house the component:
 
-```ts
-// project/ui-extensions/greeter.module.ts
+```ts title="src/plugins/greeter/ui/greeter.module.ts"
 import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
 import { SharedModule } from '@vendure/admin-ui/core';
 import { GreeterComponent } from './greeter.component';
 
 @NgModule({
-  imports: [
-    SharedModule,
-    RouterModule.forChild([{
-      path: '',
-      pathMatch: 'full',
-      component: GreeterComponent,
-      data: { breadcrumb: 'Greeter' },
-    }]),
-  ],
-  declarations: [GreeterComponent],
+    imports: [
+        SharedModule,
+        RouterModule.forChild([{
+            path: '',
+            pathMatch: 'full',
+            component: GreeterComponent,
+            data: {breadcrumb: 'Greeter'},
+        }]),
+    ],
+    declarations: [GreeterComponent],
 })
 export class GreeterModule {}
 ```
 
-{{< alert "primary" >}}
-**Note:** The `SharedModule` should, in general, always be imported by your extension modules. It provides the basic Angular
+:::note
+The `SharedModule` should, in general, always be imported by your extension modules. It provides the basic Angular
 directives and other common functionality that any extension would require.
-{{< /alert >}}
+:::
 
 ## 4. Pass the extension to the `compileUiExtensions` function
 
 Now we need to tell the `compileUiExtensions` function where to find the extension, and which file contains the NgModule itself (since a non-trivial UI extension will likely contain multiple files).
 
-```ts
-// project/vendure-config.ts
+```ts title="src/vendure-config.ts"
 import path from 'path';
 import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
 import { VendureConfig } from '@vendure/core';
 import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
 
 export const config: VendureConfig = {
-  // ...
-  plugins: [
-    AdminUiPlugin.init({
-      port: 5001,
-      app: compileUiExtensions({
-        outputPath: path.join(__dirname, '../admin-ui'),
-        extensions: [{
-          extensionPath: path.join(__dirname, 'ui-extensions'),
-          ngModules: [{
-            type: 'lazy',
-            route: 'greet',
-            ngModuleFileName: 'greeter.module.ts',
-            ngModuleName: 'GreeterModule',
-          }],
-        }],
-      }),
-    }),
-  ],
-}
+    // ...
+    plugins: [
+        AdminUiPlugin.init({
+            port: 5001,
+            app: compileUiExtensions({
+                outputPath: path.join(__dirname, '../admin-ui'),
+                extensions: [{
+                    extensionPath: path.join(__dirname, 'ui-extensions'),
+                    ngModules: [{
+                        type: 'lazy',
+                        route: 'greet',
+                        ngModuleFileName: 'greeter.module.ts',
+                        ngModuleName: 'GreeterModule',
+                    }],
+                }],
+            }),
+        }),
+    ],
+};
 ```
 
 ## 5. Start the server to compile
@@ -112,15 +109,11 @@ The `compileUiExtensions()` function returns a `compile()` function which will b
 
 Next, these source files will be run through the Angular compiler, the output of which will be visible in the console.
 
-{{< alert "warning" >}}
-**Note:** The first time the compiler is run, an additional step ([compatibility compiler](https://angular.io/guide/ivy#ivy-and-libraries)) is run to make sure all dependencies work with the latest version of Angular. This step can take up to a few minutes.
-{{< /alert >}}
-
 Now go to the Admin UI app in your browser and log in. You should now be able to manually enter the URL `http://localhost:3000/admin/extensions/greet` and you should see the component with the "Hello!" header:
 
 ![./ui-extensions-greeter.webp](./ui-extensions-greeter.webp)
 
-{{< alert warning >}}
+:::caution
 **Note:** the TypeScript source files of your UI extensions **must not** be compiled by your regular TypeScript build task. This is because they will instead be compiled by the Angular compiler when you run `compileUiExtensions()`. You can exclude them in your main `tsconfig.json` by adding a line to the "exclude" array:
 ```json
 {
@@ -129,9 +122,4 @@ Now go to the Admin UI app in your browser and log in. You should now be able to
   ]
 }
 ```
-{{< /alert >}}
-
-
-## Next Steps
-
-Now you have created your new route, you need a way for your admin to access it. See [Adding Navigation Items]({{< relref "../modifying-navigation-items" >}})
+:::

+ 70 - 73
docs/docs/guides/extending-the-admin-ui/using-other-frameworks/index.md

@@ -7,9 +7,9 @@ weight: 1
 
 Although the Admin UI is an Angular app, it is possible to create UI extensions using any web technology - React, Vue, plain JavaScript, etc.
 
-{{< alert "primary" >}}
+:::info
 For working examples of a UI extensions built with **Vue** and **React**, see the [real-world-vendure ui extensions](https://github.com/vendure-ecommerce/real-world-vendure/tree/master/src/ui-extensions)
-{{< /alert >}}
+:::
 
 There is still a small amount of Angular "glue code" needed to let the compiler know how to integrate your extension, so let's take a look at how this is done.
 
@@ -42,93 +42,90 @@ In this example, we will work with the following folder structure, and use Creat
 
 Here's the Angular code needed to tell the compiler where to find your extension:
 
-```ts
-// ui-extension/modules/react-extension.module.ts
-
+```ts title="src/ui-extension/modules/react-extension.module.ts"
 import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
 import { hostExternalFrame } from '@vendure/admin-ui/core';
 
 @NgModule({
-  imports: [
-    RouterModule.forChild([
-      hostExternalFrame({
-        path: '',
-
-        // You can also use parameters which allow the app
-        // to have dynamic routing, e.g.
-        // path: ':slug'
-        // Then you can use the getActivatedRoute() function from the
-        // UiDevkitClient in order to access the value of the "slug"
-        // parameter.
-
-        breadcrumbLabel: 'React App',
-        // This is the URL to the compiled React app index.
-        // The next step will explain the "assets/react-app" path.
-        extensionUrl: './assets/react-app/index.html',
-        openInNewTab: false,
-      }),
-    ]),
-  ],
+    imports: [
+        RouterModule.forChild([
+            hostExternalFrame({
+                path: '',
+
+                // You can also use parameters which allow the app
+                // to have dynamic routing, e.g.
+                // path: ':slug'
+                // Then you can use the getActivatedRoute() function from the
+                // UiDevkitClient in order to access the value of the "slug"
+                // parameter.
+
+                breadcrumbLabel: 'React App',
+                // This is the URL to the compiled React app index.
+                // The next step will explain the "assets/react-app" path.
+                extensionUrl: './assets/react-app/index.html',
+                openInNewTab: false,
+            }),
+        ]),
+    ],
 })
 export class ReactUiExtensionModule {}
 ```
 
-{{< alert "primary" >}}
-Note: If you are using **Create React App**, you should additionally update your package.json file to include the [homepage property](https://create-react-app.dev/docs/deployment/#building-for-relative-paths) so that it works when run from the admin ui assets directory:
+:::note
+If you are using **Create React App**, you should additionally update your package.json file to include the [homepage property](https://create-react-app.dev/docs/deployment/#building-for-relative-paths) so that it works when run from the admin ui assets directory:
 `"homepage": "/admin/assets/react-app/"`
-{{< /alert >}}
+:::
 
 ## 4. Define the AdminUiExtension config
 
-Next we will define an [AdminUiExtension]({{< relref "admin-ui-extension" >}}) object which is passed to the `compileUiExtensions()` function in your Vendure config:
+Next we will define an [AdminUiExtension](/reference/admin-ui-api/ui-devkit/admin-ui-extension/) object which is passed to the `compileUiExtensions()` function in your Vendure config:
 
-```ts
-// vendure-config.ts
+```ts title="src/vendure-config.ts"
 import path from 'path';
 import { VendureConfig } from '@vendure/core';
 import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
 import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
 
 export const config: VendureConfig = {
-  // ...
-  plugins: [
-    AdminUiPlugin.init({
-      route: "admin",
-      port: 3002,
-      app: compileUiExtensions({
-        outputPath: path.join(__dirname, '../admin-ui'),
-        extensions: [{
-          // Points to the path containing our Angular "glue code" module
-          extensionPath: path.join(__dirname, 'ui-extension/modules'),
-          ngModules: [
-            {
-              // We want to lazy-load our extension...
-              type: 'lazy',
-              // ...when the `/admin/extensions/react-ui`
-              // route is activated
-              route: 'react-ui',
-              // The filename of the extension module
-              // relative to the `extensionPath` above
-              ngModuleFileName: 'react-extension.module.ts',
-              // The name of the extension module class exported
-              // from the module file.
-              ngModuleName: 'ReactUiExtensionModule',
-            },
-          ],
-          staticAssets: [
-            // This is where we tell the compiler to copy the compiled React app
-            // artifacts over to the Admin UI's `/static` directory. In this case we
-            // also rename "build" to "react-app". This is why the `extensionUrl`
-            // in the module config points to './assets/react-app/index.html'.
-            { path: path.join(__dirname, 'ui-extension/react-app/build'), rename: 'react-app' },
-          ],
-        }],
-        devMode: true,
-      }),
-    }),
-  ]
-}
+    // ...
+    plugins: [
+        AdminUiPlugin.init({
+            route: 'admin',
+            port: 3002,
+            app: compileUiExtensions({
+                outputPath: path.join(__dirname, '../admin-ui'),
+                extensions: [{
+                    // Points to the path containing our Angular "glue code" module
+                    extensionPath: path.join(__dirname, 'ui-extension/modules'),
+                    ngModules: [
+                        {
+                            // We want to lazy-load our extension...
+                            type: 'lazy',
+                            // ...when the `/admin/extensions/react-ui`
+                            // route is activated
+                            route: 'react-ui',
+                            // The filename of the extension module
+                            // relative to the `extensionPath` above
+                            ngModuleFileName: 'react-extension.module.ts',
+                            // The name of the extension module class exported
+                            // from the module file.
+                            ngModuleName: 'ReactUiExtensionModule',
+                        },
+                    ],
+                    staticAssets: [
+                        // This is where we tell the compiler to copy the compiled React app
+                        // artifacts over to the Admin UI's `/static` directory. In this case we
+                        // also rename "build" to "react-app". This is why the `extensionUrl`
+                        // in the module config points to './assets/react-app/index.html'.
+                        {path: path.join(__dirname, 'ui-extension/react-app/build'), rename: 'react-app'},
+                    ],
+                }],
+                devMode: true,
+            }),
+        }),
+    ]
+};
 ```
 
 ## 5. Build your extension
@@ -172,14 +169,14 @@ If your extension does not have a build step, you can still include the theme st
 
 ### UiDevkitClient
 
-The `@vendure/ui-devkit` package provides a number of helper methods which allow your extension to seamlessly interact with the underlying Admin UI infrastructure, collectively known as the [UiDevkitClient]({{< relref "ui-devkit-client" >}}). The client allows your extension to:
+The `@vendure/ui-devkit` package provides a number of helper methods which allow your extension to seamlessly interact with the underlying Admin UI infrastructure, collectively known as the [UiDevkitClient](/reference/admin-ui-api/ui-devkit/ui-devkit-client/). The client allows your extension to:
 
 * Make GraphQL queries & mutations, without the need for your own HTTP or GraphQL client, with full integration with the Admin UI client-side GraphQL cache.
 * Display toast notifications.
 
 #### setTargetOrigin
 
-The UiDevkitClient uses the browser's [postMessage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) to communicate between the Admin UI app and your extension. For security reasons this communication channel is restricted to a specific domain (where your extension app will be running from). To configure this, use the [setTargetOrigin]({{< relref "ui-devkit-client" >}}#settargetorigin) function:
+The UiDevkitClient uses the browser's [postMessage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) to communicate between the Admin UI app and your extension. For security reasons this communication channel is restricted to a specific domain (where your extension app will be running from). To configure this, use the [setTargetOrigin](/reference/admin-ui-api/ui-devkit/ui-devkit-client/#settargetorigin) function:
 
 ```ts
 import { setTargetOrigin } from '@vendure/ui-devkit';
@@ -213,7 +210,7 @@ const disableProduct = (id: string) => {
 
 If your extension does not have a build step, you can still include the UiDevkitClient as a local resource, which will expose a `VendureUiClient` global object:
 
-```HTML
+```html
 <!-- src/ui-extension/plain-js-app/index.html -->
 <head>
   <script src="../devkit/ui-devkit.js"></script>
@@ -237,4 +234,4 @@ If your extension does not have a build step, you can still include the UiDevkit
 
 ## Next Steps
 
-Now you have created your extension, you need a way for your admin to access it. See [Adding Navigation Items]({{< relref "../modifying-navigation-items" >}})
+Now you have created your extension, you need a way for your admin to access it. See [Adding Navigation Items](/guides/extending-the-admin-ui/modifying-navigation-items/)

+ 15 - 1
docs/sidebars.js

@@ -86,10 +86,24 @@ const sidebars = {
         {
             type: 'category',
             label: 'Extending the Admin UI',
-            items: [{ type: 'autogenerated', dirName: 'guides/extending-the-admin-ui' }],
             customProps: {
                 icon: icon.computer,
             },
+            items: [
+                'guides/extending-the-admin-ui/introduction',
+                'guides/extending-the-admin-ui/using-angular/index',
+                'guides/extending-the-admin-ui/using-other-frameworks/index',
+                'guides/extending-the-admin-ui/add-actions-to-pages/index',
+                'guides/extending-the-admin-ui/adding-ui-translations/index',
+                'guides/extending-the-admin-ui/admin-ui-theming-branding/index',
+                'guides/extending-the-admin-ui/creating-detail-views/index',
+                'guides/extending-the-admin-ui/creating-list-views/index',
+                'guides/extending-the-admin-ui/custom-detail-components/index',
+                'guides/extending-the-admin-ui/custom-form-inputs/index',
+                'guides/extending-the-admin-ui/custom-timeline-components/index',
+                'guides/extending-the-admin-ui/dashboard-widgets/index',
+                'guides/extending-the-admin-ui/modifying-navigation-items/index',
+            ],
         },
         {
             type: 'category',