[wip] Plugin dev docs (#10090)
* Plugin index page * backend vs frontend * Plugin creator docs * Feature list * More docs * More images * Additional docs * Cleanup unit test docs * Cleanup * Update frontend docs * Update * Improve examples * Update file list
BIN
docs/docs/assets/images/plugin/plugin-creator-activate.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-dev.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-devops.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-frontend.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-install.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-license.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-metadata.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-mixins.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-npm-build.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-panel.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
docs/docs/assets/images/plugin/plugin-creator-verify.png
Normal file
After Width: | Height: | Size: 22 KiB |
263
docs/docs/plugins/creator.md
Normal file
@@ -0,0 +1,263 @@
|
||||
---
|
||||
title: Plugin Creator
|
||||
---
|
||||
|
||||
## Plugin Creator Tool
|
||||
|
||||
The plugin framework provided for InvenTree is powerful and flexible - which also means that it can be a bit complex to get started, especially for new developers.
|
||||
|
||||
To assist in creating a new plugin, we provide a [plugin creator command line tool](https://github.com/inventree/plugin-creator).
|
||||
|
||||
This tool allows developers to quickly scaffold a new InvenTree plugin, and provides a basic structure to build upon.
|
||||
|
||||
The plugin creator tool allows the developer to select which plugin features they wish to include, and generates a basic plugin structure with the selected features.
|
||||
|
||||
### Features
|
||||
|
||||
The plugin creator tool provides a number of features to help you get started with plugin development:
|
||||
|
||||
- **Metadata Input**: Easily input metadata for your plugin, including name, description, and author information.
|
||||
- **License Selection**: Choose from a variety of licenses for your plugin, with "MIT" as the default.
|
||||
- **Feature Selection**: Select which plugin features you want to include, such as mixins and frontend features.
|
||||
- **Devops Integration**: Optionally set up Git version control, automatic code formatting, and other development tools.
|
||||
- **Deploy Support**: Generate a basic structure for your plugin that can be easily deployed to an InvenTree instance, and published to PyPI.
|
||||
- **Frontend Development**: Set up a development server for frontend features, including hot reloading and build tools.
|
||||
|
||||
### Requirements
|
||||
|
||||
This page provides an overview of how to install and use the plugin creator tool, as well as some tips for creating your own plugins. The documentation here uses the "default" options as provided by the plugin creator tool, but you can customize the options to suit your needs.
|
||||
|
||||
It is assumed that you have a working InvenTree instance, and you have a development environment setup using our [devcontainer guide](../develop/devcontainer.md).
|
||||
|
||||
## Installation
|
||||
|
||||
To get started using the creator tool, you will need to install it via PIP:
|
||||
|
||||
```bash
|
||||
pip install -U inventree-plugin-creator
|
||||
```
|
||||
|
||||
## Create Plugin
|
||||
|
||||
Begin the plugin creation process by running the following command:
|
||||
|
||||
```bash
|
||||
create-inventree-plugin
|
||||
```
|
||||
|
||||
### Plugin Metadata
|
||||
|
||||
Firstly, you will enter the metadata for the plugin:
|
||||
|
||||
{{ image("plugin/plugin-creator-metadata.png", "Plugin Metadata") }}
|
||||
|
||||
### License
|
||||
|
||||
Select the license for your plugin. The default is "MIT", but you can choose from a variety of licenses.
|
||||
|
||||
{{ image("plugin/plugin-creator-license.png", "Plugin License") }}
|
||||
|
||||
### Plugin Features
|
||||
|
||||
Next, the creator tool will prompt you to select the features you wish to include in your plugin.
|
||||
|
||||
#### Select Mixins
|
||||
|
||||
Select the [plugin mixins](./index.md/#plugin-mixins) you wish to use in your plugin:
|
||||
|
||||
{{ image("plugin/plugin-creator-mixins.png", "Plugin Mixins") }}
|
||||
|
||||
#### Select Frontend Features
|
||||
|
||||
If you selected the *UserInterfaceMixin* in the previous step (as we did in this example), you will be prompted to select the frontend features you wish to include in your plugin:
|
||||
|
||||
The available frontend features include:
|
||||
|
||||
- **Custom dashboard items**: Create custom dashboard widgets for the InvenTree user interface.
|
||||
- **Custom panel items**: Add custom panels to the InvenTree interface.
|
||||
- **Custom settings display**: Create custom settings pages for your plugin.
|
||||
|
||||
{{ image("plugin/plugin-creator-frontend.png", "Plugin Frontend Features") }}
|
||||
|
||||
### Git Setup
|
||||
|
||||
If you wish to include Git integration in your plugin, you can select the options here. This will set up a Git repository for your plugin, and configure automatic code formatting using [pre-commit](https://pre-commit.com/).
|
||||
|
||||
Additionally, you can choose to setup CI integration (for either GitHub or GitLab) to automatically run tests and checks on your plugin code.
|
||||
|
||||
{{ image("plugin/plugin-creator-devops.png", "Plugin DevOps Features") }}
|
||||
|
||||
|
||||
## Install Plugin
|
||||
|
||||
The plugin has now been created - it will be located in the directory you specified during the creation process.
|
||||
|
||||
In the example above, we created a plugin called "MyCustomPlugin". We can verify that the plugin files have been created:
|
||||
|
||||
```bash
|
||||
cd MyCustomPlugin
|
||||
ls -al
|
||||
```
|
||||
|
||||
You should see a directory structure similar to the following:
|
||||
|
||||
| File | Description |
|
||||
| ---- | ----------- |
|
||||
| **.git** | The Git repository for your plugin (if you selected Git integration). |
|
||||
| **.github** | GitHub configuration files (if you selected GitHub integration). |
|
||||
| **.gitlab-ci.yml** | GitLab CI configuration file (if you selected GitLab integration). |
|
||||
| **.gitignore** | Git ignore file, specifying which files should be ignored by Git. |
|
||||
| **.pre-commit-config.yaml** | Configuration file for pre-commit hooks (if you selected pre-commit integration). |
|
||||
| **.editorconfig** | Editor configuration file
|
||||
| **LICENSE** | The license file for your plugin. |
|
||||
| **MANIFEST.in** | A file that specifies which files should be included in the plugin package. |
|
||||
| **README.md** | A README file for your plugin. |
|
||||
| **biome.json** | Configuration file for the Biome code formatter. |
|
||||
| **pyproject.toml** | The project configuration file for your plugin. |
|
||||
| **setup.cfg** | Rules for Python code formatting and linting. |
|
||||
| **setup.py** | The setup script for your plugin. |
|
||||
| **frontend/** | A directory containing the frontend code for your plugin (if you selected frontend features). |
|
||||
| **my_custom_plugin/** | The main plugin directory, containing the plugin code. *(Note: the name of this directory will match the name you provided during plugin creation)* |
|
||||
|
||||
### Editable Install
|
||||
|
||||
We now need to *install* the plugin (within the active Python environment) so that it can be used by InvenTree. For development purposes, we can install the plugin in [editable install](https://setuptools.pypa.io/en/latest/userguide/development_mode.html) mode, which allows us to make changes to the plugin code without needing to reinstall it.
|
||||
|
||||
```bash
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
You should see output indicating that the plugin has been installed successfully:
|
||||
|
||||
{{ image("plugin/plugin-creator-install.png", "Install Editable Plugin") }}
|
||||
|
||||
You can also verify that the plugin has been installed by running the following command:
|
||||
|
||||
```bash
|
||||
pip show inventree-my-custom-plugin
|
||||
```
|
||||
|
||||
{{ image("plugin/plugin-creator-verify.png", "Verify plugin installation") }}
|
||||
|
||||
## Activate Plugin
|
||||
|
||||
Now that the plugin has been installed, you can activate it in your InvenTree instance. If the InvenTree server is not already running, start it with:
|
||||
|
||||
```bash
|
||||
invoke dev.server
|
||||
```
|
||||
|
||||
Then, navigate to the [plugin management page](http://localhost:8000/web/settings/admin/plugin) in your InvenTree instance. You can activate the plugin by clicking the "Activate" button next to your plugin in the list.
|
||||
|
||||
{{ image("plugin/plugin-creator-activate.png", "Activate Plugin") }}
|
||||
|
||||
!!! success "Plugin Activated"
|
||||
Your plugin should now be active, and you can start developing it further!
|
||||
|
||||
## Frontend Development
|
||||
|
||||
In this example we have configured the plugin to include frontend features. In production, the frontend code will be built and served as static files. However, during development, it is often useful to run a development server which provides hot reloading and other features.
|
||||
|
||||
### Backend Configuration
|
||||
|
||||
To facilitate frontend plugin development, the InvenTree backend server needs to be configured to redirect requests for the plugin frontend to the development server. To achieve this, you need to add the following lines to your server configuration file (e.g. `./dev/config.yaml`, if you are using the default devcontainer setup):
|
||||
|
||||
```yaml
|
||||
plugin_dev:
|
||||
slug: 'my-custom-plugin' # Replace with your plugin slug
|
||||
host: "http://localhost:5174"
|
||||
```
|
||||
|
||||
!!! warning "Restart Required"
|
||||
After making changes to the configuration file, you will need to restart the InvenTree server for the changes to take effect.
|
||||
|
||||
This configuration tells the InvenTree server to redirect static file requests (for this particular plugin) to the development server running on port `5174`. This is only available in development mode, and will not be used in production.
|
||||
|
||||
### Frontend Development Server
|
||||
|
||||
The plugin creator tool provides a development setup to allow you to run a frontend development server. To install the required libraries and start the development server, run the following commands:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
You should see output indicating that the development server is running on port `5174`:
|
||||
|
||||
{{ image("plugin/plugin-creator-dev.png", "Frontend dev server") }}
|
||||
|
||||
Let's test this out! The default plugin code has provided a custom "panel" which is display on the "part detail" page. Navigate to a part detail page in your InvenTree instance, and you should see the following custom panel displayed:
|
||||
|
||||
{{ image("plugin/plugin-creator-panel.png", "Custom Panel") }}
|
||||
|
||||
!!! success "Frontend Running"
|
||||
Your frontend development server is now running, and you can start developing your plugin's frontend features!
|
||||
|
||||
## Plugin Editing
|
||||
|
||||
### Backend Code
|
||||
|
||||
The backend code for your plugin is located in the `my_custom_plugin` directory. You can edit the Python files in this directory to implement the backend functionality of your plugin.
|
||||
|
||||
Refer to the `./my_custom_plugin/core.py` file as a starting point. This is where the main plugin logic is implemented. If you selected other mixin types during the plugin creation process, you may find additional files in the `my_custom_plugin` directory that correspond to those mixins.
|
||||
|
||||
As you have installed the plugin in editable mode, any changes you make to the backend code will be immediately reflected in your InvenTree instance without needing to reinstall the plugin.
|
||||
|
||||
!!! info "Debug Server"
|
||||
Note that live reload of the backend code only works when the InvenTree server is running in debug mode. If you are running the server in production mode, you will need to restart the server to see changes.
|
||||
|
||||
### Frontend Code
|
||||
|
||||
The frontend code for your plugin is located in the `frontend/src` directory. You can edit the provided `.tsx` files to adjust the frontend functionality of your plugin.
|
||||
|
||||
Refer to the `./frontend/src/Panel.tsx` file as a starting point. This is where the custom panel for the part detail page is implemented. You can modify this file to change the content and behavior of the panel.
|
||||
|
||||
While the `npm dev` server is running, any changes you make to the frontend code will be automatically reloaded allowing for rapid development and testing of your plugin's frontend features. This avoids the need to rebuild the frontend code every time you make a change.
|
||||
|
||||
!!! info "Page Reload"
|
||||
Due to the way the InvenTree frontend is structured, you will need to manually refresh the page in your browser to see changes to the frontend code. The development server will automatically reload the frontend code, but the InvenTree server needs to be aware of the changes.
|
||||
|
||||
## Build Plugin
|
||||
|
||||
The documentation provided above relates to the development of a plugin. Once you have completed your plugin development, you should build the plugin for distribution.
|
||||
|
||||
!!! info "CI Build"
|
||||
If you have configured CI integration during the plugin creation process, the CI server will automatically build your plugin when you push changes to your repository. This is the recommended way to build and distribute your plugin.
|
||||
|
||||
### Compile Frontend Assets
|
||||
|
||||
The frontend assets for your plugin need to be compiled before the plugin can be distributed. The compiled assets (primarily `.js` files) need to be distributed with the plugin, so that they can be statically served by the InvenTree server. To achieve this, the compiled files need to be placed in the `./my_custom_plugin/static` directory. The frontend `build` step will automatically place the compiled files in this directory:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
{{ image("plugin/plugin-creator-npm-build.png", "Build Frontend") }}
|
||||
|
||||
### Build Plugin
|
||||
|
||||
Now that the frontend assets have been compiled, you can build the plugin for distribution. This will create a distributable Python package that can be installed in other InvenTree instances.
|
||||
|
||||
!!! info "Top Level Directory"
|
||||
Ensure you are in the top-level directory of your plugin (the directory containing `setup.py`) before running the build command.
|
||||
|
||||
```bash
|
||||
python -m build
|
||||
```
|
||||
|
||||
You should see output indicating that the Python package has been built successfully.
|
||||
|
||||
### Publish Plugin
|
||||
|
||||
The plugin package can now be published (e.g. to PyPI), allowing it to be remotely installed into other InvenTree installations.
|
||||
|
||||
Publishing to PyPI is outside the scope of this documentation, but you can refer to the [Python Packaging User Guide](https://packaging.python.org/tutorials/packaging-projects/) for more information on how to publish your plugin package.
|
||||
|
||||
!!! info "Automated PyPI Publishing"
|
||||
If you have configured CI integration during the plugin creation process, the CI server will automatically publish your plugin to PyPI when you create a new release. You just need to ensure that you have set up the necessary credentials in your CI environment.
|
||||
|
||||
## Further Reading
|
||||
|
||||
For a more complex walkthrough of developing a plugin, check out our [basic plugin walkthrough](../plugins/walkthrough.md).
|
198
docs/docs/plugins/frontend.md
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: UI Plugin Integration
|
||||
---
|
||||
|
||||
## Frontend Integration
|
||||
|
||||
Plugins can inherit from the [UserInterfaceMixin](./mixins/ui.md) class to provide custom UI components that can be integrated into the InvenTree web interface.
|
||||
|
||||
### Plugin Creator
|
||||
|
||||
Note that the [InvenTree plugin creator](./creator.md) can be used to scaffold a new plugin with the necessary structure for frontend integration. This will automatically set up the necessary files and configurations to get started with frontend development.
|
||||
|
||||
## Frontend Architecture
|
||||
|
||||
When designing a frontend plugin component, it is important to have at least a basic understanding of the InvenTree frontend architecture.
|
||||
|
||||
### React
|
||||
|
||||
The frontend code is written in TypeScript, and uses React for rendering components.
|
||||
|
||||
### Mantine
|
||||
|
||||
InvenTree uses the [Mantine](https://mantine.dev/) component library for building user interfaces. Mantine provides a set of pre-built components that can be used to create responsive and accessible web applications.
|
||||
|
||||
### Axios
|
||||
|
||||
InvenTree uses [Axios](https://axios-http.com/) for making API requests to the InvenTree server.
|
||||
|
||||
### Lingui
|
||||
|
||||
InvenTree uses [Lingui](https://lingui.js.org/) for internationalization (i18n) of the user interface. Lingui provides a set of tools for managing translations and rendering localized text in the frontend.
|
||||
|
||||
## Calling Functions
|
||||
|
||||
A custom UI component is rendered by specifying a source file and method name. The filename and method name are provided to the frontend via a specification in the backend (Python) code, and fetched at runtime via an API call.
|
||||
|
||||
The 'static' files for each plugin are copied to the static directory when the plugin is activated. The frontend code needs to know the path to the static files for the plugin in order to load them correctly.
|
||||
|
||||
To assist in this, the `UserInterfaceMixin` class provides a `plugin_static_file` method. This method returns the path to the static file for the plugin, which can be used in the frontend code to load the necessary resources.
|
||||
|
||||
For example, when returning a list of available UI components in a given context, the "source" attribute can be specified as follows:
|
||||
|
||||
```python
|
||||
{
|
||||
...,
|
||||
"source": self.plugin_static_file('my_plugin.js:my_plugin_function'),
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
*Note: The function name can be appended to the filename using a colon (:) separator.*
|
||||
|
||||
### Function Signature
|
||||
|
||||
The expected function signature for the frontend function is:
|
||||
|
||||
```javascript
|
||||
function my_plugin_function(context: InvenTreePluginContext) {
|
||||
// Function implementation
|
||||
return (
|
||||
<div>Hello world</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The function is expected to return a React component that will be rendered in the InvenTree web interface.
|
||||
|
||||
### Plugin Context
|
||||
|
||||
When rendering certain content in the user interface, the rendering functions are passed a `context` object which contains information about the current page being rendered. The type of the `context` object is defined in the `PluginContext` file:
|
||||
|
||||
{{ includefile("src/frontend/src/components/plugins/PluginContext.tsx", title="Plugin Context", fmt="javascript") }}
|
||||
|
||||
The following properties are available in the `context` object:
|
||||
|
||||
| Property | Description |
|
||||
| -------- | ----------- |
|
||||
| `version` | An object containing the current InvenTree version information. |
|
||||
| `user` | An object containing information about the currently logged-in user. |
|
||||
| `host` | An object containing information about the current host (server) configuration. |
|
||||
| `i18n` | An object containing internationalization (i18n) functions for translating text. |
|
||||
| `locale` | The current locale being used for the user interface. |
|
||||
| `api` | The Axios instance configured to communicate with the InvenTree API. |
|
||||
| `queryClient` | The query client instance used for managing API calls in the frontend. |
|
||||
| `navigate` | A function to navigate to a different page in the InvenTree web interface. |
|
||||
| `globalSettings` | An object containing global settings for the InvenTree instance. |
|
||||
| `userSettings` | An object containing user-specific settings. |
|
||||
| `modelInformation` | An object containing information about the models available in the InvenTree instance. |
|
||||
| `renderInstance` | A function to render a model instance |
|
||||
| `theme` | The current Mantine theme being used in the InvenTree web interface. |
|
||||
| `colorScheme` | The current color scheme being used in the InvenTree web interface. |
|
||||
| `forms` | A set of functional components for rendering forms in the InvenTree web interface. |
|
||||
|
||||
This set of components is passed through at render time to the plugin function, allowing the plugin code to hook directly into the InvenTree web interface and access the necessary context for rendering.
|
||||
|
||||
For example, the plugin can make use of the authenticated api instance, to make calls to the InvenTree API, or use the `navigate` function to redirect the user to a different page.
|
||||
|
||||
## Externalized Libraries
|
||||
|
||||
To create a plugin which integrates natively into the InvenTree UI, it is important that the plugin is compiled in a way that allows it to run within the same React context as the InvenTree frontend code.
|
||||
|
||||
To achieve this, the InvenTree UI provides a number of core libraries as "externalized" libraries. This means that these libraries are not bundled with the plugin code, but are instead provided by the InvenTree frontend code at runtime.
|
||||
|
||||
The following libraries are externalized and provided by the InvenTree frontend:
|
||||
|
||||
- `react`
|
||||
- `react-dom`
|
||||
- `react-dom/client`
|
||||
- `@mantine/core`
|
||||
- `@lingui/core`
|
||||
- `@lingui/react`
|
||||
|
||||
### Window Object
|
||||
|
||||
The externalized libraries are made available in the global `window` object, allowing the plugin code to access them directly without needing to import them.
|
||||
|
||||
This means in practice that the plugin code must be compiled in such a way that it does not include these libraries in its own bundle. Instead, it should reference them from the global `window` object.
|
||||
|
||||
### Vite Setup
|
||||
|
||||
The vite configuration for your InvenTree plugin must be confitured to correctly externalize these libraries, both in development and production builds.
|
||||
|
||||
This is *somewhat tricky* to get right, which is why we recommend using the [InvenTree plugin creator](./creator.md) to scaffold a new plugin. The plugin creator will automatically configure the necessary build settings to ensure that the plugin code is compatible with the InvenTree frontend architecture.
|
||||
|
||||
## NPM Package
|
||||
|
||||
When creating a UI plugin, the developer needs access to the type definitions for the [context](#plugin-context) object, as well as information on which libraries are externalized.
|
||||
|
||||
To support this, the InvenTree project provides a dedicated NPM package for developing plugins: [@inventreedb/ui](https://www.npmjs.com/package/@inventreedb/ui)
|
||||
|
||||
This package should be added to the `package.json` file of the plugin, and installed using NPM or Yarn. This package provides the necessary type definitions and utility functions for developing frontend plugins.
|
||||
|
||||
### Type Definitions
|
||||
|
||||
The type definitions for the `context` object are provided in the `@inventreedb/ui` package. This allows the plugin code to import the necessary types and use them in the plugin function signature:
|
||||
|
||||
```typescript
|
||||
import { InvenTreePluginContext } from '@inventreedb/ui';
|
||||
|
||||
function my_plugin_function(context: InvenTreePluginContext) {
|
||||
// Function implementation
|
||||
return (
|
||||
<MyCustomPanel context={context} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Functions
|
||||
|
||||
The `@inventreedb/ui` package also provides a set of custom functions that can be used in the plugin code. These functions allow the plugin code to make use of some of the core InvenTree functionality, rather than having to re-implement it.
|
||||
|
||||
### Custom Components
|
||||
|
||||
Additionally, the `@inventreedb/ui` package provides a set of custom components that can be used in the plugin code. This allows the plugin to construct UI components with a consistent look and feel, and to make use of the InvenTree design system.
|
||||
|
||||
## Frontend Development
|
||||
|
||||
When developing a frontend plugin, it is useful to be able to run the plugin code in a development environment, where changes can be made and tested quickly. This allows for rapid iteration and debugging of the plugin code, instead of having to rebuild and redeploy the plugin code for every change.
|
||||
|
||||
To assist with this, InvenTree can be configured to allow for loading a particular plugin in "development" mode. In this mode, loading of the frontend code is redirected from the "static" directory, to a local development server.
|
||||
|
||||
!!! into "Plugin Creator"
|
||||
Refer to the [plugin creator docs](./creator.md#frontend-development-server) for more information on how to set up a development server for your plugin.
|
||||
|
||||
### Debug Mode
|
||||
|
||||
This facility is only available when running the backend server in [debug mode](../start/config.md#debug-mode). With debug omde enabled, a single plugin can be selected for "development" mode, allowing the frontend code to be loaded from a local development server.
|
||||
|
||||
### Config File
|
||||
|
||||
To select a plugin for development, edit the server [configuration file](../start/config.md#configuration-file), add the following entry:
|
||||
|
||||
```yaml
|
||||
plugin_dev:
|
||||
slug: 'my-custom-plugin' # Replace with the slug of your plugin
|
||||
host: "http://localhost:5174" # Replace with the path to your dev server
|
||||
```
|
||||
|
||||
### Development Server
|
||||
|
||||
Assuming you have set up your plugin with the [plugin creator](./creator.md), you can start the development server using the following command:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This will automatically launch the plugin development server on port `:5174`, and the InvenTree backend is configured to redirect static file requests for this plugin, to the development server.
|
||||
|
||||
## Distributing Frontend Code
|
||||
|
||||
InvenTree plugins are distributed as Python packages, which means that the frontend code must be bundled and included in the package.
|
||||
|
||||
The typical approach (as used by the plugin creator) is to build the frontend code (using [Vite](https://vitejs.dev/)) and then copy the built files into the `static` directory of the plugin.
|
||||
|
||||
After the static files are built into the correct location, the plugin can be packaged and distributed as a Python package, which can then be installed using PIP.
|
||||
|
||||
[Python packaging](https://packaging.python.org/en/latest/) is a complex topic, and there are many resources available to help with this process. The InvenTree plugin creator provides a basic setup for packaging the plugin, but it is recommended to read up on Python packaging if you are new to this topic.
|
@@ -2,22 +2,17 @@
|
||||
title: Developing Plugins
|
||||
---
|
||||
|
||||
## How to Develop a Plugin
|
||||
## Plugin Development Guide
|
||||
|
||||
A short introductory guide for plugin beginners.
|
||||
This page serves as a short introductory guide for plugin beginners. It should be noted that there is an assumed level of familiarity with Python, Django, and the InvenTree source code.
|
||||
|
||||
### Should it be a plugin?
|
||||
First of all figure out what your plugin / code should do.
|
||||
If you want to change how InvenTree base mechanics and business logic work, a plugin will not be sufficient. Maybe fork the project or better [start a discussion](https://github.com/inventree/InvenTree/discussions) on GitHub. There might be an easier / established way to do what you want.
|
||||
### Plugin Creator
|
||||
|
||||
If you want to remove parts of the user interface -> remove the permissions for those objects / actions and the users will not see them.
|
||||
We strongly recommend that you use the [Plugin Creator](./creator.md) tool when first scaffolding your new plugin. This tool will help you to create a basic plugin structure, and will also provide you with a set of example files which can be used as a starting point for your own plugin development.
|
||||
|
||||
If you add a lot of code (over ~1000 LOC) maybe split it into multiple plugins to make upgrading and testing simpler.
|
||||
### Determine Requirements
|
||||
|
||||
### It will be a plugin!
|
||||
Great. Now please read the [plugin documentation](./index.md) to get an overview of the architecture. It is rather short as a the (builtin) mixins come with extensive docstrings.
|
||||
|
||||
### Pick your building blocks
|
||||
Before starting, you should have a clear understanding of what you want your plugin to do. In particular, consider the functionality provided by the available [plugin mixins](./index.md#plugin-mixins), and whether your plugin can be built using these mixins.
|
||||
|
||||
Consider the use-case for your plugin and define the exact function of the plugin, maybe write it down in a short readme. Then pick the mixins you need (they help reduce custom code and keep the system reliable if internal calls change).
|
||||
|
||||
@@ -30,11 +25,12 @@ Consider the use-case for your plugin and define the exact function of the plugi
|
||||
- You want to receive webhooks? Do not code your own untested function, use the WebhookEndpoint model as a base and override the perform_action method.
|
||||
- Do you need the full power of Django with custom models and all the complexity that comes with that – welcome to the danger zone and [AppMixin](./mixins/app.md). The plugin will be treated as a app by django and can maybe rack the whole instance.
|
||||
|
||||
### Define the metadata
|
||||
### Define Metadata
|
||||
|
||||
Do not forget to [declare the metadata](./index.md#plugin-options) for your plugin, those will be used in the settings. At least provide a web link so users can file issues / reach you.
|
||||
|
||||
### Development guidelines
|
||||
### Development Guidelines
|
||||
|
||||
If you want to make your life easier, try to follow these guidelines; break where it makes sense for your use case.
|
||||
|
||||
- Keep it simple - more that 1000 LOC are normally to much for a plugin
|
||||
@@ -131,7 +127,8 @@ To setup an editable install:
|
||||
pip install --editable .
|
||||
```
|
||||
|
||||
### A simple example
|
||||
### Simple Example
|
||||
|
||||
This example adds a new action under `/api/action/sample` using the ActionMixin.
|
||||
``` py
|
||||
# -*- coding: utf-8 -*-
|
||||
|
@@ -4,7 +4,7 @@ title: Plugins
|
||||
|
||||
## InvenTree Plugin Architecture
|
||||
|
||||
The InvenTree server code supports an extensible plugin architecture, allowing custom plugins to be integrated directly into the database server. This allows development of complex behaviors which are decoupled from core InvenTree code.
|
||||
The InvenTree server code supports an extensible plugin architecture, allowing custom plugins to be integrated directly into the InvenTree installation. This allows development of complex behaviors which are decoupled from core InvenTree code.
|
||||
|
||||
Plugins can be added from multiple sources:
|
||||
|
||||
@@ -18,16 +18,18 @@ For further information, read more about [installing plugins](./install.md).
|
||||
|
||||
Plugin behaviour can be controlled via the InvenTree configuration options. Refer to the [configuration guide](../start/config.md#plugin-options) for the available plugin configuration options.
|
||||
|
||||
### Backend vs Frontend Code
|
||||
|
||||
InvenTree plugins can contain both backend and frontend code. The backend code is written in Python, and is used to implement server-side functionality, such as database models, API endpoints, and background tasks.
|
||||
|
||||
The frontend code is written in JavaScript (or TypeScript), and is used to implement user interface components, such as custom UI panels.
|
||||
|
||||
You can [read more about frontend integration](./frontend.md) to learn how to integrate custom UI components into the InvenTree web interface.
|
||||
|
||||
### Creating a Plugin
|
||||
|
||||
To assist in creating a new plugin, we provide a [plugin creator command line tool](https://github.com/inventree/plugin-creator). This allows developers to quickly scaffold a new InvenTree plugin, and provides a basic structure to build upon.
|
||||
To assist in creating a new plugin, we provide a [plugin creator command line tool](./creator.md). This allows developers to quickly scaffold a new InvenTree plugin, and provides a basic structure to build upon.
|
||||
|
||||
To install and run the plugin creator:
|
||||
|
||||
```bash
|
||||
pip install inventree-plugin-creator
|
||||
create-inventree-plugin
|
||||
```
|
||||
|
||||
### Basic Plugin Walkthrough
|
||||
|
||||
@@ -39,9 +41,6 @@ Check out our [basic plugin walkthrough](../plugins/walkthrough.md) to learn how
|
||||
|
||||
Custom plugins must inherit from the [InvenTreePlugin class]({{ sourcefile("src/backend/InvenTree/plugin/plugin.py") }}). Any plugins installed via the methods outlined above will be "discovered" when the InvenTree server launches.
|
||||
|
||||
!!! warning "Name Change"
|
||||
The name of the base class was changed with `0.7.0` from `IntegrationPluginBase` to `InvenTreePlugin`.
|
||||
|
||||
### Imports
|
||||
|
||||
As the code base is evolving import paths might change. Therefore we provide stable import targets for important python APIs.
|
||||
@@ -65,7 +64,9 @@ MixinNotImplementedError # Is raised if a mixin was not implemented (core mec
|
||||
|
||||
#### Mixins
|
||||
|
||||
Mixins are split up internally to keep the source tree clean and enable better testing separation. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code [can be found here]({{ sourcefile("src/backend/InvenTree/plugin/mixins/__init__.py") }}).
|
||||
Plugin functionality is split between multiple "mixin" classes - each of which provides a specific set of features or behaviors that can be integrated into a plugin. These mixins are designed to be used in conjunction with the `InvenTreePlugin` base class, allowing developers to easily extend the functionality of their plugins. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code [can be found here]({{ sourcefile("src/backend/InvenTree/plugin/mixins/__init__.py") }}).
|
||||
|
||||
Refer to the [mixin documentation](#plugin-mixins) for a list of available mixins, and their usage.
|
||||
|
||||
#### Models and other internal InvenTree APIs
|
||||
|
||||
@@ -122,6 +123,7 @@ Supported mixin classes are:
|
||||
| [LabelPrintingMixin](./mixins/label.md) | Custom label printing support |
|
||||
| [LocateMixin](./mixins/locate.md) | Locate and identify stock items |
|
||||
| [NavigationMixin](./mixins/navigation.md) | Add custom pages to the web interface |
|
||||
| [NotificationMixin](./mixins/notification.md) | Send custom notifications in response to system events |
|
||||
| [ReportMixin](./mixins/report.md) | Add custom context data to reports |
|
||||
| [ScheduleMixin](./mixins/schedule.md) | Schedule periodic tasks |
|
||||
| [SettingsMixin](./mixins/settings.md) | Integrate user configurable settings |
|
||||
|
@@ -3,23 +3,19 @@ Title: Unit Tests
|
||||
---
|
||||
|
||||
## Unit Tests
|
||||
For complicated plugins it makes sense to add unit tests the code to ensure
|
||||
that plugins work correctly and are compatible with future versions too.
|
||||
You can run these tests as part of your ci against the current stable and
|
||||
latest tag to get notified when something breaks before it gets released as
|
||||
part of stable. InvenTree offers a framework for testing. Please refer
|
||||
to [Unit Tests](../develop/contributing.md) for more information.
|
||||
For complicated plugins it makes sense to add unit tests the code to ensure that plugins work correctly and are compatible with future versions too. You can run these tests as part of your ci against the current stable and latest tag to get notified when something breaks before it gets released as part of stable. InvenTree offers a framework for testing. Please refer to [Unit Tests](../develop/contributing.md#unit-testing) for more information.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
For plugin testing the following environment variables must be set to True:
|
||||
|
||||
| Name | Function | Value |
|
||||
| --- | --- | --- |
|
||||
| ---- | -------- | ----- |
|
||||
| INVENTREE_PLUGINS_ENABLED | Enables the use of 3rd party plugins | True |
|
||||
| INVENTREE_PLUGIN_TESTING | Enables enables all plugins no matter of their active state in the db or built-in flag | True |
|
||||
| INVENTREE_PLUGIN_TESTING_SETUP | Enables the url mixin | True |
|
||||
|
||||
### Test program
|
||||
### Test Program
|
||||
|
||||
A file called test_plugin_name.py should be added to the plugin directory. It can have the
|
||||
following structure:
|
||||
@@ -46,7 +42,8 @@ I that case module must be omitted.
|
||||
invoke dev.test -r plugin_directory.test_plugin_name.TestMyPlugin
|
||||
```
|
||||
|
||||
### do some work here... A simple Example
|
||||
### Simple Example
|
||||
|
||||
A simple example is shown here. Assume the plugin has a function that converts a price string
|
||||
that comes from a supplier API to a float value. The price might have the form "1.456,34 €".
|
||||
It can be different based on country and local settings.
|
||||
|
@@ -211,7 +211,9 @@ nav:
|
||||
- Overview: plugins/index.md
|
||||
- Installation: plugins/install.md
|
||||
- Developing a Plugin: plugins/how_to.md
|
||||
- Plugin Development Walkthrough: plugins/walkthrough.md
|
||||
- Frontend Integration: plugins/frontend.md
|
||||
- Plugin Creator: plugins/creator.md
|
||||
- Plugin Walkthrough: plugins/walkthrough.md
|
||||
- Model Metadata: plugins/metadata.md
|
||||
- Tags: plugins/tags.md
|
||||
- Unit Test: plugins/test.md
|
||||
|