diff --git a/package-lock.json b/package-lock.json index ae875aba..a781f339 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2395,6 +2395,37 @@ "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz", "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==" }, + "@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "requires": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "dependencies": { + "immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==" + } + } + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -23729,6 +23760,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", diff --git a/src/@core/layouts/HeaderLayout.js b/src/@core/layouts/HeaderLayout.js index da55d096..5c86b14f 100644 --- a/src/@core/layouts/HeaderLayout.js +++ b/src/@core/layouts/HeaderLayout.js @@ -51,7 +51,7 @@ const HeaderLayout = props => { const [windowWidth, setWindowWidth] = useState(window.innerWidth); // ** Store Vars - const layoutStore = useSelector(state => state.layout); + // const layoutStore = useSelector(state => state.layout); // ** Update Window Width const handleWindowWidth = () => { diff --git a/src/@core/layouts/HorizontalLayout.js b/src/@core/layouts/HorizontalLayout.js index 0db3a189..88c262e5 100644 --- a/src/@core/layouts/HorizontalLayout.js +++ b/src/@core/layouts/HorizontalLayout.js @@ -3,8 +3,10 @@ import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; // ** Store & Actions -import { useSelector, useDispatch } from 'react-redux'; -import { handleMenuHidden, handleContentWidth } from '@store/actions/layout'; +import { + handlerContentWidth, + handlerMenuHidden +} from '../../_redux/features/layout/layoutSlice'; // ** Third Party Components import classnames from 'classnames'; @@ -28,6 +30,8 @@ import { useNavbarType } from '@hooks/useNavbarType'; import { useFooterType } from '@hooks/useFooterType'; import { useNavbarColor } from '@hooks/useNavbarColor'; +import { useSelector, useDispatch } from '@store/storeConfig/store'; + // ** Styles import '@styles/base/core/menu/menu-types/horizontal-menu.scss'; @@ -49,17 +53,17 @@ const HorizontalLayout = props => { // ** Store Vars const dispatch = useDispatch(); - const layoutStore = useSelector(state => state.layout); + const layoutStore = useSelector(state => state.layoutState); // ** Vars const contentWidth = layoutStore.contentWidth; const isHidden = layoutStore.menuHidden; // ** Handles Content Width - const setContentWidth = val => dispatch(handleContentWidth(val)); + const setContentWidth = val => dispatch(handlerContentWidth(val)); // ** Handles Content Width - const setIsHidden = val => dispatch(handleMenuHidden(val)); + const setIsHidden = val => dispatch(handlerMenuHidden(val)); // ** UseEffect Cleanup const cleanup = () => { diff --git a/src/@core/layouts/VerticalLayout.js b/src/@core/layouts/VerticalLayout.js index 680c8049..1b62110e 100644 --- a/src/@core/layouts/VerticalLayout.js +++ b/src/@core/layouts/VerticalLayout.js @@ -3,12 +3,12 @@ import { useState, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; // ** Store & Actions -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '@store/storeConfig/store'; import { - handleMenuCollapsed, - handleContentWidth, - handleMenuHidden -} from '@store/actions/layout'; + handlerMunuCollapsed, + handlerContentWidth, + handlerMenuHidden +} from '../../_redux/features/layout/layoutSlice'; // ** Third Party Components import classnames from 'classnames'; @@ -55,7 +55,7 @@ const VerticalLayout = props => { // ** Store Vars const dispatch = useDispatch(); - const layoutStore = useSelector(state => state.layout); + const layoutStore = useSelector(state => state.layoutState); // ** Update Window Width const handleWindowWidth = () => { @@ -69,13 +69,13 @@ const VerticalLayout = props => { const isHidden = layoutStore.menuHidden; // ** Toggles Menu Collapsed - const setMenuCollapsed = val => dispatch(handleMenuCollapsed(val)); + const setMenuCollapsed = val => dispatch(handlerMunuCollapsed(val)); // ** Handles Content Width - const setContentWidth = val => dispatch(handleContentWidth(val)); + const setContentWidth = val => dispatch(handlerContentWidth(val)); // ** Handles Content Width - const setIsHidden = val => dispatch(handleMenuHidden(val)); + const setIsHidden = val => dispatch(handlerMenuHidden(val)); //** This function will detect the Route Change and will hide the menu on menu item click useEffect(() => { diff --git a/src/@core/layouts/components/layout-wrapper/index.js b/src/@core/layouts/components/layout-wrapper/index.js index 43b46567..442e6691 100644 --- a/src/@core/layouts/components/layout-wrapper/index.js +++ b/src/@core/layouts/components/layout-wrapper/index.js @@ -5,7 +5,7 @@ import { Fragment, useEffect } from 'react'; import classnames from 'classnames'; // ** Store & Actions -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '@store/storeConfig/store'; import { handleContentWidth, handleMenuCollapsed, @@ -24,7 +24,7 @@ const LayoutWrapper = props => { const dispatch = useDispatch(); const store = useSelector(state => state); const navbarStore = store.navbar; - const contentWidth = store.layout.contentWidth; + const contentWidth = store.layoutState.contentWidth; //** Vars const Tag = layout === 'HorizontalLayout' && !appLayout ? 'div' : Fragment; diff --git a/src/_redux/features/layout/layoutSlice.ts b/src/_redux/features/layout/layoutSlice.ts new file mode 100644 index 00000000..693bc12d --- /dev/null +++ b/src/_redux/features/layout/layoutSlice.ts @@ -0,0 +1,41 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { initMenuModel } from './layoutState'; + +const layoutSlice = createSlice({ + name: 'layoutSlice', + initialState: initMenuModel, + reducers: { + dispatchTopMenu: (state, action) => { + const topMenuCd = action.payload; + state.topMenuCd = topMenuCd; + }, + handlerContentWidth: (state, action) => { + const value = action.payload; + state.contentWidth = value; + }, + handlerMunuCollapsed: (state, action) => { + const value = action.payload; + localStorage.setItem('menuCollapsed', value); + state.menuCollapsed = value; + }, + handlerMenuHidden: (state, action) => { + const value = action.payload; + state.menuHidden = value; + }, + handlerRTL: (state, action) => { + const value = action.payload; + state.isRTL = value; + } + }, + extraReducers: {} +}); + +export const { + dispatchTopMenu, + handlerContentWidth, + handlerMenuHidden, + handlerMunuCollapsed, + handlerRTL +} = layoutSlice.actions; + +export const layoutReducer = layoutSlice.reducer; diff --git a/src/_redux/features/layout/layoutState.ts b/src/_redux/features/layout/layoutState.ts new file mode 100644 index 00000000..0ac540fe --- /dev/null +++ b/src/_redux/features/layout/layoutState.ts @@ -0,0 +1,23 @@ +import themeConfig from '@src/configs/themeConfig'; + +const initialMenuCollapsed = () => { + const item = window.localStorage.getItem('menuCollapsed'); + //** Parse stored json or if none return initialValue + return item ? JSON.parse(item) : themeConfig.layout.menu.isCollapsed; +}; + +export const initMenuModel: MenuModelState = { + topMenuCd: localStorage.getItem('topMenuCd') || 'basis', + isRTL: themeConfig.layout.isRTL, + menuCollapsed: initialMenuCollapsed(), + menuHidden: themeConfig.layout.menu.isHidden, + contentWidth: themeConfig.layout.contentWidth +}; + +export interface MenuModelState { + topMenuCd: string; + isRTL: boolean; + menuCollapsed: string; + menuHidden: boolean; + contentWidth: string; +} diff --git a/src/redux/actions/auth/index.js b/src/redux/actions/auth/index.js deleted file mode 100644 index 097224de..00000000 --- a/src/redux/actions/auth/index.js +++ /dev/null @@ -1,34 +0,0 @@ -// ** UseJWT import to get config -import useJwt from '@src/auth/jwt/useJwt' - -const config = useJwt.jwtConfig - -// ** Handle User Login -export const handleLogin = data => { - return dispatch => { - dispatch({ - type: 'LOGIN', - data, - config, - [config.storageTokenKeyName]: data[config.storageTokenKeyName], - [config.storageRefreshTokenKeyName]: data[config.storageRefreshTokenKeyName] - }) - - // ** Add to user, accessToken & refreshToken to localStorage - localStorage.setItem('userData', JSON.stringify(data)) - localStorage.setItem(config.storageTokenKeyName, JSON.stringify(data.accessToken)) - localStorage.setItem(config.storageRefreshTokenKeyName, JSON.stringify(data.refreshToken)) - } -} - -// ** Handle User Logout -export const handleLogout = () => { - return dispatch => { - dispatch({ type: 'LOGOUT', [config.storageTokenKeyName]: null, [config.storageRefreshTokenKeyName]: null }) - - // ** Remove user, accessToken & refreshToken from localStorage - localStorage.removeItem('userData') - localStorage.removeItem(config.storageTokenKeyName) - localStorage.removeItem(config.storageRefreshTokenKeyName) - } -} diff --git a/src/redux/actions/layout/index.js b/src/redux/actions/layout/index.js deleted file mode 100644 index 9d28e494..00000000 --- a/src/redux/actions/layout/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// ** Handles Layout Content Width (full / boxed) -export const handleContentWidth = value => dispatch => dispatch({ type: 'HANDLE_CONTENT_WIDTH', value }) - -// ** Handles Menu Collapsed State (Bool) -export const handleMenuCollapsed = value => dispatch => dispatch({ type: 'HANDLE_MENU_COLLAPSED', value }) - -// ** Handles Menu Hidden State (Bool) -export const handleMenuHidden = value => dispatch => dispatch({ type: 'HANDLE_MENU_HIDDEN', value }) - -// ** Handles RTL (Bool) -export const handleRTL = value => dispatch => dispatch({ type: 'HANDLE_RTL', value }) diff --git a/src/redux/reducers/auth/index.js b/src/redux/reducers/auth/index.js deleted file mode 100644 index df4afd3d..00000000 --- a/src/redux/reducers/auth/index.js +++ /dev/null @@ -1,26 +0,0 @@ -// ** Initial State -const initialState = { - userData: {} -}; - -const authReducer = (state = initialState, action) => { - switch (action.type) { - case 'LOGIN': - return { - ...state, - userData: action.data, - [action.config.storageTokenKeyName]: - action[action.config.storageTokenKeyName], - [action.config.storageRefreshTokenKeyName]: - action[action.config.storageRefreshTokenKeyName] - }; - case 'LOGOUT': - const obj = { ...action }; - delete obj.type; - return { ...state, userData: {}, ...obj }; - default: - return state; - } -}; - -export default authReducer; diff --git a/src/redux/reducers/layout/index.js b/src/redux/reducers/layout/index.js deleted file mode 100644 index 81cfe4b6..00000000 --- a/src/redux/reducers/layout/index.js +++ /dev/null @@ -1,35 +0,0 @@ -// ** ThemeConfig Import -import themeConfig from '@configs/themeConfig' - -// ** Returns Initial Menu Collapsed State -const initialMenuCollapsed = () => { - const item = window.localStorage.getItem('menuCollapsed') - //** Parse stored json or if none return initialValue - return item ? JSON.parse(item) : themeConfig.layout.menu.isCollapsed -} - -// ** Initial State -const initialState = { - isRTL: themeConfig.layout.isRTL, - menuCollapsed: initialMenuCollapsed(), - menuHidden: themeConfig.layout.menu.isHidden, - contentWidth: themeConfig.layout.contentWidth -} - -const layoutReducer = (state = initialState, action) => { - switch (action.type) { - case 'HANDLE_CONTENT_WIDTH': - return { ...state, contentWidth: action.value } - case 'HANDLE_MENU_COLLAPSED': - window.localStorage.setItem('menuCollapsed', action.value) - return { ...state, menuCollapsed: action.value } - case 'HANDLE_MENU_HIDDEN': - return { ...state, menuHidden: action.value } - case 'HANDLE_RTL': - return { ...state, isRTL: action.value } - default: - return state - } -} - -export default layoutReducer diff --git a/src/redux/reducers/rootReducer.ts b/src/redux/reducers/rootReducer.ts index df81f4fa..1cf72b0c 100644 --- a/src/redux/reducers/rootReducer.ts +++ b/src/redux/reducers/rootReducer.ts @@ -3,8 +3,6 @@ import { combineReducers } from 'redux'; import { all, fork } from 'redux-saga/effects'; // ** Reducers, Sagas Imports -import auth from './auth'; -import layout from './layout'; import navbar from './navbar'; import { loadingReducer } from './loading'; @@ -43,6 +41,7 @@ import { mainDashSaga, mainDahReducer } from '../../modules/main/dash'; import { menuReducer } from '../../modules/menu'; import { statisticsSaga, statisticsReducer } from '../../modules/statistics'; import { droneReducer2 } from '../../_redux/features/basis/drone/droneSlice'; +import { layoutReducer } from '../../_redux/features/layout/layoutSlice'; export function* saga() { yield all([fork(mainDashSaga)]); @@ -61,9 +60,7 @@ export function* saga() { } const rootReducer = combineReducers({ - auth, navbar, - layout, controlMapReducer, loadingReducer, mainDashState: mainDahReducer, @@ -88,8 +85,9 @@ const rootReducer = combineReducers({ faqState: faqReducer, qnaState: qnaReducer, statisticsState: statisticsReducer, - - droneState2: droneReducer2 + // ----------------------------------------------- + droneState2: droneReducer2, + layoutState: layoutReducer }); export default rootReducer; diff --git a/src/utility/hooks/useRTL.js b/src/utility/hooks/useRTL.js index 2357f908..76b2e1a4 100644 --- a/src/utility/hooks/useRTL.js +++ b/src/utility/hooks/useRTL.js @@ -2,20 +2,20 @@ import { useEffect } from 'react'; // ** Store & Actions -import { handleRTL } from '@store/actions/layout'; -import { useDispatch, useSelector } from 'react-redux'; +import { handlerRTL } from '@src/_redux/features/layout/layoutSlice'; +import { useSelector, useDispatch } from '@store/storeConfig/store'; export const useRTL = () => { // ** Store Vars const dispatch = useDispatch(); - const isRtl = useSelector(state => state.layout.isRTL); + const isRtl = useSelector(state => state.laancState.isRTL); // ** Return a wrapped version of useState's setter function const setValue = value => { try { // ** Allow value to be a function so we have same API as useState const valueToStore = value instanceof Function ? value(isRtl) : value; - dispatch(handleRTL(valueToStore)); + dispatch(handlerRTL(valueToStore)); } catch (error) { // ** A more advanced implementation would handle the error case }