Skip to content

Commit

Permalink
Website: Introduce Snippets for FE Package Managers (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackw authored May 3, 2023
1 parent 75bcdff commit c44aa7a
Show file tree
Hide file tree
Showing 31 changed files with 229 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ title: Creating a Plugin

To create a new Grafana plugin run the following command in your shell:

```shell
npx @grafana/create-plugin@latest
```
<CodeSnippets
paths={[
'createplugin-scaffold.npm.shell.md',
'createplugin-scaffold.pnpm.shell.md',
'createplugin-scaffold.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

:::info
The answers to the name, organization and type of plugin prompts are combined to create the plugin directory name and the plugin id.
Expand All @@ -25,7 +31,6 @@ In the above example, this will cause the directory and plugin ID to be named `g

When running the create command, the following prompts appear asking for confirmation before making changes:


### What is the name of your plugin?

The name of your plugin. This helps to identify its purpose.
Expand Down
2 changes: 1 addition & 1 deletion docusaurus/docs/distributing-your-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To distribute a Grafana plugin either to the community or privately, the plugin

:::info

It's not necessary to sign a plugin during development. The [docker development environment](./docker.md) that is scaffolded with `@grafana/create-plugin` will load the plugin without a signature.
It's not necessary to sign a plugin during development. The [docker development environment](./docker.mdx) that is scaffolded with `@grafana/create-plugin` will load the plugin without a signature.

:::

Expand Down
21 changes: 14 additions & 7 deletions docusaurus/docs/docker.md → docusaurus/docs/docker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,26 @@ The Docker container is configured with the necessary variables to allow easy ac

To get started run the following commands in the order listed:

- `yarn install`: Install frontend dependencies.
- `yarn dev`: Build and watch the plugin frontend code.
- <SyncCommand cmd="install" />: Install frontend dependencies.
- <SyncCommand cmd="run dev" />: Build and watch the plugin frontend code.
- `mage -v build:linux`: Build the plugin backend code. This command must be rerun every time you edit your backend files.
- `yarn server`: Start a grafana development server running on [http://localhost:3000](http://localhost:3000). Restart this command each time you run `mage` to run your new backend code.

- <SyncCommand cmd="run server" />: Start a grafana development server running on
[http://localhost:3000](http://localhost:3000). Restart this command each time you run `mage` to run your new backend
code.

### Configure the Grafana version

You can use the environment variable `GRAFANA_VERSION` to set the Grafana version whilst developing the plugin. This is useful for testing a plugin across different versions of Grafana.

```shell
GRAFANA_VERSION=8.5.5 yarn server
```
<CodeSnippets
paths={[
'docker-grafana-version.npm.shell.md',
'docker-grafana-version.pnpm.shell.md',
'docker-grafana-version.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

### Configure the Grafana image

Expand Down
14 changes: 8 additions & 6 deletions docusaurus/docs/frontend.md → docusaurus/docs/frontend.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@ title: Frontend

The frontend part of a Grafana plugin is written in Typescript with React as the view library. Within the plugin directory, you can run:

### `yarn dev`

### <SyncCommand cmd="run dev" />

Builds the plugin in development mode and watches for changes to source code to rebuild the plugin.

### `yarn build`
### <SyncCommand cmd="run build" />


Builds the plugin for production. The output can be found in the `./dist` directory.
### <SyncCommand cmd="run test" />

### `yarn test`

Launches the test runner in watch mode.
### <SyncCommand cmd="run e2e" />

### `yarn e2e`

Launches the e2e test runner. (Make sure to have an instance of Grafana running before running e2e tests.)
### <SyncCommand cmd="run lint" />

### `yarn lint`

Run the linter against source code to verify formatting and styling rules are adherred to.
### <SyncCommand cmd="run lint:fix" />

### `yarn lint:fix`

Run the linter in fix mode to automatically format the frontend code.
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ Plugin tools consists of two packages:

## Quick Start

```shell
npx @grafana/create-plugin@latest
```

Follow the prompts to scaffold a Grafana plugin. [See here](./creating-a-plugin.md) for detailed information about creating a plugin.
<CodeSnippets
paths={[
'createplugin-scaffold.npm.shell.md',
'createplugin-scaffold.pnpm.shell.md',
'createplugin-scaffold.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

Follow the prompts to scaffold a Grafana plugin. [See here](./creating-a-plugin.mdx) for detailed information about creating a plugin.

:::note

Expand All @@ -30,9 +36,12 @@ Plugins previously scaffolded with `@grafana/toolkit` can be migrated. Please se
- [Mage](https://magefile.org/)
- [Node.js](https://nodejs.org/en/download/) version 16 or above:
- When installing Node.js, you are recommended to check all checkboxes related to dependencies.
- [Yarn 1](https://classic.yarnpkg.com/lang/en/docs/install)
- Optionally [Yarn 1](https://classic.yarnpkg.com/lang/en/docs/install) or [PNPM](https://pnpm.io/installation)
- [Docker](https://docs.docker.com/get-docker/)

### Choosing a package manager
Starting from v1.3 of Create Plugin when you create a new plugin, the CLI will use `npm`, `pnpm` or `yarn` depending on which tool you use to run `@grafana/create-plugin`.

## Output

Running the above command will create a directory called `<orgName>-<pluginName>-<pluginType>` inside the current directory. Within this new directory is the initial project structure to kickstart development.
Expand Down Expand Up @@ -83,27 +92,32 @@ Depending on the answers given to the prompts there should be a structure like:

Once the installation is done you can open the plugin folder:

```shell
cd <orgName>-<pluginName>-<pluginType>
yarn install
```
<CodeSnippets
paths={[
'createplugin-install.npm.shell.md',
'createplugin-install.pnpm.shell.md',
'createplugin-install.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

## Scripts

Inside the newly create plugin, you can run some built-in commands:

### `yarn dev`
### <SyncCommand cmd="run dev" />

Builds plugin in development mode and runs in watch mode. The plugin will be rebuilt whenever you make changes to the code. You will see build errors and lint warnings in the console.

### `yarn test`
### <SyncCommand cmd="run test" />

Runs the tests and watches for changes

### `yarn build`
### <SyncCommand cmd="run build" />

Creates a production build of the plugin optimizing for the best performance. The build is minified and the filenames include hashes.

### `mage -v`
<h3><code>mage -v</code></h3>

Build backend plugin binaries for Linux, Windows and Darwin.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ We [do not support](https://grafana.com/docs/grafana/latest/developers/angular_d

- **More flexible:** With @grafana/create-plugin, developers have more control over their plugins, its dependencies, and can more easily customize the tooling to fit their specific needs.
- **Faster development time:** With its out-of-the-box development environment @grafana/create-plugin can significantly reduce development time compared to using @grafana/toolkit.
- **Improved testing capabilities:** Testing plugins with @grafana/create-plugin is much easier with github workflows that automate unit and e2e test runs whenever changes are pushed to github.
- **Improved testing capabilities:** Testing plugins with @grafana/create-plugin is much easier with github workflows that automate unit and e2e test runs whenever changes are pushed to github.
- **Better documentation:** The documentation for @grafana/create-plugin is more comprehensive and easier to discover than @grafana/toolkit.

:::warning
Expand All @@ -24,9 +24,15 @@ Before running the following command we strongly suggest backing up the code. Id

To get started, in the root directory of the existing plugin (where the `package.json` file is) run the following command and answer the prompts.

```
npx @grafana/create-plugin@latest migrate
```
<CodeSnippets
paths={[
'createplugin-migrate.npm.shell.md',
'createplugin-migrate.pnpm.shell.md',
'createplugin-migrate.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

## Prompts

Expand Down Expand Up @@ -89,7 +95,7 @@ This step will update any npm scripts in the `package.json` file to match the la

## Next steps

When the migration command finishes running, look at the changes introduced and then running `yarn install` followed by each of the npm scripts inside `package.json` to confirm the plugin can be built, tested, signed etc.
When the migration command finishes running, look at the changes introduced and then install frontend dependencies followed by running each of the npm scripts inside `package.json` to confirm the plugin can be built, tested, signed etc.

If the plugin had customizations to the toolkit configs (e.g. webpack) head over to the [advanced configuration guide](./advanced-configuration.md) to learn how to update them.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ title: Nested Plugins

Grafana app plugins can nest frontend datasource and panel plugins making it easy to ship a complete user experience. To take advantage of this feature first scaffold an app plugin using `@grafana/create-plugin`:

```bash
npx @grafana/create-plugin@latest
```
<CodeSnippets
paths={[
'createplugin-scaffold.npm.shell.md',
'createplugin-scaffold.pnpm.shell.md',
'createplugin-scaffold.yarn.shell.md',
]}
groupId="package-manager"
queryString="current-package-manager"
/>

When prompted `What type of plugin would you like?` select `app`.

Expand Down
2 changes: 2 additions & 0 deletions docusaurus/docs/snippets/createplugin-install.npm.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd <orgName>-<pluginName>-<pluginType>
npm install
2 changes: 2 additions & 0 deletions docusaurus/docs/snippets/createplugin-install.pnpm.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd <orgName>-<pluginName>-<pluginType>
pnpm install
2 changes: 2 additions & 0 deletions docusaurus/docs/snippets/createplugin-install.yarn.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd <orgName>-<pluginName>-<pluginType>
yarn install
1 change: 1 addition & 0 deletions docusaurus/docs/snippets/createplugin-migrate.npm.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx @grafana/create-plugin@latest migrate
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm dlx @grafana/create-plugin@latest migrate
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn create @grafana/plugin migrate
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx @grafana/create-plugin@latest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm dlx @grafana/create-plugin@latest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn create @grafana/plugin
1 change: 1 addition & 0 deletions docusaurus/docs/snippets/createplugin-update.npm.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx @grafana/create-plugin@latest update
1 change: 1 addition & 0 deletions docusaurus/docs/snippets/createplugin-update.pnpm.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm dlx @grafana/create-plugin@latest update
1 change: 1 addition & 0 deletions docusaurus/docs/snippets/createplugin-update.yarn.shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn create @grafana/plugin update
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GRAFANA_VERSION=8.5.5 npm run server
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GRAFANA_VERSION=8.5.5 pnpm run server
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GRAFANA_VERSION=8.5.5 yarn run server
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ title: Updating to New Releases

To update an existing plugin to use a newer version of `create-plugin` run the following update command:

```shell
npx @grafana/create-plugin@latest update
```
<CodeSnippets
paths={['createplugin-update.npm.shell.md', 'createplugin-update.pnpm.shell.md', 'createplugin-update.yarn.shell.md']}
groupId="package-manager"
queryString="current-package-manager"
/>

This command will rerun the original scaffolding commands against the configuration files, dependencies, and scripts, using the latest version of `create-plugin`. It will prompt to confirm any destructive operations are agreed to prior to being run.

Expand Down
3 changes: 2 additions & 1 deletion docusaurus/website/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const config = {
});
// clean up metadata, relref and remove heading
const cleanedContent = content
.replace(/\\\[(.+)\]\\(\({{.+}}\))/g, '$1')
.replace(/\\\[(.+?)\]\\(\({{.+?}}\))/g, '$1')
.replace(/## title: Sign a plugin\n\n# Sign a plugin/m, '')
.replace(/\*\*\*/, '');
return {
Expand Down Expand Up @@ -81,6 +81,7 @@ ${cleanedContent}
({
docs: {
path: '../docs',
exclude: ['**/snippets/**'],
sidebarPath: require.resolve('./sidebars.js'),
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
Expand Down
1 change: 1 addition & 0 deletions docusaurus/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"devDependencies": {
"@docusaurus/module-type-aliases": "2.4.0",
"@tsconfig/docusaurus": "^1.0.5",
"raw-loader": "^4.0.2",
"typescript": "^4.7.4"
},
"browserslist": {
Expand Down
68 changes: 68 additions & 0 deletions docusaurus/website/src/components/CodeSnippets/CodeSnippets.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { useEffect, useState } from 'react';
import CodeBlock from '@theme/CodeBlock';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

/*
CodeSnippets is a component that allows you to display code snippets from the docs/snippets folder.
It takes in an array of paths to the snippets you want to display, and will display them in a tabbed
interface. The paths should be relative to the docs/snippets folder, and should include the file extension.
Snippets should be named in the following format: <name>.<value>.<language>.<extension>
`value` is used for the tabs unique value and label.
language is used for syntax highlighting.
*/

function CodeSnippets({ paths, groupId, queryString }: { paths: string[]; groupId?: string; queryString?: string }) {
const snippetPaths = paths.map((path) => path.trim());
const [snippets, setSnippets] = useState([]);

useEffect(() => {
async function fetchSnippets() {
const fetchedSnippets = await Promise.all(
snippetPaths.map(async (path) => {
const [_, value, language] = path.split('.');
try {
const code = (await import(`!!raw-loader!@site/../docs/snippets/${path}`)).default;

return {
language,
value,
label: value.toUpperCase(),
code,
};
} catch (error) {
console.log(`CodeSnippets failed to load: docs/snippets/${path}`, error);
return null;
}
})
);
setSnippets(fetchedSnippets.filter((snippet) => snippet != null));
}

fetchSnippets();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

if (snippets.length === 0) {
return null;
}

if (snippets.length === 1) {
return <CodeBlock language={snippets[0].language}>{snippets[0].code}</CodeBlock>;
}

return (
// @ts-ignore - Tabs types appear to be broken.
<Tabs groupId={groupId} queryString={queryString}>
{snippets.map((snippet) => (
// @ts-ignore - TabItem types appear to be broken.
<TabItem key={snippet.value} value={snippet.value} label={snippet.label}>
<CodeBlock language={snippet.language}>{snippet.code}</CodeBlock>
</TabItem>
))}
</Tabs>
);
}

export default CodeSnippets;
Loading

0 comments on commit c44aa7a

Please sign in to comment.