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