mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	[PUI] Plugin panel context (#8190)
* Add server-side context for panel plugin rendering * Add "context" to PluginContext type * Pass server context through to client-side rendering * Bump API version
This commit is contained in:
		| @@ -1,13 +1,16 @@ | ||||
| """InvenTree API version information.""" | ||||
|  | ||||
| # InvenTree API version | ||||
| INVENTREE_API_VERSION = 259 | ||||
| INVENTREE_API_VERSION = 260 | ||||
|  | ||||
| """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" | ||||
|  | ||||
|  | ||||
| INVENTREE_API_TEXT = """ | ||||
|  | ||||
| v260 - 2024-09-26 : https://github.com/inventree/InvenTree/pull/8190 | ||||
|     - Adds facility for server-side context data to be passed to client-side plugins | ||||
|  | ||||
| v259 - 2024-09-20 : https://github.com/inventree/InvenTree/pull/8137 | ||||
|     - Implements new API endpoint for enabling custom UI features via plugins | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ class CustomPanel(TypedDict): | ||||
|         label: The label of the panel (required, human readable). | ||||
|         icon: The icon of the panel (optional, must be a valid icon identifier). | ||||
|         content: The content of the panel (optional, raw HTML). | ||||
|         context: Optional context data (dict / JSON) which will be passed to the front-end rendering function | ||||
|         source: The source of the panel (optional, path to a JavaScript file). | ||||
|     """ | ||||
|  | ||||
| @@ -26,6 +27,7 @@ class CustomPanel(TypedDict): | ||||
|     label: str | ||||
|     icon: str | ||||
|     content: str | ||||
|     context: dict | ||||
|     source: str | ||||
|  | ||||
|  | ||||
| @@ -87,6 +89,7 @@ class UserInterfaceMixin: | ||||
|             'label': 'Panel Title',  # The title of the panel (required, human readable) | ||||
|             'icon': 'icon-name',  # Icon name (optional, must be a valid icon identifier) | ||||
|             'content': '<p>Panel content</p>',  # HTML content to be rendered in the panel (optional) | ||||
|             'context': {'key': 'value'},  # Context data to be passed to the front-end rendering function (optional) | ||||
|             'source': 'static/plugin/panel.js',  # Path to a JavaScript file to be loaded (optional) | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ class PluginPanelSerializer(serializers.Serializer): | ||||
|             # Following fields are optional | ||||
|             'icon', | ||||
|             'content', | ||||
|             'context', | ||||
|             'source', | ||||
|         ] | ||||
|  | ||||
| @@ -43,6 +44,10 @@ class PluginPanelSerializer(serializers.Serializer): | ||||
|         label=_('Panel Content (HTML)'), required=False, allow_blank=True | ||||
|     ) | ||||
|  | ||||
|     context = serializers.JSONField( | ||||
|         label=_('Panel Context (JSON)'), required=False, allow_null=True, default=None | ||||
|     ) | ||||
|  | ||||
|     source = serializers.CharField( | ||||
|         label=_('Panel Source (javascript)'), required=False, allow_blank=True | ||||
|     ) | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| """Sample plugin which demonstrates user interface integrations.""" | ||||
|  | ||||
| import random | ||||
| import time | ||||
|  | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
| from InvenTree.version import INVENTREE_SW_VERSION | ||||
| from part.models import Part | ||||
| from plugin import InvenTreePlugin | ||||
| from plugin.helpers import render_template, render_text | ||||
| @@ -15,7 +19,7 @@ class SampleUserInterfacePlugin(SettingsMixin, UserInterfaceMixin, InvenTreePlug | ||||
|     SLUG = 'sampleui' | ||||
|     TITLE = 'Sample User Interface Plugin' | ||||
|     DESCRIPTION = 'A sample plugin which demonstrates user interface integrations' | ||||
|     VERSION = '1.0' | ||||
|     VERSION = '1.1' | ||||
|  | ||||
|     SETTINGS = { | ||||
|         'ENABLE_PART_PANELS': { | ||||
| @@ -81,11 +85,18 @@ class SampleUserInterfacePlugin(SettingsMixin, UserInterfaceMixin, InvenTreePlug | ||||
|             }) | ||||
|  | ||||
|         # A dynamic panel which will be injected into the UI (loaded from external file) | ||||
|         # Note that we additionally provide some "context" data to the front-end render function | ||||
|         if self.get_setting('ENABLE_DYNAMIC_PANEL'): | ||||
|             panels.append({ | ||||
|                 'name': 'dynamic_panel', | ||||
|                 'label': 'Dynamic Part Panel', | ||||
|                 'source': '/static/plugin/sample_panel.js', | ||||
|                 'context': { | ||||
|                     'version': INVENTREE_SW_VERSION, | ||||
|                     'plugin_version': self.VERSION, | ||||
|                     'random': random.randint(1, 100), | ||||
|                     'time': time.time(), | ||||
|                 }, | ||||
|                 'icon': 'part', | ||||
|             }) | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * as well as dynamically hidden, based on the provided context. | ||||
|  */ | ||||
|  | ||||
| export function renderPanel(target, context) { | ||||
| export function renderPanel(target, data) { | ||||
|  | ||||
|     if (!target) { | ||||
|         console.error("No target provided to renderPanel"); | ||||
| @@ -22,13 +22,22 @@ export function renderPanel(target, context) { | ||||
|     <p>It can be hidden or displayed based on the provided context.</p> | ||||
|  | ||||
|     <hr> | ||||
|     <h5>Context:</h5> | ||||
|     <h5>Client Context:</h5> | ||||
|  | ||||
|     <ul> | ||||
|     <li>Username: ${context.user.username()}</li> | ||||
|     <li>Is Staff: ${context.user.isStaff() ? "YES": "NO"}</li> | ||||
|     <li>Model Type: ${context.model}</li> | ||||
|     <li>Instance ID: ${context.id}</li> | ||||
|     <li>Username: ${data.user.username()}</li> | ||||
|     <li>Is Staff: ${data.user.isStaff() ? "YES": "NO"}</li> | ||||
|     <li>Model Type: ${data.model}</li> | ||||
|     <li>Instance ID: ${data.id}</li> | ||||
|     </ul> | ||||
|     <hr> | ||||
|     <h5>Server Context:</h5> | ||||
|     <ul> | ||||
|     <li>Server Version: ${data.context.version}</li> | ||||
|     <li>Plugin Version: ${data.context.plugin_version}</li> | ||||
|     <li>Random Number: ${data.context.random}</li> | ||||
|     <li>Time: ${data.context.time}</li> | ||||
|     </ul> | ||||
|     `; | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user