mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-24 21:34:01 +03:00
parent
c8346f97ba
commit
8e7a569897
@ -1,7 +1,4 @@
|
||||
const { Setting: { SCHEMES } } = require('client/constants')
|
||||
|
||||
const CHANGE_ZONE = 'CHANGE_ZONE'
|
||||
const CHANGE_SCHEME = 'CHANGE_SCHEME'
|
||||
const CHANGE_LOADING = 'CHANGE_LOADING'
|
||||
const TOGGLE_MENU = 'TOGGLE_MENU'
|
||||
const FIX_MENU = 'FIX_MENU'
|
||||
@ -12,7 +9,6 @@ const REMOVE_SNACKBAR = 'REMOVE_SNACKBAR'
|
||||
|
||||
const Actions = {
|
||||
CHANGE_ZONE,
|
||||
CHANGE_SCHEME,
|
||||
CHANGE_LOADING,
|
||||
TOGGLE_MENU,
|
||||
FIX_MENU,
|
||||
@ -27,15 +23,6 @@ module.exports = {
|
||||
type: CHANGE_ZONE,
|
||||
payload: { zone }
|
||||
}),
|
||||
updateScheme: (dispatch, getState) => {
|
||||
const current = getState()
|
||||
const currentTheme = current.Authenticated?.theme
|
||||
const userScheme = current.Authenticated?.user?.TEMPLATE?.FIREEDGE?.SCHEME
|
||||
|
||||
if (Object.values(SCHEMES).includes(userScheme) && currentTheme !== userScheme) {
|
||||
dispatch(({ type: CHANGE_SCHEME, payload: { scheme: userScheme } }))
|
||||
}
|
||||
},
|
||||
changeLoading: isLoading => ({
|
||||
type: CHANGE_LOADING,
|
||||
payload: { isLoading }
|
||||
|
@ -1,5 +1,6 @@
|
||||
const START_AUTH = 'START_AUTH'
|
||||
const SELECT_FILTER_GROUP = 'SELECT_FILTER_GROUP'
|
||||
const CHANGE_SETTINGS = 'CHANGE_SETTINGS'
|
||||
const SUCCESS_AUTH = 'SUCCESS_AUTH'
|
||||
const FAILURE_AUTH = 'FAILURE_AUTH'
|
||||
const LOGOUT = 'LOGOUT'
|
||||
@ -7,6 +8,7 @@ const LOGOUT = 'LOGOUT'
|
||||
const Actions = {
|
||||
START_AUTH,
|
||||
SELECT_FILTER_GROUP,
|
||||
CHANGE_SETTINGS,
|
||||
SUCCESS_AUTH,
|
||||
FAILURE_AUTH,
|
||||
LOGOUT
|
||||
@ -17,6 +19,20 @@ module.exports = {
|
||||
startAuth: () => ({
|
||||
type: START_AUTH
|
||||
}),
|
||||
updateSetting: (dispatch, getState) => {
|
||||
const current = getState()
|
||||
|
||||
const userScheme = current.Authenticated?.user?.TEMPLATE?.FIREEDGE?.SCHEME
|
||||
const userLang = current.Authenticated?.user?.TEMPLATE?.FIREEDGE?.LANG
|
||||
|
||||
dispatch(({
|
||||
type: CHANGE_SETTINGS,
|
||||
payload: {
|
||||
scheme: userScheme,
|
||||
lang: userLang
|
||||
}
|
||||
}))
|
||||
},
|
||||
selectFilterGroup: payload => ({
|
||||
type: SELECT_FILTER_GROUP,
|
||||
payload
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { memo } from 'react'
|
||||
import React, { memo, createElement } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { TextField, MenuItem } from '@material-ui/core'
|
||||
@ -8,31 +8,37 @@ import ErrorHelper from 'client/components/FormControl/ErrorHelper'
|
||||
import { Tr } from 'client/components/HOC/Translate'
|
||||
|
||||
const SelectController = memo(
|
||||
({ control, cy, name, label, multiple, values, error, fieldProps }) => (
|
||||
({ control, cy, name, label, multiple, native, values, error, fieldProps }) => (
|
||||
<Controller
|
||||
as={
|
||||
<TextField
|
||||
color='secondary'
|
||||
select
|
||||
fullWidth
|
||||
SelectProps={{ displayEmpty: true, multiple }}
|
||||
label={Tr(label)}
|
||||
inputProps={{ 'data-cy': cy }}
|
||||
error={Boolean(error)}
|
||||
helperText={Boolean(error) && <ErrorHelper label={error?.message} />}
|
||||
FormHelperTextProps={{ 'data-cy': `${cy}-error` }}
|
||||
{...fieldProps}
|
||||
>
|
||||
{values?.map(({ text, value }) => (
|
||||
<MenuItem key={`${name}-${value}`} value={value ?? ''}>
|
||||
{text}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
}
|
||||
render={({ value: renderValue, onChange, onBlur }) => {
|
||||
const defaultValue = multiple ? [values?.[0]?.value] : values?.[0]?.value
|
||||
|
||||
return (
|
||||
<TextField
|
||||
value={renderValue ?? defaultValue}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
color='secondary'
|
||||
select
|
||||
fullWidth
|
||||
SelectProps={{ displayEmpty: true, multiple, native }}
|
||||
label={Tr(label)}
|
||||
inputProps={{ 'data-cy': cy }}
|
||||
error={Boolean(error)}
|
||||
helperText={Boolean(error) && <ErrorHelper label={error?.message} />}
|
||||
FormHelperTextProps={{ 'data-cy': `${cy}-error` }}
|
||||
{...fieldProps}
|
||||
>
|
||||
{values?.map(({ text, value = '' }) => createElement(
|
||||
native ? 'option' : MenuItem,
|
||||
{ key: `${name}-${value}`, value },
|
||||
text
|
||||
))}
|
||||
</TextField>
|
||||
)
|
||||
}}
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={multiple ? [values[0]?.value] : values[0]?.value}
|
||||
/>
|
||||
),
|
||||
(prevProps, nextProps) => prevProps.error === nextProps.error
|
||||
@ -44,6 +50,7 @@ SelectController.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
multiple: PropTypes.bool,
|
||||
native: PropTypes.bool,
|
||||
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
error: PropTypes.oneOfType([
|
||||
PropTypes.bool,
|
||||
@ -58,6 +65,7 @@ SelectController.defaultProps = {
|
||||
name: '',
|
||||
label: '',
|
||||
multiple: false,
|
||||
native: false,
|
||||
values: [],
|
||||
error: false,
|
||||
fieldProps: undefined
|
||||
|
@ -28,19 +28,7 @@ const FormWithSchema = ({ id, cy, fields }) => {
|
||||
return (
|
||||
<Grid container spacing={1}>
|
||||
{fields?.map(
|
||||
({
|
||||
name,
|
||||
type,
|
||||
htmlType,
|
||||
label,
|
||||
values,
|
||||
multiline,
|
||||
multiple,
|
||||
dependOf,
|
||||
tooltip,
|
||||
grid,
|
||||
fieldProps
|
||||
}) => {
|
||||
({ name, type, htmlType, values, dependOf, grid, ...restOfProps }) => {
|
||||
const dataCy = `${cy}-${name}`
|
||||
const inputName = id ? `${id}.${name}` : name
|
||||
|
||||
@ -65,15 +53,11 @@ const FormWithSchema = ({ id, cy, fields }) => {
|
||||
cy: dataCy,
|
||||
type: htmlTypeValue,
|
||||
name: inputName,
|
||||
label,
|
||||
tooltip,
|
||||
multiline,
|
||||
multiple,
|
||||
values: typeof values === 'function'
|
||||
? values(dependValue)
|
||||
: values,
|
||||
error: inputError,
|
||||
fieldProps
|
||||
...restOfProps
|
||||
})}
|
||||
</Grid>
|
||||
</HiddenInput>
|
||||
|
@ -16,8 +16,9 @@
|
||||
import React, { useContext, useState, useEffect, createContext } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import root from 'window-or-global'
|
||||
import { Select } from '@material-ui/core'
|
||||
import { sprintf } from 'sprintf-js'
|
||||
|
||||
import { useAuth } from 'client/hooks'
|
||||
import { DEFAULT_LANGUAGE, LANGUAGES_URL } from 'client/constants'
|
||||
|
||||
const TranslateContext = createContext()
|
||||
@ -25,7 +26,6 @@ let languageScript = root.document?.createElement('script')
|
||||
|
||||
const GenerateScript = (
|
||||
language = DEFAULT_LANGUAGE,
|
||||
setLang = () => undefined,
|
||||
setHash = () => undefined
|
||||
) => {
|
||||
try {
|
||||
@ -33,7 +33,6 @@ const GenerateScript = (
|
||||
script.src = `${LANGUAGES_URL}/${language}.js`
|
||||
script.async = true
|
||||
script.onload = () => {
|
||||
setLang(language)
|
||||
setHash(root.locale)
|
||||
}
|
||||
root.document.body.appendChild(script)
|
||||
@ -48,17 +47,17 @@ const RemoveScript = () => {
|
||||
}
|
||||
|
||||
const TranslateProvider = ({ children }) => {
|
||||
const [lang, setLang] = useState(DEFAULT_LANGUAGE)
|
||||
const [hash, setHash] = useState({})
|
||||
const { settings: { lang } = {} } = useAuth()
|
||||
|
||||
useEffect(() => {
|
||||
GenerateScript(lang, setLang, setHash)
|
||||
GenerateScript(lang, setHash)
|
||||
return () => { RemoveScript() }
|
||||
}, [])
|
||||
}, [lang])
|
||||
|
||||
const changeLang = (language = DEFAULT_LANGUAGE) => {
|
||||
RemoveScript()
|
||||
GenerateScript(language, setLang, setHash)
|
||||
GenerateScript(language, setHash)
|
||||
}
|
||||
|
||||
const value = {
|
||||
@ -103,34 +102,6 @@ const Tr = (str = '') => {
|
||||
return translate(key, valuesTr)
|
||||
}
|
||||
|
||||
const SelectTranslate = props => {
|
||||
const context = useContext(TranslateContext)
|
||||
const languages = Array.isArray(root?.langs) ? root?.langs : []
|
||||
|
||||
const handleChange = (e, changeLang) => {
|
||||
if (e?.target?.value && typeof changeLang === 'function') {
|
||||
changeLang(e.target.value)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
native
|
||||
type="select"
|
||||
fullWidth
|
||||
onChange={e => handleChange(e, context.changeLang)}
|
||||
defaultValue={context.lang}
|
||||
{...props}
|
||||
>
|
||||
{languages.map(({ key, value }) => (
|
||||
<option value={key} key={key}>
|
||||
{value}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
|
||||
const Translate = ({ word = '', values }) => {
|
||||
const valuesTr = !Array.isArray(values) ? [values] : values
|
||||
return translate(word, valuesTr)
|
||||
@ -157,4 +128,4 @@ Translate.defaultProps = {
|
||||
values: ''
|
||||
}
|
||||
|
||||
export { TranslateContext, TranslateProvider, SelectTranslate, Translate, Tr }
|
||||
export { TranslateContext, TranslateProvider, Translate, Tr }
|
||||
|
@ -13,22 +13,6 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
import InternalLayout from 'client/components/HOC/InternalLayout'
|
||||
import MainLayout from 'client/components/HOC/MainLayout'
|
||||
import {
|
||||
TranslateContext,
|
||||
TranslateProvider,
|
||||
Translate,
|
||||
Tr,
|
||||
SelectTranslate
|
||||
} from 'client/components/HOC/Translate'
|
||||
|
||||
export {
|
||||
InternalLayout,
|
||||
MainLayout,
|
||||
TranslateContext,
|
||||
TranslateProvider,
|
||||
Translate,
|
||||
Tr,
|
||||
SelectTranslate
|
||||
}
|
||||
export { default as InternalLayout } from 'client/components/HOC/InternalLayout'
|
||||
export { default as MainLayout } from 'client/components/HOC/MainLayout'
|
||||
export * from 'client/components/HOC/Translate'
|
||||
|
@ -1,12 +1,12 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { MenuItem, MenuList, Divider, Link } from '@material-ui/core'
|
||||
import { MenuItem, MenuList, Link } from '@material-ui/core'
|
||||
import AccountCircleIcon from '@material-ui/icons/AccountCircle'
|
||||
|
||||
import { useAuth } from 'client/hooks'
|
||||
import HeaderPopover from 'client/components/Header/Popover'
|
||||
import { DevTypography } from 'client/components/Typography'
|
||||
import { Tr, SelectTranslate } from 'client/components/HOC'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, APPS, APP_URL } from 'client/constants'
|
||||
|
||||
const User = React.memo(() => {
|
||||
@ -24,10 +24,6 @@ const User = React.memo(() => {
|
||||
>
|
||||
{() => (
|
||||
<MenuList>
|
||||
<MenuItem>
|
||||
<SelectTranslate />
|
||||
</MenuItem>
|
||||
<Divider />
|
||||
<MenuItem onClick={handleLogout} data-cy="header-logout-button">
|
||||
{Tr(T.SignOut)}
|
||||
</MenuItem>
|
||||
|
@ -73,7 +73,7 @@ export default makeStyles(theme => ({
|
||||
backgroundColor: theme.palette.type === 'dark'
|
||||
? theme.palette.background.paper
|
||||
: theme.palette.primary.main,
|
||||
color: theme.palette.text.primary,
|
||||
color: theme.palette.primary.contrastText,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '1rem',
|
||||
|
@ -1,39 +1,47 @@
|
||||
import React, { memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { withStyles, Badge, Typography } from '@material-ui/core'
|
||||
import { makeStyles, Typography, Chip } from '@material-ui/core'
|
||||
|
||||
const StyledBadge = withStyles(() => ({
|
||||
badge: {
|
||||
right: -25,
|
||||
top: 13,
|
||||
fontSize: '0.7rem'
|
||||
const useStyles = makeStyles(() => ({
|
||||
root: {
|
||||
display: 'inline-flex',
|
||||
gap: '1em',
|
||||
width: '100%'
|
||||
},
|
||||
label: {
|
||||
flexGrow: 1
|
||||
}
|
||||
}))(Badge)
|
||||
}))
|
||||
|
||||
const DevTypography = memo(({ label, labelProps, color, chipProps }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const DevTypography = memo(({ label, labelProps, color, badgeProps }) => {
|
||||
return (
|
||||
<StyledBadge badgeContent="DEV" color={color} {...badgeProps}>
|
||||
<Typography {...labelProps}>{label}</Typography>
|
||||
</StyledBadge>
|
||||
<span className={classes.root}>
|
||||
<Typography {...labelProps} className={classes.label}>
|
||||
{label}
|
||||
</Typography>
|
||||
<Chip size='small' label='DEV' color={color} {...chipProps} />
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
||||
DevTypography.propTypes = {
|
||||
chipProps: PropTypes.object,
|
||||
color: PropTypes.string,
|
||||
label: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
||||
PropTypes.string.isRequired
|
||||
]),
|
||||
labelProps: PropTypes.object,
|
||||
color: PropTypes.string,
|
||||
badgeProps: PropTypes.object
|
||||
labelProps: PropTypes.object
|
||||
}
|
||||
|
||||
DevTypography.defaultProps = {
|
||||
label: '',
|
||||
labelProps: undefined,
|
||||
chipProps: undefined,
|
||||
color: 'secondary',
|
||||
badgeProps: undefined
|
||||
label: '',
|
||||
labelProps: undefined
|
||||
}
|
||||
|
||||
DevTypography.displayName = 'DevTypography'
|
||||
|
@ -13,10 +13,10 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
import { defaultApps, defaultAppName } from 'server/utils/constants/defaults'
|
||||
import { defaultApps, defaultAppName, availableLanguages } from 'server/utils/constants/defaults'
|
||||
import * as Setting from 'client/constants/setting'
|
||||
|
||||
export const JWT_NAME = 'FireedgeToken'
|
||||
export const DEFAULT_LANGUAGE = 'en'
|
||||
|
||||
export const BY = {
|
||||
text: 'OpenNebula',
|
||||
@ -37,6 +37,12 @@ export const DEFAULT_IMAGE = `${IMAGES_URL}/default.webp`
|
||||
export const IMAGE_FORMATS = ['webp', 'png', 'jpg']
|
||||
|
||||
export const FONTS_URL = `${STATIC_FILES_URL}/fonts`
|
||||
|
||||
export const SCHEMES = Setting.SCHEMES
|
||||
export const DEFAULT_SCHEME = Setting.SCHEMES.SYSTEM
|
||||
|
||||
export const LANGUAGES = availableLanguages
|
||||
export const DEFAULT_LANGUAGE = 'en'
|
||||
export const LANGUAGES_URL = `${STATIC_FILES_URL}/languages`
|
||||
|
||||
export const ONEADMIN_ID = '0'
|
||||
@ -69,7 +75,6 @@ export const DEBUG_LEVEL = {
|
||||
}
|
||||
|
||||
export * as T from 'client/constants/translates'
|
||||
export * as Setting from 'client/constants/setting'
|
||||
export * from 'client/constants/flow'
|
||||
export * from 'client/constants/states'
|
||||
export * from 'client/constants/provision'
|
||||
|
@ -61,8 +61,9 @@ module.exports = {
|
||||
|
||||
/* sections */
|
||||
Dashboard: 'Dashboard',
|
||||
Settings: 'Settings',
|
||||
/* sections - settings */
|
||||
Settings: 'Settings',
|
||||
Schema: 'Schema',
|
||||
Dark: 'Dark',
|
||||
Light: 'Light',
|
||||
System: 'System',
|
||||
|
@ -15,19 +15,20 @@
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
import {
|
||||
makeStyles,
|
||||
Container,
|
||||
Paper,
|
||||
Typography,
|
||||
TextField
|
||||
} from '@material-ui/core'
|
||||
import { makeStyles, Container, Paper, Box, Typography } from '@material-ui/core'
|
||||
|
||||
import { useAuth, useGeneral } from 'client/hooks'
|
||||
import { Tr, TranslateContext } from 'client/components/HOC'
|
||||
import { T, Setting } from 'client/constants'
|
||||
import { useForm, FormProvider } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers'
|
||||
|
||||
import FormWithSchema from 'client/components/Forms/FormWithSchema'
|
||||
import SubmitButton from 'client/components/FormControl/SubmitButton'
|
||||
|
||||
import { useAuth } from 'client/hooks'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
import { FORM_FIELDS, FORM_SCHEMA } from 'client/containers/Settings/schema'
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
header: {
|
||||
paddingTop: '1rem'
|
||||
@ -53,36 +54,27 @@ const useStyles = makeStyles(theme => ({
|
||||
|
||||
const Settings = () => {
|
||||
const classes = useStyles()
|
||||
const context = React.useContext(TranslateContext)
|
||||
// const langAvailables = Array.isArray(window?.langs) ? window?.langs : []
|
||||
|
||||
const { scheme: currentScheme } = useGeneral()
|
||||
const { updateUser } = useAuth()
|
||||
const { updateUser, settings } = useAuth()
|
||||
|
||||
const [settings, setSettings] = React.useState({
|
||||
scheme: currentScheme,
|
||||
lang: context.lang
|
||||
const { handleSubmit, setError, reset, formState, ...methods } = useForm({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: settings,
|
||||
resolver: yupResolver(FORM_SCHEMA)
|
||||
})
|
||||
|
||||
const handleChange = evt => {
|
||||
evt.preventDefault()
|
||||
evt.persist()
|
||||
React.useEffect(() => {
|
||||
// set user settings values
|
||||
reset(settings, { isSubmitted: false, error: false })
|
||||
}, [settings])
|
||||
|
||||
setSettings(prev => ({
|
||||
...prev,
|
||||
[evt.target.name]: evt.target.value
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSubmit = evt => {
|
||||
evt.preventDefault()
|
||||
|
||||
const values = Object.entries(settings)
|
||||
const onSubmit = dataForm => {
|
||||
const values = Object.entries(dataForm)
|
||||
.map(([key, value]) => `\n ${String(key).toUpperCase()} = "${value}"`)
|
||||
.join(',')
|
||||
|
||||
updateUser({ template: `FIREEDGE = [${values}]\n` })
|
||||
.then(() => context.changeLang(settings.lang))
|
||||
return updateUser({ template: `FIREEDGE = [${values}]\n` })
|
||||
// .then(() => context.changeLang(dataForm.lang))
|
||||
}
|
||||
|
||||
return (
|
||||
@ -99,53 +91,20 @@ const Settings = () => {
|
||||
<Typography variant='overline' component='div' className={classes.subheader}>
|
||||
{`${Tr(T.Configuration)} UI`}
|
||||
</Typography>
|
||||
<TextField
|
||||
id='select-scheme-type'
|
||||
select
|
||||
fullWidth
|
||||
name='scheme'
|
||||
color='secondary'
|
||||
label='Scheme'
|
||||
value={settings.scheme}
|
||||
onChange={handleChange}
|
||||
SelectProps={{
|
||||
native: true
|
||||
}}
|
||||
variant='outlined'
|
||||
>
|
||||
<option value={Setting.SCHEMES.LIGHT}>{T.Light}</option>
|
||||
<option value={Setting.SCHEMES.DARK}>{T.Dark}</option>
|
||||
<option value={Setting.SCHEMES.SYSTEM}>{T.System}</option>
|
||||
</TextField>
|
||||
|
||||
{/* is not operative yet */}
|
||||
{/* <Select
|
||||
<Box component="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<FormProvider {...methods}>
|
||||
<FormWithSchema cy='settings' fields={FORM_FIELDS} />
|
||||
</FormProvider>
|
||||
<div className={classes.actions}>
|
||||
<SubmitButton
|
||||
color='secondary'
|
||||
inputProps={{
|
||||
name: 'lang',
|
||||
id: 'select-lang',
|
||||
'data-cy': 'select-lang'
|
||||
}}
|
||||
onChange={handleChange}
|
||||
fullWidth
|
||||
native
|
||||
value={lang}
|
||||
variant='outlined'
|
||||
>
|
||||
{langAvailables.map(({ key, value }) => (
|
||||
<option value={key} key={key}>
|
||||
{value}
|
||||
</option>
|
||||
))}
|
||||
</Select> */}
|
||||
<div className={classes.actions}>
|
||||
<SubmitButton
|
||||
color='secondary'
|
||||
data-cy='settings-submit-button'
|
||||
label={Tr(T.Save)}
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
</div>
|
||||
data-cy='settings-submit-button'
|
||||
label={Tr(T.Save)}
|
||||
onClick={handleSubmit}
|
||||
isSubmitting={formState.isSubmitting}
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Container>
|
||||
)
|
||||
|
47
src/fireedge/src/client/containers/Settings/schema.js
Normal file
47
src/fireedge/src/client/containers/Settings/schema.js
Normal file
@ -0,0 +1,47 @@
|
||||
import * as yup from 'yup'
|
||||
import { T, INPUT_TYPES, SCHEMES, DEFAULT_SCHEME, DEFAULT_LANGUAGE } from 'client/constants'
|
||||
import { getValidationFromFields } from 'client/utils'
|
||||
|
||||
const SCHEME_VALUES = [
|
||||
{ text: T.System, value: SCHEMES.SYSTEM },
|
||||
{ text: T.Dark, value: SCHEMES.DARK },
|
||||
{ text: T.Light, value: SCHEMES.LIGHT }
|
||||
]
|
||||
|
||||
const LANGUAGE_VALUES =
|
||||
window?.langs?.map(({ key, value }) => ({ text: value, value: key })) ?? []
|
||||
|
||||
const SCHEME = {
|
||||
name: 'scheme',
|
||||
label: T.Schema,
|
||||
type: INPUT_TYPES.SELECT,
|
||||
values: SCHEME_VALUES,
|
||||
validation: yup
|
||||
.string()
|
||||
.trim()
|
||||
.required('Scheme field is required')
|
||||
.default(DEFAULT_SCHEME),
|
||||
grid: { md: 12 },
|
||||
fieldProps: { variant: 'outlined' }
|
||||
}
|
||||
|
||||
const LANGUAGES = {
|
||||
name: 'lang',
|
||||
label: T.Language,
|
||||
type: INPUT_TYPES.SELECT,
|
||||
values: LANGUAGE_VALUES,
|
||||
validation: yup
|
||||
.string()
|
||||
.trim()
|
||||
.required('Language field is required')
|
||||
.default(DEFAULT_LANGUAGE),
|
||||
grid: { md: 12 },
|
||||
native: true,
|
||||
fieldProps: { variant: 'outlined' }
|
||||
}
|
||||
|
||||
export const FORM_FIELDS = [SCHEME, LANGUAGES]
|
||||
|
||||
export const FORM_SCHEMA = yup.object(
|
||||
getValidationFromFields(FORM_FIELDS)
|
||||
)
|
@ -10,12 +10,13 @@ import * as serviceOne from 'client/services/one'
|
||||
import {
|
||||
startAuth,
|
||||
selectFilterGroup,
|
||||
updateSetting,
|
||||
successAuth,
|
||||
failureAuth,
|
||||
logout as logoutRequest
|
||||
} from 'client/actions/user'
|
||||
import { setGroups } from 'client/actions/pool'
|
||||
import { updateScheme, enqueueError, enqueueSuccess, closeSnackbar } from 'client/actions/general'
|
||||
import { enqueueError, enqueueSuccess, closeSnackbar } from 'client/actions/general'
|
||||
|
||||
const useAuth = () => {
|
||||
const {
|
||||
@ -25,7 +26,8 @@ const useAuth = () => {
|
||||
isLoading,
|
||||
firstRender,
|
||||
filterPool,
|
||||
user: authUser
|
||||
user: authUser,
|
||||
settings
|
||||
} = useSelector(state => state?.Authenticated, shallowEqual)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@ -79,9 +81,9 @@ const useAuth = () => {
|
||||
return serviceAuth
|
||||
.getUser()
|
||||
.then(user => dispatch(successAuth({ user })))
|
||||
.then(serviceOne.getGroups)
|
||||
.then(() => dispatch(updateSetting))
|
||||
.then(() => serviceOne.getGroups())
|
||||
.then(groups => dispatch(setGroups(groups)))
|
||||
.then(() => dispatch(updateScheme))
|
||||
.catch(err => dispatch(failureAuth({ error: err })))
|
||||
}, [dispatch, JWT_NAME, authUser])
|
||||
|
||||
@ -129,6 +131,7 @@ const useAuth = () => {
|
||||
updateUser,
|
||||
isLogged: !!jwt,
|
||||
authUser,
|
||||
settings,
|
||||
isOneAdmin: authUser?.ID === ONEADMIN_ID,
|
||||
isLoginInProcess,
|
||||
isLoading,
|
||||
|
@ -8,8 +8,7 @@ export default function useGeneral () {
|
||||
zone,
|
||||
isLoading,
|
||||
isOpenMenu,
|
||||
isFixMenu,
|
||||
scheme
|
||||
isFixMenu
|
||||
} = useSelector(state => state?.General, shallowEqual)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@ -41,7 +40,6 @@ export default function useGeneral () {
|
||||
)
|
||||
|
||||
return {
|
||||
scheme,
|
||||
isFixMenu,
|
||||
isLoading,
|
||||
isOpenMenu,
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React, { memo } from 'react'
|
||||
import { number, string, bool, oneOfType } from 'prop-types'
|
||||
import { useTheme } from '@material-ui/core'
|
||||
|
||||
const Logo = memo(({ width, height, spinner, withText, viewBox, ...props }) => {
|
||||
const theme = useTheme()
|
||||
const cloudColor = {
|
||||
child1: { from: '#0098c3', to: '#ffffff' },
|
||||
child2: { from: '#0098c3', to: '#ffffff' },
|
||||
@ -12,7 +10,7 @@ const Logo = memo(({ width, height, spinner, withText, viewBox, ...props }) => {
|
||||
child5: { from: '#bfe6f2', to: '#ffffff' }
|
||||
}
|
||||
const textColor = {
|
||||
top: theme.palette.text.primary,
|
||||
top: 'currentColor',
|
||||
bottom: '#0098c3'
|
||||
}
|
||||
return (
|
||||
|
@ -3,20 +3,20 @@ import PropTypes from 'prop-types'
|
||||
|
||||
import { CssBaseline, ThemeProvider, StylesProvider, useMediaQuery } from '@material-ui/core'
|
||||
import { createTheme, generateClassName } from 'client/theme'
|
||||
import { useGeneral } from 'client/hooks'
|
||||
import { Setting } from 'client/constants'
|
||||
import { useAuth } from 'client/hooks'
|
||||
import { SCHEMES } from 'client/constants'
|
||||
|
||||
const { SCHEMES: { DARK, LIGHT, SYSTEM } } = Setting
|
||||
const { DARK, LIGHT, SYSTEM } = SCHEMES
|
||||
|
||||
const MuiProvider = ({ theme: appTheme, children }) => {
|
||||
const { scheme } = useGeneral()
|
||||
const { settings: { scheme } = {} } = useAuth()
|
||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)')
|
||||
|
||||
const changeThemeType = () => {
|
||||
const prefersScheme = prefersDarkMode ? DARK : LIGHT
|
||||
const userScheme = scheme === SYSTEM ? prefersScheme : scheme
|
||||
const newScheme = scheme === SYSTEM ? prefersScheme : scheme
|
||||
|
||||
return createTheme(appTheme(userScheme))
|
||||
return createTheme(appTheme(newScheme))
|
||||
}
|
||||
|
||||
const [muitheme, setTheme] = React.useState(changeThemeType)
|
||||
|
@ -14,7 +14,12 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const { Actions: UserActions } = require('../actions/user')
|
||||
const { JWT_NAME, FILTER_POOL } = require('client/constants')
|
||||
const {
|
||||
JWT_NAME,
|
||||
FILTER_POOL,
|
||||
DEFAULT_LANGUAGE,
|
||||
DEFAULT_SCHEME
|
||||
} = require('client/constants')
|
||||
|
||||
const jwt =
|
||||
typeof window !== 'undefined'
|
||||
@ -29,6 +34,10 @@ const initial = {
|
||||
group: null,
|
||||
error: null,
|
||||
filterPool: FILTER_POOL.ALL_RESOURCES,
|
||||
settings: {
|
||||
scheme: DEFAULT_SCHEME,
|
||||
lang: DEFAULT_LANGUAGE
|
||||
},
|
||||
isLoginInProcess: false,
|
||||
isLoading: false,
|
||||
firstRender: true
|
||||
@ -58,6 +67,11 @@ const authentication = (state = initial, action) => {
|
||||
isLoginInProcess: false,
|
||||
...action.payload
|
||||
}
|
||||
case UserActions.CHANGE_SETTINGS:
|
||||
return {
|
||||
...state,
|
||||
settings: action.payload
|
||||
}
|
||||
case UserActions.FAILURE_AUTH:
|
||||
return {
|
||||
...state,
|
||||
|
@ -16,15 +16,13 @@
|
||||
const { Actions: PoolActions } = require('../actions/pool')
|
||||
const { Actions: UserActions } = require('../actions/user')
|
||||
const { Actions: GeneralActions } = require('../actions/general')
|
||||
const { Setting: { SCHEMES } } = require('client/constants')
|
||||
|
||||
const initial = {
|
||||
zone: 0,
|
||||
notifications: [],
|
||||
isLoading: false,
|
||||
isOpenMenu: false,
|
||||
isFixMenu: false,
|
||||
scheme: SCHEMES.DARK
|
||||
isFixMenu: false
|
||||
}
|
||||
|
||||
const General = (state = initial, action) => {
|
||||
@ -59,8 +57,6 @@ const General = (state = initial, action) => {
|
||||
notification => notification.key !== action.key
|
||||
)
|
||||
}
|
||||
case GeneralActions.CHANGE_SCHEME:
|
||||
return { ...state, ...action.payload }
|
||||
case GeneralActions.CHANGE_LOADING:
|
||||
return { ...state, ...action.payload }
|
||||
case GeneralActions.CHANGE_ZONE:
|
||||
|
@ -11,7 +11,7 @@ import VNetTemplate from 'server/utils/constants/commands/vntemplate'
|
||||
import httpCodes from 'server/utils/constants/http-codes'
|
||||
import { requestData, requestParams } from 'client/utils'
|
||||
|
||||
export const getUsers = ({ filter }) => {
|
||||
export const getUsers = ({ filter } = {}) => {
|
||||
const name = User.Actions.USER_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -25,7 +25,7 @@ export const getUsers = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getGroups = ({ filter }) => {
|
||||
export const getGroups = ({ filter } = {}) => {
|
||||
const name = Group.Actions.GROUP_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -39,7 +39,7 @@ export const getGroups = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getVNetworks = ({ filter }) => {
|
||||
export const getVNetworks = ({ filter } = {}) => {
|
||||
const name = VNet.Actions.VN_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -53,7 +53,7 @@ export const getVNetworks = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getVNetworksTemplates = ({ filter }) => {
|
||||
export const getVNetworksTemplates = ({ filter } = {}) => {
|
||||
const name = VNetTemplate.Actions.VNTEMPLATE_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -67,7 +67,7 @@ export const getVNetworksTemplates = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getTemplates = ({ filter, end, start }) => {
|
||||
export const getTemplates = ({ filter, end, start } = {}) => {
|
||||
const name = Template.Actions.TEMPLATE_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter, end, start },
|
||||
@ -81,7 +81,7 @@ export const getTemplates = ({ filter, end, start }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getMarketApps = ({ filter, end, start }) => {
|
||||
export const getMarketApps = ({ filter, end, start } = {}) => {
|
||||
const name = MarketApp.Actions.MARKETAPP_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter, end, start },
|
||||
@ -95,7 +95,7 @@ export const getMarketApps = ({ filter, end, start }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getClusters = ({ filter }) => {
|
||||
export const getClusters = ({ filter } = {}) => {
|
||||
const name = Cluster.Actions.CLUSTER_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -109,7 +109,7 @@ export const getClusters = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getDatastores = ({ filter }) => {
|
||||
export const getDatastores = ({ filter } = {}) => {
|
||||
const name = Datastore.Actions.DATASTORE_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
@ -123,7 +123,7 @@ export const getDatastores = ({ filter }) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getHosts = ({ filter }) => {
|
||||
export const getHosts = ({ filter } = {}) => {
|
||||
const name = Host.Actions.HOST_POOL_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter },
|
||||
|
Loading…
Reference in New Issue
Block a user