mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-09 03:03:41 +00:00
Refactor ImporterDrawer
- Use a single, globally accessible object - Provide global state management
This commit is contained in:
@@ -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 (
|
||||
<ImporterDrawer
|
||||
sessionId={sessionId}
|
||||
opened={isOpen}
|
||||
onClose={closeImporter}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<ProtectedRoute>
|
||||
<Flex direction='column' mih='100vh'>
|
||||
<Header />
|
||||
<Container className={classes.layoutContent} size='100%'>
|
||||
<Boundary label={'layout'}>
|
||||
<Outlet />
|
||||
</Boundary>
|
||||
{/* </ErrorBoundary> */}
|
||||
</Container>
|
||||
<Space h='xl' />
|
||||
<Footer />
|
||||
{userSettings.isSet('SHOW_SPOTLIGHT') && (
|
||||
<Spotlight
|
||||
actions={actions}
|
||||
store={firstStore}
|
||||
highlightQuery
|
||||
scrollable
|
||||
searchProps={{
|
||||
leftSection: <IconSearch size='1.2rem' />,
|
||||
placeholder: t`Search...`
|
||||
}}
|
||||
shortcut={['mod + K']}
|
||||
nothingFound={t`Nothing found...`}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<>
|
||||
<Flex direction='column' mih='100vh'>
|
||||
<Header />
|
||||
<Container className={classes.layoutContent} size='100%'>
|
||||
<Boundary label={'layout'}>
|
||||
<Outlet />
|
||||
</Boundary>
|
||||
{/* </ErrorBoundary> */}
|
||||
</Container>
|
||||
<Space h='xl' />
|
||||
<Footer />
|
||||
{userSettings.isSet('SHOW_SPOTLIGHT') && (
|
||||
<Spotlight
|
||||
actions={actions}
|
||||
store={firstStore}
|
||||
highlightQuery
|
||||
scrollable
|
||||
searchProps={{
|
||||
leftSection: <IconSearch size='1.2rem' />,
|
||||
placeholder: t`Search...`
|
||||
}}
|
||||
shortcut={['mod + K']}
|
||||
nothingFound={t`Nothing found...`}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<GlobalImporterDrawer />
|
||||
</>
|
||||
</ProtectedRoute>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* This file contains a global state manager for the importer drawer, allowing it to be opened and closed from anywhere in the app without needing to pass props down through the component tree.
|
||||
* The state includes the current session ID for the importer, as well as an optional callback function that can be executed when the importer is closed.
|
||||
* This allows for flexible handling of importer actions, such as refreshing data after an import is completed.
|
||||
* The state is managed using the Zustand library, which provides a simple and efficient way to create global state in React applications.
|
||||
* The `useImporterState` hook can be used to access and manipulate the importer state from any component, while the `openGlobalImporter` and `closeGlobalImporter` functions provide convenient ways to control the importer from outside of React components.
|
||||
*/
|
||||
|
||||
import { create } from 'zustand';
|
||||
|
||||
export interface ImporterOpenOptions {
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
interface ImporterStateProps {
|
||||
isOpen: boolean;
|
||||
sessionId: number | null;
|
||||
onCloseCallback?: () => void;
|
||||
openImporter: (sessionId: number, options?: ImporterOpenOptions) => void;
|
||||
closeImporter: () => void;
|
||||
}
|
||||
|
||||
export const useImporterState = create<ImporterStateProps>()((set, get) => ({
|
||||
isOpen: false,
|
||||
sessionId: null,
|
||||
onCloseCallback: undefined,
|
||||
|
||||
openImporter: (sessionId: number, options?: ImporterOpenOptions) => {
|
||||
set({
|
||||
sessionId,
|
||||
isOpen: true,
|
||||
onCloseCallback: options?.onClose
|
||||
});
|
||||
},
|
||||
|
||||
closeImporter: () => {
|
||||
const callback = get().onCloseCallback;
|
||||
|
||||
set({
|
||||
sessionId: null,
|
||||
isOpen: false,
|
||||
onCloseCallback: undefined
|
||||
});
|
||||
|
||||
callback?.();
|
||||
}
|
||||
}));
|
||||
|
||||
export function openGlobalImporter(
|
||||
sessionId: number,
|
||||
options?: ImporterOpenOptions
|
||||
) {
|
||||
useImporterState.getState().openImporter(sessionId, options);
|
||||
}
|
||||
|
||||
export function closeGlobalImporter() {
|
||||
useImporterState.getState().closeImporter();
|
||||
}
|
||||
|
||||
export function getGlobalImporterState() {
|
||||
return useImporterState.getState();
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
import { type ReactNode, useCallback, useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Thumbnail } from '../../components/images/Thumbnail';
|
||||
import ImporterDrawer from '../../components/importer/ImporterDrawer';
|
||||
import { ActionDropdown } from '../../components/items/ActionDropdown';
|
||||
import { RenderPart } from '../../components/render/Part';
|
||||
import { useApi } from '../../contexts/ApiContext';
|
||||
@@ -39,6 +38,7 @@ import {
|
||||
useEditApiFormModal
|
||||
} from '../../hooks/UseForm';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useImporterState } from '../../states/ImporterState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import {
|
||||
BooleanColumn,
|
||||
@@ -81,12 +81,7 @@ export function BomTable({
|
||||
const user = useUserState();
|
||||
const table = useTable('bom');
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [importOpened, setImportOpened] = useState<boolean>(false);
|
||||
|
||||
const [selectedSession, setSelectedSession] = useState<number | undefined>(
|
||||
undefined
|
||||
);
|
||||
const openImporter = useImporterState((state) => state.openImporter);
|
||||
|
||||
const tableColumns: TableColumn[] = useMemo(() => {
|
||||
return [
|
||||
@@ -501,8 +496,9 @@ export function BomTable({
|
||||
title: t`Import BOM Data`,
|
||||
fields: importSessionFields,
|
||||
onFormSuccess: (response: any) => {
|
||||
setSelectedSession(response.pk);
|
||||
setImportOpened(true);
|
||||
openImporter(response.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -690,15 +686,6 @@ export function BomTable({
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<ImporterDrawer
|
||||
sessionId={selectedSession ?? -1}
|
||||
opened={selectedSession != undefined && importOpened}
|
||||
onClose={() => {
|
||||
setSelectedSession(undefined);
|
||||
setImportOpened(false);
|
||||
table.refreshTable();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import type { TableColumn } from '@lib/types/Tables';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { IconFileUpload, IconPlus } from '@tabler/icons-react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import ImporterDrawer from '../../components/importer/ImporterDrawer';
|
||||
import { ActionDropdown } from '../../components/items/ActionDropdown';
|
||||
import { useParameterFields } from '../../forms/CommonForms';
|
||||
import { dataImporterSessionFields } from '../../forms/ImporterForms';
|
||||
@@ -22,6 +21,7 @@ import {
|
||||
useEditApiFormModal
|
||||
} from '../../hooks/UseForm';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useImporterState } from '../../states/ImporterState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import {
|
||||
DateColumn,
|
||||
@@ -129,12 +129,7 @@ export function ParameterTable({
|
||||
const [selectedParameter, setSelectedParameter] = useState<any | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const [importOpened, setImportOpened] = useState<boolean>(false);
|
||||
|
||||
const [selectedSession, setSelectedSession] = useState<number | undefined>(
|
||||
undefined
|
||||
);
|
||||
const openImporter = useImporterState((state) => state.openImporter);
|
||||
|
||||
const importSessionFields = useMemo(() => {
|
||||
const fields = dataImporterSessionFields({
|
||||
@@ -154,8 +149,9 @@ export function ParameterTable({
|
||||
title: t`Import Parameters`,
|
||||
fields: importSessionFields,
|
||||
onFormSuccess: (response: any) => {
|
||||
setSelectedSession(response.pk);
|
||||
setImportOpened(true);
|
||||
openImporter(response.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -262,15 +258,6 @@ export function ParameterTable({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ImporterDrawer
|
||||
sessionId={selectedSession ?? -1}
|
||||
opened={selectedSession !== undefined && importOpened}
|
||||
onClose={() => {
|
||||
setSelectedSession(undefined);
|
||||
setImportOpened(false);
|
||||
table.refreshTable();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
IconShoppingCart
|
||||
} from '@tabler/icons-react';
|
||||
import { type ReactNode, useCallback, useMemo, useState } from 'react';
|
||||
import ImporterDrawer from '../../components/importer/ImporterDrawer';
|
||||
import { ActionDropdown } from '../../components/items/ActionDropdown';
|
||||
import ImportPartWizard from '../../components/wizards/ImportPartWizard';
|
||||
import OrderPartsWizard from '../../components/wizards/OrderPartsWizard';
|
||||
@@ -35,6 +34,7 @@ import {
|
||||
} from '../../hooks/UseForm';
|
||||
import { usePluginsWithMixin } from '../../hooks/UsePlugins';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useImporterState } from '../../states/ImporterState';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsStates';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import {
|
||||
@@ -357,12 +357,7 @@ export function PartListTable({
|
||||
});
|
||||
const user = useUserState();
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
|
||||
const [importOpened, setImportOpened] = useState<boolean>(false);
|
||||
|
||||
const [selectedSession, setSelectedSession] = useState<number | undefined>(
|
||||
undefined
|
||||
);
|
||||
const openImporter = useImporterState((state) => state.openImporter);
|
||||
|
||||
const importSessionFields = useMemo(() => {
|
||||
const fields = dataImporterSessionFields({
|
||||
@@ -383,8 +378,9 @@ export function PartListTable({
|
||||
title: t`Import Parts`,
|
||||
fields: importSessionFields,
|
||||
onFormSuccess: (response: any) => {
|
||||
setSelectedSession(response.pk);
|
||||
setImportOpened(true);
|
||||
openImporter(response.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -598,15 +594,6 @@ export function PartListTable({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ImporterDrawer
|
||||
sessionId={selectedSession ?? -1}
|
||||
opened={selectedSession != undefined && importOpened}
|
||||
onClose={() => {
|
||||
setSelectedSession(undefined);
|
||||
setImportOpened(false);
|
||||
table.refreshTable();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import { formatDecimal } from '@lib/functions/Formatting';
|
||||
import type { TableFilter } from '@lib/types/Filters';
|
||||
import type { TableColumn } from '@lib/types/Tables';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import ImporterDrawer from '../../components/importer/ImporterDrawer';
|
||||
import { RenderInstance } from '../../components/render/Instance';
|
||||
import { formatCurrency } from '../../defaults/formatters';
|
||||
import { dataImporterSessionFields } from '../../forms/ImporterForms';
|
||||
@@ -36,6 +35,7 @@ import {
|
||||
} from '../../hooks/UseForm';
|
||||
import useStatusCodes from '../../hooks/UseStatusCodes';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useImporterState } from '../../states/ImporterState';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsStates';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import {
|
||||
@@ -77,12 +77,7 @@ export function PurchaseOrderLineItemTable({
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
const navigate = useNavigate();
|
||||
const user = useUserState();
|
||||
|
||||
// Data import
|
||||
const [importOpened, setImportOpened] = useState<boolean>(false);
|
||||
const [selectedSession, setSelectedSession] = useState<number | undefined>(
|
||||
undefined
|
||||
);
|
||||
const openImporter = useImporterState((state) => state.openImporter);
|
||||
|
||||
const importSessionFields = useMemo(() => {
|
||||
const fields = dataImporterSessionFields({
|
||||
@@ -115,8 +110,9 @@ export function PurchaseOrderLineItemTable({
|
||||
title: t`Import Line Items`,
|
||||
fields: importSessionFields,
|
||||
onFormSuccess: (response: any) => {
|
||||
setSelectedSession(response.pk);
|
||||
setImportOpened(true);
|
||||
openImporter(response.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -452,15 +448,6 @@ export function PurchaseOrderLineItemTable({
|
||||
modelField: 'part'
|
||||
}}
|
||||
/>
|
||||
<ImporterDrawer
|
||||
sessionId={selectedSession ?? -1}
|
||||
opened={selectedSession != undefined && importOpened}
|
||||
onClose={() => {
|
||||
setSelectedSession(undefined);
|
||||
setImportOpened(false);
|
||||
table.refreshTable();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ModelType } from '@lib/enums/ModelType';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import type { TableFilter } from '@lib/types/Filters';
|
||||
import type { TableColumn } from '@lib/types/Tables';
|
||||
import ImporterDrawer from '../../components/importer/ImporterDrawer';
|
||||
import { AttachmentLink } from '../../components/items/AttachmentLink';
|
||||
import { RenderUser } from '../../components/render/User';
|
||||
import { dataImporterSessionFields } from '../../forms/ImporterForms';
|
||||
@@ -19,14 +18,14 @@ import {
|
||||
useDeleteApiFormModal
|
||||
} from '../../hooks/UseForm';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useImporterState } from '../../states/ImporterState';
|
||||
import { DateColumn, StatusColumn } from '../ColumnRenderers';
|
||||
import { StatusFilterOptions, UserFilter } from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export default function ImportSessionTable() {
|
||||
const table = useTable('importsession');
|
||||
|
||||
const [opened, setOpened] = useState<boolean>(false);
|
||||
const openImporter = useImporterState((state) => state.openImporter);
|
||||
|
||||
const [selectedSession, setSelectedSession] = useState<number | undefined>(
|
||||
undefined
|
||||
@@ -47,7 +46,9 @@ export default function ImportSessionTable() {
|
||||
}),
|
||||
onFormSuccess: (response: any) => {
|
||||
setSelectedSession(response.pk);
|
||||
setOpened(true);
|
||||
openImporter(response.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
table.refreshTable();
|
||||
}
|
||||
});
|
||||
@@ -159,19 +160,12 @@ export default function ImportSessionTable() {
|
||||
enableSelection: true,
|
||||
onRowClick: (record: any) => {
|
||||
setSelectedSession(record.pk);
|
||||
setOpened(true);
|
||||
openImporter(record.pk, {
|
||||
onClose: table.refreshTable
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ImporterDrawer
|
||||
sessionId={selectedSession ?? -1}
|
||||
opened={selectedSession !== undefined && opened}
|
||||
onClose={() => {
|
||||
setSelectedSession(undefined);
|
||||
setOpened(false);
|
||||
table.refreshTable();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user