User Interface Mixin
User Interface Mixin¶
The UserInterfaceMixin
class provides a set of methods to implement custom functionality for the InvenTree web interface.
Enable User Interface Mixin¶
To enable user interface plugins, the global setting ENABLE_PLUGINS_INTERFACE
must be enabled, in the plugin settings.
Custom UI Features¶
The InvenTree user interface functionality can be extended in various ways using plugins. Multiple types of user interface features can be added to the InvenTree user interface.
The entrypoint for user interface plugins is the UserInterfaceMixin
class, which provides a number of methods which can be overridden to provide custom functionality. The get_ui_features
method is used to extract available user interface features from the plugin:
Return a list of custom features to be injected into the UI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
feature_type
|
FeatureType
|
The type of feature being requested |
required |
context
|
dict
|
Additional context data provided by the UI (query parameters) |
required |
request
|
Request
|
HTTPRequest object (including user information) |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list[UIFeature]
|
A list of custom UIFeature dicts to be injected into the UI |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
|
Note here that the get_ui_features
calls other methods to extract the available features from the plugin, based on the requested feature type. These methods can be overridden to provide custom functionality.
Implementation
Your custom plugin does not need to override the get_ui_features
method. Instead, override one of the other methods to provide custom functionality.
UIFeature Return Type¶
The get_ui_features
method should return a list of UIFeature
objects, which define the available user interface features for the plugin. The UIFeature
class is defined as follows:
Base type definition for a ui feature.
Attributes:
Name | Type | Description |
---|---|---|
key |
str
|
The key of the feature (required, must be a unique identifier) |
title |
str
|
The title of the feature (required, human readable) |
description |
str
|
The long-form description of the feature (optional, human readable) |
icon |
str
|
The icon of the feature (optional, must be a valid icon identifier) |
feature_type |
FeatureType
|
The feature type (required, see documentation for all available types) |
options |
dict
|
Feature options (required, see documentation for all available options for each type) |
context |
dict
|
Additional context data to be passed to the rendering function (optional, dict) |
source |
str
|
The source of the feature (required, path to a JavaScript file, with optional function name). |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
Note that the options field contains fields which may be specific to a particular feature type - read the documentation below on each feature type for more information.
Dynamic Feature Loading¶
Each of the provided feature types can be loaded dynamically by the plugin, based on the information provided in the API request. For example, the plugin can choose to show or hide a particular feature based on the user permissions, or the current state of the system.
For examples of this dynamic feature loading, refer to the sample plugin implementation which demonstrates how to dynamically load custom panels based on the provided context.
Javascript Source Files¶
The rendering function for the custom user interface features expect that the plugin provides a Javascript source file which contains the necessary code to render the custom content. The path to this file should be provided in the source
field of the UIFeature
object.
Note that the source
field can include the name of the function to be called (if this differs from the expected default function name).
For example:
"source": "/static/plugins/my_plugin/my_plugin.js:my_custom_function"
Available UI Feature Types¶
The following user interface feature types are available:
Dashboard Items¶
The InvenTree dashboard is a collection of "items" which are displayed on the main dashboard page. Custom dashboard items can be added to the dashboard by implementing the get_ui_dashboard_items
method:
Return a list of custom dashboard items to be injected into the UI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request
|
Request
|
HTTPRequest object (including user information) |
required |
context
|
dict
|
Additional context data provided by the UI (query parameters) |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list[UIFeature]
|
A list of custom dashboard items to be injected into the UI |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
|
Dashboard Item Options¶
The options field in the returned UIFeature
object can contain the following properties:
Options type definition for a custom dashboard item.
Attributes:
Name | Type | Description |
---|---|---|
width |
int
|
The minimum width of the dashboard item (integer, defaults to 2) |
height |
int
|
The minimum height of the dashboard item (integer, defaults to 2) |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
58 59 60 61 62 63 64 65 66 67 |
|
Source Function¶
The frontend code expects a path to a javascript file containing a function named renderDashboardItem
which will be called to render the custom dashboard item. Note that this function name can be overridden by appending the function name in the source
field of the UIFeature
object.
Example¶
Refer to the sample plugin for an example of how to implement server side rendering for custom panels.
Panels¶
Many of the pages in the InvenTree web interface are built using a series of "panels" which are displayed on the page. Custom panels can be added to these pages, by implementing the get_ui_panels
method:
Return a list of custom panels to be injected into the UI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request
|
Request
|
HTTPRequest object (including user information) |
required |
context
|
dict
|
Additional context data provided by the UI (query parameters) |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list[UIFeature]
|
A list of custom panels to be injected into the UI |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
|
Panel Options¶
The options field in the returned UIFeature
object can contain the following properties:
Options type definition for a custom panel.
Attributes:
Name | Type | Description |
---|---|---|
icon |
The icon of the panel (optional, must be a valid icon identifier). |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
50 51 52 53 54 55 |
|
Source Function¶
The frontend code expects a path to a javascript file containing a function named renderPanel
which will be called to render the custom panel. Note that this function name can be overridden by appending the function name in the source
field of the UIFeature
object.
Example¶
Refer to the sample plugin for an example of how to implement server side rendering for custom panels.
Template Editors¶
The get_ui_template_editors
feature type can be used to provide custom template editors.
Return a list of custom template editors to be injected into the UI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request
|
Request
|
HTTPRequest object (including user information) |
required |
context
|
dict
|
Additional context data provided by the UI (query parameters) |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list[UIFeature]
|
A list of custom template editors to be injected into the UI |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
|
Template previews¶
The get_ui_template_previews
feature type can be used to provide custom template previews:
Return a list of custom template previews to be injected into the UI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request
|
Request
|
HTTPRequest object (including user information) |
required |
context
|
dict
|
Additional context data provided by the UI (query parameters) |
required |
Returns:
Name | Type | Description |
---|---|---|
list |
list[UIFeature]
|
A list of custom template previews to be injected into the UI |
Source code in src/backend/InvenTree/plugin/base/ui/mixins.py
160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
|
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:
Plugin Context
import { useMantineColorScheme, useMantineTheme } from '@mantine/core';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useShallow } from 'zustand/react/shallow';
import { api, queryClient } from '../../App';
import { useLocalState } from '../../states/LocalState';
import {
useGlobalSettingsState,
useUserSettingsState
} from '../../states/SettingsState';
import { useUserState } from '../../states/UserState';
import {
INVENTREE_MANTINE_VERSION,
INVENTREE_PLUGIN_VERSION,
INVENTREE_REACT_VERSION,
type InvenTreePluginContext
} from '@lib/types/Plugins';
import {
useBulkEditApiFormModal,
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../hooks/UseForm';
export const useInvenTreeContext = () => {
const [locale, host] = useLocalState(useShallow((s) => [s.language, s.host]));
const navigate = useNavigate();
const user = useUserState();
const { colorScheme } = useMantineColorScheme();
const theme = useMantineTheme();
const globalSettings = useGlobalSettingsState();
const userSettings = useUserSettingsState();
const contextData = useMemo<InvenTreePluginContext>(() => {
return {
version: {
inventree: INVENTREE_PLUGIN_VERSION,
react: INVENTREE_REACT_VERSION,
reactDom: INVENTREE_REACT_VERSION,
mantine: INVENTREE_MANTINE_VERSION
},
user: user,
host: host,
locale: locale,
api: api,
queryClient: queryClient,
navigate: navigate,
globalSettings: globalSettings,
userSettings: userSettings,
theme: theme,
colorScheme: colorScheme,
forms: {
bulkEdit: useBulkEditApiFormModal,
create: useCreateApiFormModal,
delete: useDeleteApiFormModal,
edit: useEditApiFormModal
}
};
}, [
user,
host,
api,
locale,
queryClient,
navigate,
globalSettings,
userSettings,
theme,
colorScheme
]);
return contextData;
};
This context data can be used to provide additional information to the rendering functions, and can be used to dynamically render content based on the current state of the system.
Additional Context¶
Note that additional context can be passed to the rendering functions by adding additional key-value pairs to the context
field in the UIFeature
return type (provided by the backend via the API). This field is optional, and can be used at the discretion of the plugin developer.
File Distribution¶
When distributing a custom UI plugin, the plugin should include the necessary frontend code to render the custom content. This frontend code should be included in the plugin package, and should be made available to the InvenTree frontend when the plugin is installed.
The simplest (and recommended) way to achieve this is to distribute the compiled javascript files with the plugin package, in a top-level static
directory. This directory will be automatically collected by InvenTree when the plugin is installed, and the files will be copied to the appropriate location.
Read more about static plugin files for more information.
Sample Plugin¶
A (very simple) sample plugin which implements custom user interface functionality is provided in the InvenTree source code, which provides a full working example of how to implement custom user interface functionality.
A sample plugin which demonstrates user interface integrations.
Source code in src/backend/InvenTree/plugin/samples/integration/user_interface_sample.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
|
More Examples¶
Some more complex examples of user interface plugins can be found on the InvenTree GitHub repository:
Consistent Theming¶
When developing a custom UI plugin for InvenTree, the plugin should aim to match the existing InvenTree theme as closely as possible. This will help to ensure that the custom content fits seamlessly into the existing user interface.
To achieve this, we strongly recommend that you use the same framework as the InvenTree frontend - which is built using React on top of the Mantine UI component library.
Mantine¶
The Mantine UI component library is used throughout the InvenTree frontend, and provides a consistent look and feel to the user interface. By using Mantine components in your custom UI plugin, you can ensure that your custom content fits seamlessly into the existing InvenTree theme.
InvenTree Component Library¶
We are working to develop and distribute a library of custom InvenTree components which can be used to build custom UI plugins. This library will be made available to plugin developers in the near future.
Examples¶
Refer to some of the existing InvenTree plugins linked above for examples of building custom UI plugins using the Mantine component library for seamless integration.
Building a User Interface Plugin¶
The technology stack which allows custom plugins to hook into the InvenTree user interface utilizes the following components:
While you don't need to be an expert in all of these technologies, it is recommended that you have a basic understanding of how they work together to build the InvenTree user interface. To get started, you should familiarize yourself with the frontend code (at ./src/frontend/
) as well as the vite configuration for the InvenTree plugin creator.
Bundled with InvenTree¶
If a plugin is bundled with a separate copy of React libraries, issues may arise either due to version mismatches or because the React context is not shared between the InvenTree core and the plugin. This can lead to issues with rendering components, as the React context may not be shared between the two libraries.
To avoid issues, the InvenTree UI provides globally accessible components, which can be used as external modules by the plugin. This allows the plugin to use the same React context as the InvenTree core, and ensures that the plugin is compatible with the InvenTree user interface.
The following modules are provided as global objects at runtime:
React
ReactDOM
ReactDOMClient
Additionally, for the Mantine library, the following modules are provided as global objects at runtime:
@mantine/core
@mantine/hooks
@mantine/notifications
To use these modules in your plugin, they must be correctly externalized in the Vite configuration. Getting this right is crucial to ensure that the plugin is compatible with the InvenTree user interface. The InvenTree plugin creator provides a good starting point for this configuration, and can be used to generate a new plugin with the correct configuration.
Bundled Version
Keep in mind that the version of React and Mantine used in the InvenTree core may differ from the version used in your plugin. It is recommended to use the same version as the InvenTree core to avoid compatibility issues.
Plugin Creator¶
The InvenTree plugin creator provides an out-of-the-box setup for creating InvenTree plugins which integrate into the user interface. This includes a pre-configured Vite setup, which allows you to quickly get started with building your own custom UI plugins.
Using the plugin creator tool is the recommended way to get started with building custom UI plugins for InvenTree, as it provides a solid foundation to build upon. It is also the only method which is officially supported by the InvenTree development team!
DIY¶
Of course, you can also build your own custom UI plugins from scratch. This is a more advanced option, and requires a good understanding of the InvenTree codebase, as well as the technologies used to build the user interface. You are free to use other web technologies, however if you choose to do this, don't expect any support from the InvenTree development team. We will only provide support for plugins which are built using the recommended stack, and which follow the guidelines outlined in this documentation.