2022-05-12 06:57:25 +00:00
|
|
|
import React, { Fragment, ReactNode } from 'react';
|
2022-01-19 16:50:25 +00:00
|
|
|
import {
|
2022-05-12 06:57:25 +00:00
|
|
|
IconButton,
|
|
|
|
Box,
|
|
|
|
CloseButton,
|
|
|
|
Flex,
|
|
|
|
Image,
|
|
|
|
HStack,
|
|
|
|
VStack,
|
|
|
|
Icon,
|
|
|
|
useColorModeValue,
|
|
|
|
Link,
|
|
|
|
Text,
|
|
|
|
BoxProps,
|
|
|
|
FlexProps,
|
|
|
|
Menu,
|
|
|
|
MenuButton,
|
|
|
|
MenuItem,
|
|
|
|
MenuList,
|
|
|
|
Accordion,
|
|
|
|
AccordionButton,
|
|
|
|
AccordionPanel,
|
|
|
|
AccordionItem,
|
|
|
|
AccordionIcon,
|
|
|
|
useMediaQuery,
|
|
|
|
} from '@chakra-ui/react';
|
2022-05-12 11:36:18 +00:00
|
|
|
import { FiUser, FiCode, FiSettings, FiMenu, FiUsers, FiChevronDown } from 'react-icons/fi';
|
2022-05-12 06:57:25 +00:00
|
|
|
import { BiCustomize } from 'react-icons/bi';
|
|
|
|
import { AiOutlineKey } from 'react-icons/ai';
|
|
|
|
import { SiOpenaccess, SiJsonwebtokens } from 'react-icons/si';
|
|
|
|
import { MdSecurity } from 'react-icons/md';
|
|
|
|
import { RiDatabase2Line } from 'react-icons/ri';
|
|
|
|
import { BsCheck2Circle } from 'react-icons/bs';
|
|
|
|
import { HiOutlineMail, HiOutlineOfficeBuilding } from 'react-icons/hi';
|
|
|
|
import { IconType } from 'react-icons';
|
|
|
|
import { ReactText } from 'react';
|
|
|
|
import { useMutation, useQuery } from 'urql';
|
|
|
|
import { NavLink, useNavigate, useLocation } from 'react-router-dom';
|
|
|
|
import { useAuthContext } from '../contexts/AuthContext';
|
|
|
|
import { AdminLogout } from '../graphql/mutation';
|
|
|
|
import { MetaQuery } from '../graphql/queries';
|
2022-05-07 16:40:29 +00:00
|
|
|
|
|
|
|
interface SubRoutes {
|
2022-05-12 06:57:25 +00:00
|
|
|
name: string;
|
|
|
|
icon: IconType;
|
|
|
|
route: string;
|
2022-05-07 16:40:29 +00:00
|
|
|
}
|
2022-01-19 16:50:25 +00:00
|
|
|
|
|
|
|
interface LinkItemProps {
|
2022-05-12 06:57:25 +00:00
|
|
|
name: string;
|
|
|
|
icon: IconType;
|
|
|
|
route: string;
|
|
|
|
subRoutes?: SubRoutes[];
|
2022-01-19 16:50:25 +00:00
|
|
|
}
|
|
|
|
const LinkItems: Array<LinkItemProps> = [
|
2022-05-12 06:57:25 +00:00
|
|
|
{
|
|
|
|
name: 'Environment ',
|
|
|
|
icon: FiSettings,
|
|
|
|
route: '/',
|
|
|
|
subRoutes: [
|
|
|
|
{
|
|
|
|
name: 'OAuth Config',
|
|
|
|
icon: AiOutlineKey,
|
|
|
|
route: '/oauth-setting',
|
|
|
|
},
|
2022-05-07 16:40:29 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
{ name: 'Roles', icon: FiUser, route: '/roles' },
|
|
|
|
{
|
|
|
|
name: 'JWT Secrets',
|
|
|
|
icon: SiJsonwebtokens,
|
|
|
|
route: '/jwt-config',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Session Storage',
|
|
|
|
icon: RiDatabase2Line,
|
|
|
|
route: '/session-storage',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Email Configurations',
|
|
|
|
icon: HiOutlineMail,
|
|
|
|
route: '/email-config',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Domain White Listing',
|
|
|
|
icon: BsCheck2Circle,
|
|
|
|
route: '/whitelist-variables',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Organization Info',
|
|
|
|
icon: HiOutlineOfficeBuilding,
|
|
|
|
route: '/organization-info',
|
|
|
|
},
|
|
|
|
{ name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
|
|
|
|
{
|
|
|
|
name: 'UI Customization',
|
|
|
|
icon: BiCustomize,
|
|
|
|
route: '/ui-customization',
|
|
|
|
},
|
|
|
|
{ name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
|
|
|
|
{
|
|
|
|
name: ' Security',
|
|
|
|
icon: MdSecurity,
|
|
|
|
route: '/admin-secret',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{ name: 'Users', icon: FiUsers, route: '/users' },
|
2022-01-19 16:50:25 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
interface SidebarProps extends BoxProps {
|
2022-05-12 06:57:25 +00:00
|
|
|
onClose: () => void;
|
2022-01-19 16:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
2022-05-12 06:57:25 +00:00
|
|
|
const { pathname } = useLocation();
|
|
|
|
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
|
|
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
|
|
|
return (
|
|
|
|
<Box
|
2022-05-12 11:36:18 +00:00
|
|
|
transition='3s ease'
|
2022-05-12 06:57:25 +00:00
|
|
|
bg={useColorModeValue('white', 'gray.900')}
|
2022-05-12 11:36:18 +00:00
|
|
|
borderRight='1px'
|
2022-05-12 06:57:25 +00:00
|
|
|
borderRightColor={useColorModeValue('gray.200', 'gray.700')}
|
|
|
|
w={{ base: 'full', md: 60 }}
|
2022-05-12 11:36:18 +00:00
|
|
|
pos='fixed'
|
|
|
|
h='full'
|
2022-05-12 06:57:25 +00:00
|
|
|
{...rest}
|
|
|
|
>
|
2022-05-12 11:36:18 +00:00
|
|
|
<Flex h='20' alignItems='center' mx='18' justifyContent='space-between' flexDirection='column'>
|
|
|
|
<NavLink to='/'>
|
|
|
|
<Flex alignItems='center' mt='6'>
|
|
|
|
<Image src='https://authorizer.dev/images/logo.png' alt='logo' height='36px' />
|
|
|
|
<Text fontSize='large' ml='2' letterSpacing='3'>
|
2022-05-12 06:57:25 +00:00
|
|
|
AUTHORIZER
|
|
|
|
</Text>
|
|
|
|
</Flex>
|
|
|
|
</NavLink>
|
|
|
|
<CloseButton display={{ base: 'flex', md: 'none' }} onClick={onClose} />
|
|
|
|
</Flex>
|
2022-01-25 07:36:52 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
<Accordion defaultIndex={[0]} allowMultiple>
|
2022-05-12 11:36:18 +00:00
|
|
|
<AccordionItem textAlign='center' border='none' w='100%'>
|
2022-05-12 06:57:25 +00:00
|
|
|
{LinkItems.map((link) =>
|
|
|
|
link?.subRoutes ? (
|
|
|
|
<div key={link.name}>
|
|
|
|
<AccordionButton>
|
2022-05-12 11:36:18 +00:00
|
|
|
<Text as='div' fontSize='md'>
|
2022-05-12 06:57:25 +00:00
|
|
|
<NavItem
|
|
|
|
icon={link.icon}
|
|
|
|
color={pathname === link.route ? 'blue.500' : ''}
|
|
|
|
style={{ outline: 'unset' }}
|
|
|
|
height={12}
|
|
|
|
ml={-1}
|
|
|
|
mb={isNotSmallerScreen ? -1 : -4}
|
|
|
|
w={isNotSmallerScreen ? '100%' : '310%'}
|
|
|
|
>
|
|
|
|
<Fragment>
|
|
|
|
{link.name}
|
|
|
|
<Box display={{ base: 'none', md: 'flex' }} ml={12}>
|
|
|
|
<FiChevronDown />
|
|
|
|
</Box>
|
|
|
|
</Fragment>
|
|
|
|
</NavItem>
|
|
|
|
</Text>
|
|
|
|
</AccordionButton>
|
|
|
|
<AccordionPanel>
|
|
|
|
{link.subRoutes?.map((sublink) => (
|
2022-05-12 11:36:18 +00:00
|
|
|
<NavLink key={sublink.name} to={sublink.route} onClick={onClose}>
|
2022-05-12 06:57:25 +00:00
|
|
|
{' '}
|
2022-05-12 11:36:18 +00:00
|
|
|
<Text as='div' fontSize='xs' ml={2}>
|
|
|
|
<NavItem icon={sublink.icon} color={pathname === sublink.route ? 'blue.500' : ''} height={8}>
|
2022-05-12 06:57:25 +00:00
|
|
|
{sublink.name}
|
|
|
|
</NavItem>{' '}
|
|
|
|
</Text>
|
|
|
|
</NavLink>
|
|
|
|
))}
|
|
|
|
</AccordionPanel>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<NavLink key={link.name} to={link.route}>
|
|
|
|
{' '}
|
2022-05-12 11:36:18 +00:00
|
|
|
<Text as='div' fontSize='md' w='100%' mt={-2}>
|
2022-05-12 06:57:25 +00:00
|
|
|
<NavItem
|
|
|
|
icon={link.icon}
|
|
|
|
color={pathname === link.route ? 'blue.500' : ''}
|
|
|
|
height={12}
|
|
|
|
onClick={onClose}
|
|
|
|
>
|
|
|
|
{link.name}
|
|
|
|
</NavItem>{' '}
|
|
|
|
</Text>
|
|
|
|
</NavLink>
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
<Link
|
2022-05-12 11:36:18 +00:00
|
|
|
href='/playground'
|
|
|
|
target='_blank'
|
2022-05-12 06:57:25 +00:00
|
|
|
style={{
|
|
|
|
textDecoration: 'none',
|
|
|
|
}}
|
|
|
|
_focus={{ _boxShadow: 'none' }}
|
|
|
|
>
|
|
|
|
<NavItem icon={FiCode}>API Playground</NavItem>
|
|
|
|
</Link>
|
|
|
|
</AccordionItem>
|
|
|
|
</Accordion>
|
2022-03-09 06:23:34 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
{data?.meta?.version && (
|
2022-05-12 11:36:18 +00:00
|
|
|
<Flex alignContent='center'>
|
2022-05-12 06:57:25 +00:00
|
|
|
{' '}
|
2022-05-12 11:36:18 +00:00
|
|
|
<Text color='gray.400' fontSize='sm' textAlign='center' position='absolute' bottom='5' left='7'>
|
2022-05-12 06:57:25 +00:00
|
|
|
Current Version: {data.meta.version}
|
|
|
|
</Text>
|
|
|
|
</Flex>
|
|
|
|
)}
|
|
|
|
</Box>
|
|
|
|
);
|
2022-01-19 16:50:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
interface NavItemProps extends FlexProps {
|
2022-05-12 06:57:25 +00:00
|
|
|
icon: IconType;
|
|
|
|
children: ReactText | JSX.Element | JSX.Element[];
|
2022-01-19 16:50:25 +00:00
|
|
|
}
|
|
|
|
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
|
2022-05-12 06:57:25 +00:00
|
|
|
return (
|
|
|
|
<Flex
|
2022-05-12 11:36:18 +00:00
|
|
|
align='center'
|
|
|
|
p='3'
|
|
|
|
mx='3'
|
|
|
|
borderRadius='md'
|
|
|
|
role='group'
|
|
|
|
cursor='pointer'
|
2022-05-12 06:57:25 +00:00
|
|
|
_hover={{
|
|
|
|
bg: 'blue.500',
|
|
|
|
color: 'white',
|
|
|
|
}}
|
|
|
|
{...rest}
|
|
|
|
>
|
|
|
|
{icon && (
|
|
|
|
<Icon
|
2022-05-12 11:36:18 +00:00
|
|
|
mr='4'
|
|
|
|
fontSize='16'
|
2022-05-12 06:57:25 +00:00
|
|
|
_groupHover={{
|
|
|
|
color: 'white',
|
|
|
|
}}
|
|
|
|
as={icon}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{children}
|
|
|
|
</Flex>
|
|
|
|
);
|
2022-01-19 16:50:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
interface MobileProps extends FlexProps {
|
2022-05-12 06:57:25 +00:00
|
|
|
onOpen: () => void;
|
2022-01-19 16:50:25 +00:00
|
|
|
}
|
|
|
|
export const MobileNav = ({ onOpen, ...rest }: MobileProps) => {
|
2022-05-12 06:57:25 +00:00
|
|
|
const [_, logout] = useMutation(AdminLogout);
|
|
|
|
const { setIsLoggedIn } = useAuthContext();
|
|
|
|
const navigate = useNavigate();
|
2022-01-19 16:50:25 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
const handleLogout = async () => {
|
|
|
|
await logout();
|
|
|
|
setIsLoggedIn(false);
|
|
|
|
navigate('/', { replace: true });
|
|
|
|
};
|
2022-01-19 16:50:25 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
return (
|
|
|
|
<Flex
|
|
|
|
ml={{ base: 0, md: 60 }}
|
|
|
|
px={{ base: 4, md: 4 }}
|
2022-05-12 11:36:18 +00:00
|
|
|
height='20'
|
|
|
|
position='fixed'
|
|
|
|
right='0'
|
|
|
|
left='0'
|
|
|
|
alignItems='center'
|
2022-05-12 06:57:25 +00:00
|
|
|
bg={useColorModeValue('white', 'gray.900')}
|
2022-05-12 11:36:18 +00:00
|
|
|
borderBottomWidth='1px'
|
2022-05-12 06:57:25 +00:00
|
|
|
borderBottomColor={useColorModeValue('gray.200', 'gray.700')}
|
|
|
|
justifyContent={{ base: 'space-between', md: 'flex-end' }}
|
|
|
|
zIndex={99}
|
|
|
|
{...rest}
|
|
|
|
>
|
|
|
|
<IconButton
|
|
|
|
display={{ base: 'flex', md: 'none' }}
|
|
|
|
onClick={onOpen}
|
2022-05-12 11:36:18 +00:00
|
|
|
variant='outline'
|
|
|
|
aria-label='open menu'
|
2022-05-12 06:57:25 +00:00
|
|
|
icon={<FiMenu />}
|
|
|
|
/>
|
2022-01-19 16:50:25 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
<Image
|
2022-05-12 11:36:18 +00:00
|
|
|
src='https://authorizer.dev/images/logo.png'
|
|
|
|
alt='logo'
|
|
|
|
height='36px'
|
2022-05-12 06:57:25 +00:00
|
|
|
display={{ base: 'flex', md: 'none' }}
|
|
|
|
/>
|
2022-01-19 16:50:25 +00:00
|
|
|
|
2022-05-12 06:57:25 +00:00
|
|
|
<HStack spacing={{ base: '0', md: '6' }}>
|
|
|
|
<Flex alignItems={'center'}>
|
|
|
|
<Menu>
|
2022-05-12 11:36:18 +00:00
|
|
|
<MenuButton py={2} transition='all 0.3s' _focus={{ boxShadow: 'none' }}>
|
2022-05-12 06:57:25 +00:00
|
|
|
<HStack mr={5}>
|
|
|
|
<FiUser />
|
2022-05-12 11:36:18 +00:00
|
|
|
<VStack display={{ base: 'none', md: 'flex' }} alignItems='flex-start' spacing='1px' ml='2'>
|
|
|
|
<Text fontSize='sm'>Admin</Text>
|
2022-05-12 06:57:25 +00:00
|
|
|
</VStack>
|
|
|
|
<Box display={{ base: 'none', md: 'flex' }}>
|
|
|
|
<FiChevronDown />
|
|
|
|
</Box>
|
|
|
|
</HStack>
|
|
|
|
</MenuButton>
|
|
|
|
<MenuList
|
|
|
|
bg={useColorModeValue('white', 'gray.900')}
|
|
|
|
borderColor={useColorModeValue('gray.200', 'gray.700')}
|
|
|
|
>
|
|
|
|
<MenuItem onClick={handleLogout}>Sign out</MenuItem>
|
|
|
|
</MenuList>
|
|
|
|
</Menu>
|
|
|
|
</Flex>
|
|
|
|
</HStack>
|
|
|
|
</Flex>
|
|
|
|
);
|
|
|
|
};
|