From 836b5bc741bcf877f45064b50383319bff04661b Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 13 Jan 2022 09:37:09 +1100 Subject: [PATCH 1/5] Update plugin docs - Create separate files for each mixin - Remove old "report" plugin docs --- docs/extend/plugins.md | 60 +++++++++++++++++++++++++++--- docs/extend/plugins/action.md | 2 +- docs/extend/plugins/api.md | 0 docs/extend/plugins/app.md | 10 +++++ docs/extend/plugins/barcode.md | 2 +- docs/extend/plugins/event.md | 3 ++ docs/extend/plugins/integration.md | 7 +--- docs/extend/plugins/navigation.md | 25 +++++++++++++ docs/extend/plugins/report.md | 10 ----- docs/extend/plugins/schedule.md | 3 ++ docs/extend/plugins/settings.md | 48 ++++++++++++++++++++++++ docs/extend/plugins/urls.md | 23 ++++++++++++ mkdocs.yml | 13 +++++-- 13 files changed, 179 insertions(+), 27 deletions(-) create mode 100644 docs/extend/plugins/api.md create mode 100644 docs/extend/plugins/app.md create mode 100644 docs/extend/plugins/event.md create mode 100644 docs/extend/plugins/navigation.md delete mode 100644 docs/extend/plugins/report.md create mode 100644 docs/extend/plugins/schedule.md create mode 100644 docs/extend/plugins/settings.md create mode 100644 docs/extend/plugins/urls.md diff --git a/docs/extend/plugins.md b/docs/extend/plugins.md index eff912b..1cdcd23 100644 --- a/docs/extend/plugins.md +++ b/docs/extend/plugins.md @@ -16,9 +16,59 @@ Plugins are discovered and loaded when the server is started. !!! info "Enable Plugin Support" To enable custom plugins, plugin support must be activated in the [server configuration](../start/config.md). -Multiple plugins are supported: +### Plugin Base Class -- [Reporting plugins](./plugins/report.md) -- [Barcode plugins](./plugins/barcode.md) -- [Action plugins](./plugins/action.md) -- [Integration plugins](./plugins/integration.md) +Custom plugins must inherit from the [IntegrationPluginBase class](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/integration.py). Any plugins installed via the methods outlined above will be "discovered" when the InvenTree server launches. + +### Plugin Options + +Some metadata options can be defined as constants in the plugins class + +``` python +PLUGIN_SLUG = None # Used in URLs, setting-names etc. when a unique slug as a reference is needed -> the plugin name is used if not set +PLUGIN_TITLE = None # A nice human friendly name for the plugin -> used in titles, as plugin name etc. + +AUTHOR = None # Author of the plugin, git commit information is used if not present +PUBLISH_DATE = None # Publishing date of the plugin, git commit information is used if not present +VERSION = None # Version of the plugin +WEBSITE = None # Website for the plugin, developer etc. -> is shown in plugin overview if set +``` + +Refer to the [sample plugins](https://github.com/inventree/InvenTree/tree/master/InvenTree/plugin/samples) for further examples. + +### Plugin Config + +A *PluginConfig* database entry will be created for each plugin "discovered" when the server launches. This configuration entry is used to determine if a particular plugin is enabled. + +The configuration entries must be enabled via the [InvenTree admin interface](../settings/admin.md). + +!!! warning "Disabled by Default" + Newly discovered plugins are disabled by default, and must be manually enabled by an admin user + +### Plugin Mixins + +Common use cases are covered by pre-supplied modules in the form of mixins (similar to how [django](https://docs.djangoproject.com/en/stable/topics/class-based-views/mixins/) does it). Each mixin enables the integration into a specific area of InvenTree. Sometimes it also enhances the plugin with helper functions to supply often used functions out-of-the-box. + +Supported mixin classes are: + +- [ActionMixin](./plugins/action.md) +- [APICallMixin](./plugins/api.md) +- [AppMixin](./plugins/app.md) +- [BarcodeMixin](./plugins/barcode.md) +- [EventMixin](./plugins/event.md) +- [NavigationMixin](./plugins/navigation.md) +- [ScheduleMixin](./plugins/schedule.md) +- [SettingsMixin](./plugins/settings.md) +- [UrlsMixin](./plugins/urls.md) + +## Installing a Plugin + +Plugins can either be loaded from paths in the InvenTree install directory or as a plugin installed via pip. We recommend installation via pip as this enables hassle-free upgrades. + +For development new plugins can be placed ina a subdirectory in `src/InvenTree/plugins`. Built-In plugins ship in `src/InvenTree/plugin/builtin`. To achive full unit-testing for all mixins there are some sample implementations in `src/InvenTree/plugin/samples`. These are not loaded in production mode. + +### Plugin Installation File + +Plugins installation can be simplified by providing a list of plugins in a plugin configuration file. This file (by default, 'plugins.txt' in the same directory as the server configuration file) contains a list of required plugin packages. + +Plugins can be installed from this file by simply running the command `invoke plugins`. diff --git a/docs/extend/plugins/action.md b/docs/extend/plugins/action.md index 94c2feb..36eb245 100644 --- a/docs/extend/plugins/action.md +++ b/docs/extend/plugins/action.md @@ -2,7 +2,7 @@ title: Action Plugins --- -### Action Plugins +## ActionMixin Arbitrary "actions" can be called by POSTing data to the `/api/action/` endpoint. The POST request must include the name of the action to be performed, and a matching ActionPlugin plugin must be loaded by the server. Arbitrary data can also be provided to the action plugin via the POST data: diff --git a/docs/extend/plugins/api.md b/docs/extend/plugins/api.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/extend/plugins/app.md b/docs/extend/plugins/app.md new file mode 100644 index 0000000..d953b21 --- /dev/null +++ b/docs/extend/plugins/app.md @@ -0,0 +1,10 @@ +--- +title: App Mixin +--- + +## AppMixin + +If this mixin is added to a plugin the directory the plugin class is defined in is added to the list of `INSTALLED_APPS` in the InvenTree server configuration. + +!!! warning "Danger Zone" + Only use this mixin if you have an understanding of djangos [app system](https://docs.djangoproject.com/en/stable/ref/applications). Plugins with this mixin are deeply integrated into InvenTree and can cause difficult to reproduce or long-running errors. Use the built-in testing functions of django to make sure your code does not cause unwanted behaviour in InvenTree before releasing. diff --git a/docs/extend/plugins/barcode.md b/docs/extend/plugins/barcode.md index c5d188d..6e7b16d 100644 --- a/docs/extend/plugins/barcode.md +++ b/docs/extend/plugins/barcode.md @@ -1,5 +1,5 @@ --- -title: Barcode Plugins +title: Barcode Mixin --- ### Barcode Plugins diff --git a/docs/extend/plugins/event.md b/docs/extend/plugins/event.md new file mode 100644 index 0000000..55f5ca2 --- /dev/null +++ b/docs/extend/plugins/event.md @@ -0,0 +1,3 @@ +--- +title: Event Mixin +--- \ No newline at end of file diff --git a/docs/extend/plugins/integration.md b/docs/extend/plugins/integration.md index fb109d8..e247ee1 100644 --- a/docs/extend/plugins/integration.md +++ b/docs/extend/plugins/integration.md @@ -24,12 +24,7 @@ WEBSITE = None # Website for the plugin, developer etc. -> is shown in plugin o -#### Installing a Plugin - -Plugins can either be loaded from paths in the InvenTree install directory or as a plugin installed via pip. We recommend installation via pip as this enables hassle-free upgrades. - -For development new plugins can be placed ina a subdirectroy in `src/InvenTree/plugins`. Built-In plugins ship in `src/InvenTree/plugin/builtin`. To achive full unit-testing for all mixins there are some sample implementations in `src/InvenTree/plugin/samples`. These are not loaded in production mode. - +## #### Mixins Common use cases are covered by pre-supplied modules in the form of mixins (similar to how [django](https://docs.djangoproject.com/en/stable/topics/class-based-views/mixins/) does it). Each mixin enables the integration into a specific area of InvenTree. Sometimes it also enhances the plugin with helper functions to supply often used functions out-of-the-box. diff --git a/docs/extend/plugins/navigation.md b/docs/extend/plugins/navigation.md new file mode 100644 index 0000000..86e3ce4 --- /dev/null +++ b/docs/extend/plugins/navigation.md @@ -0,0 +1,25 @@ +--- +title: Navigation Mixin +--- + +## NavigationMixin + +Use the class constant `NAVIGATION` for a array of links that should be added to InvenTrees navigation header. +The array must contain at least one dict that at least define a name and a link for each element. The link must be formatted for a URL pattern name lookup - links to external sites are not possible directly. The optional icon must be a class reference to an icon (InvenTree ships with fontawesome 4 by default). + +``` python +class MyNavigationPlugin(NavigationMixin, IntegrationPluginBase): + + PLUGIN_NAME = "NavigationPlugin" + + NAVIGATION = [ + {'name': 'SampleIntegration', 'link': 'plugin:sample:hi', 'icon': 'fas fa-box'}, + ] + + NAVIGATION_TAB_NAME = "Sample Nav" + NAVIGATION_TAB_ICON = 'fas fa-plus' +``` + +The optional class constants `NAVIGATION_TAB_NAME` and `NAVIGATION_TAB_ICON` can be used to change the name and icon for the parent navigation node. + + diff --git a/docs/extend/plugins/report.md b/docs/extend/plugins/report.md deleted file mode 100644 index d4b4f89..0000000 --- a/docs/extend/plugins/report.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Reporting Plugins ---- - -### Reporting Plugins - -InvenTree can generate customized reports (for example stocktake information, packing lists, acceptance test reports, etc). - -!!! missing "TODO" - Include more information here on reporting plugins diff --git a/docs/extend/plugins/schedule.md b/docs/extend/plugins/schedule.md new file mode 100644 index 0000000..df0d38e --- /dev/null +++ b/docs/extend/plugins/schedule.md @@ -0,0 +1,3 @@ +--- +title: Schedule Mixin +--- \ No newline at end of file diff --git a/docs/extend/plugins/settings.md b/docs/extend/plugins/settings.md new file mode 100644 index 0000000..484ed81 --- /dev/null +++ b/docs/extend/plugins/settings.md @@ -0,0 +1,48 @@ +--- +title: Settings Mixin +--- + +## SettingsMixin + +The *SettingsMixin* allows the plugin to save and load persistent settings to the database. + +- Plugin settings are stored against the individual plugin, and thus do not have to be unique +- Plugin settings are stored using a "key:value" pair + +Use the class constant `SETTINGS` for a dict of settings that should be added as global database settings. + +The dict must be formatted similar to the following sample. Take a look at the settings defined in `InvenTree.common.models.InvenTreeSetting` for all possible parameters. + + +``` python +class PluginWithSettings(SettingsMixin, IntegrationPluginBase): + + PLUGIN_NAME = "PluginWithSettings" + + SETTINGS = { + 'API_ENABLE': { + 'name': 'API Functionality', + 'description': 'Enable remote API queries', + 'validator': bool, + 'default': True, + }, + 'API_KEY': { + 'name': 'API Key', + 'description': 'Security key for accessing remote API', + 'default': '', + }, + 'API_URL': { + 'name': _('API URL'), + 'description': _('Base URL for remote server'), + 'default': 'http://remote.url/api', + }, + } +``` + +This mixin defines the helper functions `plugin.get_setting` and `plugin.set_seting` to access all plugin specific settings: + +```python +api_url = self.get_setting('API_URL') +``` + + diff --git a/docs/extend/plugins/urls.md b/docs/extend/plugins/urls.md new file mode 100644 index 0000000..1892a94 --- /dev/null +++ b/docs/extend/plugins/urls.md @@ -0,0 +1,23 @@ +--- +title: URLs Mixin +--- + +## UrlsMixin + +Use the class constant `URLS` for a array of URLs that should be added to InvenTrees URL paths or override the `plugin.setup_urls` function. + +The array has to contain valid URL patterns as defined in the [django documentation](https://docs.djangoproject.com/en/stable/topics/http/urls/). + +``` python +class MyUrlsPlugin(URLsMixin, IntegrationPluginBase): + + PLUGIN_NAME = "UrlsMixin" + + URLS = [ + url(r'increase/(?P\d+)/(?P\d+)/', self.view_increase, name='increase-level'), + ] +``` + +The URLs get exposed under `/plugin/{plugin.slug}/*` and get exposed to the template engine with the prefix `plugin:{plugin.slug}:` (for usage with the [url tag](https://docs.djangoproject.com/en/stable/ref/templates/builtins/#url)). + + diff --git a/mkdocs.yml b/mkdocs.yml index 804349e..192a789 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -111,10 +111,15 @@ nav: - Python Interface: extend/python.md - Plugins: - Overview: extend/plugins.md - - Reporting: extend/plugins/report.md - - Barcode: extend/plugins/barcode.md - - Action: extend/plugins/action.md - - Integration: extend/plugins/integration.md + - Action Mixin: extend/plugins/action.md + - API Mixin: extend/plugins/api.md + - App Mixin: extend/plugins/app.md + - Barcode Mixin: extend/plugins/barcode.md + - Event Mixin: extend/plugins/event.md + - Navigation Mixin: extend/plugins/navigation.md + - Schedule Mixin: extend/plugins/schedule.md + - Settings Mixin: extend/plugins/settings.md + - URL Mixin: extend/plugins/urls.md - Themes: extend/themes.md - Third-Party: extend/integrate.md - App: From 2f479b5d4ef8d83c2a0fa0dc718d791a07a82a27 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 13 Jan 2022 09:43:37 +1100 Subject: [PATCH 2/5] Add documentation for "events" mixin --- docs/extend/plugins/event.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/extend/plugins/event.md b/docs/extend/plugins/event.md index 55f5ca2..5dbf92d 100644 --- a/docs/extend/plugins/event.md +++ b/docs/extend/plugins/event.md @@ -1,3 +1,36 @@ --- title: Event Mixin ---- \ No newline at end of file +--- + +## EventMixin + +The `EventMixin` class enables plugins to respond to certain triggered events. + +When a certain (server-side) event occurs, the background worker passes the event information to any plugins which inherit from the `EventMixin` base class. + +Implementing classes must provide a `process_event` function: + +```python +class EventPlugin(EventMixin, IntegrationPluginBase): + """ + A simple example plugin which responds to events on the InvenTree server. + + This example simply prints out the event information. + A more complex plugin could respond to specific events however it wanted. + """ + + PLUGIN_NAME = "EventPlugin" + PLUGIN_SLUG = "event" + PLUGIN_TITLE = "Triggered Events" + + def process_event(self, event, *args, **kwargs): + print(f"Processing triggered event: '{event}'") +``` + +### Events + +Events are passed through using a string identifier, e.g. 'build.completed' + +The arguments (and keyword arguments) passed to the receiving function depend entirely on the type of event. + +Implementing a response to a particular event requires a working knowledge of the InvenTree code base, especially related to that event being received. From e6a99ee1eca5504ef23067f8d9af1898885e4e4e Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 13 Jan 2022 09:50:05 +1100 Subject: [PATCH 3/5] Docs for API and schedule mixins --- docs/extend/plugins/api.md | 7 +++++++ docs/extend/plugins/schedule.md | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/extend/plugins/api.md b/docs/extend/plugins/api.md index e69de29..1b9638c 100644 --- a/docs/extend/plugins/api.md +++ b/docs/extend/plugins/api.md @@ -0,0 +1,7 @@ +--- +title: Schedule Mixin +--- + +## APICallMixin + +The APICallMixin class provides basic functionality for integration with an external API. diff --git a/docs/extend/plugins/schedule.md b/docs/extend/plugins/schedule.md index df0d38e..5a713b7 100644 --- a/docs/extend/plugins/schedule.md +++ b/docs/extend/plugins/schedule.md @@ -1,3 +1,7 @@ --- title: Schedule Mixin ---- \ No newline at end of file +--- + +## ScheduleMixin + +The ScheduleMixin class provides a plugin with the ability to call functions at regular intervals. From 1a98204c76e3ffc243496fbf72455a434a9bcc3c Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 13 Jan 2022 10:37:54 +1100 Subject: [PATCH 4/5] Adds documentation for scheduled task mixin --- docs/extend/plugins/schedule.md | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/docs/extend/plugins/schedule.md b/docs/extend/plugins/schedule.md index 5a713b7..6752980 100644 --- a/docs/extend/plugins/schedule.md +++ b/docs/extend/plugins/schedule.md @@ -5,3 +5,47 @@ title: Schedule Mixin ## ScheduleMixin The ScheduleMixin class provides a plugin with the ability to call functions at regular intervals. + +- Functions are registered with the InvenTree worker which runs as a background process. +- Scheduled functions do not accept any arguments +- Plugin member functions can be called +- Global functions can be specified using dotted notation + +### Example + +An example of a plugin which supports scheduled tasks: + +```python +class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, IntegrationPluginBase): + """ + Sample plugin which runs a scheduled task, and provides user configuration. + """ + + PLUGIN_NAME = "Scheduled Tasks" + PLUGIN_SLUG = 'schedule' + + SCHEDULED_TASKS = { + 'global': { + 'func': 'some_module.function', + 'schedule': 'H', # Run every hour + }, + 'member': { + 'func': 'foo', + 'schedule': 'I', # Minutes + 'minutes': 15, + }, + } + + SETTINGS = { + 'SECRET': { + 'name': 'A secret', + 'description': 'User configurable value', + }, + } + + def foo(self): + """ + This function runs every 15 minutes + """ + secret_value = self.get_setting('SECRET') + print(f"foo - SECRET = {secret_value}) From 9c0d9b9952023711ae3a35468eb8f1504f327d5b Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 13 Jan 2022 10:40:03 +1100 Subject: [PATCH 5/5] typo fix --- docs/extend/plugins/schedule.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/extend/plugins/schedule.md b/docs/extend/plugins/schedule.md index 6752980..c4a74e5 100644 --- a/docs/extend/plugins/schedule.md +++ b/docs/extend/plugins/schedule.md @@ -49,3 +49,4 @@ class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, IntegrationPluginBase): """ secret_value = self.get_setting('SECRET') print(f"foo - SECRET = {secret_value}) +```