Skip to content

Commit

Permalink
docs: Improve ui extensions docs to better align with CLI use
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Sep 17, 2024
1 parent 52d5892 commit a126cc0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 42 deletions.
94 changes: 62 additions & 32 deletions docs/docs/guides/extending-the-admin-ui/defining-routes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,38 @@ Routes can be defined natively using either **Angular** or **React**. It is also

## Example: Creating a "Greeter" route

### 1. Create the route component
### 1. Create a plugin

We will first quickly scaffold a new plugin to house our UI extensions:

- Run `npx vendure add` from your project root
- Select `Create a new Vendure plugin` and when prompted for a name, name it **"greeter"**
- After the plugin is created, you will be prompted to add features to the plugin. Select `[Plugin: UI] Set up Admin UI extensions`

You should now have a new plugin scaffolded at `./src/plugins/greeter`, with some empty UI extension files in the `ui`
directory. If you check your `vendure-config.ts` file you should also see that your `AdminUiPlugin.init()` call has been modified
to compile the UI extensions:

```ts
AdminUiPlugin.init({
route: 'admin',
port: serverPort + 2,
adminUiConfig: {
apiPort: serverPort,
},
// highlight-start
app: compileUiExtensions({
outputPath: path.join(__dirname, '../admin-ui'),
extensions: [
GreeterPlugin.ui,
],
devMode: true,
}),
// highlight-end
}),
```

### 2. Create the route component

First we need to create the component which will be mounted at the route. This component can be either an Angular component or a React component.

Expand Down Expand Up @@ -42,7 +73,7 @@ export class GreeterComponent {
</TabItem>
<TabItem value="React" label="React">

```ts title="src/plugins/greeter/ui/components/Greeter.tsx"
```ts title="src/plugins/greeter/ui/components/greeter/Greeter.tsx"
import React from 'react';

export function Greeter() {
Expand All @@ -63,7 +94,7 @@ The `<vdr-page-block>` (Angular) and `<div className="page-block">` (React) is a
:::


### 2. Define the route
### 3. Define the route

Next we need to define a route in our `routes.ts` file. Note that this file can have any name, but "routes.ts" is a convention.

Expand Down Expand Up @@ -110,39 +141,34 @@ export default [

The `path: ''` is actually optional, since `''` is the default value. But this is included here to show that you can mount different components at different paths. See the section on route parameters below.

### 3. Add the route to the extension config
### 4. Add the route to the extension config

Now we need to add this routes file to our extension definition:
Since you have used the CLI to scaffold your plugin, this part has already been done for you. But for the sake of completeness
this is the part of your plugin which is configured to point to your routes file:

```ts title="src/vendure-config.ts"
import { VendureConfig } from '@vendure/core';
import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
import * as path from 'path';
```ts title="src/plugins/greeter/greeter.plugin.ts"
// ...
export class GreeterPlugin {
static options: PluginInitOptions;

static init(options: PluginInitOptions): Type<GreeterPlugin> {
this.options = options;
return GreeterPlugin;
}

// highlight-start
static ui: AdminUiExtension = {
id: 'greeter-ui',
extensionPath: path.join(__dirname, 'ui'),
routes: [{ route: 'greeter', filePath: 'routes.ts' }],
providers: ['providers.ts'],
};
// highlight-end
}

export const config: VendureConfig = {
// ...
plugins: [
AdminUiPlugin.init({
port: 3002,
app: compileUiExtensions({
outputPath: path.join(__dirname, '../admin-ui'),
extensions: [
{
id: 'greeter',
extensionPath: path.join(__dirname, 'plugins/greeter/ui'),
// highlight-start
routes: [{ route: 'greet', filePath: 'routes.ts' }],
// highlight-end
},
],
}),
}),
],
};
```

Note that by specifying `route: 'greet'`, we are "mounting" the routes at the `/extensions/greet` path.
Note that by specifying `route: 'greeter'`, we are "mounting" the routes at the `/extensions/greeter` path.

:::info

Expand All @@ -154,7 +180,11 @@ more information.

The `filePath` property is relative to the directory specified in the `extensionPath` property. In this case, the `routes.ts` file is located at `src/plugins/greeter/ui/routes.ts`.

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:
### 5. Test it out

Now run your app with `npm run dev`. Wait for it to compile the Admin UI extensions.

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/greeter` and you should see the component with the "Hello!" header:

![./ui-extensions-greeter.webp](./ui-extensions-greeter.webp)

Expand Down
56 changes: 46 additions & 10 deletions docs/docs/guides/extending-the-admin-ui/getting-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@ UI extensions fall into two categories:
:::cli
Use `npx vendure add` and select "Set up Admin UI extensions".

If you don't already have any plugins in your project, first create a plugin to house your
UI extensions. Then select:

```sh
[Plugin: UI] Set up Admin UI extensions
```

Then follow the prompts, which will guide you through the process of
setting up the necessary files and folders for your UI extensions.
:::

### Manual setup

It is recommended to use the `vendure add` command as described above, but if you prefer to set up the
Admin UI extensions manually, follow these steps:
Admin UI extensions manually, or just want to get a better understanding of what the CLI is doing, follow these steps:

First, install the [`@vendure/ui-devkit` package](https://www.npmjs.com/package/@vendure/ui-devkit) as a dev dependency:

Expand Down Expand Up @@ -99,14 +106,40 @@ export default [
];
```

Now we can configure the paths to your UI extension files. By convention, we will add this config object as a
static property on your plugin class:

```ts title="src/plugins/my-plugin/my.plugin.ts"
import * as path from 'path';
import { PluginCommonModule, Type, VendurePlugin } from '@vendure/core';
// highlight-next-line
import { AdminUiExtension } from '@vendure/ui-devkit/compiler';

@VendurePlugin({
imports: [PluginCommonModule],
compatibility: '^3.0.0',
})
export class MyPlugin {

// highlight-start
static ui: AdminUiExtension = {
id: 'my-plugin-ui',
extensionPath: path.join(__dirname, 'ui'),
routes: [{ route: 'my-plugin', filePath: 'routes.ts' }],
providers: ['providers.ts'],
};
// highlight-end
}
```

You can then use the [`compileUiExtensions` function](/reference/admin-ui-api/ui-devkit/compile-ui-extensions/) to compile your UI extensions and add them to the Admin UI app bundle.

```ts title="src/vendure-config.ts"
import { VendureConfig } from '@vendure/core';
import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
// highlight-next-line
import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
import * as path from 'path';
import { MyPlugin } from './plugins/greeter/my.plugin'

export const config: VendureConfig = {
// ...
Expand All @@ -117,11 +150,7 @@ export const config: VendureConfig = {
app: compileUiExtensions({
outputPath: path.join(__dirname, '../admin-ui'),
extensions: [
{
id: 'test-extension',
extensionPath: path.join(__dirname, 'plugins/my-plugin/ui'),
providers: ['providers.ts'],
},
MyPlugin.ui,
],
devMode: true,
}),
Expand All @@ -134,15 +163,18 @@ export const config: VendureConfig = {
};
```

Everything above will be automatically done for you when you use the CLI.

Now when you start the server, the following will happen:

1. A new folder called `admin-ui` will be created in the root of your project (as specified by the `outputPath` option). This is a temporary directory (it should not be added to version control) which will contain the source files of your custom Admin UI app.
2. During bootstrap, the `compileUiExtensions` function will be called, which will compile the Admin UI app and serve it in development mode. The dev server will be listening on port `4200` but this port will also be proxied to port `3000` (as specified by `apiOptions.port`). This step can take up to a minute or two, depending on the speed of your machine.

:::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()`.
**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:
You can exclude them in your main `tsconfig.json` by adding a line to the "exclude" array (this is already defined on a default Vendure project):

```json title="tsconfig.json"
{
Expand Down Expand Up @@ -196,7 +228,8 @@ export default [

### Specifying providers

When defining UI extensions in the `compileUiExtensions()` function, you must specify at least one providers file. This is done by passing an array of file paths, where each file path is relative to the directory specified by the `extensionPath` option.
When defining UI extensions in the `compileUiExtensions()` function, you must specify at least one providers file.
This is done by passing an array of file paths, where each file path is relative to the directory specified by the `extensionPath` option.

```ts title="src/vendure-config.ts"
import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
Expand All @@ -207,6 +240,9 @@ import * as path from 'path';
compileUiExtensions({
outputPath: path.join(__dirname, '../admin-ui'),
extensions: [
// Note: this object will usually be
// found in the `ui` static property
// of a plugin like `MyPlugin.ui`.
{
id: 'test-extension',
extensionPath: path.join(__dirname, 'plugins/my-plugin/ui'),
Expand Down

0 comments on commit a126cc0

Please sign in to comment.