mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Plugin helper function (#8220)
* Add helper function for constructing URL to static file * Fix PluginListTable - Allow uninstallation of plugin - Allow deletion of plugin config * Move helper method to InvenTreePlugin class * Bump API version info
This commit is contained in:
parent
cbe4569416
commit
e9640f4f15
@ -1,14 +1,17 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 261
|
INVENTREE_API_VERSION = 262
|
||||||
|
|
||||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
INVENTREE_API_TEXT = """
|
||||||
|
|
||||||
261 - 2024-09;26 : https://github.com/inventree/InvenTree/pull/8184
|
262 - 2024-09-30 : https://github.com/inventree/InvenTree/pull/8220
|
||||||
|
- Tweak permission requirements for uninstalling plugins via API
|
||||||
|
|
||||||
|
261 - 2024-09-26 : https://github.com/inventree/InvenTree/pull/8184
|
||||||
- Fixes for BuildOrder API serializers
|
- Fixes for BuildOrder API serializers
|
||||||
|
|
||||||
v260 - 2024-09-26 : https://github.com/inventree/InvenTree/pull/8190
|
v260 - 2024-09-26 : https://github.com/inventree/InvenTree/pull/8190
|
||||||
|
@ -21,11 +21,11 @@ from InvenTree.filters import SEARCH_ORDER_FILTER
|
|||||||
from InvenTree.mixins import (
|
from InvenTree.mixins import (
|
||||||
CreateAPI,
|
CreateAPI,
|
||||||
ListAPI,
|
ListAPI,
|
||||||
|
RetrieveDestroyAPI,
|
||||||
RetrieveUpdateAPI,
|
RetrieveUpdateAPI,
|
||||||
RetrieveUpdateDestroyAPI,
|
|
||||||
UpdateAPI,
|
UpdateAPI,
|
||||||
)
|
)
|
||||||
from InvenTree.permissions import IsSuperuser
|
from InvenTree.permissions import IsSuperuser, IsSuperuserOrReadOnly
|
||||||
from plugin import registry
|
from plugin import registry
|
||||||
from plugin.base.action.api import ActionPluginView
|
from plugin.base.action.api import ActionPluginView
|
||||||
from plugin.base.barcodes.api import barcode_api_urls
|
from plugin.base.barcodes.api import barcode_api_urls
|
||||||
@ -143,7 +143,7 @@ class PluginList(ListAPI):
|
|||||||
search_fields = ['key', 'name']
|
search_fields = ['key', 'name']
|
||||||
|
|
||||||
|
|
||||||
class PluginDetail(RetrieveUpdateDestroyAPI):
|
class PluginDetail(RetrieveDestroyAPI):
|
||||||
"""API detail endpoint for PluginConfig object.
|
"""API detail endpoint for PluginConfig object.
|
||||||
|
|
||||||
get:
|
get:
|
||||||
@ -158,6 +158,7 @@ class PluginDetail(RetrieveUpdateDestroyAPI):
|
|||||||
|
|
||||||
queryset = PluginConfig.objects.all()
|
queryset = PluginConfig.objects.all()
|
||||||
serializer_class = PluginSerializers.PluginConfigSerializer
|
serializer_class = PluginSerializers.PluginConfigSerializer
|
||||||
|
permission_classes = [IsSuperuserOrReadOnly]
|
||||||
lookup_field = 'key'
|
lookup_field = 'key'
|
||||||
lookup_url_kwarg = 'plugin'
|
lookup_url_kwarg = 'plugin'
|
||||||
|
|
||||||
|
@ -438,3 +438,11 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
|
|||||||
self.package = package
|
self.package = package
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
|
def plugin_static_file(self, *args):
|
||||||
|
"""Construct a path to a static file within the plugin directory."""
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
return '/' + os.path.join(settings.STATIC_URL, 'plugins', self.SLUG, *args)
|
||||||
|
@ -17,7 +17,8 @@ import {
|
|||||||
IconHelpCircle,
|
IconHelpCircle,
|
||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
IconPlaylistAdd,
|
IconPlaylistAdd,
|
||||||
IconRefresh
|
IconRefresh,
|
||||||
|
IconTrash
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
@ -352,9 +353,10 @@ export default function PluginListTable() {
|
|||||||
{
|
{
|
||||||
hidden:
|
hidden:
|
||||||
record.is_builtin != false ||
|
record.is_builtin != false ||
|
||||||
record.is_installed != true ||
|
!record.is_installed ||
|
||||||
record.active != false,
|
record.active != false,
|
||||||
title: t`Activate`,
|
title: t`Activate`,
|
||||||
|
tooltip: t`Activate selected plugin`,
|
||||||
color: 'green',
|
color: 'green',
|
||||||
icon: <IconCircleCheck />,
|
icon: <IconCircleCheck />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -364,11 +366,9 @@ export default function PluginListTable() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hidden:
|
hidden: !record.active || !record.is_package || !record.package_name,
|
||||||
record.active != true ||
|
|
||||||
record.is_package != true ||
|
|
||||||
!record.package_name,
|
|
||||||
title: t`Update`,
|
title: t`Update`,
|
||||||
|
tooltip: t`Update selected plugin`,
|
||||||
color: 'blue',
|
color: 'blue',
|
||||||
icon: <IconRefresh />,
|
icon: <IconRefresh />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -377,10 +377,37 @@ export default function PluginListTable() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hidden: record.is_installed != false,
|
// Uninstall an installed plugin
|
||||||
title: t`Delete`,
|
// Must be inactive, not a builtin, not a sample, and installed as a package
|
||||||
|
hidden:
|
||||||
|
!user.isSuperuser() ||
|
||||||
|
record.active ||
|
||||||
|
record.is_builtin ||
|
||||||
|
record.is_sample ||
|
||||||
|
!record.is_installed ||
|
||||||
|
!record.is_package,
|
||||||
|
title: t`Uninstall`,
|
||||||
|
tooltip: t`Uninstall selected plugin`,
|
||||||
color: 'red',
|
color: 'red',
|
||||||
icon: <IconCircleX />,
|
icon: <IconCircleX />,
|
||||||
|
onClick: () => {
|
||||||
|
setSelectedPlugin(record.key);
|
||||||
|
uninstallPluginModal.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Delete a plugin configuration
|
||||||
|
// Must be inactive, not a builtin, not a sample, and not installed (i.e. no matching plugin)
|
||||||
|
hidden:
|
||||||
|
record.active ||
|
||||||
|
record.is_builtin ||
|
||||||
|
record.is_sample ||
|
||||||
|
record.is_installed ||
|
||||||
|
!user.isSuperuser(),
|
||||||
|
title: t`Delete`,
|
||||||
|
tooltip: t`Delete selected plugin configuration`,
|
||||||
|
color: 'red',
|
||||||
|
icon: <IconTrash />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setSelectedPlugin(record.key);
|
setSelectedPlugin(record.key);
|
||||||
deletePluginModal.open();
|
deletePluginModal.open();
|
||||||
@ -436,7 +463,7 @@ export default function PluginListTable() {
|
|||||||
const uninstallPluginModal = useEditApiFormModal({
|
const uninstallPluginModal = useEditApiFormModal({
|
||||||
title: t`Uninstall Plugin`,
|
title: t`Uninstall Plugin`,
|
||||||
url: ApiEndpoints.plugin_uninstall,
|
url: ApiEndpoints.plugin_uninstall,
|
||||||
// pathParams: { key: selectedPlugin },
|
pathParams: { key: selectedPlugin },
|
||||||
fetchInitialData: false,
|
fetchInitialData: false,
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
fields: {
|
fields: {
|
||||||
@ -460,15 +487,14 @@ export default function PluginListTable() {
|
|||||||
|
|
||||||
const deletePluginModal = useDeleteApiFormModal({
|
const deletePluginModal = useDeleteApiFormModal({
|
||||||
url: ApiEndpoints.plugin_list,
|
url: ApiEndpoints.plugin_list,
|
||||||
pathParams: { key: selectedPlugin },
|
pk: selectedPlugin,
|
||||||
|
fetchInitialData: false,
|
||||||
title: t`Delete Plugin`,
|
title: t`Delete Plugin`,
|
||||||
preFormWarning: t`Deleting this plugin configuration will remove all associated settings and data. Are you sure you want to delete this plugin?`,
|
preFormWarning: t`Deleting this plugin configuration will remove all associated settings and data. Are you sure you want to delete this plugin?`,
|
||||||
table: table
|
table: table
|
||||||
});
|
});
|
||||||
|
|
||||||
const reloadPlugins = useCallback(() => {
|
const reloadPlugins = useCallback(() => {
|
||||||
console.log('reloadPlugins:');
|
|
||||||
|
|
||||||
api
|
api
|
||||||
.post(apiUrl(ApiEndpoints.plugin_reload), {
|
.post(apiUrl(ApiEndpoints.plugin_reload), {
|
||||||
full_reload: true,
|
full_reload: true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user