2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

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

View File

@ -3,7 +3,9 @@ Plugin mixin classes
""" """
from django.conf.urls import url, include 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 from plugin.urls import PLUGIN_BASE
@ -18,43 +20,48 @@ class SettingsMixin:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.add_mixin('settings', 'has_settings', __class__) self.add_mixin('settings', 'has_settings', __class__)
self.globalsettings = getattr(self, 'SETTINGS', None) self.settings = getattr(self, 'SETTINGS', {})
@property @property
def has_settings(self): def has_settings(self):
""" """
Does this plugin use custom global settings Does this plugin use custom global settings
""" """
return bool(self.globalsettings) return bool(self.settings)
@property def get_setting(self, key):
def globalsettingspatterns(self):
""" """
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): # Find the plugin configuration associated with this plugin
"""
Get global name of setting
"""
return f'PLUGIN_{self.slug.upper()}_{key}'
def get_globalsetting(self, key): try:
""" plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
get plugin global setting by key except (OperationalError, ProgrammingError) as error:
""" plugin = None
from common.models import InvenTreeSetting
return InvenTreeSetting.get_setting(self._globalsetting_name(key)) 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: class UrlsMixin:

View File

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

View File

@ -2,6 +2,9 @@
"""Base Class for InvenTree plugins""" """Base Class for InvenTree plugins"""
from django.utils.text import slugify
class InvenTreePlugin(): class InvenTreePlugin():
""" """
Base class for a plugin Base class for a plugin
@ -10,9 +13,28 @@ class InvenTreePlugin():
# Override the plugin name for each concrete plugin instance # Override the plugin name for each concrete plugin instance
PLUGIN_NAME = '' PLUGIN_NAME = ''
PLUGIN_SLUG = ''
PLUGIN_TITLE = ''
def plugin_name(self): def plugin_name(self):
"""get plugin name""" """
Return the name of this plugin plugin
"""
return self.PLUGIN_NAME 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): def __init__(self):
pass pass

View File

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

View File

@ -44,6 +44,15 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
'default': True, 'default': True,
'validator': bool, '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 = [ NAVIGATION = [

View File

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

View File

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

View File

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

View File

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

View File

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