Files
AFFiNE/apps/web/src/pages/public-workspace/[workspaceId]/[pageId].tsx
T

151 lines
4.0 KiB
TypeScript

import { displayFlex, styled } from '@affine/component';
import { Breadcrumbs } from '@affine/component';
import { IconButton } from '@affine/component';
import { useTranslation } from '@affine/i18n';
import { useDataCenterPublicWorkspace } from '@affine/store';
import { PaperIcon, SearchIcon } from '@blocksuite/icons';
import dynamic from 'next/dynamic';
import NextLink from 'next/link';
import { useRouter } from 'next/router';
import { ReactElement, useEffect, useMemo } from 'react';
import { PageLoading } from '@/components/loading';
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
import { useModal } from '@/store/globalModal';
import type { NextPageWithLayout } from '../..//_app';
const DynamicBlocksuite = dynamic(() => import('@/components/editor'), {
ssr: false,
});
const Page: NextPageWithLayout = () => {
const router = useRouter();
const { workspaceId, pageId } = router.query;
const { error, workspace: workspaceUnit } = useDataCenterPublicWorkspace(
typeof workspaceId === 'string' ? workspaceId : null
);
const { triggerQuickSearchModal } = useModal();
const { t } = useTranslation();
const page = useMemo(() => {
if (typeof pageId !== 'string') {
return null;
}
if (workspaceUnit?.blocksuiteWorkspace) {
return workspaceUnit.blocksuiteWorkspace.getPage(pageId);
}
return null;
}, [workspaceUnit, pageId]);
const workspace = workspaceUnit?.blocksuiteWorkspace;
const pageTitle = page?.meta.title;
const workspaceName = workspace?.meta.name;
useEffect(() => {
const pageNotFound = workspace?.meta.pageMetas.every(p => p.id !== pageId);
if (workspace && pageNotFound) {
router.push('/404');
}
}, [workspace, router, pageId]);
useEffect(() => {
if (error) {
router.push('/404');
}
}, [router, error]);
if (!workspace) {
return <PageLoading />;
}
return (
<PageContainer>
<NavContainer>
<Breadcrumbs>
<StyledBreadcrumbs href={`/public-workspace/${workspaceId}`}>
<WorkspaceUnitAvatar
size={24}
name={workspaceName}
workspaceUnit={workspaceUnit}
/>
<span>{workspaceName}</span>
</StyledBreadcrumbs>
<StyledBreadcrumbs
href={`/public-workspace/${workspaceId}/${pageId}`}
>
<PaperIcon fontSize={24} />
<span>{pageTitle ? pageTitle : t('Untitled')}</span>
</StyledBreadcrumbs>
</Breadcrumbs>
<SearchButton
onClick={() => {
triggerQuickSearchModal();
}}
>
<SearchIcon />
</SearchButton>
</NavContainer>
{page && (
<DynamicBlocksuite
page={page}
workspace={workspace}
setEditor={editor => {
editor.readonly = true;
}}
/>
)}
</PageContainer>
);
};
Page.getLayout = function getLayout(page: ReactElement) {
return <div>{page}</div>;
};
export default Page;
export const PageContainer = styled.div(({ theme }) => {
return {
height: '100vh',
overflowY: 'auto',
backgroundColor: theme.colors.pageBackground,
};
});
export const NavContainer = styled.div(({ theme }) => {
return {
width: '100vw',
padding: '0 12px',
height: '60px',
...displayFlex('start', 'center'),
backgroundColor: theme.colors.pageBackground,
};
});
export const StyledBreadcrumbs = styled(NextLink)(({ theme }) => {
return {
flex: 1,
...displayFlex('center', 'center'),
paddingLeft: '12px',
span: {
padding: '0 12px',
fontSize: theme.font.base,
lineHeight: theme.font.lineHeight,
},
':hover': { color: theme.colors.primaryColor },
transition: 'all .15s',
':visited': {
color: theme.colors.popoverColor,
':hover': { color: theme.colors.primaryColor },
},
};
});
export const SearchButton = styled(IconButton)(({ theme }) => {
return {
color: theme.colors.iconColor,
fontSize: '24px',
marginLeft: 'auto',
padding: '0 24px',
};
});