mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-27 19:16:44 +00:00
chore: bump zustand (#9577)
* bump zustand to v5 * add missing shallow * fix missing shallow --------- Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
parent
71cf9f5452
commit
c41760a500
@ -101,7 +101,7 @@
|
||||
"react-window": "1.8.10",
|
||||
"recharts": "^2.15.0",
|
||||
"styled-components": "^6.1.14",
|
||||
"zustand": "^4.5.5"
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.10",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { BackgroundImage } from '@mantine/core';
|
||||
import { useEffect } from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { generateUrl } from '../functions/urls';
|
||||
import { useServerApiState } from '../states/ApiState';
|
||||
|
||||
@ -11,10 +12,9 @@ export default function SplashScreen({
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
const [server, fetchServerApiState] = useServerApiState((state) => [
|
||||
state.server,
|
||||
state.fetchServerApiState
|
||||
]);
|
||||
const [server, fetchServerApiState] = useServerApiState(
|
||||
useShallow((state) => [state.server, state.fetchServerApiState])
|
||||
);
|
||||
|
||||
// Fetch server data on mount if no server data is present
|
||||
useEffect(() => {
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
IconFilter
|
||||
} from '@tabler/icons-react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import type { CalendarState } from '../../hooks/UseCalendar';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import { FilterSelectDrawer } from '../../tables/FilterSelectDrawer';
|
||||
@ -51,12 +52,12 @@ export default function Calendar({
|
||||
filters,
|
||||
state,
|
||||
...calendarProps
|
||||
}: InvenTreeCalendarProps) {
|
||||
}: Readonly<InvenTreeCalendarProps>) {
|
||||
const [monthSelectOpened, setMonthSelectOpened] = useState<boolean>(false);
|
||||
|
||||
const [filtersVisible, setFiltersVisible] = useState<boolean>(false);
|
||||
|
||||
const [locale] = useLocalState((s) => [s.language]);
|
||||
const [locale] = useLocalState(useShallow((s) => [s.language]));
|
||||
|
||||
const selectMonth = useCallback(
|
||||
(date: DateValue) => {
|
||||
|
@ -5,6 +5,7 @@ import { IconInfoCircle } from '@tabler/icons-react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { type Layout, Responsive, WidthProvider } from 'react-grid-layout';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useDashboardItems } from '../../hooks/UseDashboardItems';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import DashboardMenu from './DashboardMenu';
|
||||
@ -21,12 +22,14 @@ export default function DashboardLayout() {
|
||||
|
||||
// local/remote storage values for widget / layout
|
||||
const [remoteWidgets, setRemoteWidgets, remoteLayouts, setRemoteLayouts] =
|
||||
useLocalState((state) => [
|
||||
state.widgets,
|
||||
state.setWidgets,
|
||||
state.layouts,
|
||||
state.setLayouts
|
||||
]);
|
||||
useLocalState(
|
||||
useShallow((state) => [
|
||||
state.widgets,
|
||||
state.setWidgets,
|
||||
state.layouts,
|
||||
state.setLayouts
|
||||
])
|
||||
);
|
||||
|
||||
const [editing, setEditing] = useDisclosure(false);
|
||||
const [removing, setRemoving] = useDisclosure(false);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ActionIcon, Center, Group, Text, Tooltip } from '@mantine/core';
|
||||
import { IconServer } from '@tabler/icons-react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
import { ColorToggle } from '../items/ColorToggle';
|
||||
import { LanguageToggle } from '../items/LanguageToggle';
|
||||
@ -12,7 +13,7 @@ export function AuthFormOptions({
|
||||
hostname: string;
|
||||
toggleHostEdit: () => void;
|
||||
}>) {
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
|
||||
return (
|
||||
<Center mx={'md'}>
|
||||
|
@ -18,6 +18,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../../App';
|
||||
import {
|
||||
doBasicLogin,
|
||||
@ -37,11 +38,13 @@ export function AuthenticationForm() {
|
||||
const simpleForm = useForm({ initialValues: { email: '' } });
|
||||
const [classicLoginMode, setMode] = useDisclosure(true);
|
||||
const [auth_config, sso_enabled, password_forgotten_enabled] =
|
||||
useServerApiState((state) => [
|
||||
state.auth_config,
|
||||
state.sso_enabled,
|
||||
state.password_forgotten_enabled
|
||||
]);
|
||||
useServerApiState(
|
||||
useShallow((state) => [
|
||||
state.auth_config,
|
||||
state.sso_enabled,
|
||||
state.password_forgotten_enabled
|
||||
])
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { isLoggedIn } = useUserState();
|
||||
@ -207,11 +210,13 @@ export function RegistrationForm() {
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
const [auth_config, registration_enabled, sso_registration] =
|
||||
useServerApiState((state) => [
|
||||
state.auth_config,
|
||||
state.registration_enabled,
|
||||
state.sso_registration_enabled
|
||||
]);
|
||||
useServerApiState(
|
||||
useShallow((state) => [
|
||||
state.auth_config,
|
||||
state.registration_enabled,
|
||||
state.sso_registration_enabled
|
||||
])
|
||||
);
|
||||
const [isRegistering, setIsRegistering] = useState<boolean>(false);
|
||||
|
||||
async function handleRegistration() {
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
|
||||
import type { HostList } from '@lib/types/Server';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { Wrapper } from '../../pages/Auth/Layout';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
@ -37,11 +38,9 @@ export function InstanceOptions({
|
||||
setHostEdit: () => void;
|
||||
}>) {
|
||||
const [hostListEdit, setHostListEdit] = useToggle([false, true] as const);
|
||||
const [setHost, setHostList, hostList] = useLocalState((state) => [
|
||||
state.setHost,
|
||||
state.setHostList,
|
||||
state.hostList
|
||||
]);
|
||||
const [setHost, setHostList, hostList] = useLocalState(
|
||||
useShallow((state) => [state.setHost, state.setHostList, state.hostList])
|
||||
);
|
||||
const hostListData = Object.keys(hostList).map((key) => ({
|
||||
value: key,
|
||||
label: hostList[key]?.name
|
||||
@ -111,7 +110,7 @@ function ServerInfo({
|
||||
hostList: HostList;
|
||||
hostKey: string;
|
||||
}>) {
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
|
||||
const items: any[] = [
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ import type { FieldValues, UseControllerReturn } from 'react-hook-form';
|
||||
import { FixedSizeGrid as Grid } from 'react-window';
|
||||
|
||||
import type { ApiFormFieldType } from '@lib/types/Forms';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useIconState } from '../../../states/IconState';
|
||||
import { ApiIcon } from '../../items/ApiIcon';
|
||||
|
||||
@ -119,7 +120,7 @@ function ComboboxDropdown({
|
||||
onChange: (newVal: string | null) => void;
|
||||
open: boolean;
|
||||
}>) {
|
||||
const iconPacks = useIconState((s) => s.packages);
|
||||
const iconPacks = useIconState(useShallow((s) => s.packages));
|
||||
const icons = useMemo<RenderIconType[]>(() => {
|
||||
return iconPacks.flatMap((pack) =>
|
||||
Object.entries(pack.icons).flatMap(([name, icon]) =>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useIconState } from '../../states/IconState';
|
||||
import * as classes from './ApiIcon.css';
|
||||
|
||||
@ -9,7 +10,9 @@ type ApiIconProps = {
|
||||
export const ApiIcon = ({ name: _name, size = 22 }: ApiIconProps) => {
|
||||
const [iconPackage, name, variant] = _name.split(':');
|
||||
const icon = useIconState(
|
||||
(s) => s.packagesMap[iconPackage]?.icons[name]?.variants[variant]
|
||||
useShallow(
|
||||
(s) => s.packagesMap[iconPackage]?.icons[name]?.variants[variant]
|
||||
)
|
||||
);
|
||||
|
||||
const unicode = icon ? String.fromCodePoint(Number.parseInt(icon, 16)) : '';
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Select } from '@mantine/core';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { getSupportedLanguages } from '../../contexts/LanguageContext';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
|
||||
export function LanguageSelect({ width = 80 }: Readonly<{ width?: number }>) {
|
||||
const [value, setValue] = useState<string | null>(null);
|
||||
const [locale, setLanguage] = useLocalState((state) => [
|
||||
state.language,
|
||||
state.setLanguage
|
||||
]);
|
||||
const [locale, setLanguage] = useLocalState(
|
||||
useShallow((state) => [state.language, state.setLanguage])
|
||||
);
|
||||
const [langOptions, setLangOptions] = useState<any[]>([]);
|
||||
|
||||
// change global language on change
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
|
||||
export const OnlyStaff = ({ children }: { children: any }) => {
|
||||
const [user] = useUserState((state) => [state.user]);
|
||||
const [user] = useUserState(useShallow((state) => [state.user]));
|
||||
|
||||
if (user?.is_staff) return children;
|
||||
return <Trans>This information is only available for staff users</Trans>;
|
||||
|
@ -16,6 +16,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../../App';
|
||||
import { generateUrl } from '../../functions/urls';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
@ -32,14 +33,14 @@ type AboutLookupRef = {
|
||||
|
||||
export function AboutInvenTreeModal({
|
||||
context,
|
||||
id
|
||||
id,
|
||||
innerProps
|
||||
}: Readonly<
|
||||
ContextModalProps<{
|
||||
modalBody: string;
|
||||
}>
|
||||
>) {
|
||||
const [user] = useUserState((state) => [state.user]);
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [user] = useUserState(useShallow((state) => [state.user]));
|
||||
|
||||
if (!user?.is_staff)
|
||||
return (
|
||||
@ -47,7 +48,18 @@ export function AboutInvenTreeModal({
|
||||
<Trans>This information is only available for staff users</Trans>
|
||||
</Text>
|
||||
);
|
||||
return <AboutContent context={context} id={id} innerProps={innerProps} />;
|
||||
}
|
||||
|
||||
const AboutContent = ({
|
||||
context,
|
||||
id
|
||||
}: Readonly<
|
||||
ContextModalProps<{
|
||||
modalBody: string;
|
||||
}>
|
||||
>) => {
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
const { isLoading, data } = useQuery({
|
||||
queryKey: ['version'],
|
||||
queryFn: () => api.get(apiUrl(ApiEndpoints.version)).then((res) => res.data)
|
||||
@ -185,7 +197,7 @@ export function AboutInvenTreeModal({
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function renderVersionBadge(data: any) {
|
||||
const badgeType = () => {
|
||||
|
@ -2,6 +2,7 @@ import { Trans } from '@lingui/react/macro';
|
||||
import { Badge, Button, Divider, Group, Stack, Table } from '@mantine/core';
|
||||
import type { ContextModalProps } from '@mantine/modals';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
import { OnlyStaff } from '../items/OnlyStaff';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
@ -10,7 +11,7 @@ export function ServerInfoModal({
|
||||
context,
|
||||
id
|
||||
}: ContextModalProps<{ modalBody: string }>) {
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
|
@ -3,6 +3,7 @@ import { IconExclamationCircle } from '@tabler/icons-react';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { docLinks } from '../../defaults/links';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsState';
|
||||
@ -26,7 +27,7 @@ interface AlertInfo {
|
||||
*/
|
||||
export function Alerts() {
|
||||
const user = useUserState();
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
|
||||
const [dismissed, setDismissed] = useState<string[]>([]);
|
||||
|
@ -5,6 +5,7 @@ import { Link, Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
||||
import type { To } from 'react-router-dom';
|
||||
|
||||
import type { UiSizeType } from '@lib/types/Core';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
import * as classes from './DetailDrawer.css';
|
||||
@ -37,10 +38,9 @@ function DetailDrawerComponent({
|
||||
const content = renderContent(id);
|
||||
const opened = useMemo(() => !!id && !!content, [id, content]);
|
||||
|
||||
const [detailDrawerStack, addDetailDrawer] = useLocalState((state) => [
|
||||
state.detailDrawerStack,
|
||||
state.addDetailDrawer
|
||||
]);
|
||||
const [detailDrawerStack, addDetailDrawer] = useLocalState(
|
||||
useShallow((state) => [state.detailDrawerStack, state.addDetailDrawer])
|
||||
);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
@ -91,7 +91,9 @@ export function DetailDrawerLink({
|
||||
to,
|
||||
text
|
||||
}: Readonly<{ to: To; text: string }>) {
|
||||
const addDetailDrawer = useLocalState((state) => state.addDetailDrawer);
|
||||
const addDetailDrawer = useLocalState(
|
||||
useShallow((state) => state.addDetailDrawer)
|
||||
);
|
||||
|
||||
const onNavigate = useCallback(() => {
|
||||
addDetailDrawer(1);
|
||||
|
@ -1,7 +1,3 @@
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { navigateToLink } from '@lib/functions/Navigation';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
ActionIcon,
|
||||
Container,
|
||||
@ -16,6 +12,12 @@ import { IconBell, IconSearch } from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { type ReactNode, useEffect, useMemo, useState } from 'react';
|
||||
import { useMatch, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { navigateToLink } from '@lib/functions/Navigation';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../../App';
|
||||
import type { NavigationUIFeature } from '../../components/plugins/PluginUIFeatureTypes';
|
||||
import { getNavTabs } from '../../defaults/links';
|
||||
@ -38,11 +40,10 @@ import { NotificationDrawer } from './NotificationDrawer';
|
||||
import { SearchDrawer } from './SearchDrawer';
|
||||
|
||||
export function Header() {
|
||||
const [setNavigationOpen, navigationOpen] = useLocalState((state) => [
|
||||
state.setNavigationOpen,
|
||||
state.navigationOpen
|
||||
]);
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [setNavigationOpen, navigationOpen] = useLocalState(
|
||||
useShallow((state) => [state.setNavigationOpen, state.navigationOpen])
|
||||
);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
const [navDrawerOpened, { open: openNavDrawer, close: closeNavDrawer }] =
|
||||
useDisclosure(navigationOpen);
|
||||
const [
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { doLogout } from '../../functions/auth';
|
||||
import * as classes from '../../main.css';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
@ -25,10 +26,9 @@ import { vars } from '../../theme';
|
||||
|
||||
export function MainMenu() {
|
||||
const navigate = useNavigate();
|
||||
const [user, username] = useUserState((state) => [
|
||||
state.user,
|
||||
state.username
|
||||
]);
|
||||
const [user, username] = useUserState(
|
||||
useShallow((state) => [state.user, state.username])
|
||||
);
|
||||
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
||||
|
||||
return (
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
import type { ModelType } from '@lib/enums/ModelType';
|
||||
import { cancelEvent } from '@lib/functions/Events';
|
||||
import { navigateToLink } from '@lib/functions/Navigation';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { identifierString } from '../../functions/conversion';
|
||||
import { usePluginPanels } from '../../hooks/UsePluginPanels';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
@ -262,19 +263,21 @@ function IndexPanelComponent({
|
||||
selectedPanel,
|
||||
panels
|
||||
}: Readonly<PanelProps>) {
|
||||
const lastUsedPanel = useLocalState((state) => {
|
||||
const panelName =
|
||||
selectedPanel || state.lastUsedPanels[pageKey] || panels[0]?.name;
|
||||
const lastUsedPanel = useLocalState(
|
||||
useShallow((state) => {
|
||||
const panelName =
|
||||
selectedPanel || state.lastUsedPanels[pageKey] || panels[0]?.name;
|
||||
|
||||
const panel = panels.findIndex(
|
||||
(p) => p.name === panelName && !p.disabled && !p.hidden
|
||||
);
|
||||
if (panel === -1) {
|
||||
return panels.find((p) => !p.disabled && !p.hidden)?.name || '';
|
||||
}
|
||||
const panel = panels.findIndex(
|
||||
(p) => p.name === panelName && !p.disabled && !p.hidden
|
||||
);
|
||||
if (panel === -1) {
|
||||
return panels.find((p) => !p.disabled && !p.hidden)?.name || '';
|
||||
}
|
||||
|
||||
return panelName;
|
||||
});
|
||||
return panelName;
|
||||
})
|
||||
);
|
||||
|
||||
return <Navigate to={lastUsedPanel} replace />;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useMantineColorScheme, useMantineTheme } from '@mantine/core';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api, queryClient } from '../../App';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import {
|
||||
@ -24,7 +24,7 @@ import {
|
||||
} from '../../hooks/UseForm';
|
||||
|
||||
export const useInvenTreeContext = () => {
|
||||
const [locale, host] = useLocalState((s) => [s.language, s.host]);
|
||||
const [locale, host] = useLocalState(useShallow((s) => [s.language, s.host]));
|
||||
const navigate = useNavigate();
|
||||
const user = useUserState();
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
|
@ -4,6 +4,7 @@ import { I18nProvider } from '@lingui/react';
|
||||
import { LoadingOverlay, Text } from '@mantine/core';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../App';
|
||||
import { useServerApiState } from '../states/ApiState';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
@ -61,8 +62,8 @@ export const getSupportedLanguages = (): Record<string, string> => {
|
||||
export function LanguageContext({
|
||||
children
|
||||
}: Readonly<{ children: JSX.Element }>) {
|
||||
const [language] = useLocalState((state) => [state.language]);
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [language] = useLocalState(useShallow((state) => [state.language]));
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
|
||||
useEffect(() => {
|
||||
activateLocale(defaultLocale);
|
||||
|
@ -4,6 +4,7 @@ import { MantineProvider, createTheme } from '@mantine/core';
|
||||
import { ModalsProvider } from '@mantine/modals';
|
||||
import { Notifications } from '@mantine/notifications';
|
||||
import { ContextMenuProvider } from 'mantine-contextmenu';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { AboutInvenTreeModal } from '../components/modals/AboutInvenTreeModal';
|
||||
import { LicenseModal } from '../components/modals/LicenseModal';
|
||||
import { QrModal } from '../components/modals/QrModal';
|
||||
@ -15,7 +16,7 @@ import { colorSchema } from './colorSchema';
|
||||
export function ThemeContext({
|
||||
children
|
||||
}: Readonly<{ children: JSX.Element }>) {
|
||||
const [userTheme] = useLocalState((state) => [state.userTheme]);
|
||||
const [userTheme] = useLocalState(useShallow((state) => [state.userTheme]));
|
||||
|
||||
// Theme
|
||||
const myTheme = createTheme({
|
||||
|
@ -4,6 +4,7 @@ import { IconBarcode, IconLink, IconPointer } from '@tabler/icons-react';
|
||||
import type { NavigateFunction } from 'react-router-dom';
|
||||
|
||||
import { openContextModal } from '@mantine/modals';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
import { useUserState } from '../states/UserState';
|
||||
import { aboutInvenTree, docLinks, licenseInfo, serverInfo } from './links';
|
||||
@ -16,7 +17,9 @@ export function openQrModal(navigate: NavigateFunction) {
|
||||
}
|
||||
|
||||
export function getActions(navigate: NavigateFunction) {
|
||||
const setNavigationOpen = useLocalState((state) => state.setNavigationOpen);
|
||||
const setNavigationOpen = useLocalState(
|
||||
useShallow((state) => state.setNavigationOpen)
|
||||
);
|
||||
const { user } = useUserState();
|
||||
|
||||
const actions: SpotlightActionData[] = [
|
||||
|
@ -500,15 +500,19 @@ function StockOperationsRow({
|
||||
props.removeFn(props.idx);
|
||||
};
|
||||
|
||||
const callChangeFn = (idx: number, key: string, value: any) => {
|
||||
setTimeout(() => props.changeFn(idx, key, value), 0);
|
||||
};
|
||||
|
||||
const [packagingOpen, packagingHandlers] = useDisclosure(false, {
|
||||
onOpen: () => {
|
||||
if (transfer) {
|
||||
props.changeFn(props.idx, 'packaging', record?.packaging || undefined);
|
||||
callChangeFn(props.idx, 'packaging', record?.packaging || undefined);
|
||||
}
|
||||
},
|
||||
onClose: () => {
|
||||
if (transfer) {
|
||||
props.changeFn(props.idx, 'packaging', undefined);
|
||||
callChangeFn(props.idx, 'packaging', undefined);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -520,7 +524,7 @@ function StockOperationsRow({
|
||||
},
|
||||
onClose: () => {
|
||||
setStatus(undefined);
|
||||
props.changeFn(props.idx, 'status', undefined);
|
||||
callChangeFn(props.idx, 'status', undefined);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,8 @@ import { Anchor, Divider, Group, Loader, Text } from '@mantine/core';
|
||||
import { useToggle } from '@mantine/hooks';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { setApiDefaults } from '../../App';
|
||||
import { AuthFormOptions } from '../../components/forms/AuthFormOptions';
|
||||
import { AuthenticationForm } from '../../components/forms/AuthenticationForm';
|
||||
@ -19,15 +21,12 @@ import { useLocalState } from '../../states/LocalState';
|
||||
import { Wrapper } from './Layout';
|
||||
|
||||
export default function Login() {
|
||||
const [hostKey, setHost, hostList] = useLocalState((state) => [
|
||||
state.hostKey,
|
||||
state.setHost,
|
||||
state.hostList
|
||||
]);
|
||||
const [server, fetchServerApiState] = useServerApiState((state) => [
|
||||
state.server,
|
||||
state.fetchServerApiState
|
||||
]);
|
||||
const [hostKey, setHost, hostList] = useLocalState(
|
||||
useShallow((state) => [state.hostKey, state.setHost, state.hostList])
|
||||
);
|
||||
const [server, fetchServerApiState] = useServerApiState(
|
||||
useShallow((state) => [state.server, state.fetchServerApiState])
|
||||
);
|
||||
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
|
||||
const hostname =
|
||||
hostList[hostKey] === undefined ? t`No selection` : hostList[hostKey]?.name;
|
||||
@ -36,7 +35,10 @@ export default function Login() {
|
||||
const location = useLocation();
|
||||
const [searchParams] = useSearchParams();
|
||||
const [sso_registration, registration_enabled] = useServerApiState(
|
||||
(state) => [state.sso_registration_enabled, state.registration_enabled]
|
||||
useShallow((state) => [
|
||||
state.sso_registration_enabled,
|
||||
state.registration_enabled
|
||||
])
|
||||
);
|
||||
const both_reg_enabled =
|
||||
registration_enabled() || sso_registration() || false;
|
||||
|
@ -7,6 +7,7 @@ import { useMemo } from 'react';
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import type { ApiFormFieldSet } from '@lib/types/Forms';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { ActionButton } from '../../../../components/buttons/ActionButton';
|
||||
import { YesNoUndefinedButton } from '../../../../components/buttons/YesNoButton';
|
||||
import { ActionDropdown } from '../../../../components/items/ActionDropdown';
|
||||
@ -17,10 +18,9 @@ import { useUserState } from '../../../../states/UserState';
|
||||
export function AccountDetailPanel() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [user, fetchUserState] = useUserState((state) => [
|
||||
state.user,
|
||||
state.fetchUserState
|
||||
]);
|
||||
const [user, fetchUserState] = useUserState(
|
||||
useShallow((state) => [state.user, state.fetchUserState])
|
||||
);
|
||||
|
||||
const userFields: ApiFormFieldSet = useMemo(() => {
|
||||
return {
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../../../../App';
|
||||
import { StylishText } from '../../../../components/items/StylishText';
|
||||
import { ProviderLogin, authApi } from '../../../../functions/auth';
|
||||
@ -40,10 +41,9 @@ import { QrRegistrationForm } from './QrRegistrationForm';
|
||||
import { useReauth } from './useConfirm';
|
||||
|
||||
export function SecurityContent() {
|
||||
const [auth_config, sso_enabled] = useServerApiState((state) => [
|
||||
state.auth_config,
|
||||
state.sso_enabled
|
||||
]);
|
||||
const [auth_config, sso_enabled] = useServerApiState(
|
||||
useShallow((state) => [state.auth_config, state.sso_enabled])
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
@ -510,7 +510,9 @@ function MfaAddSection({
|
||||
refetch: () => void;
|
||||
showRecoveryCodes: (codes: Recoverycodes) => void;
|
||||
}>) {
|
||||
const [auth_config] = useServerApiState((state) => [state.auth_config]);
|
||||
const [auth_config] = useServerApiState(
|
||||
useShallow((state) => [state.auth_config])
|
||||
);
|
||||
const [totpQrOpen, { open: openTotpQr, close: closeTotpQr }] =
|
||||
useDisclosure(false);
|
||||
const [totpQr, setTotpQr] = useState<{ totp_url: string; secret: string }>();
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
import { IconRestore } from '@tabler/icons-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { ColorToggle } from '../../../../components/items/ColorToggle';
|
||||
import { LanguageSelect } from '../../../../components/items/LanguageSelect';
|
||||
import { StylishText } from '../../../../components/items/StylishText';
|
||||
@ -34,11 +35,9 @@ const LOOKUP = Object.assign(
|
||||
|
||||
export function UserTheme({ height }: Readonly<{ height: number }>) {
|
||||
const theme = useMantineTheme();
|
||||
const [userTheme, setTheme, setLanguage] = useLocalState((state) => [
|
||||
state.userTheme,
|
||||
state.setTheme,
|
||||
state.setLanguage
|
||||
]);
|
||||
const [userTheme, setTheme, setLanguage] = useLocalState(
|
||||
useShallow((state) => [state.userTheme, state.setTheme, state.setLanguage])
|
||||
);
|
||||
|
||||
// radius
|
||||
function getMark(value: number) {
|
||||
|
@ -4,6 +4,7 @@ import { Accordion, Alert, Stack } from '@mantine/core';
|
||||
import { IconInfoCircle } from '@tabler/icons-react';
|
||||
import { lazy } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { StylishText } from '../../../../components/items/StylishText';
|
||||
import { GlobalSettingList } from '../../../../components/settings/SettingList';
|
||||
import { Loadable } from '../../../../functions/loading';
|
||||
@ -20,7 +21,7 @@ const PluginErrorTable = Loadable(
|
||||
|
||||
export default function PluginManagementPanel() {
|
||||
const pluginsEnabled = useServerApiState(
|
||||
(state) => state.server.plugins_enabled
|
||||
useShallow((state) => state.server.plugins_enabled)
|
||||
);
|
||||
|
||||
const user = useUserState();
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import PermissionDenied from '../../../components/errors/PermissionDenied';
|
||||
import PageTitle from '../../../components/nav/PageTitle';
|
||||
import { SettingsHeader } from '../../../components/nav/SettingsHeader';
|
||||
@ -309,7 +310,7 @@ export default function SystemSettings() {
|
||||
|
||||
const user = useUserState();
|
||||
|
||||
const [server] = useServerApiState((state) => [state.server]);
|
||||
const [server] = useServerApiState(useShallow((state) => [state.server]));
|
||||
|
||||
if (!user.isLoggedIn()) {
|
||||
return <Skeleton />;
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import PageTitle from '../../../components/nav/PageTitle';
|
||||
import { SettingsHeader } from '../../../components/nav/SettingsHeader';
|
||||
import type { PanelType } from '../../../components/panels/Panel';
|
||||
@ -23,10 +24,9 @@ import { AccountContent } from './AccountSettings/UserPanel';
|
||||
* User settings page
|
||||
*/
|
||||
export default function UserSettings() {
|
||||
const [user, isLoggedIn] = useUserState((state) => [
|
||||
state.user,
|
||||
state.isLoggedIn
|
||||
]);
|
||||
const [user, isLoggedIn] = useUserState(
|
||||
useShallow((state) => [state.user, state.isLoggedIn])
|
||||
);
|
||||
|
||||
const userSettingsPanels: PanelType[] = useMemo(() => {
|
||||
return [
|
||||
|
@ -11,6 +11,7 @@ import { apiUrl } from '@lib/functions/Api';
|
||||
import type { TableFilter } from '@lib/types/Filters';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../../App';
|
||||
import { AddItemButton } from '../../components/buttons/AddItemButton';
|
||||
import { EditApiForm } from '../../components/forms/ApiForm';
|
||||
@ -63,8 +64,7 @@ export function UserDrawer({
|
||||
throwError: true
|
||||
});
|
||||
|
||||
const currentUserPk = useUserState((s) => s.user?.pk);
|
||||
|
||||
const currentUserPk = useUserState(useShallow((s) => s.user?.pk));
|
||||
const isCurrentUser = useMemo(
|
||||
() => currentUserPk === Number.parseInt(id, 10),
|
||||
[currentUserPk, id]
|
||||
|
@ -2,6 +2,7 @@ import { useEffect } from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
|
||||
import { getBaseUrl } from '@lib/functions/Navigation';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { api, queryClient } from '../App';
|
||||
import { ApiProvider } from '../contexts/ApiContext';
|
||||
import { ThemeContext } from '../contexts/ThemeContext';
|
||||
@ -10,7 +11,7 @@ import { routes } from '../router';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
|
||||
export default function DesktopAppView() {
|
||||
const [hostList] = useLocalState((state) => [state.hostList]);
|
||||
const [hostList] = useLocalState(useShallow((state) => [state.hostList]));
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(hostList).length === 0) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import '@mantine/core/styles.css';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
import { lazy, useEffect } from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { setApiDefaults } from '../App';
|
||||
import { Loadable } from '../functions/loading';
|
||||
@ -17,7 +18,9 @@ const DesktopAppView = Loadable(lazy(() => import('./DesktopAppView')));
|
||||
|
||||
// Main App
|
||||
export default function MainView() {
|
||||
const [allowMobile] = useLocalState((state) => [state.allowMobile]);
|
||||
const [allowMobile] = useLocalState(
|
||||
useShallow((state) => [state.allowMobile])
|
||||
);
|
||||
// Set initial login status
|
||||
useEffect(() => {
|
||||
try {
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Anchor, Center, Container, Stack, Text, Title } from '@mantine/core';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { ThemeContext } from '../contexts/ThemeContext';
|
||||
import { docLinks } from '../defaults/links';
|
||||
import { IS_DEV } from '../main';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
|
||||
export default function MobileAppView() {
|
||||
const [setAllowMobile] = useLocalState((state) => [state.setAllowMobile]);
|
||||
const [setAllowMobile] = useLocalState(
|
||||
useShallow((state) => [state.setAllowMobile])
|
||||
);
|
||||
|
||||
function ignore() {
|
||||
setAllowMobile(true);
|
||||
|
@ -5465,11 +5465,6 @@ use-sidecar@^1.1.2:
|
||||
detect-node-es "^1.1.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
use-sync-external-store@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9"
|
||||
integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
@ -5712,9 +5707,7 @@ zod@^3.22.4:
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
||||
zustand@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.5.tgz#f8c713041543715ec81a2adda0610e1dc82d4ad1"
|
||||
integrity sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==
|
||||
dependencies:
|
||||
use-sync-external-store "1.2.2"
|
||||
zustand@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.3.tgz#b323435b73d06b2512e93c77239634374b0e407f"
|
||||
integrity sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==
|
||||
|
Loading…
x
Reference in New Issue
Block a user