* 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
10 KiB
title
title |
---|
UI Plugin Integration |
Frontend Integration
Plugins can inherit from the UserInterfaceMixin class to provide custom UI components that can be integrated into the InvenTree web interface.
Plugin Creator
Note that the InvenTree plugin creator 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 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 for making API requests to the InvenTree server.
Lingui
InvenTree uses Lingui 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:
{
...,
"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:
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 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 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
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:
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 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. 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, add the following entry:
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, you can start the development server using the following command:
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) 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 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.