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,9 @@
import { LightButton } from '@/ui/input/button/components/LightButton';
type CancelButtonProps = {
onCancel?: () => void;
};
export const CancelButton = ({ onCancel }: CancelButtonProps) => {
return <LightButton title="Cancel" accent="tertiary" onClick={onCancel} />;
};

View File

@ -0,0 +1,29 @@
import styled from '@emotion/styled';
import { CancelButton } from './CancelButton';
import { SaveButton } from './SaveButton';
const StyledContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;
type SaveAndCancelButtonsProps = {
onSave?: () => void;
onCancel?: () => void;
isSaveDisabled?: boolean;
};
export const SaveAndCancelButtons = ({
onSave,
onCancel,
isSaveDisabled,
}: SaveAndCancelButtonsProps) => {
return (
<StyledContainer>
<CancelButton onCancel={onCancel} />
<SaveButton onSave={onSave} disabled={isSaveDisabled} />
</StyledContainer>
);
};

View File

@ -0,0 +1,21 @@
import { Button } from '@/ui/input/button/components/Button';
import { IconDeviceFloppy } from '@/ui/input/constants/icons';
type SaveButtonProps = {
onSave?: () => void;
disabled?: boolean;
};
export const SaveButton = ({ onSave, disabled }: SaveButtonProps) => {
return (
<Button
title="Save"
variant="primary"
size="small"
accent="blue"
disabled={disabled}
onClick={onSave}
Icon={IconDeviceFloppy}
/>
);
};

View File

@ -0,0 +1,9 @@
import styled from '@emotion/styled';
const StyledSettingsHeaderContainer = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
`;
export { StyledSettingsHeaderContainer as SettingsHeaderContainer };

View File

@ -0,0 +1,79 @@
import { ReactNode } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconChevronRight } from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { SoonPill } from '@/ui/display/pill/components/SoonPill';
import { Card } from '@/ui/layout/card/components/Card';
type SettingsNavigationCardProps = {
children: ReactNode;
disabled?: boolean;
hasSoonPill?: boolean;
Icon: IconComponent;
onClick?: () => void;
title: string;
};
const StyledCard = styled(Card)<{
disabled?: boolean;
onClick?: () => void;
}>`
color: ${({ theme }) => theme.font.color.tertiary};
cursor: ${({ disabled, onClick }) =>
disabled ? 'not-allowed' : onClick ? 'pointer' : 'default'};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding-bottom: ${({ theme }) => theme.spacing(4)};
padding-top: ${({ theme }) => theme.spacing(4)};
`;
const StyledHeader = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
`;
const StyledTitle = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
flex: 1 0 auto;
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(2)};
justify-content: flex-start;
`;
const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.light};
`;
const StyledDescription = styled.div`
padding-left: ${({ theme }) => theme.spacing(8)};
`;
export const SettingsNavigationCard = ({
children,
disabled,
hasSoonPill,
Icon,
onClick,
title,
}: SettingsNavigationCardProps) => {
const theme = useTheme();
return (
<StyledCard disabled={disabled} onClick={onClick}>
<StyledHeader>
<Icon size={theme.icon.size.lg} stroke={theme.icon.stroke.sm} />
<StyledTitle>
{title}
{hasSoonPill && <SoonPill />}
</StyledTitle>
<StyledIconChevronRight size={theme.icon.size.sm} />
</StyledHeader>
<StyledDescription>{children}</StyledDescription>
</StyledCard>
);
};

View File

@ -0,0 +1,152 @@
import { useCallback } from 'react';
import { useMatch, useNavigate, useResolvedPath } from 'react-router-dom';
import { useAuth } from '@/auth/hooks/useAuth';
import { AppPath } from '@/types/AppPath';
import {
IconAt,
IconCalendarEvent,
IconColorSwatch,
IconHierarchy2,
IconLogout,
IconMail,
IconRobot,
IconSettings,
IconUserCircle,
IconUsers,
} from '@/ui/display/icon';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { NavigationDrawerItemGroup } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup';
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
export const SettingsNavigationDrawerItems = () => {
const navigate = useNavigate();
const { signOut } = useAuth();
const handleLogout = useCallback(() => {
signOut();
navigate(AppPath.SignIn);
}, [signOut, navigate]);
const isMessagingEnabled = useIsFeatureEnabled('IS_MESSAGING_ENABLED');
const isAccountsItemActive = !!useMatch({
path: useResolvedPath('/settings/accounts').pathname,
end: true,
});
const isAccountsEmailsItemActive = !!useMatch({
path: useResolvedPath('/settings/accounts/emails').pathname,
end: true,
});
return (
<>
<NavigationDrawerSection>
<NavigationDrawerSectionTitle label="User" />
<NavigationDrawerItem
label="Profile"
to="/settings/profile"
Icon={IconUserCircle}
active={
!!useMatch({
path: useResolvedPath('/settings/profile').pathname,
end: true,
})
}
/>
<NavigationDrawerItem
label="Appearance"
to="/settings/profile/appearance"
Icon={IconColorSwatch}
active={
!!useMatch({
path: useResolvedPath('/settings/profile/appearance').pathname,
end: true,
})
}
/>
{isMessagingEnabled && (
<NavigationDrawerItemGroup>
<NavigationDrawerItem
label="Accounts"
to="/settings/accounts"
Icon={IconAt}
active={isAccountsItemActive}
/>
<NavigationDrawerItem
level={2}
label="Emails"
to="/settings/accounts/emails"
Icon={IconMail}
active={isAccountsEmailsItemActive}
/>
<NavigationDrawerItem
level={2}
label="Calendars"
Icon={IconCalendarEvent}
soon
/>
</NavigationDrawerItemGroup>
)}
</NavigationDrawerSection>
<NavigationDrawerSection>
<NavigationDrawerSectionTitle label="Workspace" />
<NavigationDrawerItem
label="General"
to="/settings/workspace"
Icon={IconSettings}
active={
!!useMatch({
path: useResolvedPath('/settings/workspace').pathname,
end: true,
})
}
/>
<NavigationDrawerItem
label="Members"
to="/settings/workspace-members"
Icon={IconUsers}
active={
!!useMatch({
path: useResolvedPath('/settings/workspace-members').pathname,
end: true,
})
}
/>
<NavigationDrawerItem
label="Data model"
to="/settings/objects"
Icon={IconHierarchy2}
active={
!!useMatch({
path: useResolvedPath('/settings/objects').pathname,
end: false,
})
}
/>
<NavigationDrawerItem
label="Developers"
to="/settings/developers/api-keys"
Icon={IconRobot}
active={
!!useMatch({
path: useResolvedPath('/settings/developers/api-keys').pathname,
end: true,
})
}
/>
</NavigationDrawerSection>
<NavigationDrawerSection>
<NavigationDrawerSectionTitle label="Other" />
<NavigationDrawerItem
label="Logout"
onClick={handleLogout}
Icon={IconLogout}
/>
</NavigationDrawerSection>
</>
);
};

View File

@ -0,0 +1,14 @@
import styled from '@emotion/styled';
import { objectSettingsWidth } from '../data-model/constants/objectSettings';
const StyledSettingsPageContainer = styled.div<{ width?: number }>`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(8)};
overflow: auto;
padding: ${({ theme }) => theme.spacing(8)};
width: ${({ width }) => (width ? width + 'px' : objectSettingsWidth)};
`;
export { StyledSettingsPageContainer as SettingsPageContainer };

View File

@ -0,0 +1,20 @@
import { Meta, StoryObj } from '@storybook/react';
import { CancelButton } from '../SaveAndCancelButtons/CancelButton';
const meta: Meta<typeof CancelButton> = {
title: 'Modules/Settings/CancelButton',
component: CancelButton,
};
export default meta;
type Story = StoryObj<typeof CancelButton>;
export const Default: Story = {
argTypes: {
onCancel: { control: false },
},
args: {
onCancel: () => {},
},
};

View File

@ -0,0 +1,31 @@
import { Meta, StoryObj } from '@storybook/react';
import { SaveButton } from '../SaveAndCancelButtons/SaveButton';
const meta: Meta<typeof SaveButton> = {
title: 'Modules/Settings/SaveButton',
component: SaveButton,
};
export default meta;
type Story = StoryObj<typeof SaveButton>;
export const Default: Story = {
argTypes: {
onSave: { control: false },
},
args: {
onSave: () => {},
disabled: false,
},
};
export const Disabled: Story = {
argTypes: {
onSave: { control: false },
},
args: {
onSave: () => {},
disabled: true,
},
};