From 2e4273020852ac061f928d392a0fbf4caf9ab84f Mon Sep 17 00:00:00 2001 From: samuelndm Date: Fri, 26 Mar 2021 17:16:58 -0300 Subject: [PATCH] feat: add subitems at sidebar --- src/assets/styles/theme.js | 6 +- .../Navigation/Headerbar/Headerbar.jsx | 21 +++-- src/components/Navigation/Navigation.jsx | 15 +++- src/components/Navigation/NavigationData.js | 86 +++++++++++++------ .../Navigation/Sidebar/Logo/index.jsx | 12 ++- .../Navigation/Sidebar/Logo/styles.js | 16 +++- .../Navigation/Sidebar/NavItem/NavItem.jsx | 43 ++++++++-- .../NavItem/NavSubItems/NavSubItems.jsx | 16 ---- .../Sidebar/NavItem/NavSubItems/styles.js | 3 - .../Sidebar/NavItem/SubItems/SubItems.jsx | 34 ++++++++ .../Sidebar/NavItem/SubItems/styles.js | 24 ++++++ .../Navigation/Sidebar/NavItem/styles.js | 13 ++- src/components/Navigation/Sidebar/Sidebar.jsx | 17 +++- src/components/Navigation/Sidebar/styles.js | 2 +- src/components/UI/Link/Link.js | 69 +++++++++++++++ src/components/UI/Link/styles.js | 48 +++++++++++ src/components/UI/index.js | 1 + src/pages/SignIn/styles.js | 4 +- src/pages/User/User.jsx | 12 +-- src/routes/index.js | 47 ++++++---- src/utils/components/navigation/navigation.js | 7 +- src/utils/index.js | 1 + src/utils/utils.js | 8 ++ 23 files changed, 396 insertions(+), 109 deletions(-) delete mode 100644 src/components/Navigation/Sidebar/NavItem/NavSubItems/NavSubItems.jsx delete mode 100644 src/components/Navigation/Sidebar/NavItem/NavSubItems/styles.js create mode 100644 src/components/Navigation/Sidebar/NavItem/SubItems/SubItems.jsx create mode 100644 src/components/Navigation/Sidebar/NavItem/SubItems/styles.js create mode 100644 src/components/UI/Link/Link.js create mode 100644 src/components/UI/Link/styles.js create mode 100644 src/utils/utils.js diff --git a/src/assets/styles/theme.js b/src/assets/styles/theme.js index 1b0992b..5a9db67 100644 --- a/src/assets/styles/theme.js +++ b/src/assets/styles/theme.js @@ -70,7 +70,11 @@ export default { sidebar: { width: '70px', icons: { - color: '#888da8' + color: { + light: lighten(0.1, '#888da8'), + base: '#888da8', + dark: darken(0.1, '#888da8') + } } }, headerbar: { diff --git a/src/components/Navigation/Headerbar/Headerbar.jsx b/src/components/Navigation/Headerbar/Headerbar.jsx index 50353fc..ae67fb3 100644 --- a/src/components/Navigation/Headerbar/Headerbar.jsx +++ b/src/components/Navigation/Headerbar/Headerbar.jsx @@ -6,14 +6,22 @@ import PropTypes from 'prop-types' import * as S from './styles' -const Headerbar = ({ navItems, isSidebarExpanded, setIsSidebarExpanded }) => { +const Headerbar = ({ + navItems, + isSidebarExpanded, + setIsSidebarExpanded, + setCurrentExpandedItem +}) => { console.log('navItems', navItems) + + const handleClick = (event) => { + event.preventDefault() + setIsSidebarExpanded((prev) => !prev) + setCurrentExpandedItem(null) + } return ( - setIsSidebarExpanded((prev) => !prev)} - > + {isSidebarExpanded ? : } @@ -23,7 +31,8 @@ const Headerbar = ({ navItems, isSidebarExpanded, setIsSidebarExpanded }) => { Headerbar.propTypes = { navItems: PropTypes.array.isRequired, isSidebarExpanded: PropTypes.bool.isRequired, - setIsSidebarExpanded: PropTypes.func.isRequired + setIsSidebarExpanded: PropTypes.func.isRequired, + setCurrentExpandedItem: PropTypes.func.isRequired } export default Headerbar diff --git a/src/components/Navigation/Navigation.jsx b/src/components/Navigation/Navigation.jsx index 18885be..76d187f 100644 --- a/src/components/Navigation/Navigation.jsx +++ b/src/components/Navigation/Navigation.jsx @@ -3,26 +3,33 @@ import React, { useState } from 'react' import { useAuthContext } from 'contexts/AuthProvider/AuthProvider' import Headerbar from './Headerbar/Headerbar' -import { sidebarData, headerbarData } from './NavigationData' +import * as NavigationData from './NavigationData' import Sidebar from './Sidebar/Sidebar' import * as S from './styles' const Navigation = () => { const { isSignedIn } = useAuthContext() const [isSidebarExpanded, setIsSidebarExpanded] = useState(false) + const [currentExpandedItem, setCurrentExpandedItem] = useState(null) - if (!isSignedIn) return null return ( ) diff --git a/src/components/Navigation/NavigationData.js b/src/components/Navigation/NavigationData.js index 4362e5a..022d6b6 100644 --- a/src/components/Navigation/NavigationData.js +++ b/src/components/Navigation/NavigationData.js @@ -4,108 +4,140 @@ import * as FaIcons from 'react-icons/fa' import * as FiIcons from 'react-icons/fi' import * as IoIcons from 'react-icons/io' -export const sidebarData = [ +import { v4 as uuid_v4 } from 'uuid' + +export const sidebarNotLoggedIn = [ + { + title: 'Login', + path: '/login', + icon: , + id: uuid_v4() + } +] + +export const sidebarLoggedIn = [ { title: 'Global', path: '/global', - icon: + icon: , + id: uuid_v4() }, { title: 'Blueprint Manager', - path: '/blueprint_manager', icon: , + id: uuid_v4(), - subNav: [ + subItems: [ { title: 'Node Manager', - path: '/blueprint_manager/node' + path: '/blueprint_manager/node', + id: uuid_v4() }, { title: 'Lanes Manager', - path: '/blueprint_manager/lanes' + path: '/blueprint_manager/lanes', + id: uuid_v4() }, { title: 'Builder', - path: '/blueprint_manager/builder' + path: '/blueprint_manager/builder', + id: uuid_v4() } ] }, { title: 'Monitoring', - path: '/monitoring', icon: , + id: uuid_v4(), - subNav: [ + subItems: [ { title: 'General Stats', - path: '/monitoring/general_stats' + path: '/monitoring/general_stats', + id: uuid_v4() }, { title: 'Process Monitoring', - path: '/monitoring/process' + path: '/monitoring/process', + id: uuid_v4() }, { title: 'Edit Process', - path: '/monitoring/edit_process' + path: '/monitoring/edit_process', + id: uuid_v4() }, { title: 'Auditing', - path: '/monitoring/auditing' + path: '/monitoring/auditing', + id: uuid_v4() } ] }, { title: 'Insights', - path: '/insights', icon: , + id: uuid_v4(), - subNav: [ + subItems: [ { title: 'Task Performance', - path: '/insights/task_performance' + path: '/insights/task_performance', + id: uuid_v4() }, { title: 'Process Performance', - path: '/insights/process_performance' + path: '/insights/process_performance', + id: uuid_v4() }, { title: 'Process Network', - path: '/insights/process_network' + path: '/insights/process_network', + id: uuid_v4() } ] }, { title: 'Toolbox', - path: '/toolbox', icon: , + id: uuid_v4(), - subNav: [ + subItems: [ { title: 'Notifications', - path: '/toolbox/notifications' + path: '/toolbox/notifications', + id: uuid_v4() }, { title: 'Permissions', - path: '/toolbox/permissions' + path: '/toolbox/permissions', + id: uuid_v4() } ] }, { title: 'Settings', - path: '/settings', icon: , + id: uuid_v4(), - subNav: [ + subItems: [ { title: 'Manage Clusters', - path: '/settings/manage_clusters' + path: '/settings/manage_clusters', + id: uuid_v4() }, { title: 'Manage Users', - path: '/settings/manage_users' + path: '/settings/manage_users', + id: uuid_v4() } ] + }, + { + title: 'Logout', + path: '/logout', + icon: , + id: uuid_v4() } ] -export const headerbarData = [] +export const headerbar = [] diff --git a/src/components/Navigation/Sidebar/Logo/index.jsx b/src/components/Navigation/Sidebar/Logo/index.jsx index be05fc5..aa380d0 100644 --- a/src/components/Navigation/Sidebar/Logo/index.jsx +++ b/src/components/Navigation/Sidebar/Logo/index.jsx @@ -1,10 +1,12 @@ import React from 'react' +import PropTypes from 'prop-types' + import * as S from './styles' -const Logo = () => { +const Logo = ({ isSidebarExpanded }) => { return ( - + { strokeWidth="6" /> - Logo + {isSidebarExpanded && Logo} ) } +Logo.propTypes = { + isSidebarExpanded: PropTypes.bool.isRequired +} + export default Logo diff --git a/src/components/Navigation/Sidebar/Logo/styles.js b/src/components/Navigation/Sidebar/Logo/styles.js index 339a794..68ee3e7 100644 --- a/src/components/Navigation/Sidebar/Logo/styles.js +++ b/src/components/Navigation/Sidebar/Logo/styles.js @@ -1,9 +1,17 @@ import styled, { css } from 'styled-components' export const Container = styled.div` - align-items: center; - display: flex; - justify-content: space-between; + ${({ theme, isSidebarExpanded }) => css` + align-items: center; + border-bottom: ${isSidebarExpanded + ? `1px solid ${theme.border.color}` + : 'none'}; + display: flex; + height: var(--headerbar-height); + justify-content: flex-start; + padding: 0 0 0 23px; + width: 100%; + `} ` export const Image = styled.svg` @@ -16,6 +24,6 @@ export const Text = styled.span` color: ${theme.colors.black}; font-size: ${theme.font.sizes.medium}; font-weight: ${theme.font.weight.bold}; - margin-left: ${theme.spacings.xxsmall}; + padding: 0 0 0 20px; `} ` diff --git a/src/components/Navigation/Sidebar/NavItem/NavItem.jsx b/src/components/Navigation/Sidebar/NavItem/NavItem.jsx index bd6c06e..72c4f73 100644 --- a/src/components/Navigation/Sidebar/NavItem/NavItem.jsx +++ b/src/components/Navigation/Sidebar/NavItem/NavItem.jsx @@ -1,19 +1,50 @@ import React from 'react' +import * as C from 'components' import PropTypes from 'prop-types' import * as S from './styles' +import SubItems from './SubItems/SubItems' -const NavItem = ({ navItem, isSidebarExpanded, setIsSidebarExpanded }) => { +const NavItem = ({ + navItem, + isSidebarExpanded, + setIsSidebarExpanded, + currentExpandedItem, + setCurrentExpandedItem +}) => { const handleClick = (event) => { event.preventDefault() setIsSidebarExpanded(true) + setCurrentExpandedItem( + currentExpandedItem === navItem?.id ? null : navItem.id + ) } return ( - - {navItem?.icon} - {isSidebarExpanded && {navItem?.title || ''}} + + {navItem?.path ? ( + + + {navItem?.icon} + {isSidebarExpanded && {navItem?.title || ''}} + + + ) : ( + <> + + {navItem?.icon} + {isSidebarExpanded && {navItem?.title || ''}} + + + {isSidebarExpanded && currentExpandedItem === navItem?.id && ( + + )} + + )} ) } @@ -21,7 +52,9 @@ const NavItem = ({ navItem, isSidebarExpanded, setIsSidebarExpanded }) => { NavItem.propTypes = { navItem: PropTypes.object, isSidebarExpanded: PropTypes.bool.isRequired, - setIsSidebarExpanded: PropTypes.func.isRequired + setIsSidebarExpanded: PropTypes.func.isRequired, + currentExpandedItem: PropTypes.bool.isRequired, + setCurrentExpandedItem: PropTypes.func.isRequired } export default NavItem diff --git a/src/components/Navigation/Sidebar/NavItem/NavSubItems/NavSubItems.jsx b/src/components/Navigation/Sidebar/NavItem/NavSubItems/NavSubItems.jsx deleted file mode 100644 index 00d611b..0000000 --- a/src/components/Navigation/Sidebar/NavItem/NavSubItems/NavSubItems.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' - -import PropTypes from 'prop-types' - -import * as S from './styles' - -const NavSubItems = ({ subItems }) => { - console.log('subItems', subItems) - return -} - -NavSubItems.propTypes = { - subItems: PropTypes.array.isRequired -} - -export default NavSubItems diff --git a/src/components/Navigation/Sidebar/NavItem/NavSubItems/styles.js b/src/components/Navigation/Sidebar/NavItem/NavSubItems/styles.js deleted file mode 100644 index 38ad6c1..0000000 --- a/src/components/Navigation/Sidebar/NavItem/NavSubItems/styles.js +++ /dev/null @@ -1,3 +0,0 @@ -import styled from 'styled-components' - -export const Container = styled.div`` diff --git a/src/components/Navigation/Sidebar/NavItem/SubItems/SubItems.jsx b/src/components/Navigation/Sidebar/NavItem/SubItems/SubItems.jsx new file mode 100644 index 0000000..fbde448 --- /dev/null +++ b/src/components/Navigation/Sidebar/NavItem/SubItems/SubItems.jsx @@ -0,0 +1,34 @@ +import React, { useEffect } from 'react' +import { VscCircleFilled } from 'react-icons/vsc' + +import * as C from 'components' +import PropTypes from 'prop-types' +import * as UTIL from 'utils' +import { v4 as uuid_v4 } from 'uuid' + +import * as S from './styles' + +const SubItems = ({ subItems = [] }) => { + useEffect(() => { + UTIL.Components.handleSidebarExpanded(true, '300px') + + return () => UTIL.Components.handleSidebarExpanded(true) + }, []) + return ( + + {subItems.map((subItem) => ( + + + {subItem?.title || '*'} + + + ))} + + ) +} + +SubItems.propTypes = { + subItems: PropTypes.array.isRequired +} + +export default SubItems diff --git a/src/components/Navigation/Sidebar/NavItem/SubItems/styles.js b/src/components/Navigation/Sidebar/NavItem/SubItems/styles.js new file mode 100644 index 0000000..394e3c3 --- /dev/null +++ b/src/components/Navigation/Sidebar/NavItem/SubItems/styles.js @@ -0,0 +1,24 @@ +import styled, { css } from 'styled-components' + +export const Container = styled.div` + align-items: flex-start; + display: flex; + flex-direction: column; + height: auto; + justify-content: flex-start; + padding: 0 55px; + width: 100%; +` + +export const SubItem = styled.span` + ${({ theme }) => css` + color: ${theme.navigation.sidebar.icons.color.dark}; + margin: 0 0 5px; + padding: 5px; + white-space: nowrap; + + &:hover { + color: ${theme.colors.primary.light}; + } + `} +` diff --git a/src/components/Navigation/Sidebar/NavItem/styles.js b/src/components/Navigation/Sidebar/NavItem/styles.js index 08ccce7..61f42f7 100644 --- a/src/components/Navigation/Sidebar/NavItem/styles.js +++ b/src/components/Navigation/Sidebar/NavItem/styles.js @@ -1,14 +1,23 @@ import styled, { css } from 'styled-components' export const Container = styled.div` + align-items: flex-start; + display: flex; + flex-direction: column; + height: auto; + justify-content: flex-start; + width: 100%; +` + +export const LinkContent = styled.div` ${({ theme }) => css` align-items: center; - color: ${theme.navigation.sidebar.icons.color}; + color: ${theme.navigation.sidebar.icons.color.base}; cursor: pointer; display: flex; + height: 100%; height: 60px; justify-content: flex-start; - padding: 0 0 0 9px; width: 100%; &:hover { diff --git a/src/components/Navigation/Sidebar/Sidebar.jsx b/src/components/Navigation/Sidebar/Sidebar.jsx index 2baf426..306af67 100644 --- a/src/components/Navigation/Sidebar/Sidebar.jsx +++ b/src/components/Navigation/Sidebar/Sidebar.jsx @@ -8,21 +8,28 @@ import Logo from './Logo' import NavItem from './NavItem/NavItem' import * as S from './styles' -const Sidebar = ({ navItems, isSidebarExpanded, setIsSidebarExpanded }) => { +const Sidebar = ({ + navItems, + isSidebarExpanded, + setIsSidebarExpanded, + currentExpandedItem, + setCurrentExpandedItem +}) => { useEffect(() => { UTIL.Components.handleSidebarExpanded(isSidebarExpanded) }, [isSidebarExpanded]) return ( + - - {navItems?.map((navItem) => ( ))} @@ -34,7 +41,9 @@ const Sidebar = ({ navItems, isSidebarExpanded, setIsSidebarExpanded }) => { Sidebar.propTypes = { navItems: PropTypes.array.isRequired, isSidebarExpanded: PropTypes.bool.isRequired, - setIsSidebarExpanded: PropTypes.func.isRequired + setIsSidebarExpanded: PropTypes.func.isRequired, + currentExpandedItem: PropTypes.bool.isRequired, + setCurrentExpandedItem: PropTypes.func.isRequired } export default Sidebar diff --git a/src/components/Navigation/Sidebar/styles.js b/src/components/Navigation/Sidebar/styles.js index fa6bf70..0353253 100644 --- a/src/components/Navigation/Sidebar/styles.js +++ b/src/components/Navigation/Sidebar/styles.js @@ -9,7 +9,6 @@ export const Container = styled.div` left: 0; max-width: var(--sidebar-width); overflow: hidden; - padding: 15px; position: fixed; top: 0; transition: max-width ${theme.navigation.transition}; @@ -23,5 +22,6 @@ export const NavItems = styled.div` display: flex; flex-direction: column; justify-content: flex-start; + padding: 0 0 0 23px; width: 100%; ` diff --git a/src/components/UI/Link/Link.js b/src/components/UI/Link/Link.js new file mode 100644 index 0000000..8fc0ca5 --- /dev/null +++ b/src/components/UI/Link/Link.js @@ -0,0 +1,69 @@ +import React from 'react' +import { Link as RouterLink } from 'react-router-dom' + +import PropTypes from 'prop-types' +import * as UTIL from 'utils' + +import * as S from './styles' + +const Link = ({ + url, + target, + title, + children, + childrenPosition, + color, + colorOnHover, + margin, + padding, + width, + height, + setHasClicked +}) => { + return ( + + {UTIL.isExternalUrl(url) ? ( + + {title && {title || ''}} + {children} + + ) : ( + { + setHasClicked && setHasClicked(true) + }} + > + {title && {title || ''}} + {children} + + )} + + ) +} + +Link.propTypes = { + url: PropTypes.string, + target: PropTypes.string, + title: PropTypes.string, + children: PropTypes.element, + childrenPosition: PropTypes.string, + color: PropTypes.string, + colorOnHover: PropTypes.string, + margin: PropTypes.string, + padding: PropTypes.string, + width: PropTypes.string, + height: PropTypes.string, + setHasClicked: PropTypes.func +} + +export default Link diff --git a/src/components/UI/Link/styles.js b/src/components/UI/Link/styles.js new file mode 100644 index 0000000..e5066a7 --- /dev/null +++ b/src/components/UI/Link/styles.js @@ -0,0 +1,48 @@ +import styled, { css } from 'styled-components' + +export const Container = styled.div` + ${({ + width, + margin, + padding, + height, + display, + childrenPosition, + color, + fontSize, + fontWeight, + colorOnHover + }) => css` + width: ${width || 'auto'}; + & a { + align-items: center; + all: unset; + color: ${color || '#000'}; + cursor: pointer; + display: ${display || 'flex'}; + font-size: ${fontSize || '14px'}; + font-weight: ${fontWeight || '500'}; + height: ${height || 'auto'}; + justify-content: ${() => { + switch (childrenPosition) { + case 'left': + return 'flex-start' + case 'right': + return 'flex-end' + default: + return 'center' + } + }}; + margin: ${margin || '0'}; + padding: ${padding || '0'}; + width: ${width || 'auto'}; + &:hover { + ${colorOnHover && `color: ${colorOnHover}`}; + } + } + `} +` + +export const LinkAnchor = styled.a`` + +export const Title = styled.p`` diff --git a/src/components/UI/index.js b/src/components/UI/index.js index aca1c78..7c8d901 100644 --- a/src/components/UI/index.js +++ b/src/components/UI/index.js @@ -1,3 +1,4 @@ export { default as Button } from './Button/Button' +export { default as Link } from './Link/Link' export { default as Spinner } from './Spinner/Spinner' export { default as TextField } from './TextField/TextField' diff --git a/src/pages/SignIn/styles.js b/src/pages/SignIn/styles.js index 7e58be1..69034f3 100644 --- a/src/pages/SignIn/styles.js +++ b/src/pages/SignIn/styles.js @@ -1,9 +1,7 @@ import * as PS from 'assets/styles/pages' import styled from 'styled-components' -export const Container = styled(PS.PageContainer)` - padding: 0; -` +export const Container = styled(PS.PageContainer)`` export const Title = styled(PS.PageTitle)`` diff --git a/src/pages/User/User.jsx b/src/pages/User/User.jsx index 12d47c8..bfb650a 100644 --- a/src/pages/User/User.jsx +++ b/src/pages/User/User.jsx @@ -1,26 +1,16 @@ import React from 'react' -import * as C from 'components' import { useAuthContext } from 'contexts/AuthProvider/AuthProvider' import * as S from './styles' const User = () => { - const { user, signOut } = useAuthContext() - - const handleSignOut = (event, signOut) => { - event.preventDefault() - signOut() - } + const { user } = useAuthContext() return ( {user} - - handleSignOut(e, signOut)} fullWidth> - Sign out - ) diff --git a/src/routes/index.js b/src/routes/index.js index 02586e1..a89419b 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,6 +1,7 @@ import React, { Suspense, lazy } from 'react' -import { Route, Switch } from 'react-router-dom' +import { Redirect, Route, Switch } from 'react-router-dom' +import { useAuthContext } from 'contexts/AuthProvider/AuthProvider' import PrivateRoute from 'routes/PrivateRoute' const SignIn = lazy(() => import('pages/SignIn/SignIn')) @@ -11,23 +12,35 @@ const ProcessMonitoring = lazy(() => import('pages/ProcessMonitoring/ProcessMonitoring') ) -const Routes = () => ( - - - - +const Routes = () => { + const { signOut } = useAuthContext() - - - + return ( + + + + - - - -) + + + + { + signOut() + return + }} + /> + + + + + ) +} export default Routes diff --git a/src/utils/components/navigation/navigation.js b/src/utils/components/navigation/navigation.js index f0f87dd..38e1eef 100644 --- a/src/utils/components/navigation/navigation.js +++ b/src/utils/components/navigation/navigation.js @@ -1,6 +1,9 @@ -export const handleSidebarExpanded = (isSidebarExpanded) => { +export const handleSidebarExpanded = ( + isSidebarExpanded, + customWidth = '250px' +) => { document.documentElement.style.setProperty( '--sidebar-width', - isSidebarExpanded ? ' 250px' : '70px' + isSidebarExpanded ? customWidth : '70px' ) } diff --git a/src/utils/index.js b/src/utils/index.js index e3d6bda..a7ade72 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,2 +1,3 @@ +export * from './utils' export * as Components from './components' export * as Notifications from './notifications/notifications' diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..3c3168f --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,8 @@ +export const isExternalUrl = (url) => { + if (url) { + const regex = /http:|https:|www\./g + return regex.test(url) + } + + return false +}