Coverage for src/backend/InvenTree/plugin/base/ui/mixins.py: 57%
35 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""UserInterfaceMixin class definition.
3Allows integration of custom UI elements into the React user interface.
4"""
6from typing import Literal, TypedDict
8import structlog
9from rest_framework.request import Request
11from plugin import PluginMixinEnum
13logger = structlog.get_logger('inventree')
16# List of supported feature types
17FeatureType = Literal[
18 'spotlight_action', # Custom actions for the spotlight search
19 'dashboard', # Custom dashboard items
20 'panel', # Custom panels
21 'template_editor', # Custom template editor
22 'template_preview', # Custom template preview
23 'navigation', # Custom navigation items
24 'primary_action', # Custom primary action buttons
25]
28class UIFeature(TypedDict):
29 """Base type definition for a ui feature.
31 Attributes:
32 key: The key of the feature (required, must be a unique identifier)
33 title: The title of the feature (required, human readable)
34 description: The long-form description of the feature (optional, human readable)
35 icon: The icon of the feature (optional, must be a valid icon identifier)
36 feature_type: The feature type (required, see documentation for all available types)
37 options: Feature options (required, see documentation for all available options for each type)
38 context: Additional context data to be passed to the rendering function (optional, dict)
39 source: The source of the feature (required, path to a JavaScript file, with optional function name).
40 """
42 key: str
43 title: str
44 description: str
45 icon: str
46 feature_type: FeatureType
47 options: dict
48 context: dict
49 source: str
52class CustomPanelOptions(TypedDict):
53 """Options type definition for a custom panel.
55 Attributes:
56 icon: The icon of the panel (optional, must be a valid icon identifier).
57 """
60class CustomDashboardItemOptions(TypedDict):
61 """Options type definition for a custom dashboard item.
63 Attributes:
64 width: The minimum width of the dashboard item (integer, defaults to 2)
65 height: The minimum height of the dashboard item (integer, defaults to 2)
66 """
68 width: int
69 height: int
72class UserInterfaceMixin:
73 """Plugin mixin class which handles injection of custom elements into the front-end interface.
75 - All content is accessed via the API, as requested by the user interface.
76 - This means that content can be dynamically generated, based on the current state of the system.
77 """
79 class MixinMeta:
80 """Metaclass for this plugin mixin."""
82 MIXIN_NAME = 'ui'
84 def __init__(self):
85 """Register mixin."""
86 super().__init__()
87 self.add_mixin(PluginMixinEnum.USER_INTERFACE, True, __class__)
89 def get_ui_features(
90 self, feature_type: FeatureType, context: dict, request: Request, **kwargs
91 ) -> list[UIFeature]:
92 """Return a list of custom features to be injected into the UI.
94 Arguments:
95 feature_type: The type of feature being requested
96 context: Additional context data provided by the UI (query parameters)
97 request: HTTPRequest object (including user information)
99 Returns:
100 list: A list of custom UIFeature dicts to be injected into the UI
102 """
103 feature_map = {
104 'spotlight_action': self.get_ui_spotlight_actions,
105 'dashboard': self.get_ui_dashboard_items,
106 'navigation': self.get_ui_navigation_items,
107 'panel': self.get_ui_panels,
108 'template_editor': self.get_ui_template_editors,
109 'template_preview': self.get_ui_template_previews,
110 'primary_action': self.get_ui_primary_actions,
111 }
113 if feature_type in feature_map:
114 return feature_map[feature_type](request, context, **kwargs)
115 else:
116 logger.warning(f'Invalid feature type: {feature_type}')
117 return []
119 def get_ui_spotlight_actions(
120 self, request: Request, context: dict, **kwargs
121 ) -> list[UIFeature]:
122 """Return a list of custom actions to be injected into the UI spotlight.
124 Args:
125 request: HTTPRequest object (including user information)
126 context: Additional context data provided by the UI (query parameters)
128 Returns:
129 list: A list of custom actions to be injected into the UI spotlight.
130 """
131 # Default implementation returns an empty list
132 return []
134 def get_ui_panels(
135 self, request: Request, context: dict, **kwargs
136 ) -> list[UIFeature]:
137 """Return a list of custom panels to be injected into the UI.
139 Args:
140 request: HTTPRequest object (including user information)
141 context: Additional context data provided by the UI (query parameters)
143 Returns:
144 list: A list of custom panels to be injected into the UI
145 """
146 # Default implementation returns an empty list
147 return []
149 def get_ui_dashboard_items(
150 self, request: Request, context: dict, **kwargs
151 ) -> list[UIFeature]:
152 """Return a list of custom dashboard items to be injected into the UI.
154 Args:
155 request: HTTPRequest object (including user information)
156 context: Additional context data provided by the UI (query parameters)
158 Returns:
159 list: A list of custom dashboard items to be injected into the UI
160 """
161 # Default implementation returns an empty list
162 return []
164 def get_ui_template_editors(
165 self, request: Request, context: dict, **kwargs
166 ) -> list[UIFeature]:
167 """Return a list of custom template editors to be injected into the UI.
169 Args:
170 request: HTTPRequest object (including user information)
171 context: Additional context data provided by the UI (query parameters)
173 Returns:
174 list: A list of custom template editors to be injected into the UI
175 """
176 # Default implementation returns an empty list
177 return []
179 def get_ui_template_previews(
180 self, request: Request, context: dict, **kwargs
181 ) -> list[UIFeature]:
182 """Return a list of custom template previews to be injected into the UI.
184 Args:
185 request: HTTPRequest object (including user information)
186 context: Additional context data provided by the UI (query parameters)
188 Returns:
189 list: A list of custom template previews to be injected into the UI
190 """
191 # Default implementation returns an empty list
192 return []
194 def get_ui_navigation_items(
195 self, request: Request, context: dict, **kwargs
196 ) -> list[UIFeature]:
197 """Return a list of custom navigation items to be injected into the UI.
199 Args:
200 request: HTTPRequest object (including user information)
201 context: Additional context data provided by the UI (query parameters)
203 Returns:
204 list: A list of custom navigation items to be injected into the UI
205 """
206 # Default implementation returns an empty list
207 return []
209 def get_ui_primary_actions(
210 self, request: Request, context: dict, **kwargs
211 ) -> list[UIFeature]:
212 """Return a list of custom primary action buttons to be injected into the UI.
214 Args:
215 request: HTTPRequest object (including user information)
216 context: Additional context data provided by the UI (query parameters)
218 Returns:
219 list: A list of custom primary action buttons to be injected into the UI
220 """
221 # Sample code to render conditional primary action button based on context
222 # items = []
223 # if self.my_assert_function(context):
224 # items.append({
225 # 'key': 'sample-primary-action',
226 # 'title': 'Sample Primary Action',
227 # 'icon': 'ti:plus:outline',
228 # 'options': {'url': '/core/sample-primary-action/', 'color': 'orange'},
229 # })
230 # return items
232 # Default implementation returns an empty list
233 return []