mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-27 14:16:02 +00:00
PUI Plugin Panels (#7470)
* Adds basic API endpoint for requesting plugin panels
* Split PanelType out into own file
* Placeholder for a plugin panel loaded dynamically
* Add some dummy data for the plugin panels
* Example of plugin panel selection based on page
* Expose some global window attributes
* Add new setting
* Disable panel return if plugin integration is not enabled
* Update hook to auto-magically load plugin panels
* Allow custom panel integration for more panel groups
* Remove debug call
* Tweak query return data
* async fn
* Adds <PluginPanel> component for handling panel render
* Cleanup
* Prevent API requests before instance ID is known
* Pass instance data through
* Framework for a sample plugin which implements custom panels
* offload custom panels to sample plugin
* Load raw HTML content
* Expand custom panel rendering demo
* Adjust API endpoints
* Add function to clear out static files which do not match installed plugin(s)
* Update static files when installing plugins from file
* Update static files when installing or uninstalling a plugin
* Update static files on config change
* Pass more information through to plugin panels
* Prepend hostname to plugin source
* Pass instance detail through
* Cleanup code for passing data through to plugin panels
- Define interface type
- Shorten variable names
* Update docs requirements
* Revert "Update docs requirements"
This reverts commit 63a06d97f5.
* Add placeholder for documentation
* Fix imports
* Add a broken panel which tries to load a non-existent javascript file
* Render error message if plugin does not load correctly
* Only allow superuser to perform plugin actions
* Code cleanup
* Add "dynamic" contnt - javascript file - to example plugin
* Remove default values
* Cleanup unused code
* PanelGroup updates
* Cleanup hooks for changing panel state
* More work needed...
* Code cleanup
* More updates / refactoring
- Allow dynamic hiding of a particular panel
- Pass target ref as positional argument
- Better handling of async calls
* Documentation
* Bump API version
* Provide theme object to plugin context
* Adjust sample plugin
* Docs updates
* Fix includefile call in docs
* Improve type annotation
* Cleanup
* Enable plugin panels for "purchasing index" and "sales index" pages
* Fix for plugin query check
* Improvements to panel selection
- Code refactor / cleanup
- Ensure that a valid panel is always displayed
- Allow plugin panels to persist, even after reload
* Playwright test fixes
* Update src/frontend/src/hooks/UsePluginPanels.tsx
Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com>
* Update src/frontend/src/components/plugins/PluginPanel.tsx
Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com>
* Update src/frontend/src/components/plugins/PluginContext.tsx
Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com>
* Fix context
* Add more context data
* Docs updates
* Reimplement local state
* Fix mkdocs.yml
* Expose 'colorScheme' to plugin context
* Define CustomPanel type definition
* Add unit testing for user interface plugins
* Add front-end tests for plugin panels
* Add new setting to plugin_settings_keys
* Adds helper function for annotating build line allocations
* Improve query efficiency
- Especially around unit testing
- Ensure all settings are generated
- Do not auto-create settings during registry load
* Improve query efficiency for build order operations
* Reduce max query count for specific test
* Revert query count limit
* playwright test updates
---------
Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"""Sample plugin which demonstrates user interface integrations."""
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from part.models import Part
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.helpers import render_template, render_text
|
||||
from plugin.mixins import SettingsMixin, UserInterfaceMixin
|
||||
|
||||
|
||||
class SampleUserInterfacePlugin(SettingsMixin, UserInterfaceMixin, InvenTreePlugin):
|
||||
"""A sample plugin which demonstrates user interface integrations."""
|
||||
|
||||
NAME = 'SampleUI'
|
||||
SLUG = 'sampleui'
|
||||
TITLE = 'Sample User Interface Plugin'
|
||||
DESCRIPTION = 'A sample plugin which demonstrates user interface integrations'
|
||||
VERSION = '1.0'
|
||||
|
||||
SETTINGS = {
|
||||
'ENABLE_PART_PANELS': {
|
||||
'name': _('Enable Part Panels'),
|
||||
'description': _('Enable custom panels for Part views'),
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
'ENABLE_PURCHASE_ORDER_PANELS': {
|
||||
'name': _('Enable Purchase Order Panels'),
|
||||
'description': _('Enable custom panels for Purchase Order views'),
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'ENABLE_BROKEN_PANELS': {
|
||||
'name': _('Enable Broken Panels'),
|
||||
'description': _('Enable broken panels for testing'),
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
'ENABLE_DYNAMIC_PANEL': {
|
||||
'name': _('Enable Dynamic Panel'),
|
||||
'description': _('Enable dynamic panels for testing'),
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
}
|
||||
|
||||
def get_custom_panels(self, instance_type: str, instance_id: int, request):
|
||||
"""Return a list of custom panels to be injected into the UI."""
|
||||
panels = []
|
||||
|
||||
# First, add a custom panel which will appear on every type of page
|
||||
# This panel will contain a simple message
|
||||
|
||||
content = render_text(
|
||||
"""
|
||||
This is a <i>sample panel</i> which appears on every page.
|
||||
It renders a simple string of <b>HTML</b> content.
|
||||
|
||||
<br>
|
||||
<h5>Instance Details:</h5>
|
||||
<ul>
|
||||
<li>Instance Type: {{ instance_type }}</li>
|
||||
<li>Instance ID: {{ instance_id }}</li>
|
||||
</ul>
|
||||
""",
|
||||
context={'instance_type': instance_type, 'instance_id': instance_id},
|
||||
)
|
||||
|
||||
panels.append({
|
||||
'name': 'sample_panel',
|
||||
'label': 'Sample Panel',
|
||||
'content': content,
|
||||
})
|
||||
|
||||
# A broken panel which tries to load a non-existent JS file
|
||||
if self.get_setting('ENABLE_BROKEN_PANElS'):
|
||||
panels.append({
|
||||
'name': 'broken_panel',
|
||||
'label': 'Broken Panel',
|
||||
'source': '/this/does/not/exist.js',
|
||||
})
|
||||
|
||||
# A dynamic panel which will be injected into the UI (loaded from external file)
|
||||
if self.get_setting('ENABLE_DYNAMIC_PANEL'):
|
||||
panels.append({
|
||||
'name': 'dynamic_panel',
|
||||
'label': 'Dynamic Part Panel',
|
||||
'source': '/static/plugin/sample_panel.js',
|
||||
'icon': 'part',
|
||||
})
|
||||
|
||||
# Next, add a custom panel which will appear on the 'part' page
|
||||
# Note that this content is rendered from a template file,
|
||||
# using the django templating system
|
||||
if self.get_setting('ENABLE_PART_PANELS') and instance_type == 'part':
|
||||
try:
|
||||
part = Part.objects.get(pk=instance_id)
|
||||
except (Part.DoesNotExist, ValueError):
|
||||
part = None
|
||||
|
||||
# Note: This panel will *only* be available if the part is active
|
||||
if part and part.active:
|
||||
content = render_template(
|
||||
self, 'uidemo/custom_part_panel.html', context={'part': part}
|
||||
)
|
||||
|
||||
panels.append({
|
||||
'name': 'part_panel',
|
||||
'label': 'Part Panel',
|
||||
'content': content,
|
||||
})
|
||||
|
||||
# Next, add a custom panel which will appear on the 'purchaseorder' page
|
||||
if (
|
||||
self.get_setting('ENABLE_PURCHASE_ORDER_PANELS')
|
||||
and instance_type == 'purchaseorder'
|
||||
):
|
||||
panels.append({
|
||||
'name': 'purchase_order_panel',
|
||||
'label': 'Purchase Order Panel',
|
||||
'content': 'This is a custom panel which appears on the <b>Purchase Order</b> view page.',
|
||||
})
|
||||
|
||||
return panels
|
||||
Reference in New Issue
Block a user