More refactoring:

- Rename "mixins_globalsettings" to "mixing_settings"
- Fix translation on settings page template
This commit is contained in:
Oliver 2022-01-02 11:21:06 +11:00
parent 737467a1fd
commit f3bfe6e7ca
11 changed files with 91 additions and 53 deletions

View File

@ -4,8 +4,7 @@ from __future__ import unicode_literals
from django.contrib import admin
import plugin.models as models
from plugin import plugin_reg
import plugin.registry as registry
def plugin_update(queryset, new_status: bool):
"""general function for bulk changing plugins"""
@ -20,7 +19,7 @@ def plugin_update(queryset, new_status: bool):
# reload plugins if they changed
if apps_changed:
plugin_reg.reload_plugins()
registry.plugin_registry.reload_plugins()
@admin.action(description='Activate plugin(s)')
@ -42,6 +41,13 @@ class PluginSettingInline(admin.TabularInline):
model = models.PluginSetting
read_only_fields = [
'key',
]
def has_add_permission(self, request, obj):
return False
class PluginConfigAdmin(admin.ModelAdmin):
"""Custom admin with restricted id fields"""

View File

@ -3,7 +3,9 @@ Plugin mixin classes
"""
from django.conf.urls import url, include
from django.db.utils import OperationalError, ProgrammingError
from plugin.models import PluginConfig, PluginSetting
from plugin.urls import PLUGIN_BASE
@ -18,43 +20,48 @@ class SettingsMixin:
def __init__(self):
super().__init__()
self.add_mixin('settings', 'has_settings', __class__)
self.globalsettings = getattr(self, 'SETTINGS', None)
self.settings = getattr(self, 'SETTINGS', {})
@property
def has_settings(self):
"""
Does this plugin use custom global settings
"""
return bool(self.globalsettings)
return bool(self.settings)
@property
def globalsettingspatterns(self):
def get_setting(self, key):
"""
Get patterns for InvenTreeSetting defintion
Return the 'value' of the setting associated with this plugin
"""
if self.has_settings:
return {f'PLUGIN_{self.slug.upper()}_{key}': value for key, value in self.globalsettings.items()}
return None
def _globalsetting_name(self, key):
"""
Get global name of setting
"""
return f'PLUGIN_{self.slug.upper()}_{key}'
# Find the plugin configuration associated with this plugin
def get_globalsetting(self, key):
"""
get plugin global setting by key
"""
from common.models import InvenTreeSetting
return InvenTreeSetting.get_setting(self._globalsetting_name(key))
try:
plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
except (OperationalError, ProgrammingError) as error:
plugin = None
if not plugin:
# Plugin cannot be found, return default value
return PluginSetting.get_setting_default(key, settings=self.settings)
def set_globalsetting(self, key, value, user):
return PluginSetting.get_setting(key, plugin=plugin, settings=self.settings)
def set_setting(self, key, value, user):
"""
set plugin global setting by key
Set plugin setting value by key
"""
from common.models import InvenTreeSetting
return InvenTreeSetting.set_setting(self._globalsetting_name(key), value, user)
try:
plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
except (OperationalError, ProgrammingError) as error:
plugin = None
if not plugin:
# Cannot find associated plugin model, return
return
PluginSetting.set_setting(key, value, user, plugin=plugin, settings=self.settings)
class UrlsMixin:

View File

@ -59,8 +59,6 @@ class IntegrationPluginBase(MixinBase, plugin.InvenTreePlugin):
"""
The IntegrationPluginBase class is used to integrate with 3rd party software
"""
PLUGIN_SLUG = None
PLUGIN_TITLE = None
AUTHOR = None
DESCRIPTION = None
@ -84,11 +82,7 @@ class IntegrationPluginBase(MixinBase, plugin.InvenTreePlugin):
# region properties
@property
def slug(self):
"""slug for the plugin"""
slug = getattr(self, 'PLUGIN_SLUG', None)
if not slug:
slug = self.plugin_name()
return slugify(slug)
return self.plugin_slug()
@property
def human_name(self):

View File

@ -2,6 +2,9 @@
"""Base Class for InvenTree plugins"""
from django.utils.text import slugify
class InvenTreePlugin():
"""
Base class for a plugin
@ -10,9 +13,28 @@ class InvenTreePlugin():
# Override the plugin name for each concrete plugin instance
PLUGIN_NAME = ''
PLUGIN_SLUG = ''
PLUGIN_TITLE = ''
def plugin_name(self):
"""get plugin name"""
"""
Return the name of this plugin plugin
"""
return self.PLUGIN_NAME
def plugin_slug(self):
slug = getattr(self, 'PLUGIN_SLUG', None)
if slug is None:
slug = self.plugin_name()
return slugify(slug)
def plugin_title(self):
return self.PLUGIN_TITLE
def __init__(self):
pass

View File

@ -50,7 +50,7 @@ class Plugins:
# integration specific
self.installed_apps = [] # Holds all added plugin_paths
# mixins
self.mixins_globalsettings = {}
self.mixins_settings = {}
# region public plugin functions
def load_plugins(self):
@ -252,8 +252,8 @@ class Plugins:
logger.info('Registering IntegrationPlugin global settings')
for slug, plugin in plugins:
if plugin.mixin_enabled('settings'):
plugin_setting = plugin.globalsettingspatterns
self.mixins_globalsettings[slug] = plugin_setting
plugin_setting = plugin.settings
self.mixins_settings[slug] = plugin_setting
# Add to settings dir
InvenTreeSetting.SETTINGS.update(plugin_setting)
@ -263,7 +263,7 @@ class Plugins:
# collect all settings
plugin_settings = {}
for _, plugin_setting in self.mixins_globalsettings.items():
for _, plugin_setting in self.mixins_settings.items():
plugin_settings.update(plugin_setting)
# remove settings
@ -271,7 +271,7 @@ class Plugins:
InvenTreeSetting.SETTINGS.pop(setting)
# clear cache
self.mixins_globalsettings = {}
self.mixins_Fsettings = {}
# endregion
# region integration_app

View File

@ -44,6 +44,15 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
'default': True,
'validator': bool,
},
'API_KEY': {
'name': _('API Key'),
'description': _('Key required for accessing external API'),
},
'NUMERICAL_SETTING': {
'name': _('Numerical'),
'description': _('A numerical setting'),
'validator': int,
},
}
NAVIGATION = [

View File

@ -26,9 +26,9 @@ def inactive_plugin_list(*args, **kwargs):
@register.simple_tag()
def plugin_globalsettings(plugin, *args, **kwargs):
""" Return a list of all global settings for a plugin """
return plugin_reg.mixins_globalsettings.get(plugin)
def plugin_settings(plugin, *args, **kwargs):
""" Return a list of all custom settings for a plugin """
return plugin_reg.mixins_settings.get(plugin)
@register.simple_tag()

View File

@ -46,15 +46,15 @@ class SettingsMixinTest(BaseMixinDefinition, TestCase):
# calling settings
# not existing
self.assertEqual(self.mixin.get_globalsetting('ABCD'), '')
self.assertEqual(self.mixin_nothing.get_globalsetting('ABCD'), '')
self.assertEqual(self.mixin.get_setting('ABCD'), '')
self.assertEqual(self.mixin_nothing.get_setting('ABCD'), '')
# right setting
self.mixin.set_globalsetting('SETTING1', '12345', self.test_user)
self.assertEqual(self.mixin.get_globalsetting('SETTING1'), '12345')
self.mixin.set_setting('SETTING1', '12345', self.test_user)
self.assertEqual(self.mixin.get_setting('SETTING1'), '12345')
# no setting
self.assertEqual(self.mixin_nothing.get_globalsetting(''), '')
self.assertEqual(self.mixin_nothing.get_setting(''), '')
class UrlsMixinTest(BaseMixinDefinition, TestCase):

View File

@ -63,11 +63,11 @@ class PluginTagTests(TestCase):
"""test that all inactive plugins are listed"""
self.assertEqual(plugin_tags.inactive_plugin_list(), plugin_reg.plugins_inactive)
def test_tag_plugin_globalsettings(self):
def test_tag_plugin_settings(self):
"""check all plugins are listed"""
self.assertEqual(
plugin_tags.plugin_globalsettings(self.sample),
plugin_reg.mixins_globalsettings.get(self.sample)
plugin_tags.plugin_settings(self.sample),
plugin_reg.mixins_settings.get(self.sample)
)
def test_tag_mixin_enabled(self):

View File

@ -5,7 +5,7 @@
<h4>{% trans "Settings" %}</h4>
</div>
{% plugin_globalsettings plugin_key as plugin_settings %}
{% plugin_settings plugin_key as plugin_settings %}
<table class='table table-striped table-condensed'>
<tbody>

View File

@ -13,7 +13,7 @@
<span class='fas {{ icon }}'></span>
{% endif %}
</td>
<td><strong>{% trans setting.name %}</strong></td>
<td><strong>{{ setting.name }}</strong></td>
<td>
{% if setting.is_bool %}
<div class='form-check form-switch'>
@ -32,7 +32,7 @@
</div>
{% endif %}
<td>
{% trans setting.description %}
{{ setting.description }}
</td>
<td>
<div class='btn-group float-right'>