[React] Settings state manager (#5687)

* Add interface definition for settings

* Fetch global and user settings as state object

* Cleanup dead code

* Fetch settings when performing token login
This commit is contained in:
Oliver 2023-10-12 00:36:53 +11:00 committed by GitHub
parent bf7c1b43bd
commit 0925fbbad2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 117 additions and 26 deletions

View File

@ -16,7 +16,9 @@ import { PlaceholderPill } from '../items/Placeholder';
export function MainMenu() {
const { classes, theme } = InvenTreeStyle();
const [username] = useUserState((state) => [state.user?.name]);
const [username] = useUserState((state) => [
state.user?.name ?? state.user?.username
]);
return (
<Menu width={260} position="bottom-end">
<Menu.Target>

View File

@ -7,6 +7,10 @@ import { api } from '../App';
import { ApiPaths, url, useServerApiState } from '../states/ApiState';
import { useLocalState } from '../states/LocalState';
import { useSessionState } from '../states/SessionState';
import {
useGlobalSettingsState,
useUserSettingsState
} from '../states/SettingsState';
import { useUserState } from '../states/UserState';
export const doClassicLogin = async (username: string, password: string) => {
@ -56,14 +60,19 @@ export const doSimpleLogin = async (email: string) => {
return mail;
};
// Perform a login using a token
export const doTokenLogin = (token: string) => {
const { setToken } = useSessionState.getState();
const { fetchUserState } = useUserState.getState();
const { fetchServerApiState } = useServerApiState.getState();
const globalSettingsState = useGlobalSettingsState.getState();
const userSettingsState = useUserSettingsState.getState();
setToken(token);
fetchUserState();
fetchServerApiState();
globalSettingsState.fetchSettings();
userSettingsState.fetchSettings();
};
export function handleReset(navigate: any, values: { email: string }) {

View File

@ -4,31 +4,6 @@ import { api } from '../App';
import { emptyServerAPI } from '../defaults/defaults';
import { ServerAPIProps, UserProps } from './states';
interface UserStateProps {
user: UserProps | undefined;
setUser: (newUser: UserProps) => void;
fetchApiState: () => void;
}
/**
* Global user information state, using Zustand manager
*/
export const useApiState = create<UserStateProps>((set, get) => ({
user: undefined,
setUser: (newUser: UserProps) => set({ user: newUser }),
fetchApiState: async () => {
// Fetch user data
await api.get(url(ApiPaths.user_me)).then((response) => {
const user: UserProps = {
name: `${response.data.first_name} ${response.data.last_name}`,
email: response.data.email,
username: response.data.username
};
set({ user: user });
});
}
}));
interface ServerApiStateProps {
server: ServerAPIProps;
setServer: (newServer: ServerAPIProps) => void;
@ -55,6 +30,8 @@ export enum ApiPaths {
user_reset = 'api-user-reset',
user_reset_set = 'api-user-reset-set',
settings_global_list = 'api-settings-global-list',
settings_user_list = 'api-settings-user-list',
notifications_list = 'api-notifications-list',
barcode = 'api-barcode',
@ -102,6 +79,10 @@ export function endpoint(path: ApiPaths): string {
return '/auth/password/reset/';
case ApiPaths.user_reset_set:
return '/auth/password/reset/confirm/';
case ApiPaths.settings_global_list:
return 'settings/global/';
case ApiPaths.settings_user_list:
return 'settings/user/';
case ApiPaths.notifications_list:
return 'notifications/';
case ApiPaths.barcode:

View File

@ -0,0 +1,49 @@
/**
* State management for remote (server side) settings
*/
import { create } from 'zustand';
import { api } from '../App';
import { ApiPaths, url } from './ApiState';
import { Setting } from './states';
interface SettingsStateProps {
settings: Setting[];
fetchSettings: () => void;
}
/**
* State management for global (server side) settings
*/
export const useGlobalSettingsState = create<SettingsStateProps>(
(set, get) => ({
settings: [],
fetchSettings: async () => {
await api
.get(url(ApiPaths.settings_global_list))
.then((response) => {
set({ settings: response.data });
})
.catch((error) => {
console.error('Error fetching global settings:', error);
});
}
})
);
/**
* State management for user (server side) settings
*/
export const useUserSettingsState = create<SettingsStateProps>((set, get) => ({
settings: [],
fetchSettings: async () => {
await api
.get(url(ApiPaths.settings_user_list))
.then((response) => {
set({ settings: response.data });
})
.catch((error) => {
console.error('Error fetching user settings:', error);
});
}
}));

View File

@ -37,6 +37,8 @@ export const useUserState = create<UserStateProps>((set, get) => ({
.get(url(ApiPaths.user_roles))
.then((response) => {
const user: UserProps = get().user as UserProps;
// Update user with role data
user.roles = response.data.roles;
user.is_staff = response.data.is_staff ?? false;
user.is_superuser = response.data.is_superuser ?? false;

View File

@ -29,6 +29,41 @@ export interface ServerAPIProps {
active_plugins: PluginProps[];
}
// Type interface defining a single 'setting' object
export interface Setting {
pk: number;
key: string;
value: string;
name: string;
description: string;
type: SettingType;
units: string;
choices: SettingChoice[];
model_name: string | null;
api_url: string | null;
typ: SettingTyp;
plugin?: string;
method?: string;
}
export interface SettingChoice {
value: string;
display_name: string;
}
export enum SettingTyp {
Inventree = 'inventree',
Plugin = 'plugin',
User = 'user',
Notification = 'notification'
}
export enum SettingType {
Boolean = 'boolean',
Integer = 'integer',
String = 'string'
}
export interface PluginProps {
name: string;
slug: string;

View File

@ -9,12 +9,23 @@ import { url_base } from '../main';
import { routes } from '../router';
import { useLocalState } from '../states/LocalState';
import { useSessionState } from '../states/SessionState';
import {
useGlobalSettingsState,
useUserSettingsState
} from '../states/SettingsState';
import { useUserState } from '../states/UserState';
export default function DesktopAppView() {
const [hostList] = useLocalState((state) => [state.hostList]);
const [fetchUserState] = useUserState((state) => [state.fetchUserState]);
const [fetchGlobalSettings] = useGlobalSettingsState((state) => [
state.fetchSettings
]);
const [fetchUserSettings] = useUserSettingsState((state) => [
state.fetchSettings
]);
// Local state initialization
if (Object.keys(hostList).length === 0) {
console.log('Loading default host list');
@ -30,6 +41,8 @@ export default function DesktopAppView() {
if (token && !fetchedServerSession) {
setFetchedServerSession(true);
fetchUserState();
fetchGlobalSettings();
fetchUserSettings();
}
}, [token, fetchedServerSession]);