mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Plugin missing fix (#5653)
* Add 'is_installed' property to PluginConfig model - Allow us to show users which plugins are "outdated" * Cleanup plugin table - Display clearly if a plugin is no longer installed * Fixes for plugin table * Revert change due to failing CI
This commit is contained in:
parent
88314da7b3
commit
78905a45c7
@ -83,6 +83,18 @@ class PluginList(ListAPI):
|
|||||||
|
|
||||||
queryset = queryset.filter(pk__in=matches)
|
queryset = queryset.filter(pk__in=matches)
|
||||||
|
|
||||||
|
# Filter queryset by 'installed' flag
|
||||||
|
if 'installed' in params:
|
||||||
|
installed = str2bool(params['installed'])
|
||||||
|
|
||||||
|
matches = []
|
||||||
|
|
||||||
|
for result in queryset:
|
||||||
|
if result.is_installed() == installed:
|
||||||
|
matches.append(result.pk)
|
||||||
|
|
||||||
|
queryset = queryset.filter(pk__in=matches)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
filter_backends = SEARCH_ORDER_FILTER
|
filter_backends = SEARCH_ORDER_FILTER
|
||||||
|
@ -104,9 +104,9 @@ class PluginConfig(InvenTree.models.MetadataMixin, models.Model):
|
|||||||
self.plugin: InvenTreePlugin = plugin
|
self.plugin: InvenTreePlugin = plugin
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
"""Customize pickeling behaviour."""
|
"""Customize pickling behavior."""
|
||||||
state = super().__getstate__()
|
state = super().__getstate__()
|
||||||
state.pop("plugin", None) # plugin cannot be pickelt in some circumstances when used with drf views, remove it (#5408)
|
state.pop("plugin", None) # plugin cannot be pickled in some circumstances when used with drf views, remove it (#5408)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
||||||
@ -120,14 +120,23 @@ class PluginConfig(InvenTree.models.MetadataMixin, models.Model):
|
|||||||
self.active = True
|
self.active = True
|
||||||
|
|
||||||
if not reload:
|
if not reload:
|
||||||
if (self.active is False and self.__org_active is True) or \
|
if self.active != self.__org_active:
|
||||||
(self.active is True and self.__org_active is False):
|
|
||||||
if settings.PLUGIN_TESTING:
|
if settings.PLUGIN_TESTING:
|
||||||
warnings.warn('A reload was triggered', stacklevel=2)
|
warnings.warn('A reload was triggered', stacklevel=2)
|
||||||
registry.reload_plugins()
|
registry.reload_plugins()
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@admin.display(boolean=True, description=_('Installed'))
|
||||||
|
def is_installed(self) -> bool:
|
||||||
|
"""Simple check to determine if this plugin is installed.
|
||||||
|
|
||||||
|
A plugin might not be installed if it has been removed from the system,
|
||||||
|
but the PluginConfig associated with it still exists.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.plugin is not None
|
||||||
|
|
||||||
@admin.display(boolean=True, description=_('Sample plugin'))
|
@admin.display(boolean=True, description=_('Sample plugin'))
|
||||||
def is_sample(self) -> bool:
|
def is_sample(self) -> bool:
|
||||||
"""Is this plugin a sample app?"""
|
"""Is this plugin a sample app?"""
|
||||||
|
@ -56,12 +56,14 @@ class PluginConfigSerializer(serializers.ModelSerializer):
|
|||||||
'mixins',
|
'mixins',
|
||||||
'is_builtin',
|
'is_builtin',
|
||||||
'is_sample',
|
'is_sample',
|
||||||
|
'is_installed',
|
||||||
]
|
]
|
||||||
|
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
'key',
|
'key',
|
||||||
'is_builtin',
|
'is_builtin',
|
||||||
'is_sample',
|
'is_sample',
|
||||||
|
'is_installed',
|
||||||
]
|
]
|
||||||
|
|
||||||
meta = serializers.DictField(read_only=True)
|
meta = serializers.DictField(read_only=True)
|
||||||
|
@ -45,34 +45,24 @@ function loadPluginTable(table, options={}) {
|
|||||||
return '{% trans "No plugins found" %}';
|
return '{% trans "No plugins found" %}';
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
|
||||||
field: 'active',
|
|
||||||
title: '',
|
|
||||||
sortable: true,
|
|
||||||
formatter: function(value, row) {
|
|
||||||
if (row.active) {
|
|
||||||
return `<span class='fa fa-check-circle icon-green' title='{% trans "This plugin is active" %}'></span>`;
|
|
||||||
} else {
|
|
||||||
return `<span class='fa fa-times-circle icon-red' title ='{% trans "This plugin is not active" %}'></span>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: 'name',
|
field: 'name',
|
||||||
title: '{% trans "Plugin Description" %}',
|
title: '{% trans "Plugin" %}',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
switchable: false,
|
||||||
formatter: function(value, row) {
|
formatter: function(value, row) {
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
if (row.active) {
|
if (!row.is_installed) {
|
||||||
html += `<strong>${value}</strong>`;
|
html += `<span class='fa fa-question-circle' title='{% trans "This plugin is no longer installed" %}'></span>`;
|
||||||
if (row.meta && row.meta.description) {
|
} else if (row.active) {
|
||||||
html += ` - <small>${row.meta.description}</small>`;
|
html += `<span class='fa fa-check-circle icon-green' title='{% trans "This plugin is active" %}'></span>`;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
html += `<em>${value}</em>`;
|
html += `<span class='fa fa-times-circle icon-red' title ='{% trans "This plugin is installed but not active" %}'></span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html += ` <span>${value}</span>`;
|
||||||
|
|
||||||
if (row.is_builtin) {
|
if (row.is_builtin) {
|
||||||
html += `<span class='badge bg-success rounded-pill badge-right'>{% trans "Builtin" %}</span>`;
|
html += `<span class='badge bg-success rounded-pill badge-right'>{% trans "Builtin" %}</span>`;
|
||||||
}
|
}
|
||||||
@ -84,6 +74,12 @@ function loadPluginTable(table, options={}) {
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'meta.description',
|
||||||
|
title: '{% trans "Description" %}',
|
||||||
|
sortable: false,
|
||||||
|
switchable: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'meta.version',
|
field: 'meta.version',
|
||||||
title: '{% trans "Version" %}',
|
title: '{% trans "Version" %}',
|
||||||
@ -104,15 +100,18 @@ function loadPluginTable(table, options={}) {
|
|||||||
{
|
{
|
||||||
field: 'meta.author',
|
field: 'meta.author',
|
||||||
title: '{% trans "Author" %}',
|
title: '{% trans "Author" %}',
|
||||||
|
sortable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'actions',
|
field: 'actions',
|
||||||
title: '',
|
title: '',
|
||||||
|
switchable: false,
|
||||||
|
sortable: false,
|
||||||
formatter: function(value, row) {
|
formatter: function(value, row) {
|
||||||
let buttons = '';
|
let buttons = '';
|
||||||
|
|
||||||
// Check if custom plugins are enabled for this instance
|
// Check if custom plugins are enabled for this instance
|
||||||
if (options.custom && !row.is_builtin) {
|
if (options.custom && !row.is_builtin && row.is_installed) {
|
||||||
if (row.active) {
|
if (row.active) {
|
||||||
buttons += makeIconButton('fa-stop-circle icon-red', 'btn-plugin-disable', row.pk, '{% trans "Disable Plugin" %}');
|
buttons += makeIconButton('fa-stop-circle icon-red', 'btn-plugin-disable', row.pk, '{% trans "Disable Plugin" %}');
|
||||||
} else {
|
} else {
|
||||||
|
@ -471,6 +471,10 @@ function getPluginTableFilters() {
|
|||||||
type: 'bool',
|
type: 'bool',
|
||||||
title: '{% trans "Sample" %}',
|
title: '{% trans "Sample" %}',
|
||||||
},
|
},
|
||||||
|
installed: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Installed" %}'
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user