From 6ea20e477bca00be0b6c661d03889b21fbb82a06 Mon Sep 17 00:00:00 2001 From: JimmFly <447268514@qq.com> Date: Wed, 10 Apr 2024 07:27:02 +0000 Subject: [PATCH] feat(core): add sign in to not found page (#6496) close AFF-211 --- .../affine-other-page-layout/index.css.ts | 25 ++++- .../affine-other-page-layout/layout.tsx | 36 +++--- .../mobile-navbar.tsx | 2 +- .../auth-components/auth-page-container.tsx | 20 +--- .../components/auth-components/share.css.ts | 16 ++- .../not-found-page/not-found-page.tsx | 105 +++++++++++++----- .../components/not-found-page/styles.css.ts | 2 +- .../component/src/ui/empty/empty-svg.tsx | 10 +- .../frontend/component/src/ui/empty/empty.tsx | 22 +++- .../component/src/ui/empty/index.css.ts | 24 ++++ .../frontend/component/src/ui/empty/style.ts | 19 ---- .../components/workspace-upgrade/upgrade.tsx | 15 +-- packages/frontend/core/src/pages/404.tsx | 38 +++++-- packages/frontend/core/src/pages/sign-in.tsx | 31 ++++-- .../workspace/detail-page/detail-page.tsx | 2 +- .../core/src/pages/workspace/index.tsx | 3 +- 16 files changed, 245 insertions(+), 125 deletions(-) create mode 100644 packages/frontend/component/src/ui/empty/index.css.ts delete mode 100644 packages/frontend/component/src/ui/empty/style.ts diff --git a/packages/frontend/component/src/components/affine-other-page-layout/index.css.ts b/packages/frontend/component/src/components/affine-other-page-layout/index.css.ts index 863abcabd9..bffdf0e7f0 100644 --- a/packages/frontend/component/src/components/affine-other-page-layout/index.css.ts +++ b/packages/frontend/component/src/components/affine-other-page-layout/index.css.ts @@ -17,11 +17,12 @@ export const topNav = style({ left: 0, right: 0, display: 'flex', + position: 'fixed', alignItems: 'center', justifyContent: 'space-between', padding: '16px 120px', - selectors: { - '&.mobile': { + '@media': { + 'screen and (max-width: 1024px)': { padding: '16px 20px', }, }, @@ -29,6 +30,11 @@ export const topNav = style({ export const topNavLinks = style({ display: 'flex', columnGap: 4, + '@media': { + 'screen and (max-width: 1024px)': { + display: 'none', + }, + }, }); export const topNavLink = style({ color: cssVar('textPrimaryColor'), @@ -46,6 +52,21 @@ export const iconButton = style({ }, }, }); +export const hideInWideScreen = style({ + '@media': { + 'screen and (min-width: 1024px)': { + display: 'none', + position: 'absolute', + }, + }, +}); +export const hideInSmallScreen = style({ + '@media': { + 'screen and (max-width: 1024px)': { + display: 'none', + }, + }, +}); export const menu = style({ width: '100vw', height: '100vh', diff --git a/packages/frontend/component/src/components/affine-other-page-layout/layout.tsx b/packages/frontend/component/src/components/affine-other-page-layout/layout.tsx index c58891324c..f5128aad39 100644 --- a/packages/frontend/component/src/components/affine-other-page-layout/layout.tsx +++ b/packages/frontend/component/src/components/affine-other-page-layout/layout.tsx @@ -1,7 +1,6 @@ import { Button } from '@affine/component/ui/button'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { Logo1Icon } from '@blocksuite/icons'; -import clsx from 'clsx'; import { useCallback } from 'react'; import { DesktopNavbar } from './desktop-navbar'; @@ -9,10 +8,8 @@ import * as styles from './index.css'; import { MobileNavbar } from './mobile-navbar'; export const AffineOtherPageLayout = ({ - isSmallScreen, children, }: { - isSmallScreen: boolean; children: React.ReactNode; }) => { const t = useAFFiNEI18N(); @@ -23,25 +20,22 @@ export const AffineOtherPageLayout = ({ return (
-
- - - - {isSmallScreen ? ( + {environment.isDesktop ? null : ( +
+ + + + + + - ) : ( - <> - - - - )} -
+
+ )} {children}
diff --git a/packages/frontend/component/src/components/affine-other-page-layout/mobile-navbar.tsx b/packages/frontend/component/src/components/affine-other-page-layout/mobile-navbar.tsx index 1d544b27fd..5cebda88d7 100644 --- a/packages/frontend/component/src/components/affine-other-page-layout/mobile-navbar.tsx +++ b/packages/frontend/component/src/components/affine-other-page-layout/mobile-navbar.tsx @@ -29,7 +29,7 @@ export const MobileNavbar = () => { ); return ( -
+
> = ({ children, title, subtitle }) => { - const [isSmallScreen, setIsSmallScreen] = useState(false); - - useEffect(() => { - const checkScreenSize = () => { - setIsSmallScreen(window.innerWidth <= 1024); - }; - checkScreenSize(); - window.addEventListener('resize', checkScreenSize); - return () => window.removeEventListener('resize', checkScreenSize); - }, []); - return ( - +
@@ -28,7 +16,9 @@ export const AuthPageContainer: FC<

{subtitle}

{children}
- {isSmallScreen ? null : } +
+ +
diff --git a/packages/frontend/component/src/components/auth-components/share.css.ts b/packages/frontend/component/src/components/auth-components/share.css.ts index d3b4827201..0a4ed1bbd7 100644 --- a/packages/frontend/component/src/components/auth-components/share.css.ts +++ b/packages/frontend/component/src/components/auth-components/share.css.ts @@ -179,8 +179,12 @@ globalStyle(`${authPageContainer} a`, { color: cssVar('linkColor'), }); export const signInPageContainer = style({ - width: '400px', - margin: '205px auto 0', + height: '100vh', + width: '100%', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', }); export const input = style({ width: '330px', @@ -190,3 +194,11 @@ export const input = style({ }, }, }); + +export const hideInSmallScreen = style({ + '@media': { + 'screen and (max-width: 1024px)': { + display: 'none', + }, + }, +}); diff --git a/packages/frontend/component/src/components/not-found-page/not-found-page.tsx b/packages/frontend/component/src/components/not-found-page/not-found-page.tsx index 6506b64be9..1646f05432 100644 --- a/packages/frontend/component/src/components/not-found-page/not-found-page.tsx +++ b/packages/frontend/component/src/components/not-found-page/not-found-page.tsx @@ -4,6 +4,7 @@ import { SignOutIcon } from '@blocksuite/icons'; import { Avatar } from '../../ui/avatar'; import { Button, IconButton } from '../../ui/button'; import { Tooltip } from '../../ui/tooltip'; +import { AffineOtherPageLayout } from '../affine-other-page-layout'; import type { User } from '../auth-components'; import { NotFoundPattern } from './not-found-pattern'; import { @@ -14,9 +15,57 @@ import { export interface NotFoundPageProps { user?: User | null; + signInComponent?: JSX.Element; onBack: () => void; onSignOut: () => void; } +export const NoPermissionOrNotFound = ({ + user, + onBack, + onSignOut, + signInComponent, +}: NotFoundPageProps) => { + const t = useAFFiNEI18N(); + + return ( + +
+
+ {user ? ( + <> +
+ +
+

{t['404.hint']()}

+
+ +
+
+ + {user.email} + + + + + +
+ + ) : ( + signInComponent + )} +
+
+
+ ); +}; + export const NotFoundPage = ({ user, onBack, @@ -25,35 +74,37 @@ export const NotFoundPage = ({ const t = useAFFiNEI18N(); return ( -
-
-
- -
-

{t['404.hint']()}

-
- -
- - {user ? ( + +
+
- - {user.email} - - - - - +
- ) : null} +

{t['404.hint']()}

+
+ +
+ + {user ? ( +
+ + {user.email} + + + + + +
+ ) : null} +
-
+ ); }; diff --git a/packages/frontend/component/src/components/not-found-page/styles.css.ts b/packages/frontend/component/src/components/not-found-page/styles.css.ts index 19035bd35c..825d6d6909 100644 --- a/packages/frontend/component/src/components/not-found-page/styles.css.ts +++ b/packages/frontend/component/src/components/not-found-page/styles.css.ts @@ -3,7 +3,7 @@ import { style } from '@vanilla-extract/css'; export const notFoundPageContainer = style({ fontSize: cssVar('fontBase'), color: cssVar('textPrimaryColor'), - height: '100%', + height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', diff --git a/packages/frontend/component/src/ui/empty/empty-svg.tsx b/packages/frontend/component/src/ui/empty/empty-svg.tsx index ec91fb1b1a..2ab35adc82 100644 --- a/packages/frontend/component/src/ui/empty/empty-svg.tsx +++ b/packages/frontend/component/src/ui/empty/empty-svg.tsx @@ -1,8 +1,16 @@ import { memo } from 'react'; -export const EmptySvg = memo(function EmptySvg() { +export const EmptySvg = memo(function EmptySvg({ + style, + className, +}: { + style?: React.CSSProperties; + className?: string; +}) { return ( { + const cssVar = assignInlineVars({ + [styles.svgWidth]: containerStyle?.width, + [styles.svgHeight]: containerStyle?.height, + [styles.svgFontSize]: containerStyle?.fontSize, + }); return ( - +
- +
{title && (

)} - +

); }; diff --git a/packages/frontend/component/src/ui/empty/index.css.ts b/packages/frontend/component/src/ui/empty/index.css.ts new file mode 100644 index 0000000000..0556e22db9 --- /dev/null +++ b/packages/frontend/component/src/ui/empty/index.css.ts @@ -0,0 +1,24 @@ +import { createVar, style } from '@vanilla-extract/css'; + +import { displayFlex } from '../../styles'; + +export const svgWidth = createVar(); +export const svgHeight = createVar(); +export const svgFontSize = createVar(); + +export const emptyContainer = style({ + height: '100%', + ...displayFlex('center', 'center'), + flexDirection: 'column', + color: 'var(--affine-text-secondary-color)', +}); +export const emptySvg = style({ + vars: { + [svgWidth]: '248px', + [svgHeight]: '216px', + [svgFontSize]: 'inherit', + }, + width: svgWidth, + height: svgHeight, + fontSize: svgFontSize, +}); diff --git a/packages/frontend/component/src/ui/empty/style.ts b/packages/frontend/component/src/ui/empty/style.ts deleted file mode 100644 index faa1d8dbe9..0000000000 --- a/packages/frontend/component/src/ui/empty/style.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { CSSProperties } from 'react'; - -import { displayFlex, styled } from '../../styles'; - -export const StyledEmptyContainer = styled('div')<{ style?: CSSProperties }>(({ - style, -}) => { - return { - height: '100%', - ...displayFlex('center', 'center'), - flexDirection: 'column', - color: 'var(--affine-text-secondary-color)', - svg: { - width: style?.width ?? '248px', - height: style?.height ?? '216px', - fontSize: style?.fontSize ?? 'inherit', - }, - }; -}); diff --git a/packages/frontend/core/src/components/workspace-upgrade/upgrade.tsx b/packages/frontend/core/src/components/workspace-upgrade/upgrade.tsx index 1052f68c3e..1a884beb9d 100644 --- a/packages/frontend/core/src/components/workspace-upgrade/upgrade.tsx +++ b/packages/frontend/core/src/components/workspace-upgrade/upgrade.tsx @@ -1,13 +1,11 @@ import { Button } from '@affine/component/ui/button'; import { AffineShapeIcon } from '@affine/core/components/page-list'; // TODO: import from page-list temporarily, need to defined common svg icon/images management. import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; -import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper'; import { useWorkspaceStatus } from '@affine/core/hooks/use-workspace-status'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useService, Workspace, WorkspaceManager } from '@toeverything/infra'; import { useState } from 'react'; -import { WorkspaceSubPath } from '../../shared'; import { mixpanel } from '../../utils'; import * as styles from './upgrade.css'; import { ArrowCircleIcon, HeartBreakIcon } from './upgrade-icon'; @@ -20,7 +18,6 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() { const currentWorkspace = useService(Workspace); const workspaceManager = useService(WorkspaceManager); const upgradeStatus = useWorkspaceStatus(currentWorkspace, s => s.upgrade); - const { openPage } = useNavigateHelper(); const t = useAFFiNEI18N(); const onButtonClick = useAsyncCallback(async () => { @@ -36,7 +33,10 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() { const newWorkspace = await currentWorkspace.upgrade.upgrade(workspaceManager); if (newWorkspace) { - openPage(newWorkspace.id, WorkspaceSubPath.ALL); + location.pathname = `/workspace/${newWorkspace.id}/all`; + //FIXME: use openPage will cause a bug, which will cause the 'v1 to v4' test fail. + // params.workspaceId will not be updated, so the page will not be re-rendered and still show the 404 page. + // openPage(newWorkspace.id, WorkspaceSubPath.ALL); } else { // blocksuite may enter an incorrect state, reload to reset it. location.reload(); @@ -44,12 +44,7 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() { } catch (error) { setError(error instanceof Error ? error.message : '' + error); } - }, [ - upgradeStatus?.upgrading, - currentWorkspace.upgrade, - workspaceManager, - openPage, - ]); + }, [upgradeStatus?.upgrading, currentWorkspace.upgrade, workspaceManager]); return (
diff --git a/packages/frontend/core/src/pages/404.tsx b/packages/frontend/core/src/pages/404.tsx index 8d112e5c92..de1fa48338 100644 --- a/packages/frontend/core/src/pages/404.tsx +++ b/packages/frontend/core/src/pages/404.tsx @@ -1,4 +1,7 @@ -import { NotFoundPage } from '@affine/component/not-found-page'; +import { + NoPermissionOrNotFound, + NotFoundPage, +} from '@affine/component/not-found-page'; import { useSession } from '@affine/core/hooks/affine/use-current-user'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import type { ReactElement } from 'react'; @@ -7,10 +10,16 @@ import { useCallback, useState } from 'react'; import { SignOutModal } from '../components/affine/sign-out-modal'; import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper'; import { signOutCloud } from '../utils/cloud-utils'; +import { SignIn } from './sign-in'; -export const PageNotFound = (): ReactElement => { +export const PageNotFound = ({ + noPermission, +}: { + noPermission?: boolean; +}): ReactElement => { const { user } = useSession(); const { jumpToIndex } = useNavigateHelper(); + const { reload } = useSession(); const [open, setOpen] = useState(false); const handleBackButtonClick = useCallback( @@ -24,15 +33,26 @@ export const PageNotFound = (): ReactElement => { const onConfirmSignOut = useAsyncCallback(async () => { setOpen(false); - await signOutCloud('/signIn'); - }, [setOpen]); + await signOutCloud(); + await reload(); + }, [reload]); return ( <> - + {noPermission ? ( + } + /> + ) : ( + + )} + { +export const SignIn = () => { const paymentRedirectRef = useRef<'redirect' | 'ignore' | null>(null); const [{ state, email = '', emailType = 'changePassword' }, setAuthAtom] = useAtom(authAtom); @@ -87,14 +88,26 @@ export const Component = () => { return ( - +
+ +
); }; + +export const Component = () => { + return ( + +
+ +
+
+ ); +}; diff --git a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx index 7982f4ed74..89d79a6907 100644 --- a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx +++ b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx @@ -331,7 +331,7 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => { // if sync engine has been synced and the page is null, show 404 page. if (pageListReady && !page) { - return ; + return ; } if (!page) { diff --git a/packages/frontend/core/src/pages/workspace/index.tsx b/packages/frontend/core/src/pages/workspace/index.tsx index 6e72b8c1eb..37078128a4 100644 --- a/packages/frontend/core/src/pages/workspace/index.tsx +++ b/packages/frontend/core/src/pages/workspace/index.tsx @@ -77,9 +77,8 @@ export const Component = (): ReactElement => { // if listLoading is false, we can show 404 page, otherwise we should show loading page. if (listLoading === false && meta === undefined) { - return ; + return ; } - if (!workspace) { return ; }