Migrate to a monorepo structure (#2909)

This commit is contained in:
Charles Bochet
2023-12-10 18:10:54 +01:00
committed by GitHub
parent a70a9281eb
commit 5bdca9de6c
2304 changed files with 37152 additions and 25869 deletions

View File

@ -0,0 +1,74 @@
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems';
import { SupportChat } from '@/support/components/SupportChat';
import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersionLink';
import {
NavigationDrawer,
NavigationDrawerProps,
} from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
import { useIsSettingsPage } from '../hooks/useIsSettingsPage';
import { currentMobileNavigationDrawerState } from '../states/currentMobileNavigationDrawerState';
import { MainNavigationDrawerItems } from './MainNavigationDrawerItems';
export type AppNavigationDrawerProps = {
className?: string;
};
export const AppNavigationDrawer = ({
className,
}: AppNavigationDrawerProps) => {
const isMobile = useIsMobile();
const isSettingsPage = useIsSettingsPage();
const currentMobileNavigationDrawer = useRecoilValue(
currentMobileNavigationDrawerState,
);
const setIsNavigationDrawerOpen = useSetRecoilState(
isNavigationDrawerOpenState,
);
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isSettingsDrawer = isMobile
? currentMobileNavigationDrawer === 'settings'
: isSettingsPage;
const drawerProps: NavigationDrawerProps = isSettingsDrawer
? {
isSubMenu: true,
title: 'Settings',
children: <SettingsNavigationDrawerItems />,
footer: <GithubVersionLink />,
}
: {
logo:
(currentWorkspace?.logo &&
getImageAbsoluteURIOrBase64(currentWorkspace.logo)) ??
undefined,
title: currentWorkspace?.displayName ?? undefined,
children: <MainNavigationDrawerItems />,
footer: <SupportChat />,
};
useEffect(() => {
setIsNavigationDrawerOpen(!isMobile);
}, [isMobile, setIsNavigationDrawerOpen]);
return (
<NavigationDrawer
className={className}
isSubMenu={drawerProps.isSubMenu}
logo={drawerProps.logo}
title={drawerProps.title}
footer={drawerProps.footer}
>
{drawerProps.children}
</NavigationDrawer>
);
};

View File

@ -0,0 +1,82 @@
import { useLocation, useNavigate } from 'react-router-dom';
import { useSetRecoilState } from 'recoil';
import { useCurrentUserTaskCount } from '@/activities/tasks/hooks/useCurrentUserDueTaskCount';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { Favorites } from '@/favorites/components/Favorites';
import { ObjectMetadataNavItems } from '@/object-metadata/components/ObjectMetadataNavItems';
import {
IconBell,
IconCheckbox,
IconSearch,
IconSettings,
IconTargetArrow,
} from '@/ui/display/icon';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useIsTasksPage } from '../hooks/useIsTasksPage';
export const MainNavigationDrawerItems = () => {
const isMobile = useIsMobile();
const { toggleCommandMenu } = useCommandMenu();
const isTasksPage = useIsTasksPage();
const { currentUserDueTaskCount } = useCurrentUserTaskCount();
const navigate = useNavigate();
const location = useLocation();
const setNavigationMemorizedUrl = useSetRecoilState(
navigationMemorizedUrlState,
);
return (
<>
{!isMobile && (
<NavigationDrawerSection>
<NavigationDrawerItem
label="Search"
Icon={IconSearch}
onClick={toggleCommandMenu}
keyboard={['⌘', 'K']}
/>
<NavigationDrawerItem
label="Notifications"
to="/inbox"
Icon={IconBell}
soon
/>
<NavigationDrawerItem
label="Settings"
onClick={() => {
setNavigationMemorizedUrl(location.pathname + location.search);
navigate('/settings/profile');
}}
Icon={IconSettings}
/>
<NavigationDrawerItem
label="Tasks"
to="/tasks"
active={isTasksPage}
Icon={IconCheckbox}
count={currentUserDueTaskCount}
/>
</NavigationDrawerSection>
)}
<Favorites />
<NavigationDrawerSection>
<NavigationDrawerSectionTitle label="Workspace" />
<ObjectMetadataNavItems />
<NavigationDrawerItem
label="Opportunities"
to="/objects/opportunities"
active={location.pathname === '/objects/opportunities'}
Icon={IconTargetArrow}
/>
</NavigationDrawerSection>
</>
);
};

View File

@ -0,0 +1,91 @@
import { useNavigate } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import {
IconCheckbox,
IconList,
IconSearch,
IconSettings,
} from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { NavigationBar } from '@/ui/navigation/navigation-bar/components/NavigationBar';
import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState';
import { useIsSettingsPage } from '../hooks/useIsSettingsPage';
import { useIsTasksPage } from '../hooks/useIsTasksPage';
import { currentMobileNavigationDrawerState } from '../states/currentMobileNavigationDrawerState';
type NavigationBarItemName = 'main' | 'search' | 'tasks' | 'settings';
export const MobileNavigationBar = () => {
const [isCommandMenuOpened] = useRecoilState(isCommandMenuOpenedState);
const { closeCommandMenu, toggleCommandMenu } = useCommandMenu();
const isTasksPage = useIsTasksPage();
const isSettingsPage = useIsSettingsPage();
const navigate = useNavigate();
const [isNavigationDrawerOpen, setIsNavigationDrawerOpen] = useRecoilState(
isNavigationDrawerOpenState,
);
const [currentMobileNavigationDrawer, setCurrentMobileNavigationDrawer] =
useRecoilState(currentMobileNavigationDrawerState);
const activeItemName = isNavigationDrawerOpen
? currentMobileNavigationDrawer
: isCommandMenuOpened
? 'search'
: isTasksPage
? 'tasks'
: isSettingsPage
? 'settings'
: 'main';
const items: {
name: NavigationBarItemName;
Icon: IconComponent;
onClick: () => void;
}[] = [
{
name: 'main',
Icon: IconList,
onClick: () => {
closeCommandMenu();
setIsNavigationDrawerOpen(
(previousIsOpen) => activeItemName !== 'main' || !previousIsOpen,
);
setCurrentMobileNavigationDrawer('main');
},
},
{
name: 'search',
Icon: IconSearch,
onClick: () => {
setIsNavigationDrawerOpen(false);
toggleCommandMenu();
},
},
{
name: 'tasks',
Icon: IconCheckbox,
onClick: () => {
closeCommandMenu();
setIsNavigationDrawerOpen(false);
navigate('/tasks');
},
},
{
name: 'settings',
Icon: IconSettings,
onClick: () => {
closeCommandMenu();
setIsNavigationDrawerOpen(
(previousIsOpen) => activeItemName !== 'settings' || !previousIsOpen,
);
setCurrentMobileNavigationDrawer('settings');
},
},
];
return <NavigationBar activeItemName={activeItemName} items={items} />;
};

View File

@ -0,0 +1,77 @@
import { useEffect } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { Meta, StoryObj } from '@storybook/react';
import { useSetRecoilState } from 'recoil';
import { currentMobileNavigationDrawerState } from '@/navigation/states/currentMobileNavigationDrawerState';
import { AppPath } from '@/types/AppPath';
import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import {
AppNavigationDrawer,
AppNavigationDrawerProps,
} from '../AppNavigationDrawer';
const MobileNavigationDrawerStateSetterEffect = ({
mobileNavigationDrawer = 'main',
}: {
mobileNavigationDrawer?: 'main' | 'settings';
}) => {
const isMobile = useIsMobile();
const setIsNavigationDrawerOpen = useSetRecoilState(
isNavigationDrawerOpenState,
);
const setCurrentMobileNavigationDrawer = useSetRecoilState(
currentMobileNavigationDrawerState,
);
useEffect(() => {
if (!isMobile) return;
setIsNavigationDrawerOpen(true);
setCurrentMobileNavigationDrawer(mobileNavigationDrawer);
}, [
isMobile,
mobileNavigationDrawer,
setCurrentMobileNavigationDrawer,
setIsNavigationDrawerOpen,
]);
return null;
};
type StoryArgs = AppNavigationDrawerProps & {
mobileNavigationDrawer?: 'main' | 'settings';
routePath: string;
};
const meta: Meta<StoryArgs> = {
title: 'Modules/Navigation/AppNavigationDrawer',
decorators: [
(Story, { args }) => (
<MemoryRouter initialEntries={[args.routePath]}>
<Story />
<MobileNavigationDrawerStateSetterEffect
mobileNavigationDrawer={args.mobileNavigationDrawer}
/>
</MemoryRouter>
),
SnackBarDecorator,
],
component: AppNavigationDrawer,
args: { routePath: AppPath.Index },
};
export default meta;
type Story = StoryObj<StoryArgs>;
export const Main: Story = {};
export const Settings: Story = {
args: {
mobileNavigationDrawer: 'settings',
routePath: '/settings/appearance',
},
};

View File

@ -0,0 +1,4 @@
import { useLocation } from 'react-router-dom';
export const useIsSettingsPage = () =>
useLocation().pathname.match(/\/settings\//g) !== null;

View File

@ -0,0 +1,3 @@
import { useLocation } from 'react-router-dom';
export const useIsTasksPage = () => useLocation().pathname === '/tasks';

View File

@ -0,0 +1,6 @@
import { atom } from 'recoil';
export const currentMobileNavigationDrawerState = atom<'main' | 'settings'>({
key: 'currentMobileNavigationDrawerState',
default: 'main',
});