New page structure (#1377)

* - new page structure

* - removed unecessary task changes

* - handleClick -> onClick
This commit is contained in:
brendanlaschke 2023-08-30 15:10:16 +02:00 committed by GitHub
parent 85155a634f
commit fa33506b96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 182 additions and 282 deletions

View File

@ -0,0 +1,19 @@
import { IconButton } from '@/ui/button/components/IconButton';
import { IconPlus } from '@/ui/icon';
type OwnProps = {
onClick: () => void;
};
export function PageAddButton({ onClick }: OwnProps) {
return (
<IconButton
icon={<IconPlus size={16} />}
size="medium"
variant="secondary"
data-testid="add-button"
accent="default"
onClick={onClick}
/>
);
}

View File

@ -1,5 +1,4 @@
import { PAGE_BAR_MIN_HEIGHT } from '../page-bar/components/PageBar';
import { PAGE_BAR_MIN_HEIGHT } from './PageHeader';
import { RightDrawerContainer } from './RightDrawerContainer';
type OwnProps = {

View File

@ -0,0 +1,20 @@
import { IconButton } from '@/ui/button/components/IconButton';
import { IconHeart } from '@/ui/icon';
type OwnProps = {
isFavorite: boolean;
onClick: () => void;
};
export function PageFavoriteButton({ isFavorite, onClick }: OwnProps) {
return (
<IconButton
icon={<IconHeart size={16} />}
size="medium"
variant="secondary"
data-testid="add-button"
accent={isFavorite ? 'danger' : 'default'}
onClick={onClick}
/>
);
}

View File

@ -67,7 +67,7 @@ type OwnProps = {
title: string;
hasBackButton?: boolean;
icon: ReactNode;
children: JSX.Element | JSX.Element[];
children?: JSX.Element | JSX.Element[];
};
export function PageHeader({ title, hasBackButton, icon, children }: OwnProps) {

View File

@ -5,7 +5,7 @@ type OwnProps = {
onAddButtonClick?: () => void;
};
export function PageBarHotkeys({ onAddButtonClick }: OwnProps) {
export function PageHotkeys({ onAddButtonClick }: OwnProps) {
useScopedHotkeys('c', () => onAddButtonClick?.(), TableHotkeyScope.Table, [
onAddButtonClick,
]);

View File

@ -2,8 +2,7 @@ import styled from '@emotion/styled';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { PageBar } from '../page-bar/components/PageBar';
import { PageHeader } from './PageHeader';
import { RightDrawerContainer } from './RightDrawerContainer';
type OwnProps = {
@ -24,7 +23,7 @@ export function SubMenuTopBarContainer({ children, title, icon }: OwnProps) {
return (
<StyledContainer isMobile={isMobile}>
{isMobile && <PageBar title={title} icon={icon} />}
{isMobile && <PageHeader title={title} icon={icon} />}
<RightDrawerContainer topMargin={16}>{children}</RightDrawerContainer>
</StyledContainer>
);

View File

@ -1,53 +0,0 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
import { PAGE_BAR_MIN_HEIGHT, PageBar } from '../page-bar/components/PageBar';
import { PageBarHotkeys } from '../page-bar/components/PageBarHotkeys';
import { RightDrawerContainer } from './RightDrawerContainer';
type OwnProps = {
children: JSX.Element | JSX.Element[];
title: string;
hasBackButton?: boolean;
isFavorite?: boolean;
icon: ReactNode;
onAddButtonClick?: () => void;
onFavoriteButtonClick?: () => void;
extraButtons?: ReactNode[];
};
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;
export function WithTopBarContainer({
children,
title,
hasBackButton,
isFavorite,
icon,
onAddButtonClick,
onFavoriteButtonClick,
extraButtons,
}: OwnProps) {
return (
<StyledContainer>
<PageBarHotkeys onAddButtonClick={onAddButtonClick} />
<PageBar
title={title}
hasBackButton={hasBackButton}
isFavorite={isFavorite}
icon={icon}
onAddButtonClick={onAddButtonClick}
onFavoriteButtonClick={onFavoriteButtonClick}
extraButtons={extraButtons}
/>
<RightDrawerContainer topMargin={PAGE_BAR_MIN_HEIGHT + 16 + 16}>
{children}
</RightDrawerContainer>
</StyledContainer>
);
}

View File

@ -1,142 +0,0 @@
import { ReactNode, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { IconButton } from '@/ui/button/components/IconButton';
import { LightIconButton } from '@/ui/button/components/LightIconButton';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconChevronLeft, IconHeart, IconPlus } from '@/ui/icon/index';
import NavCollapseButton from '@/ui/navbar/components/NavCollapseButton';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { OverflowingTextWithTooltip } from '../../../tooltip/OverflowingTextWithTooltip';
import { isNavbarOpenedState } from '../../states/isNavbarOpenedState';
export const PAGE_BAR_MIN_HEIGHT = 40;
const StyledTopBarContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.noisy};
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-direction: row;
font-size: ${({ theme }) => theme.font.size.lg};
justify-content: space-between;
min-height: ${PAGE_BAR_MIN_HEIGHT}px;
padding: ${({ theme }) => theme.spacing(2)};
padding-left: 0;
padding-right: ${({ theme }) => theme.spacing(3)};
`;
const StyledLeftContainer = styled.div`
align-items: center;
display: flex;
flex-direction: row;
width: 100%;
`;
const StyledTitleContainer = styled.div`
display: flex;
font-size: ${({ theme }) => theme.font.size.md};
margin-left: ${({ theme }) => theme.spacing(1)};
max-width: 50%;
`;
const StyledTopBarButtonContainer = styled.div`
margin-right: ${({ theme }) => theme.spacing(1)};
`;
const StyledTopBarIconTitleContainer = styled.div`
align-items: center;
display: flex;
flex-direction: row;
padding-left: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
const StyledActionButtonsContainer = styled.div`
display: inline-flex;
gap: ${({ theme }) => theme.spacing(2)};
`;
type OwnProps = {
title: string;
hasBackButton?: boolean;
isFavorite?: boolean;
icon: ReactNode;
onAddButtonClick?: () => void;
onFavoriteButtonClick?: () => void;
extraButtons?: ReactNode[];
};
export function PageBar({
title,
hasBackButton,
isFavorite,
icon,
onAddButtonClick,
onFavoriteButtonClick,
extraButtons,
}: OwnProps) {
const navigate = useNavigate();
const navigateBack = useCallback(() => navigate(-1), [navigate]);
const isNavbarOpened = useRecoilValue(isNavbarOpenedState);
return (
<>
<StyledTopBarContainer>
<StyledLeftContainer>
{!isNavbarOpened && (
<StyledTopBarButtonContainer>
<NavCollapseButton direction="right" hide={true} />
</StyledTopBarButtonContainer>
)}
{hasBackButton && (
<StyledTopBarButtonContainer>
<LightIconButton
size="medium"
accent="tertiary"
icon={<IconChevronLeft />}
onClick={navigateBack}
/>
</StyledTopBarButtonContainer>
)}
<StyledTopBarIconTitleContainer>
{icon}
<StyledTitleContainer data-testid="top-bar-title">
<OverflowingTextWithTooltip text={title} />
</StyledTitleContainer>
</StyledTopBarIconTitleContainer>
</StyledLeftContainer>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<StyledActionButtonsContainer>
{onFavoriteButtonClick && (
<IconButton
icon={<IconHeart size={16} />}
size="medium"
variant="secondary"
data-testid="add-button"
accent={isFavorite ? 'danger' : 'default'}
onClick={onFavoriteButtonClick}
/>
)}
{onAddButtonClick && (
<IconButton
icon={<IconPlus size={16} />}
size="medium"
variant="secondary"
data-testid="add-button"
accent="default"
onClick={onAddButtonClick}
/>
)}
{extraButtons}
</StyledActionButtonsContainer>
</RecoilScope>
</StyledTopBarContainer>
</>
);
}

View File

@ -6,8 +6,13 @@ import { v4 } from 'uuid';
import { CompanyTable } from '@/companies/table/components/CompanyTable';
import { SEARCH_COMPANY_QUERY } from '@/search/graphql/queries/searchCompanyQuery';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { PageHotkeys } from '@/ui/layout/components/PageHotkeys';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { EntityTableContextMenu } from '@/ui/table/context-menu/components/EntityTableContextMenu';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
@ -66,22 +71,29 @@ export function Companies() {
return (
<SpreadsheetImportProvider>
<WithTopBarContainer
title="Companies"
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
onAddButtonClick={handleAddButtonClick}
>
<RecoilScope
scopeId="companies"
SpecificContext={TableRecoilScopeContext}
<PageContainer>
<PageHeader
title="Companies"
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
>
<StyledTableContainer>
<CompanyTable />
</StyledTableContainer>
<EntityTableActionBar />
<EntityTableContextMenu />
</RecoilScope>
</WithTopBarContainer>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageHotkeys onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope
scopeId="companies"
SpecificContext={TableRecoilScopeContext}
>
<StyledTableContainer>
<CompanyTable />
</StyledTableContainer>
<EntityTableActionBar />
<EntityTableContextMenu />
</RecoilScope>
</PageBody>
</PageContainer>
</SpreadsheetImportProvider>
);
}

View File

@ -3,7 +3,9 @@ import styled from '@emotion/styled';
import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
@ -16,17 +18,18 @@ export function CompaniesMockMode() {
const theme = useTheme();
return (
<>
<WithTopBarContainer
<PageContainer>
<PageHeader
title="Companies"
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
>
/>
<PageBody>
<RecoilScope SpecificContext={TableRecoilScopeContext}>
<StyledTableContainer>
<CompanyTableMockMode />
</StyledTableContainer>
</RecoilScope>
</WithTopBarContainer>
</>
</PageBody>
</PageContainer>
);
}

View File

@ -5,13 +5,17 @@ import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargeta
import { CompanyTeam } from '@/companies/components/CompanyTeam';
import { useCompanyQuery } from '@/companies/hooks/useCompanyQuery';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { GenericEditableField } from '@/ui/editable-field/components/GenericEditableField';
import { EditableFieldDefinitionContext } from '@/ui/editable-field/contexts/EditableFieldDefinitionContext';
import { EditableFieldEntityIdContext } from '@/ui/editable-field/contexts/EditableFieldEntityIdContext';
import { EditableFieldMutationContext } from '@/ui/editable-field/contexts/EditableFieldMutationContext';
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageFavoriteButton } from '@/ui/layout/components/PageFavoriteButton';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
@ -46,24 +50,28 @@ export function CompanyShow() {
}
return (
<>
<PageContainer>
<PageTitle title={company.name || 'No Name'} />
<WithTopBarContainer
<PageHeader
title={company.name ?? ''}
hasBackButton
isFavorite={isFavorite}
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
onFavoriteButtonClick={handleFavoriteButtonClick}
extraButtons={[
>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: company.id,
type: ActivityTargetableEntityType.Company,
}}
/>,
]}
>
/>
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope SpecificContext={ShowPageRecoilScopeContext}>
<ShowPageContainer>
<ShowPageLeftContainer>
@ -110,7 +118,7 @@ export function CompanyShow() {
/>
</ShowPageContainer>
</RecoilScope>
</WithTopBarContainer>
</>
</PageBody>
</PageContainer>
);
}

View File

@ -4,8 +4,13 @@ import { v4 } from 'uuid';
import { PeopleTable } from '@/people/table/components/PeopleTable';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconUser } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { PageHotkeys } from '@/ui/layout/components/PageHotkeys';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { EntityTableContextMenu } from '@/ui/table/context-menu/components/EntityTableContextMenu';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
@ -58,19 +63,29 @@ export function People() {
return (
<SpreadsheetImportProvider>
<RecoilScope scopeId="people" SpecificContext={TableRecoilScopeContext}>
<WithTopBarContainer
<PageContainer>
<PageHeader
title="People"
icon={<IconUser size={theme.icon.size.sm} />}
onAddButtonClick={handleAddButtonClick}
icon={<IconUser size={theme.icon.size.md} />}
>
<StyledTableContainer>
<PeopleTable />
</StyledTableContainer>
<EntityTableActionBar />
<EntityTableContextMenu />
</WithTopBarContainer>
</RecoilScope>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageHotkeys onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope
scopeId="people"
SpecificContext={TableRecoilScopeContext}
>
<StyledTableContainer>
<PeopleTable />
</StyledTableContainer>
<EntityTableActionBar />
<EntityTableContextMenu />
</RecoilScope>
</PageBody>
</PageContainer>
</SpreadsheetImportProvider>
);
}

View File

@ -6,13 +6,17 @@ import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargeta
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { GET_PERSON } from '@/people/graphql/queries/getPerson';
import { usePersonQuery } from '@/people/hooks/usePersonQuery';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { GenericEditableField } from '@/ui/editable-field/components/GenericEditableField';
import { EditableFieldDefinitionContext } from '@/ui/editable-field/contexts/EditableFieldDefinitionContext';
import { EditableFieldEntityIdContext } from '@/ui/editable-field/contexts/EditableFieldEntityIdContext';
import { EditableFieldMutationContext } from '@/ui/editable-field/contexts/EditableFieldMutationContext';
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
import { IconUser } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageFavoriteButton } from '@/ui/layout/components/PageFavoriteButton';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
@ -64,24 +68,28 @@ export function PersonShow() {
}
return (
<>
<PageContainer>
<PageTitle title={person.displayName || 'No Name'} />
<WithTopBarContainer
<PageHeader
title={person.firstName ?? ''}
icon={<IconUser size={theme.icon.size.md} />}
hasBackButton
isFavorite={isFavorite}
onFavoriteButtonClick={handleFavoriteButtonClick}
extraButtons={[
>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: person.id,
type: ActivityTargetableEntityType.Person,
}}
/>,
]}
>
/>
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope SpecificContext={ShowPageRecoilScopeContext}>
<ShowPageContainer>
<ShowPageLeftContainer>
@ -130,7 +138,7 @@ export function PersonShow() {
/>
</ShowPageContainer>
</RecoilScope>
</WithTopBarContainer>
</>
</PageBody>
</PageContainer>
);
}

View File

@ -4,10 +4,14 @@ import styled from '@emotion/styled';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext';
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { FilterDropdownButton } from '@/ui/filter-n-sort/components/FilterDropdownButton';
import { FiltersHotkeyScope } from '@/ui/filter-n-sort/types/FiltersHotkeyScope';
import { IconArchive, IconCheck, IconCheckbox } from '@/ui/icon/index';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { TabList } from '@/ui/tab/components/TabList';
import { TopBar } from '@/ui/top-bar/TopBar';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
@ -45,30 +49,38 @@ export function Tasks() {
];
return (
<WithTopBarContainer
title="Tasks"
onAddButtonClick={() => openCreateActivity(ActivityType.Task)}
icon={<IconCheckbox size={theme.icon.size.md} />}
>
<StyledTasksContainer>
<RecoilScope SpecificContext={TasksRecoilScopeContext}>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList context={TasksRecoilScopeContext} tabs={TASK_TABS} />
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
context={TasksRecoilScopeContext}
HotkeyScope={FiltersHotkeyScope.FilterDropdownButton}
/>
}
<PageContainer>
<PageHeader
title="Tasks"
icon={<IconCheckbox size={theme.icon.size.md} />}
>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageAddButton
onClick={() => openCreateActivity(ActivityType.Task)}
/>
<TaskGroups />
</RecoilScope>
</StyledTasksContainer>
</WithTopBarContainer>
</PageHeader>
<PageBody>
<StyledTasksContainer>
<RecoilScope SpecificContext={TasksRecoilScopeContext}>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList context={TasksRecoilScopeContext} tabs={TASK_TABS} />
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
context={TasksRecoilScopeContext}
HotkeyScope={FiltersHotkeyScope.FilterDropdownButton}
/>
}
/>
<TaskGroups />
</RecoilScope>
</StyledTasksContainer>
</PageBody>
</PageContainer>
);
}