Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crux-ui): reorganize the menu structure #977

Merged
merged 2 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web/crux-ui/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"log": "Log",

"home": "Home",
"settings": "Settings",
"components": "Components",
"integrations": "Integrations",
"tools": "Tools",

"logout": "Log out",

Expand Down
29 changes: 17 additions & 12 deletions web/crux-ui/src/components/main/nav-button.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
import DyoIcon from '@app/elements/dyo-icon'
import DyoLink from '@app/elements/dyo-link'
import clsx from 'clsx'
import { useRouter } from 'next/router'

interface NavButtonProps {
children: string
type NavButtonProps = {
className?: string
href: string
target?: string
passHref?: boolean
icon?: JSX.Element
icon: string
text: string
activeIndicator?: boolean
}

const NavButton = (props: NavButtonProps) => {
const { children, href, target, passHref, icon } = props
const { className, activeIndicator, href, target, icon, text } = props

const router = useRouter()

const active = router.asPath.startsWith(href)
const active = activeIndicator && router.asPath.startsWith(href)

return (
<>
<div className={clsx('pl-8 py-2', active ? 'bg-dark w-full' : null)}>
<DyoLink href={href} passHref={passHref} target={target} qaLabel={`menu-item-${children}`}>
<div className="flex flex-row">
<div className="flex items-center mr-2 text-bright text-sm font-semibold">{icon}</div>
{children}
<div className={clsx(className ?? 'pl-8 py-1.5', active ? 'bg-dark w-full' : null)}>
<DyoLink href={href} target={target} qaLabel={`menu-item-${text}`}>
<div className="flex flex-row text-bright">
<div className="flex items-center mr-2 text-bright text-sm font-semibold">
<DyoIcon src={icon} alt={text} />
</div>

{text}
</div>
</DyoLink>
</div>

<div className={clsx('w-1 py-2', active ? 'bg-dyo-turquoise opacity-50' : null)}>&nbsp;</div>
<div className={clsx('w-1 py-1.5', active ? 'bg-dyo-turquoise opacity-50' : null)}>&nbsp;</div>
</>
)
}
Expand Down
18 changes: 7 additions & 11 deletions web/crux-ui/src/components/main/nav-section.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import DyoIcon from '@app/elements/dyo-icon'
import useTranslation from 'next-translate/useTranslation'
import NavButton from './nav-button'

Expand All @@ -9,7 +8,7 @@ export type MenuOption = {
icon: string
}

interface NavSectionProps {
type NavSectionProps = {
title: string
options: MenuOption[]
className?: string
Expand All @@ -20,17 +19,14 @@ export const NavSection = (props: NavSectionProps) => {

const { t } = useTranslation('common')

const optionToIcon = (it: MenuOption) => <DyoIcon src={it.icon} alt={t(it.text)} />

return (
<div className={className}>
<p className="text-bright px-6 text-sm tracking-widest">{title.toUpperCase()}</p>
<ul className="list-none flex flex-col text-bright">
{options.map((option, index) => (
<li key={index} className="flex flex-row items-center mt-2">
<NavButton href={option.link} icon={optionToIcon(option)} target={option.target}>
{t(option.text)}
</NavButton>
<p className="text-light px-6 text-sm tracking-widest">{title.toUpperCase()}</p>

<ul className="list-none flex flex-col text-bright pt-2">
{options.map((it, index) => (
<li key={index} className="flex flex-row items-center">
<NavButton activeIndicator href={it.link} icon={it.icon} text={t(it.text)} target={it.target} />
</li>
))}
</ul>
Expand Down
90 changes: 90 additions & 0 deletions web/crux-ui/src/components/main/profile-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { DyoCard } from '@app/elements/dyo-card'
import useTeamRoutes from '@app/hooks/use-team-routes'
import { UserMeta, UserMetaTeam } from '@app/models'
import { ROUTE_DOCS, ROUTE_LOGOUT, ROUTE_PROFILE, ROUTE_TEAMS, TeamRoutes } from '@app/routes'
import clsx from 'clsx'
import useTranslation from 'next-translate/useTranslation'
import Image from 'next/image'
import NavButton from './nav-button'

interface TeamSelectionCardProps {
className?: string
meta: UserMeta
onTeamSelected: (team: UserMetaTeam) => void
}

const menuItemsOf = (routes: TeamRoutes) => [
{
icon: '/audit.svg',
text: 'audit',
link: routes.audit.list(),
},
{
icon: '/team.svg',
text: 'teams',
link: ROUTE_TEAMS,
},
{
icon: '/documentation.svg',
text: 'documentation',
link: ROUTE_DOCS,
target: '_blank',
},
{
icon: '/logout.svg',
text: 'logout',
link: ROUTE_LOGOUT,
},
]

const ProfileCard = (props: TeamSelectionCardProps) => {
const { meta, className, onTeamSelected } = props

const { t } = useTranslation('common')
const routes = useTeamRoutes()

const teamRoutes = useTeamRoutes()
const menuitems = menuItemsOf(teamRoutes)

return (
<DyoCard className={clsx(className, 'px-4 py-2 gap-4 text-bright')}>
<div className="flex flex-row border-b-2 border-light-grey">
<NavButton className="m-2" href={ROUTE_PROFILE} icon="/profile.svg" text={t('profile')} />
</div>

<p className="text-light px-2 text-sm tracking-widest">{t('yourTeams').toUpperCase()}</p>

{meta.teams.map(team => {
const currentTeam = team.slug === routes?.teamSlug

return (
<div
key={`team-${team.slug}`}
className={clsx('flex flex-row items-center mx-6', currentTeam ? null : 'cursor-pointer')}
onClick={currentTeam ? null : () => onTeamSelected(team)}
>
<Image
className={currentTeam ? null : 'opacity-30 bg-blend-darken'}
src="/default_team_avatar.svg"
alt={t('teamAvatar')}
width={32}
height={32}
/>

<div className="ml-4">{team.name}</div>
</div>
)
})}

<div className="flex flex-col border-t-2 border-light-grey">
{menuitems.map(it => (
<div key={it.link} className="flex flex-row">
<NavButton className="m-2" href={it.link} icon={it.icon} text={t(it.text)} />
</div>
))}
</div>
</DyoCard>
)
}

export default ProfileCard
71 changes: 14 additions & 57 deletions web/crux-ui/src/components/main/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import DyoIcon from '@app/elements/dyo-icon'
import DyoLink from '@app/elements/dyo-link'
import useTeamRoutes from '@app/hooks/use-team-routes'
import {
ROUTE_COMPOSER,
ROUTE_DOCS,
ROUTE_INDEX,
ROUTE_LOGOUT,
ROUTE_PROFILE,
ROUTE_TEAMS,
ROUTE_TEMPLATES,
TeamRoutes,
} from '@app/routes'
import { ROUTE_COMPOSER, ROUTE_INDEX, ROUTE_TEMPLATES, TeamRoutes } from '@app/routes'
import useTranslation from 'next-translate/useTranslation'
import Image from 'next/image'
import NavButton from './nav-button'
Expand All @@ -27,7 +17,7 @@ export interface SidebarProps {

export const sidebarSectionsOf = (routes: TeamRoutes): MenuSection[] => [
{
title: 'project',
title: 'components',
items: [
{
icon: '/projects.svg',
Expand All @@ -39,11 +29,6 @@ export const sidebarSectionsOf = (routes: TeamRoutes): MenuSection[] => [
text: 'deployments',
link: routes.deployment.list(),
},
],
},
{
title: 'components',
items: [
{
icon: '/servers.svg',
text: 'nodes',
Expand All @@ -59,6 +44,11 @@ export const sidebarSectionsOf = (routes: TeamRoutes): MenuSection[] => [
text: 'configBundles',
link: routes.configBundles.list(),
},
],
},
{
title: 'integrations',
items: [
{
icon: '/storage.svg',
text: 'storages',
Expand All @@ -74,6 +64,11 @@ export const sidebarSectionsOf = (routes: TeamRoutes): MenuSection[] => [
text: 'notifications',
link: routes.notification.list(),
},
],
},
{
title: 'tools',
items: [
{
icon: '/template.svg',
text: 'templates',
Expand All @@ -86,37 +81,6 @@ export const sidebarSectionsOf = (routes: TeamRoutes): MenuSection[] => [
},
],
},
{
title: 'settings',
items: [
{
icon: '/audit.svg',
text: 'audit',
link: routes.audit.list(),
},
{
icon: '/team.svg',
text: 'teams',
link: ROUTE_TEAMS,
},
{
icon: '/profile.svg',
text: 'profile',
link: ROUTE_PROFILE,
},
{
icon: '/documentation.svg',
text: 'documentation',
link: ROUTE_DOCS,
target: '_blank',
},
{
icon: '/logout.svg',
text: 'logout',
link: ROUTE_LOGOUT,
},
],
},
]

export const Sidebar = (props: SidebarProps) => {
Expand Down Expand Up @@ -145,18 +109,11 @@ export const Sidebar = (props: SidebarProps) => {
{sidebarSections && (
<div className="flex flex-col grow">
<div className="flex text-bright my-6">
<NavButton href={routes.dashboard.index()} icon={<DyoIcon src="/dashboard.svg" alt={t('dashboard')} />}>
{t('dashboard')}
</NavButton>
<NavButton activeIndicator href={routes.dashboard.index()} icon="/dashboard.svg" text={t('dashboard')} />
</div>

{sidebarSections.map((it, index) => (
<NavSection
key={index}
className={index < sidebarSections.length - 1 ? 'mb-6' : 'mt-auto mb-3'}
title={t(it.title)}
options={it.items}
/>
<NavSection key={index} className="mb-6" title={t(it.title)} options={it.items} />
))}
</div>
)}
Expand Down
56 changes: 0 additions & 56 deletions web/crux-ui/src/components/main/team-selection-card.tsx

This file was deleted.

7 changes: 4 additions & 3 deletions web/crux-ui/src/components/main/top-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router'
import { useState } from 'react'
import UserDefaultAvatar from '../team/user-default-avatar'
import TeamSelectionCard from './team-selection-card'
import ProfileCard from './profile-card'

interface TopbarProps {
className?: string
Expand Down Expand Up @@ -60,12 +60,13 @@ const Topbar = (props: TopbarProps) => {
{!teamSelectionVisible ? null : (
<>
<div className="w-full absolute bottom-0 right-0">
<TeamSelectionCard
className="flex flex-col flex-grow absolute top-0 right-0 mt-2 z-20"
<ProfileCard
className="flex flex-col absolute top-0 right-0 mt-2 z-20"
meta={meta}
onTeamSelected={onTeamSelected}
/>
</div>

<div className="w-full h-full fixed top-0 right-0 z-10" onClick={toggleTeamSelection} />
</>
)}
Expand Down
Loading