diff --git a/docs/docs/assets/images/plugin/mouser.png b/docs/docs/assets/images/plugin/mouser.png index f4100f550d..4163d2f775 100644 Binary files a/docs/docs/assets/images/plugin/mouser.png and b/docs/docs/assets/images/plugin/mouser.png differ diff --git a/docs/docs/assets/images/plugin/panel_with_userinput.png b/docs/docs/assets/images/plugin/panel_with_userinput.png new file mode 100644 index 0000000000..cc5de0a635 Binary files /dev/null and b/docs/docs/assets/images/plugin/panel_with_userinput.png differ diff --git a/docs/docs/extend/plugins/panel.md b/docs/docs/extend/plugins/panel.md index 4a7a9318aa..e518ced947 100644 --- a/docs/docs/extend/plugins/panel.md +++ b/docs/docs/extend/plugins/panel.md @@ -53,7 +53,7 @@ Or to add a template file that will be rendered as javascript code, from the plu Note : see convention for template directory above. -## Example Implementation +## Example Implementations Refer to the `CustomPanelSample` example class in the `./plugin/samples/integration/` directory, for a fully worked example of how custom UI panels can be implemented. @@ -74,9 +74,9 @@ from django.http import HttpResponse from order.views import PurchaseOrderDetail from plugin import InvenTreePlugin -from plugin.mixins import PanelMixin, SettingsMixin, UrlsMixin +from plugin.mixins import PanelMixin, UrlsMixin -class MouserCartPanel(PanelMixin, SettingsMixin, InvenTreePlugin, UrlsMixin): +class MouserCartPanel(PanelMixin, InvenTreePlugin, UrlsMixin): value=1 @@ -147,9 +147,10 @@ async function JGetCart(){ {% endraw %} ``` -We start with a bit of javascript. The function JGetCart just calls the url that has been defined in the python code above. -The url consists of a full path `plugin:plugin-name:url-name`. The plugin-name is the SLUG that was defined in the plugin code. -order.pk is the parameter that is passed to python. +We start with a bit of javascript. The function JGetCart just calls the url +that has been defined in the python code above. The url consists of a full +path `plugin:plugin-name:url-name`. The plugin-name is the SLUG that was +defined in the plugin code. order.pk is the parameter that is passed to python. The button is defined with `class="btn btn-info` This is an InvenTree predefined button. There a are lots of others available. Here are some examples of available colors: @@ -160,3 +161,98 @@ Please have a look at the css files for more options. The last line renders the !!! tip "Give it a try" Each time you press the button, the value will be increased. + +### Handling user input + +A common user case is user input that needs to be passed from the panel into +the plugin for further processing. Lets have a look at another example. We +will define two user input fields. One is an integer the other one a string. +A button will be defined to submit the data. Something like that: + +{% with id="panel_with_userinput", url="plugin/panel_with_userinput.png", description="Panel with user input" %} {% include "img.html" %} {% endwith %} + +Here is the plugin code: + +```python +from django.urls import path +from django.http import HttpResponse + +from plugin import InvenTreePlugin +from plugin.mixins import PanelMixin, UrlsMixin + +class ExamplePanel(PanelMixin, InvenTreePlugin, UrlsMixin): + + NAME = "ExamplePanel" + SLUG = "examplepanel" + TITLE = "Example for data input" + AUTHOR = "Michael" + DESCRIPTION = "This plugin passes user input from the panel to the plugin" + +# Create the panel that will display on every view + def get_custom_panels(self, view, request): + panels = [] + panels.append({ + 'title': 'Example Info', + 'icon': 'fa-industry', + 'content_template': 'example_panel/example.html', + }) + return panels + + def setup_urls(self): + return [ + path("example///", + self.do_something, name = 'transfer'), + ] + +# Define the function that will be called. + def do_something(self, request, layer, size): + + print('Example panel received:', layer, size) + return HttpResponse(f'OK') +``` + +The start is easy because it is the same as in the example above. +Lets concentrate on the setup_urls. This time we use +path (imported from django.urls) instead of url for definition. Using path makes it easier to +define the data types. No regular expressions. The URL takes two parameters, +layer and size, and passes them to the python function do_something for further processing. +Now the html template: + +```html +{% raw %} + + +
+ Number of Layers
+
+ Size of Board in mm
+ +
+ + +{% endraw %} +``` + +The HTML defines the form for user input, one number and one string. Each +form has an ID that is used in the javascript code to get the input of the form. +The response URL must match the URL defined in the plugin. Here we have a number +(999999) and a string (Size). These get replaced with the content of the fields +upon execution using replace. Watch out for the ticks around the 999999 and Size. They prevent +them from being interpreted by the django template engine and replaced by +something else. + +The function inventreeFormDataUpload is a helper function defined by InvenTree +that does the POST request, handles errors and the csrftoken. + +!!! tip "Give it a try" + change the values in the fields and push Save. You will see the values + in the InvenTree log.