From 437dddc75f6d705bcfe57f3e1b2c274e987b2ffc Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 8 Apr 2026 06:01:00 +1000 Subject: [PATCH] [UI] Import context (#11685) * Refactor ImporterDrawer - Use a single, globally accessible object - Provide global state management * Expose global importer state to the plugin interface * Improve registration of data import serializers * Update frontend version / docs * Bump API version --- .../InvenTree/InvenTree/api_version.py | 5 +- src/backend/InvenTree/importer/registry.py | 6 +- src/backend/InvenTree/order/serializers.py | 5 +- src/frontend/CHANGELOG.md | 4 ++ src/frontend/lib/types/Plugins.tsx | 10 +++ src/frontend/package.json | 2 +- .../importer/GlobalImporterDrawer.tsx | 20 ++++++ src/frontend/src/components/nav/Layout.tsx | 54 ++++++++-------- .../src/components/plugins/PluginContext.tsx | 13 ++++ src/frontend/src/states/ImporterState.tsx | 62 +++++++++++++++++++ src/frontend/src/tables/bom/BomTable.tsx | 23 ++----- .../src/tables/general/ParameterTable.tsx | 23 ++----- src/frontend/src/tables/part/PartTable.tsx | 23 ++----- .../purchasing/PurchaseOrderLineItemTable.tsx | 23 ++----- .../tables/settings/ImportSessionTable.tsx | 22 +++---- 15 files changed, 178 insertions(+), 117 deletions(-) create mode 100644 src/frontend/src/components/importer/GlobalImporterDrawer.tsx create mode 100644 src/frontend/src/states/ImporterState.tsx diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 354c46c20c..eddaf22bed 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,11 +1,14 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 470 +INVENTREE_API_VERSION = 471 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v471 -> 2026-04-07 : https://github.com/inventree/InvenTree/pull/11685 + - Adds data importer support for the "SalesOrderShipment" model + v470 -> 2026-04-01 : https://github.com/inventree/InvenTree/pull/11659 - Renames "is_staff" field to "is_admin" and updates help texts accordingly to highlight current security boundaries diff --git a/src/backend/InvenTree/importer/registry.py b/src/backend/InvenTree/importer/registry.py index 28d96d0a79..b57fe9e3ee 100644 --- a/src/backend/InvenTree/importer/registry.py +++ b/src/backend/InvenTree/importer/registry.py @@ -19,14 +19,14 @@ class DataImportSerializerRegister: def register(self, serializer) -> None: """Register a new serializer with the importer registry.""" if not issubclass(serializer, DataImportSerializerMixin): - logger.debug('Invalid serializer class: %s', type(serializer)) + logger.debug('Invalid serializer class: %s', serializer.__name__) return if not issubclass(serializer, Serializer): - logger.debug('Invalid serializer class: %s', type(serializer)) + logger.debug('Invalid serializer class: %s', serializer.__name__) return - logger.debug('Registering serializer class for import: %s', type(serializer)) + logger.debug('Registering serializer class for import: %s', serializer.__name__) if serializer not in self.supported_serializers: self.supported_serializers.append(serializer) diff --git a/src/backend/InvenTree/order/serializers.py b/src/backend/InvenTree/order/serializers.py index 0721ff312b..e761fdba8c 100644 --- a/src/backend/InvenTree/order/serializers.py +++ b/src/backend/InvenTree/order/serializers.py @@ -1297,7 +1297,10 @@ class SalesOrderLineItemSerializer( @register_importer() class SalesOrderShipmentSerializer( - FilterableSerializerMixin, NotesFieldMixin, InvenTreeModelSerializer + DataImportExportSerializerMixin, + FilterableSerializerMixin, + NotesFieldMixin, + InvenTreeModelSerializer, ): """Serializer for the SalesOrderShipment class.""" diff --git a/src/frontend/CHANGELOG.md b/src/frontend/CHANGELOG.md index c3c4341132..188953ee63 100644 --- a/src/frontend/CHANGELOG.md +++ b/src/frontend/CHANGELOG.md @@ -2,6 +2,10 @@ This file contains historical changelog information for the InvenTree UI components library. +### 0.10.0 - April 2026 + +Exposes the `importer` object to the plugin context, allow plugins to initialize a data import session using the data importer wizard. + ### 0.9.0 - March 2026 Exposes the `useMonitorBackgroundTask` hook, which allows plugins to monitor the status of a background task and display notifications when the task is complete. This is useful for plugins that offload long-running tasks to the background and want to provide feedback to the user when the task is complete. diff --git a/src/frontend/lib/types/Plugins.tsx b/src/frontend/lib/types/Plugins.tsx index cc10083b6e..840d695d6d 100644 --- a/src/frontend/lib/types/Plugins.tsx +++ b/src/frontend/lib/types/Plugins.tsx @@ -48,6 +48,13 @@ export type InvenTreeFormsContext = { stockActions: StockAdjustmentFormsContext; }; +export type ImporterDrawerContext = { + open: (sessionId: number, options?: { onClose?: () => void }) => void; + close: () => void; + isOpen: () => boolean; + sessionId: () => number | null; +}; + /** * A set of properties which are passed to a plugin, * for rendering an element in the user interface. @@ -59,6 +66,8 @@ export type InvenTreeFormsContext = { * @param globalSettings - The global settings (see ../states/SettingsState.tsx) * @param navigate - The navigation function (see react-router-dom) * @param theme - The current Mantine theme + * @param forms - A set of functions for opening various API forms (see ../components/Forms.tsx) + * @param importer - A set of functions for controlling the global importer drawer (see ../components/importer/GlobalImporterDrawer.tsx) * @param colorScheme - The current Mantine color scheme (e.g. 'light' / 'dark') * @param host - The current host URL * @param i18n - The i18n instance for translations (from @lingui/core) @@ -87,6 +96,7 @@ export type InvenTreePluginContext = { navigate: NavigateFunction; theme: MantineTheme; forms: InvenTreeFormsContext; + importer: ImporterDrawerContext; colorScheme: MantineColorScheme; model?: ModelType | string; id?: string | number | null; diff --git a/src/frontend/package.json b/src/frontend/package.json index 39f635c9a9..6c43c020f4 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@inventreedb/ui", "description": "UI components for the InvenTree project", - "version": "0.9.0", + "version": "0.10.0", "private": false, "type": "module", "license": "MIT", diff --git a/src/frontend/src/components/importer/GlobalImporterDrawer.tsx b/src/frontend/src/components/importer/GlobalImporterDrawer.tsx new file mode 100644 index 0000000000..de34229b14 --- /dev/null +++ b/src/frontend/src/components/importer/GlobalImporterDrawer.tsx @@ -0,0 +1,20 @@ +import { useImporterState } from '../../states/ImporterState'; +import ImporterDrawer from './ImporterDrawer'; + +export default function GlobalImporterDrawer() { + const isOpen = useImporterState((state) => state.isOpen); + const sessionId = useImporterState((state) => state.sessionId); + const closeImporter = useImporterState((state) => state.closeImporter); + + if (!isOpen || sessionId === null) { + return null; + } + + return ( + + ); +} diff --git a/src/frontend/src/components/nav/Layout.tsx b/src/frontend/src/components/nav/Layout.tsx index 9607520db8..741f6d14ad 100644 --- a/src/frontend/src/components/nav/Layout.tsx +++ b/src/frontend/src/components/nav/Layout.tsx @@ -21,6 +21,7 @@ import { } from '../../states/SettingsStates'; import { useUserState } from '../../states/UserState'; import { Boundary } from '../Boundary'; +import GlobalImporterDrawer from '../importer/GlobalImporterDrawer'; import { ApiIcon } from '../items/ApiIcon'; import { useInvenTreeContext } from '../plugins/PluginContext'; import { callExternalPluginFunction } from '../plugins/PluginSource'; @@ -118,31 +119,34 @@ export default function LayoutComponent() { return ( - -
- - - - - {/* */} - - -