diff --git a/src/fireedge/src/client/apps/sunstone/_app.js b/src/fireedge/src/client/apps/sunstone/_app.js index 7b8948d326..cdc73aff7a 100644 --- a/src/fireedge/src/client/apps/sunstone/_app.js +++ b/src/fireedge/src/client/apps/sunstone/_app.js @@ -28,14 +28,17 @@ const APP_NAME = _APPS.sunstone.name const SunstoneApp = () => { const { isLogged, jwt, firstRender } = useAuth() - const { getAuthUser, logout } = useAuthApi() + const { getAuthUser, logout, getSunstoneViews } = useAuthApi() const { changeTitle } = useGeneralApi() React.useEffect(() => { (async () => { try { - jwt && changeTitle(APP_NAME) - jwt && getAuthUser() + if (jwt) { + changeTitle(APP_NAME) + getAuthUser() + getSunstoneViews() + } } catch { logout() } diff --git a/src/fireedge/src/client/components/Header/View.js b/src/fireedge/src/client/components/Header/View.js new file mode 100644 index 0000000000..854ae848f1 --- /dev/null +++ b/src/fireedge/src/client/components/Header/View.js @@ -0,0 +1,56 @@ +import * as React from 'react' + +import { Button } from '@material-ui/core' +import { ViewGrid as ViewIcon, VerifiedBadge as SelectIcon } from 'iconoir-react' + +import { useAuth, useAuthApi } from 'client/features/Auth' +import Search from 'client/components/Search' + +import HeaderPopover from 'client/components/Header/Popover' +import headerStyles from 'client/components/Header/styles' + +const View = () => { + const classes = headerStyles() + const { view, views } = useAuth() + const { changeView } = useAuthApi() + + const handleChangeView = newView => { + newView && newView !== view && changeView(newView) + } + + const renderResult = (viewName, handleClose) => ( + + ) + + const viewNames = React.useMemo(() => Object.keys(views), [view]) + + return ( + } + buttonProps={{ 'data-cy': 'header-view-button', variant: 'outlined' }} + headerTitle='Switch view' + > + {({ handleClose }) => ( + renderResult(item, handleClose)} + /> + )} + + ) +} + +export default View diff --git a/src/fireedge/src/client/components/Header/index.js b/src/fireedge/src/client/components/Header/index.js index baead97c8a..f443247c0a 100644 --- a/src/fireedge/src/client/components/Header/index.js +++ b/src/fireedge/src/client/components/Header/index.js @@ -31,6 +31,7 @@ import { useAuth } from 'client/features/Auth' import { useGeneral, useGeneralApi } from 'client/features/General' import User from 'client/components/Header/User' +import View from 'client/components/Header/View' import Group from 'client/components/Header/Group' import Zone from 'client/components/Header/Zone' import headerStyles from 'client/components/Header/styles' @@ -75,6 +76,7 @@ const Header = ({ scrollContainer }) => { )} + {!isOneAdmin && } diff --git a/src/fireedge/src/client/features/Auth/actionsView.js b/src/fireedge/src/client/features/Auth/actionsView.js new file mode 100644 index 0000000000..8c8bf2e949 --- /dev/null +++ b/src/fireedge/src/client/features/Auth/actionsView.js @@ -0,0 +1,29 @@ +import { createAsyncThunk, createAction } from '@reduxjs/toolkit' + +import { authService } from 'client/features/Auth/services' +import { logout } from 'client/features/Auth/actions' + +import { httpCodes } from 'server/utils/constants' +import { T } from 'client/constants' + +export const getSunstoneViews = createAsyncThunk( + 'sunstone/views', + async (_, { dispatch }) => { + try { + const views = await authService.getSunstoneViews() ?? {} + // const config = await authService.getSunstoneConfig() + + return { + views, + view: Object.keys(views)[0] + } + } catch (error) { + status === httpCodes.unauthorized.id && dispatch(logout(T.SessionExpired)) + } + } +) + +export const changeView = createAction( + 'sunstone/change-view', + view => ({ payload: { view } }) +) diff --git a/src/fireedge/src/client/features/Auth/hooks.js b/src/fireedge/src/client/features/Auth/hooks.js index e102edc5d9..cf27917d2e 100644 --- a/src/fireedge/src/client/features/Auth/hooks.js +++ b/src/fireedge/src/client/features/Auth/hooks.js @@ -3,6 +3,7 @@ import { useDispatch, useSelector, shallowEqual } from 'react-redux' import { unwrapResult } from '@reduxjs/toolkit' import * as actions from 'client/features/Auth/actions' +import * as actionsView from 'client/features/Auth/actionsView' export const useAuth = () => { const auth = useSelector(state => state.auth, shallowEqual) @@ -32,6 +33,9 @@ export const useAuthApi = () => { login: user => unwrapDispatch(actions.login(user)), getAuthUser: () => dispatch(actions.getUser()), changeGroup: data => unwrapDispatch(actions.changeGroup(data)), - logout: () => dispatch(actions.logout()) + logout: () => dispatch(actions.logout()), + + getSunstoneViews: () => unwrapDispatch(actionsView.getSunstoneViews()), + changeView: data => unwrapDispatch(actionsView.changeView(data)) } } diff --git a/src/fireedge/src/client/features/Auth/services.js b/src/fireedge/src/client/features/Auth/services.js index c17500afcf..6abfe75428 100644 --- a/src/fireedge/src/client/features/Auth/services.js +++ b/src/fireedge/src/client/features/Auth/services.js @@ -14,5 +14,15 @@ export const authService = ({ if (!res?.id || res?.id !== httpCodes.ok.id) throw res return res?.data?.USER ?? {} + }), + getSunstoneViews: () => RestClient.get('/api/sunstone/views').then(res => { + if (!res?.id || res?.id !== httpCodes.ok.id) throw res + + return res?.data ?? {} + }), + getSunstoneConfig: () => RestClient.get('/api/user/config').then(res => { + if (!res?.id || res?.id !== httpCodes.ok.id) throw res + + return res?.data ?? {} }) }) diff --git a/src/fireedge/src/client/features/Auth/slice.js b/src/fireedge/src/client/features/Auth/slice.js index facd4ed3a3..8c9300b697 100644 --- a/src/fireedge/src/client/features/Auth/slice.js +++ b/src/fireedge/src/client/features/Auth/slice.js @@ -1,6 +1,7 @@ import { createSlice } from '@reduxjs/toolkit' import { login, getUser, logout, changeFilter, changeGroup } from 'client/features/Auth/actions' +import { getSunstoneViews, changeView } from 'client/features/Auth/actionsView' import { JWT_NAME, FILTER_POOL, DEFAULT_SCHEME, DEFAULT_LANGUAGE } from 'client/constants' import { isBackend } from 'client/utils' @@ -38,7 +39,10 @@ const { actions, reducer } = createSlice({ changeFilter.type, login.fulfilled.type, getUser.fulfilled.type, - changeGroup.fulfilled.type + changeGroup.fulfilled.type, + // sunstone views + getSunstoneViews.fulfilled.type, + changeView.type ].includes(type) }, (state, { payload }) => ({ ...state, ...payload })