mirror of
https://github.com/balzack/databag.git
synced 2025-02-11 19:19:16 +00:00
updating access screens
This commit is contained in:
parent
4ae70543db
commit
2541417662
@ -4,13 +4,14 @@ import { Login } from './login/Login';
|
||||
import { Admin } from './admin/Admin';
|
||||
import { CreateAccount } from './createAccount/CreateAccount';
|
||||
import { ThemeProvider } from "styled-components";
|
||||
import { Select } from 'antd';
|
||||
|
||||
import login from 'images/login.png';
|
||||
import dogin from 'images/dogin.png';
|
||||
import bogin from 'images/bogin.png';
|
||||
|
||||
export function Access({ mode }) {
|
||||
|
||||
const { state } = useAccess();
|
||||
const { state, actions } = useAccess();
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={state.colors}>
|
||||
@ -22,7 +23,7 @@ export function Access({ mode }) {
|
||||
<img className="splash" src={dogin} alt="Databag Splash" />
|
||||
)}
|
||||
{ state.scheme === 'light' && (
|
||||
<img className="splash" src={login} alt="Databag Splash" />
|
||||
<img className="splash" src={bogin} alt="Databag Splash" />
|
||||
)}
|
||||
</div>
|
||||
<div className="right">
|
||||
@ -35,6 +36,30 @@ export function Access({ mode }) {
|
||||
{ mode === 'admin' && (
|
||||
<Admin />
|
||||
)}
|
||||
<div className="footer">
|
||||
<div className="option">
|
||||
<div className="label">{state.strings.theme}</div>
|
||||
<Select
|
||||
defaultValue={null}
|
||||
size="small"
|
||||
style={{ width: 128 }}
|
||||
value={state.theme}
|
||||
onChange={actions.setTheme}
|
||||
options={state.themes}
|
||||
/>
|
||||
</div>
|
||||
<div className="option">
|
||||
<div className="label">{state.strings.language}</div>
|
||||
<Select
|
||||
defaultValue={null}
|
||||
size="small"
|
||||
style={{ width: 128 }}
|
||||
value={state.language}
|
||||
onChange={actions.setLanguage}
|
||||
options={state.languages}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -50,6 +75,32 @@ export function Access({ mode }) {
|
||||
{ mode === 'admin' && (
|
||||
<Admin />
|
||||
)}
|
||||
|
||||
<div className="footer">
|
||||
<div className="option">
|
||||
<div className="label">{state.strings.theme}</div>
|
||||
<Select
|
||||
defaultValue={null}
|
||||
size="small"
|
||||
style={{ width: 128 }}
|
||||
value={state.theme}
|
||||
onChange={actions.setTheme}
|
||||
options={state.themes}
|
||||
/>
|
||||
</div>
|
||||
<div className="option">
|
||||
<div className="label">{state.strings.language}</div>
|
||||
<Select
|
||||
defaultValue={null}
|
||||
size="small"
|
||||
style={{ width: 128 }}
|
||||
value={state.language}
|
||||
onChange={actions.setLanguage}
|
||||
options={state.languages}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,8 +1,22 @@
|
||||
import styled from 'styled-components';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
export const AccessWrapper = styled.div`
|
||||
height: 100%;
|
||||
color: ${props => props.theme.hintText};
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
|
||||
.option {
|
||||
gap: 8px;
|
||||
|
||||
.label {
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.full-layout {
|
||||
width: 100%;
|
||||
@ -13,8 +27,9 @@ export const AccessWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
background: ${Colors.formBackground};
|
||||
background: ${props => props.theme.frameArea};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@ -41,8 +56,9 @@ export const AccessWrapper = styled.div`
|
||||
.right {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background: ${Colors.formBackground};
|
||||
background: ${props => props.theme.frameArea};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ export function Admin() {
|
||||
}
|
||||
catch(err) {
|
||||
modal.error({
|
||||
title: 'Login Error',
|
||||
content: 'Please confirm your password.',
|
||||
bodyStyle: { padding: 16 },
|
||||
title: <span style={state.menuStyle}>{state.strings.adminError}</span>,
|
||||
content: <span style={state.menuStyle}>{state.strings.adminMessage}</span>,
|
||||
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -36,20 +36,20 @@ export function Admin() {
|
||||
<UserOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-title">Admin</div>
|
||||
<div className="form-title">{state.strings.admin}</div>
|
||||
<div className="form-form">
|
||||
<Form name="basic" wrapperCol={{ span: 24, }}>
|
||||
|
||||
<Form.Item name="password">
|
||||
<Input.Password placeholder={ state.unclaimed ? 'New Password' : 'Password' } spellCheck="false"
|
||||
<Input.Password placeholder={ state.unclaimed ? state.strings.newPassword : state.strings.password } spellCheck="false"
|
||||
onChange={(e) => actions.setPassword(e.target.value)} autoComplete="current-password"
|
||||
onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div className="form-button">
|
||||
<div className="form-login">
|
||||
<Button type="primary" block onClick={login} size="middle" loading={state.busy}
|
||||
disabled={!state.password}>Login</Button>
|
||||
<Button className={state.password ? 'enabled' : 'disabled'} type="primary" block onClick={login} size="middle" loading={state.busy}
|
||||
disabled={!state.password}>{state.strings.login}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -7,6 +7,22 @@ export const AdminWrapper = styled.div`
|
||||
height: 90%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.disabled {
|
||||
background-color: ${props => props.theme.disabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.idleText};
|
||||
}
|
||||
}
|
||||
|
||||
.enabled {
|
||||
background-color: ${props => props.theme.enabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.activeText};
|
||||
}
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-size: 24px;
|
||||
|
@ -4,6 +4,7 @@ import { getNodeStatus } from 'api/getNodeStatus';
|
||||
import { setNodeStatus } from 'api/setNodeStatus';
|
||||
import { getNodeConfig } from 'api/getNodeConfig';
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { SettingsContext } from 'context/SettingsContext';
|
||||
|
||||
export function useAdmin() {
|
||||
|
||||
@ -12,10 +13,13 @@ export function useAdmin() {
|
||||
placeholder: '',
|
||||
unclaimed: null,
|
||||
busy: false,
|
||||
strings: {},
|
||||
menuStyle: {},
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
const app = useContext(AppContext);
|
||||
const settings = useContext(SettingsContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
@ -61,6 +65,11 @@ export function useAdmin() {
|
||||
},
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { strings, menuStyle } = settings.state;
|
||||
updateState({ strings, menuStyle });
|
||||
}, [settings.state]);
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,9 @@ export function CreateAccount() {
|
||||
}
|
||||
catch(err) {
|
||||
modal.error({
|
||||
title: 'Create Account Error',
|
||||
content: 'Please check with your administrator.',
|
||||
bodyStyle: { padding: 16 },
|
||||
title: <span style={state.menuStyle}>{state.strings.createError}</span>,
|
||||
content: <span style={state.menuStyle}>{state.strings.createMessage}</span>,
|
||||
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -36,32 +36,32 @@ export function CreateAccount() {
|
||||
<SettingOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-title">Create Account</div>
|
||||
<div className="form-title">{state.strings.createAccount}</div>
|
||||
<div className="form-form">
|
||||
<Form name="basic" wrapperCol={{ span: 24, }}>
|
||||
|
||||
<Form.Item name="username" validateStatus={state.validateStatus} help={state.help}>
|
||||
<Input placeholder="Username" spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
<Input placeholder={state.strings.username} spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div className="form-space"></div>
|
||||
|
||||
<Form.Item name="password">
|
||||
<Input.Password placeholder="Password" spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
<Input.Password placeholder={state.strings.newPassword} spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="confirm">
|
||||
<Input.Password placeholder="Confirm Password" spellCheck="false" onChange={(e) => actions.setConfirm(e.target.value)}
|
||||
<Input.Password placeholder={state.strings.confirmPassword} spellCheck="false" onChange={(e) => actions.setConfirm(e.target.value)}
|
||||
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div className="form-button">
|
||||
<div className="form-create">
|
||||
<Button type="primary" block onClick={create} disabled={ actions.isDisabled()}
|
||||
<Button className={actions.isDisabled() ? 'disabled' : 'enabled'} type="primary" block onClick={create} disabled={ actions.isDisabled()}
|
||||
loading={state.busy} size="middle">
|
||||
Create Account
|
||||
{state.strings.create}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@ -69,7 +69,7 @@ export function CreateAccount() {
|
||||
<div className="form-button">
|
||||
<div className="form-login">
|
||||
<Button type="link" block onClick={(e) => actions.onLogin()}>
|
||||
Account Login
|
||||
{state.strings.accountLogin}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,6 +8,22 @@ export const CreateAccountWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.disabled {
|
||||
background-color: ${props => props.theme.disabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.idleText};
|
||||
}
|
||||
}
|
||||
|
||||
.enabled {
|
||||
background-color: ${props => props.theme.enabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.activeText};
|
||||
}
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useContext, useState, useEffect, useRef } from 'react';
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { SettingsContext } from 'context/SettingsContext';
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { getUsername } from 'api/getUsername';
|
||||
|
||||
@ -13,11 +14,14 @@ export function useCreateAccount() {
|
||||
busy: false,
|
||||
validatetatus: 'success',
|
||||
help: '',
|
||||
strings: {},
|
||||
menuStyle: {},
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { search } = useLocation();
|
||||
const app = useContext(AppContext);
|
||||
const settings = useContext(SettingsContext);
|
||||
const debounce = useRef(null);
|
||||
|
||||
const updateState = (value) => {
|
||||
@ -91,6 +95,11 @@ export function useCreateAccount() {
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const { strings, menuStyle } = settings.state;
|
||||
updateState({ strings, menuStyle });
|
||||
}, [settings.state]);
|
||||
|
||||
useEffect(() => {
|
||||
let params = new URLSearchParams(search);
|
||||
let token = params.get("add");
|
||||
|
@ -14,9 +14,9 @@ export function Login() {
|
||||
}
|
||||
catch(err) {
|
||||
modal.error({
|
||||
title: 'Login Error',
|
||||
content: 'Please confirm your username and password.',
|
||||
bodyStyle: { padding: 16 },
|
||||
title: <span style={state.menuStyle}>{state.strings.loginError}</span>,
|
||||
content: <span style={state.menuStyle}>{state.strings.loginMessage}</span>,
|
||||
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -36,32 +36,38 @@ export function Login() {
|
||||
<SettingOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-title">Login</div>
|
||||
<div className="form-title">
|
||||
<div>{ state.strings.login }</div>
|
||||
{ !state.available && state.availableSet && (
|
||||
<div className="form-message">{ state.strings.toCreate }</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="form-form">
|
||||
<Form name="basic" wrapperCol={{ span: 24, }}>
|
||||
|
||||
<Form.Item name="username">
|
||||
<Input placeholder="Username" spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
<Input placeholder={state.strings.username} spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="password">
|
||||
<Input.Password placeholder="Password" spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
<Input.Password placeholder={state.strings.password} spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
autoComplete="current-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div className="form-button">
|
||||
<div className="form-login">
|
||||
<Button type="primary" block onClick={login} disabled={ actions.isDisabled()}
|
||||
<Button className={actions.isDisabled() ? 'disabled' : 'enabled'} type="primary" block onClick={login} disabled={ actions.isDisabled()}
|
||||
size="middle" loading={state.busy}>
|
||||
Login
|
||||
{state.strings.login}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-button">
|
||||
<Button type="link" block disabled={ !state.available } onClick={(e) => actions.onCreate()}>
|
||||
Create Account
|
||||
{state.strings.createAccount}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import styled from 'styled-components';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
export const LoginWrapper = styled.div`
|
||||
max-width: 400px;
|
||||
@ -8,16 +7,32 @@ export const LoginWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.disabled {
|
||||
background-color: ${props => props.theme.disabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.idleText};
|
||||
}
|
||||
}
|
||||
|
||||
.enabled {
|
||||
background-color: ${props => props.theme.enabledArea};
|
||||
|
||||
button {
|
||||
color: ${props => props.theme.activeText};
|
||||
}
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
color: ${Colors.grey};
|
||||
color: ${props => props.theme.hintText};
|
||||
|
||||
.settings {
|
||||
color: ${Colors.grey};
|
||||
color: ${props => props.theme.hintText};
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
@ -34,6 +49,16 @@ export const LoginWrapper = styled.div`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.form-message {
|
||||
font-size: 14px;
|
||||
padding-top: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-form {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { SettingsContext } from 'context/SettingsContext';
|
||||
import { getAvailable } from 'api/getAvailable';
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
@ -9,13 +10,17 @@ export function useLogin() {
|
||||
username: '',
|
||||
password: '',
|
||||
available: false,
|
||||
availableSet: false,
|
||||
disabled: true,
|
||||
busy: false,
|
||||
strings: {},
|
||||
menuStyle: {},
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { search } = useLocation();
|
||||
const app = useContext(AppContext);
|
||||
const settings = useContext(SettingsContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
@ -60,7 +65,7 @@ export function useLogin() {
|
||||
const count = async () => {
|
||||
try {
|
||||
const available = await getAvailable()
|
||||
updateState({ available: available !== 0 })
|
||||
updateState({ availableSet: true, available: available !== 0 })
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
@ -70,6 +75,11 @@ export function useLogin() {
|
||||
// eslint-disable-next-line
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const { strings, menuStyle } = settings.state;
|
||||
updateState({ strings, menuStyle });
|
||||
}, [settings.state]);
|
||||
|
||||
const access = async (token) => {
|
||||
if (!state.busy) {
|
||||
updateState({ busy: true });
|
||||
|
@ -9,6 +9,11 @@ export function useAccess() {
|
||||
display: null,
|
||||
scheme: null,
|
||||
colors: {},
|
||||
theme: null,
|
||||
themes: [],
|
||||
language: null,
|
||||
languages: [],
|
||||
strings: {},
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -45,11 +50,18 @@ export function useAccess() {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const { colors, display, scheme } = settings.state;
|
||||
updateState({ colors, display, scheme });
|
||||
const { theme, themes, strings, language, languages, colors, display, scheme } = settings.state;
|
||||
updateState({ theme, themes, language, languages, strings, colors, display, scheme });
|
||||
}, [settings.state]);
|
||||
|
||||
const actions = {};
|
||||
const actions = {
|
||||
setTheme: (theme) => {
|
||||
settings.actions.setTheme(theme);
|
||||
},
|
||||
setLanguage: (language) => {
|
||||
settings.actions.setLanguage(language);
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ export const Colors = {
|
||||
export const LightTheme = {
|
||||
splashArea: '#8fbea7',
|
||||
baseArea: '#8fbea7',
|
||||
frameArea: '#dddddd',
|
||||
frameArea: '#e4e4e4',
|
||||
iconArea: '#ffffff',
|
||||
headerArea: '#f0f0f0',
|
||||
footerArea: '#f0f0f0',
|
||||
|
@ -94,6 +94,19 @@ export const en = {
|
||||
requestConnection: 'Request Connection',
|
||||
cancelRequest: 'Cancel Request',
|
||||
resyncContact: 'Resync Contact',
|
||||
|
||||
login: 'Login',
|
||||
create: 'Create',
|
||||
createAccount: 'Create Account',
|
||||
accountLogin: 'Account Login',
|
||||
toCreate: 'Accounts are created through a link generated from the admin dashboard.',
|
||||
admin: 'Admin',
|
||||
loginError: 'Login Error',
|
||||
loginMessage: 'Please confirm your username and password.',
|
||||
createError: 'Create Account Error',
|
||||
createMessage: 'Please check with your administrator.',
|
||||
adminError: 'Admin Access Error',
|
||||
adminMessage: 'Please confirm your password.',
|
||||
};
|
||||
|
||||
export const fr = {
|
||||
@ -192,5 +205,18 @@ export const fr = {
|
||||
requestConnection: 'Demander une Connexion',
|
||||
cancelRequest: 'Annuler la Demande',
|
||||
resyncContact: 'Resynchroniser le Contact',
|
||||
|
||||
login: 'Connecter',
|
||||
create: 'Créer',
|
||||
createAccount: 'Créer un Compte',
|
||||
accountLogin: 'Connexion au Compte',
|
||||
toCreate: 'Les comptes sont créés via un lien généré depuis le tableau de bord d\'administration.',
|
||||
admin: 'Administrateur',
|
||||
loginError: 'Erreur de connexion',
|
||||
loginMessage: 'Veuillez confirmer votre nom d\'utilisateur et votre mot de passe.',
|
||||
createError: 'Erreur de création de compte',
|
||||
createMessage: 'Veuillez vérifier auprès de votre administrateur.',
|
||||
adminError: 'Erreur d\'Accès',
|
||||
adminMessage: 'Veuillez confirmer votre mot de passe',
|
||||
};
|
||||
|
||||
|
BIN
net/web/src/images/bogin.png
Normal file
BIN
net/web/src/images/bogin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
@ -24,6 +24,7 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: #888888;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
|
@ -77,6 +77,7 @@ export function AccountAccess() {
|
||||
<Select
|
||||
defaultValue={null}
|
||||
style={{ width: 128 }}
|
||||
size="small"
|
||||
value={state.theme}
|
||||
onChange={actions.setTheme}
|
||||
options={state.themes}
|
||||
@ -87,6 +88,7 @@ export function AccountAccess() {
|
||||
<Select
|
||||
defaultValue={null}
|
||||
style={{ width: 128 }}
|
||||
size="small"
|
||||
value={state.language}
|
||||
onChange={actions.setLanguage}
|
||||
options={state.languages}
|
||||
|
Loading…
Reference in New Issue
Block a user