diff --git a/src/fireedge/src/public/actions/user.js b/src/fireedge/src/public/actions/user.js
index 24ca874daf..de616b3749 100644
--- a/src/fireedge/src/public/actions/user.js
+++ b/src/fireedge/src/public/actions/user.js
@@ -1,10 +1,12 @@
const START_AUTH = 'START_AUTH';
+const SELECT_FILTER_GROUP = 'SELECT_FILTER_GROUP';
const SUCCESS_AUTH = 'SUCCESS_AUTH';
const FAILURE_AUTH = 'FAILURE_AUTH';
const LOGOUT = 'LOGOUT';
const Actions = {
START_AUTH,
+ SELECT_FILTER_GROUP,
SUCCESS_AUTH,
FAILURE_AUTH,
LOGOUT
@@ -15,6 +17,10 @@ module.exports = {
startAuth: () => ({
type: START_AUTH
}),
+ selectFilterGroup: payload => ({
+ type: SELECT_FILTER_GROUP,
+ payload
+ }),
successAuth: payload => ({
type: SUCCESS_AUTH,
payload
diff --git a/src/fireedge/src/public/app.js b/src/fireedge/src/public/app.js
index fe25d79732..ecee3936f5 100644
--- a/src/fireedge/src/public/app.js
+++ b/src/fireedge/src/public/app.js
@@ -13,46 +13,46 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
-import React, { Suspense } from 'react';
+import React from 'react';
import { StaticRouter, BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import PropTypes from 'prop-types';
-import {
- CssBaseline,
- ThemeProvider,
- createMuiTheme,
- responsiveFontSizes
-} from '@material-ui/core';
+import { CssBaseline, ThemeProvider } from '@material-ui/core';
-import themeOne from 'client/assets/theme';
+import theme from 'client/assets/theme';
import { TranslateProvider } from 'client/components/HOC';
import Router from 'client/router';
-const theme = createMuiTheme(themeOne);
+const App = ({ location, context, store }) => {
+ React.useEffect(() => {
+ const jssStyles = document.querySelector('#jss-server-side');
+ if (jssStyles) {
+ jssStyles.parentElement.removeChild(jssStyles);
+ }
+ }, []);
-const App = ({ location, context, store }) => (
-
-
-
- {location && context ? (
- // server build
-
-
-
-
-
- ) : (
- // browser build
-
-
-
-
-
- )}
-
-
-);
+ return (
+
+
+
+
+ {location && context ? (
+ // server build
+
+
+
+ ) : (
+ // browser build
+
+
+
+ )}
+
+
+
+ );
+};
App.propTypes = {
location: PropTypes.string,
diff --git a/src/fireedge/src/public/assets/theme.js b/src/fireedge/src/public/assets/theme.js
index b289c98a7a..dea919bb62 100644
--- a/src/fireedge/src/public/assets/theme.js
+++ b/src/fireedge/src/public/assets/theme.js
@@ -1,4 +1,6 @@
-export default {
+import { createMuiTheme, responsiveFontSizes } from '@material-ui/core';
+
+const theme = createMuiTheme({
typography: {
fontFamily: ['Ubuntu', 'Lato'].join(',')
},
@@ -82,4 +84,6 @@ export default {
hint: 'rgba(0, 0, 0, 0.38)'
}
}
-};
+});
+
+export default responsiveFontSizes(theme);
diff --git a/src/fireedge/src/public/components/HOC/AuthLayout.js b/src/fireedge/src/public/components/HOC/AuthLayout.js
index 6242aee3f8..244d5c0dcb 100644
--- a/src/fireedge/src/public/components/HOC/AuthLayout.js
+++ b/src/fireedge/src/public/components/HOC/AuthLayout.js
@@ -17,19 +17,23 @@ import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
+import { LinearProgress } from '@material-ui/core';
+
import useAuth from 'client/hooks/useAuth';
import { PATH } from 'client/router/endpoints';
const AuthLayout = ({ children }) => {
- const { isLogging, isLogged, getAuthInfo } = useAuth();
+ const { isLoginInProcess, isLogged, firstRender, getAuthInfo } = useAuth();
useEffect(() => {
- if (isLogged && !isLogging) {
+ if (isLogged && !isLoginInProcess) {
getAuthInfo();
}
- }, [isLogged, isLogging]);
+ }, [isLogged, isLoginInProcess]);
- if (!isLogged) {
+ if (firstRender) {
+ return ;
+ } else if (!isLogged && !isLoginInProcess) {
return ;
}
diff --git a/src/fireedge/src/public/components/HOC/GuessLayout.js b/src/fireedge/src/public/components/HOC/GuessLayout.js
index 20ff180c92..3873a61195 100644
--- a/src/fireedge/src/public/components/HOC/GuessLayout.js
+++ b/src/fireedge/src/public/components/HOC/GuessLayout.js
@@ -23,14 +23,12 @@ import useAuth from 'client/hooks/useAuth';
import { PATH } from 'client/router/endpoints';
const GuessLayout = ({ children }) => {
- const { isLogging, isLogged, firstRender } = useAuth();
-
- if (isLogged && !isLogging) {
- return ;
- }
+ const { isLoginInProcess, isLogged, firstRender } = useAuth();
if (firstRender) {
return ;
+ } else if (isLogged && !isLoginInProcess) {
+ return ;
}
return {children};
diff --git a/src/fireedge/src/public/components/Header/index.js b/src/fireedge/src/public/components/Header/index.js
index 49d587e065..daa0884647 100644
--- a/src/fireedge/src/public/components/Header/index.js
+++ b/src/fireedge/src/public/components/Header/index.js
@@ -16,13 +16,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import {
- makeStyles,
- AppBar,
- Toolbar,
- IconButton,
- Typography
-} from '@material-ui/core';
+import { AppBar, Toolbar, IconButton, Typography } from '@material-ui/core';
import MenuIcon from '@material-ui/icons/Menu';
import useGeneral from 'client/hooks/useGeneral';
@@ -34,27 +28,30 @@ const Header = ({ title }) => {
const classes = headerStyles();
const { isOpenMenu, openMenu } = useGeneral();
- return (
-
-
- openMenu(!isOpenMenu)}
- edge="start"
- color="inherit"
- >
-
-
-
- {title}
-
-
-
-
-
+ return React.useMemo(
+ () => (
+
+
+ openMenu(!isOpenMenu)}
+ edge="start"
+ color="inherit"
+ >
+
+
+
+ {title}
+
+
+
+
+
+ ),
+ [isOpenMenu, openMenu]
);
};
diff --git a/src/fireedge/src/public/containers/Login/styles.js b/src/fireedge/src/public/containers/Login/styles.js
index 31accca346..f233229604 100644
--- a/src/fireedge/src/public/containers/Login/styles.js
+++ b/src/fireedge/src/public/containers/Login/styles.js
@@ -1,12 +1,12 @@
import { makeStyles } from '@material-ui/core';
-export default makeStyles(theme => {
+export default makeStyles(theme =>
// const getColor = theme.palette.type === 'light' ? darken : lighten;
// const getBackgroundColor = theme.palette.type === 'light' ? lighten : darken;
// color: getColor(theme.palette.error.main, 0.6),
// backgroundColor: getBackgroundColor(theme.palette.error.main, 0.9)
- return {
+ ({
root: {
display: 'flex',
flexDirection: 'column',
@@ -15,7 +15,7 @@ export default makeStyles(theme => {
paper: {
overflow: 'hidden',
padding: theme.spacing(3),
- height: 400
+ minHeight: 400
},
logo: {
display: 'block',
@@ -31,5 +31,5 @@ export default makeStyles(theme => {
helper: {
animation: '1s ease-out 0s 1'
}
- };
-});
+ })
+);
diff --git a/src/fireedge/src/public/containers/System/Users.js b/src/fireedge/src/public/containers/System/Users.js
index 4b002f1d1a..f0e62dab77 100644
--- a/src/fireedge/src/public/containers/System/Users.js
+++ b/src/fireedge/src/public/containers/System/Users.js
@@ -15,13 +15,23 @@
import React, { useEffect } from 'react';
-import { makeStyles, Card, CardContent, Typography } from '@material-ui/core';
+import {
+ makeStyles,
+ Card,
+ Chip,
+ CardContent,
+ Typography,
+ LinearProgress,
+ Box
+} from '@material-ui/core';
+import useGeneral from 'client/hooks/useGeneral';
import useOpennebula from 'client/hooks/useOpennebula';
const useStyles = makeStyles({
- root: {
- minWidth: 275
+ card: {
+ minWidth: 275,
+ marginBottom: '2em'
},
title: {
fontSize: 14
@@ -30,23 +40,43 @@ const useStyles = makeStyles({
function Users() {
const classes = useStyles();
- const { users, getUsers } = useOpennebula();
+ const { isLoading } = useGeneral();
+ const { users, groups, getUsers } = useOpennebula();
useEffect(() => {
- getUsers();
+ if (!isLoading) {
+ getUsers();
+ }
}, [getUsers]);
- console.log(users);
+ const getGroupById = id => groups?.find(({ ID }) => ID === id);
+
return (
-
-
-
-
- Word of the Day
-
-
-
-
+ <>
+ {isLoading && }
+ {users?.map(({ ID, NAME, GROUPS }, index) => (
+
+
+
+ {NAME}
+ {[GROUPS?.ID ?? []].flat().map(id => {
+ const group = getGroupById(id);
+ return group ? (
+
+ ) : null;
+ })}
+
+
+
+ ))}
+ >
);
}
diff --git a/src/fireedge/src/public/hooks/useAuth.js b/src/fireedge/src/public/hooks/useAuth.js
index 5d136bdc96..dbb949cd1b 100644
--- a/src/fireedge/src/public/hooks/useAuth.js
+++ b/src/fireedge/src/public/hooks/useAuth.js
@@ -9,6 +9,7 @@ import * as serviceUsers from 'client/services/users';
import * as serviceGroups from 'client/services/groups';
import {
startAuth,
+ selectFilterGroup,
successAuth,
failureAuth,
logout as logoutRequest
@@ -23,7 +24,7 @@ export default function useAuth() {
const {
jwt,
error,
- isLogging,
+ isLoginInProcess,
isLoading,
firstRender,
filterPool,
@@ -55,8 +56,9 @@ export default function useAuth() {
successAuth({
jwt: token,
user: { ID: id },
- isLoading: ONEADMIN_ID !== id, // is not oneadmin
- isLogging: ONEADMIN_ID !== id // is not oneadmin
+ isLoginInProcess: ONEADMIN_ID !== id // is not oneadmin
+ // isLoading: ONEADMIN_ID !== id, // is not oneadmin
+ // isLogging: ONEADMIN_ID !== id // is not oneadmin
})
);
}
@@ -67,13 +69,13 @@ export default function useAuth() {
dispatch(failureAuth({ error: err }));
});
},
- [baseURL, jwtName]
+ [dispatch, baseURL, jwtName]
);
const logout = useCallback(() => {
removeStoreData([jwtName]);
dispatch(logoutRequest());
- }, [jwtName]);
+ }, [dispatch, jwtName]);
const getAuthInfo = useCallback(() => {
dispatch(startAuth());
@@ -87,17 +89,12 @@ export default function useAuth() {
})
)
.catch(err => dispatch(failureAuth({ error: err })));
- }, [baseURL, jwtName]);
+ }, [dispatch, baseURL, jwtName]);
const setPrimaryGroup = useCallback(
values => {
if (values?.group === FILTER_POOL.ALL_RESOURCES) {
- dispatch(
- successAuth({
- isLogging: false,
- filterPool: FILTER_POOL.ALL_RESOURCES
- })
- );
+ dispatch(selectFilterGroup({ filterPool: FILTER_POOL.ALL_RESOURCES }));
} else {
dispatch(startAuth());
@@ -105,16 +102,15 @@ export default function useAuth() {
.changeGroup({ id: authUser.ID, ...values })
.then(() =>
dispatch(
- successAuth({
- filterPool: FILTER_POOL.PRIMARY_GROUP_RESOURCES,
- isLogging: false
+ selectFilterGroup({
+ filterPool: FILTER_POOL.PRIMARY_GROUP_RESOURCES
})
)
)
.catch(err => dispatch(failureAuth({ error: err })));
}
},
- [authUser, jwtName]
+ [dispatch, authUser, jwtName]
);
return {
@@ -125,7 +121,7 @@ export default function useAuth() {
authUser,
isOneAdmin: authUser?.ID === ONEADMIN_ID,
isLogged: Boolean(jwt),
- isLogging,
+ isLoginInProcess,
isLoading,
firstRender,
error,
diff --git a/src/fireedge/src/public/hooks/useOpennebula.js b/src/fireedge/src/public/hooks/useOpennebula.js
index 77884e5291..168e66c93d 100644
--- a/src/fireedge/src/public/hooks/useOpennebula.js
+++ b/src/fireedge/src/public/hooks/useOpennebula.js
@@ -7,13 +7,10 @@ import {
startOneRequest,
failureOneRequest
} from 'client/actions/pool';
+
import * as servicesGroups from 'client/services/groups';
import * as servicesUsers from 'client/services/users';
-function delay(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
export default function useOpennebula() {
const dispatch = useDispatch();
const { groups, users } = useSelector(
@@ -23,22 +20,18 @@ export default function useOpennebula() {
const getGroups = useCallback(() => {
dispatch(startOneRequest());
- return delay(2000).then(() =>
- servicesGroups
- .getGroups()
- .then(data => dispatch(setGroups(data)))
- .catch(() => dispatch(failureOneRequest('Unauthorized')))
- );
+ return servicesGroups
+ .getGroups()
+ .then(data => dispatch(setGroups(data)))
+ .catch(err => dispatch(failureOneRequest({ error: err })));
}, [dispatch]);
const getUsers = useCallback(() => {
dispatch(startOneRequest());
- return delay(2000).then(() =>
- servicesUsers
- .getUsers()
- .then(data => dispatch(setUsers(data)))
- .catch(() => dispatch(failureOneRequest('Unauthorized')))
- );
+ return servicesUsers
+ .getUsers()
+ .then(data => dispatch(setUsers(data)))
+ .catch(err => dispatch(failureOneRequest({ error: err })));
}, [dispatch]);
return {
diff --git a/src/fireedge/src/public/reducers/auth.js b/src/fireedge/src/public/reducers/auth.js
index 30939f358e..9ff9d62de5 100644
--- a/src/fireedge/src/public/reducers/auth.js
+++ b/src/fireedge/src/public/reducers/auth.js
@@ -29,7 +29,7 @@ const initial = {
group: null,
error: null,
filterPool: FILTER_POOL.ALL_RESOURCES,
- isLogging: false,
+ isLoginInProcess: false,
isLoading: false,
firstRender: true
};
@@ -51,12 +51,20 @@ const authentication = (state = initial, action) => {
isLoading: false,
...action.payload
};
+ case UserActions.SELECT_FILTER_GROUP:
+ return {
+ ...state,
+ isLoading: false,
+ isLoginInProcess: false,
+ ...action.payload
+ };
case UserActions.FAILURE_AUTH:
return {
...state,
jwt: null,
firstRender: false,
isLoading: false,
+ isLoginInProcess: false,
...action.payload
};
case UserActions.LOGOUT:
diff --git a/src/fireedge/src/public/router/index.js b/src/fireedge/src/public/router/index.js
index 58fb076875..09e59d8396 100644
--- a/src/fireedge/src/public/router/index.js
+++ b/src/fireedge/src/public/router/index.js
@@ -22,7 +22,7 @@ import Error404 from 'client/containers/Error404';
import endpoints from './endpoints';
-function Routes() {
+function Router() {
const renderRoute = ({
label = '',
path = '',
@@ -54,10 +54,10 @@ function Routes() {
{endpoints?.map(({ routes, ...endpoint }) =>
endpoint.path ? renderRoute(endpoint) : routes?.map(renderRoute)
)}
- } />
+
);
}
-export default Routes;
+export default Router;
export { endpoints };
diff --git a/src/fireedge/src/routes/entrypoints/App.js b/src/fireedge/src/routes/entrypoints/App.js
index 18d03e31d3..6dfb59402e 100644
--- a/src/fireedge/src/routes/entrypoints/App.js
+++ b/src/fireedge/src/routes/entrypoints/App.js
@@ -73,11 +73,6 @@ router.get('*', (req, res) => {