mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-03 13:58:47 +00:00
This reverts commit 902eafcc752c71d027cddac68fafd059b7b5b8fc.
This commit is contained in:
parent
cd3e7037c5
commit
aecdc0739d
@ -15,14 +15,8 @@ export function setApiDefaults() {
|
|||||||
const token = useSessionState.getState().token;
|
const token = useSessionState.getState().token;
|
||||||
|
|
||||||
api.defaults.baseURL = host;
|
api.defaults.baseURL = host;
|
||||||
|
api.defaults.headers.common['Authorization'] = `Token ${token}`;
|
||||||
if (token) {
|
|
||||||
api.defaults.headers.common['Authorization'] = `Token ${token}`;
|
|
||||||
} else {
|
|
||||||
api.defaults.headers.common['Authorization'] = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const queryClient = new QueryClient();
|
export const queryClient = new QueryClient();
|
||||||
|
|
||||||
function checkMobile() {
|
function checkMobile() {
|
||||||
|
@ -10,8 +10,15 @@ import {
|
|||||||
IconLayoutSidebarLeftCollapse,
|
IconLayoutSidebarLeftCollapse,
|
||||||
IconLayoutSidebarRightCollapse
|
IconLayoutSidebarRightCollapse
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { ReactNode, useCallback, useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Navigate,
|
||||||
|
Route,
|
||||||
|
Routes,
|
||||||
|
useNavigate,
|
||||||
|
useParams
|
||||||
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import { useLocalState } from '../../states/LocalState';
|
import { useLocalState } from '../../states/LocalState';
|
||||||
import { PlaceholderPanel } from '../items/Placeholder';
|
import { PlaceholderPanel } from '../items/Placeholder';
|
||||||
@ -37,57 +44,61 @@ export type PanelProps = {
|
|||||||
collapsible?: boolean;
|
collapsible?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function PanelGroup({
|
function BasePanelGroup({
|
||||||
pageKey,
|
pageKey,
|
||||||
panels,
|
panels,
|
||||||
onPanelChange,
|
onPanelChange,
|
||||||
selectedPanel,
|
selectedPanel,
|
||||||
collapsible = true
|
collapsible = true
|
||||||
}: PanelProps): ReactNode {
|
}: PanelProps): ReactNode {
|
||||||
const localState = useLocalState();
|
const navigate = useNavigate();
|
||||||
|
const { panel } = useParams();
|
||||||
|
|
||||||
const [panel, setPanel] = useState<string>(selectedPanel ?? '');
|
|
||||||
|
|
||||||
// Keep a list of active panels (hidden and disabled panels are not active)
|
|
||||||
const activePanels = useMemo(
|
const activePanels = useMemo(
|
||||||
() => panels.filter((panel) => !panel.hidden && !panel.disabled),
|
() => panels.filter((panel) => !panel.hidden && !panel.disabled),
|
||||||
[panels]
|
[panels]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set selected panel when component is initially loaded, or when the selected panel changes
|
const setLastUsedPanel = useLocalState((state) =>
|
||||||
|
state.setLastUsedPanel(pageKey)
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let first_panel: string = activePanels[0]?.name ?? '';
|
if (panel) {
|
||||||
let active_panel: string =
|
setLastUsedPanel(panel);
|
||||||
useLocalState.getState().getLastUsedPanel(pageKey)() ?? '';
|
|
||||||
|
|
||||||
let panelName = selectedPanel || active_panel || first_panel;
|
|
||||||
|
|
||||||
if (panelName != panel) {
|
|
||||||
setPanel(panelName);
|
|
||||||
}
|
}
|
||||||
|
// panel is intentionally no dependency as this should only run on initial render
|
||||||
if (panelName != active_panel) {
|
}, [setLastUsedPanel]);
|
||||||
useLocalState.getState().setLastUsedPanel(pageKey)(panelName);
|
|
||||||
}
|
|
||||||
}, [activePanels, panels, selectedPanel]);
|
|
||||||
|
|
||||||
// Callback when the active panel changes
|
// Callback when the active panel changes
|
||||||
const handlePanelChange = useCallback(
|
function handlePanelChange(panel: string) {
|
||||||
(panelName: string) => {
|
if (activePanels.findIndex((p) => p.name === panel) === -1) {
|
||||||
// Ensure that the panel name is valid
|
setLastUsedPanel('');
|
||||||
if (!activePanels.some((panel) => panel.name == panelName)) {
|
return navigate('../');
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setPanel(panelName);
|
navigate(`../${panel}`);
|
||||||
localState.setLastUsedPanel(pageKey)(panelName);
|
|
||||||
|
|
||||||
if (onPanelChange) {
|
// Optionally call external callback hook
|
||||||
onPanelChange(panelName);
|
if (onPanelChange) {
|
||||||
}
|
onPanelChange(panel);
|
||||||
},
|
}
|
||||||
[onPanelChange, pageKey]
|
}
|
||||||
);
|
|
||||||
|
// if the selected panel state changes update the current panel
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedPanel && selectedPanel !== panel) {
|
||||||
|
handlePanelChange(selectedPanel);
|
||||||
|
}
|
||||||
|
}, [selectedPanel, panel]);
|
||||||
|
|
||||||
|
// Update the active panel when panels changes and the active is no longer available
|
||||||
|
useEffect(() => {
|
||||||
|
if (activePanels.findIndex((p) => p.name === panel) === -1) {
|
||||||
|
setLastUsedPanel('');
|
||||||
|
return navigate('../');
|
||||||
|
}
|
||||||
|
}, [activePanels, panel]);
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState<boolean>(true);
|
const [expanded, setExpanded] = useState<boolean>(true);
|
||||||
|
|
||||||
@ -158,3 +169,38 @@ export function PanelGroup({
|
|||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function IndexPanelComponent({ pageKey, selectedPanel, panels }: PanelProps) {
|
||||||
|
const lastUsedPanel = useLocalState((state) => {
|
||||||
|
const panelName =
|
||||||
|
selectedPanel || state.lastUsedPanels[pageKey] || panels[0]?.name;
|
||||||
|
|
||||||
|
if (
|
||||||
|
panels.findIndex(
|
||||||
|
(p) => p.name === panelName && !p.disabled && !p.hidden
|
||||||
|
) === -1
|
||||||
|
) {
|
||||||
|
return panels[0]?.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return panelName;
|
||||||
|
});
|
||||||
|
|
||||||
|
return <Navigate to={lastUsedPanel} replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a panel group. The current panel will be appended to the current url.
|
||||||
|
* The last opened panel will be stored in local storage and opened if no panel is provided via url param
|
||||||
|
* @param panels - The list of panels to display
|
||||||
|
* @param onPanelChange - Callback when the active panel changes
|
||||||
|
* @param collapsible - If true, the panel group can be collapsed (defaults to true)
|
||||||
|
*/
|
||||||
|
export function PanelGroup(props: PanelProps) {
|
||||||
|
return (
|
||||||
|
<Routes>
|
||||||
|
<Route index element={<IndexPanelComponent {...props} />} />
|
||||||
|
<Route path="/:panel/*" element={<BasePanelGroup {...props} />} />
|
||||||
|
</Routes>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -27,9 +27,7 @@ export const doClassicLogin = async (username: string, password: string) => {
|
|||||||
name: 'inventree-web-app'
|
name: 'inventree-web-app'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => response.data.token)
|
||||||
return response.status == 200 ? response.data?.token : undefined;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
showNotification({
|
showNotification({
|
||||||
title: t`Login failed`,
|
title: t`Login failed`,
|
||||||
@ -39,7 +37,7 @@ export const doClassicLogin = async (username: string, password: string) => {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!token) return false;
|
if (token === false) return token;
|
||||||
|
|
||||||
// log in with token
|
// log in with token
|
||||||
doTokenLogin(token);
|
doTokenLogin(token);
|
||||||
@ -53,7 +51,6 @@ export const doClassicLogout = async () => {
|
|||||||
// TODO @matmair - logout from the server session
|
// TODO @matmair - logout from the server session
|
||||||
// Set token in context
|
// Set token in context
|
||||||
const { setToken } = useSessionState.getState();
|
const { setToken } = useSessionState.getState();
|
||||||
|
|
||||||
setToken(undefined);
|
setToken(undefined);
|
||||||
|
|
||||||
notifications.show({
|
notifications.show({
|
||||||
|
@ -22,11 +22,9 @@ import { useInstance } from '../../hooks/UseInstance';
|
|||||||
*
|
*
|
||||||
* Note: If no category ID is supplied, this acts as the top-level part category page
|
* Note: If no category ID is supplied, this acts as the top-level part category page
|
||||||
*/
|
*/
|
||||||
export function CategoryPage({
|
export default function CategoryDetail({}: {}) {
|
||||||
categoryId
|
const { id } = useParams();
|
||||||
}: {
|
|
||||||
categoryId?: string | undefined;
|
|
||||||
}) {
|
|
||||||
const [treeOpen, setTreeOpen] = useState(false);
|
const [treeOpen, setTreeOpen] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -35,8 +33,7 @@ export function CategoryPage({
|
|||||||
instanceQuery
|
instanceQuery
|
||||||
} = useInstance({
|
} = useInstance({
|
||||||
endpoint: ApiPaths.category_list,
|
endpoint: ApiPaths.category_list,
|
||||||
pk: categoryId,
|
pk: id,
|
||||||
hasPrimaryKey: true,
|
|
||||||
params: {
|
params: {
|
||||||
path_detail: true
|
path_detail: true
|
||||||
}
|
}
|
||||||
@ -52,7 +49,7 @@ export function CategoryPage({
|
|||||||
<PartListTable
|
<PartListTable
|
||||||
props={{
|
props={{
|
||||||
params: {
|
params: {
|
||||||
category: categoryId
|
category: id
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -65,7 +62,7 @@ export function CategoryPage({
|
|||||||
content: (
|
content: (
|
||||||
<PartCategoryTable
|
<PartCategoryTable
|
||||||
params={{
|
params={{
|
||||||
parent: categoryId ?? 'null'
|
parent: id
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -77,7 +74,7 @@ export function CategoryPage({
|
|||||||
content: <PlaceholderPanel />
|
content: <PlaceholderPanel />
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[categoryId]
|
[category, id]
|
||||||
);
|
);
|
||||||
|
|
||||||
const breadcrumbs = useMemo(
|
const breadcrumbs = useMemo(
|
||||||
@ -113,13 +110,3 @@ export function CategoryPage({
|
|||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detail page for a specific Part Category instance.
|
|
||||||
* Uses the :id parameter in the URL to determine which category to display.admin in
|
|
||||||
*/
|
|
||||||
export default function CategoryDetail({}: {}) {
|
|
||||||
const { id } = useParams();
|
|
||||||
|
|
||||||
return <CategoryPage categoryId={id} />;
|
|
||||||
}
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import { CategoryPage } from './CategoryDetail';
|
|
||||||
|
|
||||||
export default function PartIndex({}: {}) {
|
|
||||||
return <CategoryPage />;
|
|
||||||
}
|
|
@ -12,11 +12,9 @@ import { StockLocationTable } from '../../components/tables/stock/StockLocationT
|
|||||||
import { ApiPaths } from '../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../enums/ApiEndpoints';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
|
||||||
export function LocationPage({
|
export default function Stock() {
|
||||||
locationId
|
const { id } = useParams();
|
||||||
}: {
|
|
||||||
locationId?: string | undefined;
|
|
||||||
}) {
|
|
||||||
const [treeOpen, setTreeOpen] = useState(false);
|
const [treeOpen, setTreeOpen] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -25,8 +23,7 @@ export function LocationPage({
|
|||||||
instanceQuery
|
instanceQuery
|
||||||
} = useInstance({
|
} = useInstance({
|
||||||
endpoint: ApiPaths.stock_location_list,
|
endpoint: ApiPaths.stock_location_list,
|
||||||
pk: locationId,
|
pk: id,
|
||||||
hasPrimaryKey: true,
|
|
||||||
params: {
|
params: {
|
||||||
path_detail: true
|
path_detail: true
|
||||||
}
|
}
|
||||||
@ -41,7 +38,7 @@ export function LocationPage({
|
|||||||
content: (
|
content: (
|
||||||
<StockItemTable
|
<StockItemTable
|
||||||
params={{
|
params={{
|
||||||
location: locationId
|
location: id
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -53,13 +50,13 @@ export function LocationPage({
|
|||||||
content: (
|
content: (
|
||||||
<StockLocationTable
|
<StockLocationTable
|
||||||
params={{
|
params={{
|
||||||
parent: locationId ?? 'null'
|
parent: id
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [locationId]);
|
}, [location, id]);
|
||||||
|
|
||||||
const breadcrumbs = useMemo(
|
const breadcrumbs = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -94,13 +91,3 @@ export function LocationPage({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detail page for a specific Stock Location instance
|
|
||||||
* Uses the :id parameter in the URL to determine which location to display
|
|
||||||
*/
|
|
||||||
export default function LocationDetail({}: {}) {
|
|
||||||
const { id } = useParams();
|
|
||||||
|
|
||||||
return <LocationPage locationId={id} />;
|
|
||||||
}
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import { LocationPage } from './LocationDetail';
|
|
||||||
|
|
||||||
export default function StockIndex({}: {}) {
|
|
||||||
return <LocationPage />;
|
|
||||||
}
|
|
@ -28,12 +28,9 @@ export const ManufacturerDetail = Loadable(
|
|||||||
lazy(() => import('./pages/company/ManufacturerDetail'))
|
lazy(() => import('./pages/company/ManufacturerDetail'))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PartIndex = Loadable(lazy(() => import('./pages/part/PartIndex')));
|
|
||||||
|
|
||||||
export const CategoryDetail = Loadable(
|
export const CategoryDetail = Loadable(
|
||||||
lazy(() => import('./pages/part/CategoryDetail'))
|
lazy(() => import('./pages/part/CategoryDetail'))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PartDetail = Loadable(
|
export const PartDetail = Loadable(
|
||||||
lazy(() => import('./pages/part/PartDetail'))
|
lazy(() => import('./pages/part/PartDetail'))
|
||||||
);
|
);
|
||||||
@ -42,10 +39,6 @@ export const LocationDetail = Loadable(
|
|||||||
lazy(() => import('./pages/stock/LocationDetail'))
|
lazy(() => import('./pages/stock/LocationDetail'))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const StockIndex = Loadable(
|
|
||||||
lazy(() => import('./pages/stock/StockIndex'))
|
|
||||||
);
|
|
||||||
|
|
||||||
export const StockDetail = Loadable(
|
export const StockDetail = Loadable(
|
||||||
lazy(() => import('./pages/stock/StockDetail'))
|
lazy(() => import('./pages/stock/StockDetail'))
|
||||||
);
|
);
|
||||||
@ -126,13 +119,13 @@ export const routes = (
|
|||||||
<Route path="user/*" element={<UserSettings />} />
|
<Route path="user/*" element={<UserSettings />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="part/">
|
<Route path="part/">
|
||||||
<Route index element={<PartIndex />} />
|
<Route index element={<Navigate to="category/" />} />
|
||||||
<Route path="category/:id/*" element={<CategoryDetail />} />
|
<Route path="category/:id?/*" element={<CategoryDetail />} />
|
||||||
<Route path=":id/*" element={<PartDetail />} />
|
<Route path=":id/*" element={<PartDetail />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="stock/">
|
<Route path="stock/">
|
||||||
<Route index element={<StockIndex />} />
|
<Route index element={<Navigate to="location/" />} />
|
||||||
<Route path="location/:id/*" element={<LocationDetail />} />
|
<Route path="location/:id?/*" element={<LocationDetail />} />
|
||||||
<Route path="item/:id/*" element={<StockDetail />} />
|
<Route path="item/:id/*" element={<StockDetail />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="build/">
|
<Route path="build/">
|
||||||
|
@ -24,7 +24,6 @@ interface LocalStateProps {
|
|||||||
loader: LoaderType;
|
loader: LoaderType;
|
||||||
lastUsedPanels: Record<string, string>;
|
lastUsedPanels: Record<string, string>;
|
||||||
setLastUsedPanel: (panelKey: string) => (value: string) => void;
|
setLastUsedPanel: (panelKey: string) => (value: string) => void;
|
||||||
getLastUsedPanel: (panelKey: string) => () => string | undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useLocalState = create<LocalStateProps>()(
|
export const useLocalState = create<LocalStateProps>()(
|
||||||
@ -56,9 +55,6 @@ export const useLocalState = create<LocalStateProps>()(
|
|||||||
lastUsedPanels: { ...get().lastUsedPanels, [panelKey]: value }
|
lastUsedPanels: { ...get().lastUsedPanels, [panelKey]: value }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getLastUsedPanel(panelKey) {
|
|
||||||
return () => get().lastUsedPanels[panelKey];
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user