mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Adds API endpoints for viewing and updating plugin settings
A lot of code updates / refactoring here to get this to work as expected
This commit is contained in:
parent
f3bfe6e7ca
commit
dc9e25ebad
@ -12,11 +12,15 @@ import common.models
|
||||
INVENTREE_SW_VERSION = "0.6.0 dev"
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 22
|
||||
INVENTREE_API_VERSION = 23
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v23 -> 2022-02-02
|
||||
- Adds API endpoints for managing plugin classes
|
||||
- Adds API endpoints for managing plugin settings
|
||||
|
||||
v22 -> 2021-12-20
|
||||
- Adds API endpoint to "merge" multiple stock items
|
||||
|
||||
|
@ -71,7 +71,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
super().save()
|
||||
|
||||
@classmethod
|
||||
def allValues(cls, user=None, plugin=None, exclude_hidden=False):
|
||||
def allValues(cls, user=None, exclude_hidden=False):
|
||||
"""
|
||||
Return a dict of "all" defined global settings.
|
||||
|
||||
@ -86,10 +86,6 @@ class BaseInvenTreeSetting(models.Model):
|
||||
if user is not None:
|
||||
results = results.filter(user=user)
|
||||
|
||||
# Optionally filter by plugin
|
||||
if plugin is not None:
|
||||
results = results.filter(plugin=plugin)
|
||||
|
||||
# Query the database
|
||||
settings = {}
|
||||
|
||||
@ -238,16 +234,12 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
settings = cls.objects.all()
|
||||
|
||||
# Filter by user
|
||||
user = kwargs.get('user', None)
|
||||
|
||||
if user is not None:
|
||||
settings = settings.filter(user=user)
|
||||
|
||||
plugin = kwargs.get('plugin', None)
|
||||
|
||||
if plugin is not None:
|
||||
settings = settings.filter(plugin=plugin)
|
||||
|
||||
try:
|
||||
setting = settings.filter(**cls.get_filters(key, **kwargs)).first()
|
||||
except (ValueError, cls.DoesNotExist):
|
||||
@ -255,6 +247,16 @@ class BaseInvenTreeSetting(models.Model):
|
||||
except (IntegrityError, OperationalError):
|
||||
setting = None
|
||||
|
||||
plugin = kwargs.pop('plugin', None)
|
||||
|
||||
if plugin:
|
||||
from plugin import InvenTreePlugin
|
||||
|
||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
||||
plugin = plugin.plugin_config()
|
||||
|
||||
kwargs['plugin'] = plugin
|
||||
|
||||
# Setting does not exist! (Try to create it)
|
||||
if not setting:
|
||||
|
||||
@ -554,7 +556,9 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
|
||||
def settings_group_options():
|
||||
"""build up group tuple for settings based on gour choices"""
|
||||
"""
|
||||
Build up group tuple for settings based on your choices
|
||||
"""
|
||||
return [('', _('No group')), *[(str(a.id), str(a)) for a in Group.objects.all()]]
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" This module provides template tags for extra functionality
|
||||
"""
|
||||
This module provides template tags for extra functionality,
|
||||
over and above the built-in Django tags.
|
||||
"""
|
||||
|
||||
@ -22,6 +23,8 @@ import InvenTree.helpers
|
||||
from common.models import InvenTreeSetting, ColorTheme, InvenTreeUserSetting
|
||||
from common.settings import currency_code_default
|
||||
|
||||
from plugin.models import PluginSetting
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@ -223,8 +226,16 @@ def setting_object(key, *args, **kwargs):
|
||||
if a user-setting was requested return that
|
||||
"""
|
||||
|
||||
if 'plugin' in kwargs:
|
||||
# Note, 'plugin' is an instance of an InvenTreePlugin class
|
||||
|
||||
plugin = kwargs['plugin']
|
||||
|
||||
return PluginSetting.get_setting_object(key, plugin=plugin)
|
||||
|
||||
if 'user' in kwargs:
|
||||
return InvenTreeUserSetting.get_setting_object(key, user=kwargs['user'])
|
||||
|
||||
return InvenTreeSetting.get_setting_object(key)
|
||||
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
from .registry import plugins as plugin_reg
|
||||
from .registry import plugin_registry
|
||||
from .plugin import InvenTreePlugin
|
||||
from .integration import IntegrationPluginBase
|
||||
from .action import ActionPlugin
|
||||
|
||||
__all__ = [
|
||||
'plugin_reg', 'IntegrationPluginBase', 'ActionPlugin',
|
||||
'ActionPlugin',
|
||||
'IntegrationPluginBase',
|
||||
'InvenTreePlugin',
|
||||
'plugin_registry',
|
||||
]
|
||||
|
@ -6,6 +6,7 @@ from django.contrib import admin
|
||||
import plugin.models as models
|
||||
import plugin.registry as registry
|
||||
|
||||
|
||||
def plugin_update(queryset, new_status: bool):
|
||||
"""general function for bulk changing plugins"""
|
||||
apps_changed = False
|
||||
|
@ -11,7 +11,8 @@ from rest_framework import generics
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
|
||||
from plugin.models import PluginConfig
|
||||
from common.api import GlobalSettingsPermissions
|
||||
from plugin.models import PluginConfig, PluginSetting
|
||||
import plugin.serializers as PluginSerializers
|
||||
|
||||
|
||||
@ -76,7 +77,46 @@ class PluginInstall(generics.CreateAPIView):
|
||||
return serializer.save()
|
||||
|
||||
|
||||
class PluginSettingList(generics.ListAPIView):
|
||||
"""
|
||||
List endpoint for all plugin related settings.
|
||||
|
||||
- read only
|
||||
- only accessible by staff users
|
||||
"""
|
||||
|
||||
queryset = PluginSetting.objects.all()
|
||||
serializer_class = PluginSerializers.PluginSettingSerializer
|
||||
|
||||
permission_classes = [
|
||||
GlobalSettingsPermissions,
|
||||
]
|
||||
|
||||
|
||||
class PluginSettingDetail(generics.RetrieveUpdateAPIView):
|
||||
"""
|
||||
Detail endpoint for a plugin-specific setting.
|
||||
|
||||
Note that these cannot be created or deleted via the API
|
||||
"""
|
||||
|
||||
queryset = PluginSetting.objects.all()
|
||||
serializer_class = PluginSerializers.PluginSettingSerializer
|
||||
|
||||
# Staff permission required
|
||||
permission_classes = [
|
||||
GlobalSettingsPermissions,
|
||||
]
|
||||
|
||||
|
||||
plugin_api_urls = [
|
||||
|
||||
# Plugin settings URLs
|
||||
url(r'^settings/', include([
|
||||
url(r'^(?P<pk>\d+)/', PluginSettingDetail.as_view(), name='api-plugin-setting-detail'),
|
||||
url(r'^.*$', PluginSettingList.as_view(), name='api-plugin-setting-list'),
|
||||
])),
|
||||
|
||||
# Detail views for a single PluginConfig item
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^.*$', PluginDetail.as_view(), name='api-plugin-detail'),
|
||||
|
@ -4,17 +4,17 @@ from __future__ import unicode_literals
|
||||
from django.apps import AppConfig
|
||||
from maintenance_mode.core import set_maintenance_mode
|
||||
|
||||
from plugin.registry import plugins
|
||||
from plugin import plugin_registry
|
||||
|
||||
|
||||
class PluginAppConfig(AppConfig):
|
||||
name = 'plugin'
|
||||
|
||||
def ready(self):
|
||||
if not plugins.is_loading:
|
||||
if not plugin_registry.is_loading:
|
||||
# this is the first startup
|
||||
plugins.collect_plugins()
|
||||
plugins.load_plugins()
|
||||
plugin_registry.collect_plugins()
|
||||
plugin_registry.load_plugins()
|
||||
|
||||
# drop out of maintenance
|
||||
# makes sure we did not have an error in reloading and maintenance is still active
|
||||
|
@ -36,17 +36,14 @@ class SettingsMixin:
|
||||
|
||||
# Find the plugin configuration associated with this plugin
|
||||
|
||||
try:
|
||||
plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
|
||||
except (OperationalError, ProgrammingError) as error:
|
||||
plugin = None
|
||||
plugin = self.plugin_config()
|
||||
|
||||
if not plugin:
|
||||
if plugin:
|
||||
return PluginSetting.get_setting(key, plugin=plugin, settings=self.settings)
|
||||
else:
|
||||
# Plugin cannot be found, return default value
|
||||
return PluginSetting.get_setting_default(key, settings=self.settings)
|
||||
|
||||
return PluginSetting.get_setting(key, plugin=plugin, settings=self.settings)
|
||||
|
||||
def set_setting(self, key, value, user):
|
||||
"""
|
||||
Set plugin setting value by key
|
||||
@ -54,7 +51,7 @@ class SettingsMixin:
|
||||
|
||||
try:
|
||||
plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
|
||||
except (OperationalError, ProgrammingError) as error:
|
||||
except (OperationalError, ProgrammingError):
|
||||
plugin = None
|
||||
|
||||
if not plugin:
|
||||
|
@ -10,14 +10,14 @@ from django.conf import settings
|
||||
|
||||
# region logging / errors
|
||||
def log_plugin_error(error, reference: str = 'general'):
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
# make sure the registry is set up
|
||||
if reference not in plugin_reg.errors:
|
||||
plugin_reg.errors[reference] = []
|
||||
if reference not in plugin_registry.errors:
|
||||
plugin_registry.errors[reference] = []
|
||||
|
||||
# add error to stack
|
||||
plugin_reg.errors[reference].append(error)
|
||||
plugin_registry.errors[reference].append(error)
|
||||
|
||||
|
||||
class IntegrationPluginError(Exception):
|
||||
|
@ -9,7 +9,6 @@ import pathlib
|
||||
|
||||
from django.urls.base import reverse
|
||||
from django.conf import settings
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import plugin.plugin as plugin
|
||||
|
@ -4,7 +4,7 @@ load templates for loaded plugins
|
||||
from django.template.loaders.filesystem import Loader as FilesystemLoader
|
||||
from pathlib import Path
|
||||
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
|
||||
class PluginTemplateLoader(FilesystemLoader):
|
||||
@ -12,7 +12,7 @@ class PluginTemplateLoader(FilesystemLoader):
|
||||
def get_dirs(self):
|
||||
dirname = 'templates'
|
||||
template_dirs = []
|
||||
for plugin in plugin_reg.plugins.values():
|
||||
for plugin in plugin_registry.plugins.values():
|
||||
new_path = Path(plugin.path) / dirname
|
||||
if Path(new_path).is_dir():
|
||||
template_dirs.append(new_path)
|
||||
|
@ -10,7 +10,7 @@ from django.db import models
|
||||
|
||||
import common.models
|
||||
|
||||
from plugin import plugin_reg
|
||||
from plugin import InvenTreePlugin, plugin_registry
|
||||
|
||||
|
||||
class PluginConfig(models.Model):
|
||||
@ -72,7 +72,7 @@ class PluginConfig(models.Model):
|
||||
self.__org_active = self.active
|
||||
|
||||
# append settings from registry
|
||||
self.plugin = plugin_reg.plugins.get(self.key, None)
|
||||
self.plugin = plugin_registry.plugins.get(self.key, None)
|
||||
|
||||
def get_plugin_meta(name):
|
||||
if self.plugin:
|
||||
@ -95,10 +95,10 @@ class PluginConfig(models.Model):
|
||||
|
||||
if not reload:
|
||||
if self.active is False and self.__org_active is True:
|
||||
plugin_reg.reload_plugins()
|
||||
plugin_registry.reload_plugins()
|
||||
|
||||
elif self.active is True and self.__org_active is False:
|
||||
plugin_reg.reload_plugins()
|
||||
plugin_registry.reload_plugins()
|
||||
|
||||
return ret
|
||||
|
||||
@ -113,6 +113,58 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
|
||||
('plugin', 'key'),
|
||||
]
|
||||
|
||||
"""
|
||||
We override the following class methods,
|
||||
so that we can pass the plugin instance
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.__class__.get_setting_name(self.key, plugin=self.plugin)
|
||||
|
||||
@property
|
||||
def default_value(self):
|
||||
return self.__class__.get_setting_default(self.key, plugin=self.plugin)
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.__class__.get_setting_description(self.key, plugin=self.plugin)
|
||||
|
||||
@property
|
||||
def units(self):
|
||||
return self.__class__.get_setting_units(self.key, plugin=self.plugin)
|
||||
|
||||
def choices(self):
|
||||
return self.__class__.get_setting_choices(self.key, plugin=self.plugin)
|
||||
|
||||
@classmethod
|
||||
def get_setting_definition(cls, key, **kwargs):
|
||||
"""
|
||||
In the BaseInvenTreeSetting class, we have a class attribute named 'SETTINGS',
|
||||
which is a dict object that fully defines all the setting parameters.
|
||||
|
||||
Here, unlike the BaseInvenTreeSetting, we do not know the definitions of all settings
|
||||
'ahead of time' (as they are defined externally in the plugins).
|
||||
|
||||
Settings can be provided by the caller, as kwargs['settings'].
|
||||
|
||||
If not provided, we'll look at the plugin registry to see what settings are available,
|
||||
(if the plugin is specified!)
|
||||
"""
|
||||
|
||||
if 'settings' not in kwargs:
|
||||
|
||||
plugin = kwargs.pop('plugin', None)
|
||||
|
||||
if plugin:
|
||||
|
||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
||||
plugin = plugin.plugin_config()
|
||||
|
||||
kwargs['settings'] = plugin_registry.mixins_settings.get(plugin.key, {})
|
||||
|
||||
return super().get_setting_definition(key, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_filters(cls, key, **kwargs):
|
||||
"""
|
||||
@ -124,6 +176,8 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
|
||||
plugin = kwargs.get('plugin', None)
|
||||
|
||||
if plugin:
|
||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
||||
plugin = plugin.plugin_config()
|
||||
filters['plugin'] = plugin
|
||||
|
||||
return filters
|
||||
|
@ -1,7 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Base Class for InvenTree plugins"""
|
||||
|
||||
"""
|
||||
Base Class for InvenTree plugins
|
||||
"""
|
||||
|
||||
from django.db.utils import OperationalError, ProgrammingError
|
||||
from django.utils.text import slugify
|
||||
|
||||
|
||||
@ -10,6 +12,9 @@ class InvenTreePlugin():
|
||||
Base class for a plugin
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# Override the plugin name for each concrete plugin instance
|
||||
PLUGIN_NAME = ''
|
||||
|
||||
@ -36,5 +41,22 @@ class InvenTreePlugin():
|
||||
|
||||
return self.PLUGIN_TITLE
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def plugin_config(self, raise_error=False):
|
||||
"""
|
||||
Return the PluginConfig object associated with this plugin
|
||||
"""
|
||||
|
||||
try:
|
||||
import plugin.models
|
||||
|
||||
cfg, _ = plugin.models.PluginConfig.objects.get_or_create(
|
||||
key=self.plugin_slug(),
|
||||
name=self.plugin_name(),
|
||||
)
|
||||
except (OperationalError, ProgrammingError) as error:
|
||||
cfg = None
|
||||
|
||||
if raise_error:
|
||||
raise error
|
||||
|
||||
return cfg
|
||||
|
@ -33,7 +33,7 @@ from .helpers import get_plugin_error, IntegrationPluginError
|
||||
logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
class Plugins:
|
||||
class PluginsRegistry:
|
||||
def __init__(self) -> None:
|
||||
# plugin registry
|
||||
self.plugins = {}
|
||||
@ -225,7 +225,8 @@ class Plugins:
|
||||
self.plugins_inactive[plug_key] = plugin_db_setting
|
||||
|
||||
def _activate_plugins(self, force_reload=False):
|
||||
"""run integration functions for all plugins
|
||||
"""
|
||||
Run integration functions for all plugins
|
||||
|
||||
:param force_reload: force reload base apps, defaults to False
|
||||
:type force_reload: bool, optional
|
||||
@ -238,13 +239,13 @@ class Plugins:
|
||||
self.activate_integration_app(plugins, force_reload=force_reload)
|
||||
|
||||
def _deactivate_plugins(self):
|
||||
"""run integration deactivation functions for all plugins"""
|
||||
"""
|
||||
Run integration deactivation functions for all plugins
|
||||
"""
|
||||
self.deactivate_integration_app()
|
||||
self.deactivate_integration_globalsettings()
|
||||
# endregion
|
||||
|
||||
# region specific integrations
|
||||
# region integration_globalsettings
|
||||
def activate_integration_globalsettings(self, plugins):
|
||||
from common.models import InvenTreeSetting
|
||||
|
||||
@ -255,24 +256,16 @@ class Plugins:
|
||||
plugin_setting = plugin.settings
|
||||
self.mixins_settings[slug] = plugin_setting
|
||||
|
||||
# Add to settings dir
|
||||
InvenTreeSetting.SETTINGS.update(plugin_setting)
|
||||
|
||||
def deactivate_integration_globalsettings(self):
|
||||
from common.models import InvenTreeSetting
|
||||
|
||||
# collect all settings
|
||||
plugin_settings = {}
|
||||
|
||||
for _, plugin_setting in self.mixins_settings.items():
|
||||
plugin_settings.update(plugin_setting)
|
||||
|
||||
# remove settings
|
||||
for setting in plugin_settings:
|
||||
InvenTreeSetting.SETTINGS.pop(setting)
|
||||
|
||||
# clear cache
|
||||
self.mixins_Fsettings = {}
|
||||
# endregion
|
||||
|
||||
# region integration_app
|
||||
def activate_integration_app(self, plugins, force_reload=False):
|
||||
@ -452,4 +445,4 @@ class Plugins:
|
||||
# endregion
|
||||
|
||||
|
||||
plugins = Plugins()
|
||||
plugin_registry = PluginsRegistry()
|
||||
|
@ -52,6 +52,18 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
|
||||
'name': _('Numerical'),
|
||||
'description': _('A numerical setting'),
|
||||
'validator': int,
|
||||
'default': 123,
|
||||
},
|
||||
'CHOICE_SETTING': {
|
||||
'name': _("Choice Setting"),
|
||||
'description': _('A setting with multiple choices'),
|
||||
'choices': [
|
||||
('A', 'Anaconda'),
|
||||
('B', 'Bat'),
|
||||
('C', 'Cat'),
|
||||
('D', 'Dog'),
|
||||
],
|
||||
'default': 'A',
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,9 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from plugin.models import PluginConfig
|
||||
from common.serializers import SettingsSerializer
|
||||
|
||||
from plugin.models import PluginConfig, PluginSetting
|
||||
|
||||
|
||||
class PluginConfigSerializer(serializers.ModelSerializer):
|
||||
@ -117,3 +119,24 @@ class PluginConfigInstallSerializer(serializers.Serializer):
|
||||
# TODO
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class PluginSettingSerializer(SettingsSerializer):
|
||||
"""
|
||||
Serializer for the PluginSetting model
|
||||
"""
|
||||
|
||||
plugin = serializers.PrimaryKeyRelatedField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = PluginSetting
|
||||
fields = [
|
||||
'pk',
|
||||
'key',
|
||||
'value',
|
||||
'name',
|
||||
'description',
|
||||
'type',
|
||||
'choices',
|
||||
'plugin',
|
||||
]
|
||||
|
@ -7,7 +7,7 @@ from django import template
|
||||
from django.urls import reverse
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
|
||||
register = template.Library()
|
||||
@ -16,19 +16,19 @@ register = template.Library()
|
||||
@register.simple_tag()
|
||||
def plugin_list(*args, **kwargs):
|
||||
""" Return a list of all installed integration plugins """
|
||||
return plugin_reg.plugins
|
||||
return plugin_registry.plugins
|
||||
|
||||
|
||||
@register.simple_tag()
|
||||
def inactive_plugin_list(*args, **kwargs):
|
||||
""" Return a list of all inactive integration plugins """
|
||||
return plugin_reg.plugins_inactive
|
||||
return plugin_registry.plugins_inactive
|
||||
|
||||
|
||||
@register.simple_tag()
|
||||
def plugin_settings(plugin, *args, **kwargs):
|
||||
""" Return a list of all custom settings for a plugin """
|
||||
return plugin_reg.mixins_settings.get(plugin)
|
||||
return plugin_registry.mixins_settings.get(plugin)
|
||||
|
||||
|
||||
@register.simple_tag()
|
||||
@ -57,4 +57,4 @@ def safe_url(view_name, *args, **kwargs):
|
||||
@register.simple_tag()
|
||||
def plugin_errors(*args, **kwargs):
|
||||
"""Return all plugin errors"""
|
||||
return plugin_reg.errors
|
||||
return plugin_registry.errors
|
||||
|
@ -64,14 +64,14 @@ class PluginDetailAPITest(InvenTreeAPITestCase):
|
||||
Test the PluginConfig action commands
|
||||
"""
|
||||
from plugin.models import PluginConfig
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
url = reverse('admin:plugin_pluginconfig_changelist')
|
||||
fixtures = PluginConfig.objects.all()
|
||||
|
||||
# check if plugins were registered -> in some test setups the startup has no db access
|
||||
if not fixtures:
|
||||
plugin_reg.reload_plugins()
|
||||
plugin_registry.reload_plugins()
|
||||
fixtures = PluginConfig.objects.all()
|
||||
|
||||
print([str(a) for a in fixtures])
|
||||
|
@ -8,7 +8,7 @@ from plugin.samples.integration.sample import SampleIntegrationPlugin
|
||||
from plugin.samples.integration.another_sample import WrongIntegrationPlugin, NoIntegrationPlugin
|
||||
# from plugin.plugins import load_action_plugins, load_barcode_plugins
|
||||
import plugin.templatetags.plugin_extras as plugin_tags
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
|
||||
class InvenTreePluginTests(TestCase):
|
||||
@ -57,17 +57,17 @@ class PluginTagTests(TestCase):
|
||||
|
||||
def test_tag_plugin_list(self):
|
||||
"""test that all plugins are listed"""
|
||||
self.assertEqual(plugin_tags.plugin_list(), plugin_reg.plugins)
|
||||
self.assertEqual(plugin_tags.plugin_list(), plugin_registry.plugins)
|
||||
|
||||
def test_tag_incative_plugin_list(self):
|
||||
"""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_registry.plugins_inactive)
|
||||
|
||||
def test_tag_plugin_settings(self):
|
||||
"""check all plugins are listed"""
|
||||
self.assertEqual(
|
||||
plugin_tags.plugin_settings(self.sample),
|
||||
plugin_reg.mixins_settings.get(self.sample)
|
||||
plugin_registry.mixins_settings.get(self.sample)
|
||||
)
|
||||
|
||||
def test_tag_mixin_enabled(self):
|
||||
@ -89,4 +89,4 @@ class PluginTagTests(TestCase):
|
||||
|
||||
def test_tag_plugin_errors(self):
|
||||
"""test that all errors are listed"""
|
||||
self.assertEqual(plugin_tags.plugin_errors(), plugin_reg.errors)
|
||||
self.assertEqual(plugin_tags.plugin_errors(), plugin_registry.errors)
|
||||
|
@ -3,7 +3,7 @@ URL lookup for plugin app
|
||||
"""
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from plugin import plugin_reg
|
||||
from plugin import plugin_registry
|
||||
|
||||
|
||||
PLUGIN_BASE = 'plugin' # Constant for links
|
||||
@ -12,7 +12,7 @@ PLUGIN_BASE = 'plugin' # Constant for links
|
||||
def get_plugin_urls():
|
||||
"""returns a urlpattern that can be integrated into the global urls"""
|
||||
urls = []
|
||||
for plugin in plugin_reg.plugins.values():
|
||||
for plugin in plugin_registry.plugins.values():
|
||||
if plugin.mixin_enabled('urls'):
|
||||
urls.append(plugin.urlpatterns)
|
||||
return url(f'^{PLUGIN_BASE}/', include((urls, 'plugin')))
|
||||
|
@ -10,7 +10,7 @@
|
||||
<table class='table table-striped table-condensed'>
|
||||
<tbody>
|
||||
{% for setting in plugin_settings %}
|
||||
{% include "InvenTree/settings/setting.html" with key=setting%}
|
||||
{% include "InvenTree/settings/setting.html" with key=setting plugin=plugin %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
@ -1,7 +1,9 @@
|
||||
{% load inventree_extras %}
|
||||
{% load i18n %}
|
||||
|
||||
{% if user_setting %}
|
||||
{% if plugin %}
|
||||
{% setting_object key plugin=plugin as setting %}
|
||||
{% elif user_setting %}
|
||||
{% setting_object key user=request.user as setting %}
|
||||
{% else %}
|
||||
{% setting_object key as setting %}
|
||||
|
@ -28,9 +28,13 @@ function editSetting(pk, options={}) {
|
||||
// Is this a global setting or a user setting?
|
||||
var global = options.global || false;
|
||||
|
||||
var plugin = options.plugin;
|
||||
|
||||
var url = '';
|
||||
|
||||
if (global) {
|
||||
if (plugin) {
|
||||
url = `/api/plugin/settings/${pk}/`;
|
||||
} else if (global) {
|
||||
url = `/api/settings/global/${pk}/`;
|
||||
} else {
|
||||
url = `/api/settings/user/${pk}/`;
|
||||
|
Loading…
Reference in New Issue
Block a user