feat: create workspace from loading existing exported file (#2122)

Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
Peng Xiao
2023-05-09 15:30:01 +08:00
committed by GitHub
parent 5432aae85c
commit 7c2574b1ca
93 changed files with 2999 additions and 1406 deletions

View File

@@ -1,123 +0,0 @@
import {
Button,
Input,
Modal,
ModalCloseButton,
ModalWrapper,
styled,
} from '@affine/component';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { KeyboardEvent } from 'react';
import { useCallback, useRef, useState } from 'react';
interface ModalProps {
open: boolean;
onClose: () => void;
onCreate: (name: string) => void;
}
export const CreateWorkspaceModal = ({
open,
onClose,
onCreate,
}: ModalProps) => {
const [workspaceName, setWorkspaceName] = useState('');
const isComposition = useRef(false);
const handleCreateWorkspace = useCallback(() => {
onCreate(workspaceName);
}, [onCreate, workspaceName]);
const handleKeyDown = useCallback(
(event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter' && workspaceName && !isComposition.current) {
handleCreateWorkspace();
}
},
[handleCreateWorkspace, workspaceName]
);
const t = useAFFiNEI18N();
return (
<Modal open={open} onClose={onClose}>
<ModalWrapper width={560} height={342} style={{ padding: '10px' }}>
<Header>
<ModalCloseButton
top={6}
right={6}
onClick={() => {
onClose();
}}
/>
</Header>
<Content>
<ContentTitle>{t['New Workspace']()}</ContentTitle>
<p>{t['Workspace description']()}</p>
<Input
ref={ref => {
if (ref) {
setTimeout(() => ref.focus(), 0);
}
}}
data-testid="create-workspace-input"
onKeyDown={handleKeyDown}
placeholder={t['Set a Workspace name']()}
maxLength={15}
minLength={0}
onChange={value => {
setWorkspaceName(value);
}}
onCompositionStart={() => {
isComposition.current = true;
}}
onCompositionEnd={() => {
isComposition.current = false;
}}
/>
<Button
data-testid="create-workspace-button"
disabled={!workspaceName}
style={{
width: '260px',
textAlign: 'center',
marginTop: '16px',
opacity: !workspaceName ? 0.5 : 1,
}}
type="primary"
onClick={() => {
handleCreateWorkspace();
}}
>
{t['Create']()}
</Button>
</Content>
</ModalWrapper>
</Modal>
);
};
const Header = styled('div')({
position: 'relative',
height: '44px',
});
const Content = styled('div')(() => {
return {
padding: '0 84px',
textAlign: 'center',
fontSize: '18px',
lineHeight: '26px',
p: {
marginTop: '12px',
marginBottom: '16px',
},
};
});
const ContentTitle = styled('div')(() => {
return {
fontSize: '20px',
lineHeight: '28px',
fontWeight: 600,
textAlign: 'center',
paddingBottom: '16px',
};
});

View File

@@ -1,4 +1,6 @@
import {
Menu,
MenuItem,
Modal,
ModalCloseButton,
ModalWrapper,
@@ -9,14 +11,19 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { AccessTokenMessage } from '@affine/workspace/affine/login';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type';
import { HelpIcon, PlusIcon } from '@blocksuite/icons';
import { HelpIcon, ImportIcon, PlusIcon } from '@blocksuite/icons';
import type { DragEndEvent } from '@dnd-kit/core';
import { useCallback } from 'react';
import { useCallback, useRef } from 'react';
import type { AllWorkspace } from '../../../shared';
import { Footer } from '../footer';
import {
StyledCreateWorkspaceCard,
StyledCreateWorkspaceCardPill,
StyledCreateWorkspaceCardPillContainer,
StyledCreateWorkspaceCardPillContent,
StyledCreateWorkspaceCardPillIcon,
StyledCreateWorkspaceCardPillTextSecondary,
StyledHelperContainer,
StyledModalContent,
StyledModalHeader,
@@ -39,7 +46,8 @@ interface WorkspaceModalProps {
onClickWorkspaceSetting: (workspace: AllWorkspace) => void;
onClickLogin: () => void;
onClickLogout: () => void;
onCreateWorkspace: () => void;
onNewWorkspace: () => void;
onAddWorkspace: () => void;
onMoveWorkspace: (activeId: string, overId: string) => void;
}
@@ -53,12 +61,13 @@ export const WorkspaceListModal = ({
onClickLogout,
onClickWorkspace,
onClickWorkspaceSetting,
onCreateWorkspace,
onNewWorkspace,
onAddWorkspace,
currentWorkspaceId,
onMoveWorkspace,
}: WorkspaceModalProps) => {
const t = useAFFiNEI18N();
const anchorEL = useRef<HTMLDivElement>(null);
return (
<Modal open={open} onClose={onClose}>
<ModalWrapper
@@ -115,19 +124,96 @@ export const WorkspaceListModal = ({
[onMoveWorkspace]
)}
/>
<StyledCreateWorkspaceCard
data-testid="new-workspace"
onClick={onCreateWorkspace}
>
<StyleWorkspaceAdd className="add-icon">
<PlusIcon />
</StyleWorkspaceAdd>
{!environment.isDesktop && (
<StyledCreateWorkspaceCard
onClick={onNewWorkspace}
data-testid="new-workspace"
>
<StyleWorkspaceAdd className="add-icon">
<PlusIcon />
</StyleWorkspaceAdd>
<StyleWorkspaceInfo>
<StyleWorkspaceTitle>{t['New Workspace']()}</StyleWorkspaceTitle>
<p>{t['Create Or Import']()}</p>
</StyleWorkspaceInfo>
</StyledCreateWorkspaceCard>
<StyleWorkspaceInfo>
<StyleWorkspaceTitle>
{t['New Workspace']()}
</StyleWorkspaceTitle>
<p>{t['Create Or Import']()}</p>
</StyleWorkspaceInfo>
</StyledCreateWorkspaceCard>
)}
{environment.isDesktop && (
<Menu
placement="auto"
trigger={['click', 'hover']}
zIndex={1000}
content={
<StyledCreateWorkspaceCardPillContainer>
<StyledCreateWorkspaceCardPill>
<MenuItem
style={{
height: 'auto',
padding: '8px 12px',
}}
onClick={onNewWorkspace}
data-testid="new-workspace"
>
<StyledCreateWorkspaceCardPillContent>
<div>
<p>{t['New Workspace']()}</p>
<StyledCreateWorkspaceCardPillTextSecondary>
<p>{t['Create your own workspace']()}</p>
</StyledCreateWorkspaceCardPillTextSecondary>
</div>
<StyledCreateWorkspaceCardPillIcon>
<PlusIcon />
</StyledCreateWorkspaceCardPillIcon>
</StyledCreateWorkspaceCardPillContent>
</MenuItem>
</StyledCreateWorkspaceCardPill>
<StyledCreateWorkspaceCardPill>
<MenuItem
disabled={!environment.isDesktop}
onClick={onAddWorkspace}
data-testid="add-workspace"
style={{
height: 'auto',
padding: '8px 12px',
}}
>
<StyledCreateWorkspaceCardPillContent>
<div>
<p>{t['Add Workspace']()}</p>
<StyledCreateWorkspaceCardPillTextSecondary>
<p>{t['Add Workspace Hint']()}</p>
</StyledCreateWorkspaceCardPillTextSecondary>
</div>
<StyledCreateWorkspaceCardPillIcon>
<ImportIcon />
</StyledCreateWorkspaceCardPillIcon>
</StyledCreateWorkspaceCardPillContent>
</MenuItem>
</StyledCreateWorkspaceCardPill>
</StyledCreateWorkspaceCardPillContainer>
}
>
<StyledCreateWorkspaceCard
ref={anchorEL}
data-testid="add-or-new-workspace"
>
<StyleWorkspaceAdd className="add-icon">
<PlusIcon />
</StyleWorkspaceAdd>
<StyleWorkspaceInfo>
<StyleWorkspaceTitle>
{t['New Workspace']()}
</StyleWorkspaceTitle>
<p>{t['Create Or Import']()}</p>
</StyleWorkspaceInfo>
</StyledCreateWorkspaceCard>
</Menu>
)}
</StyledModalContent>
<Footer user={user} onLogin={onClickLogin} onLogout={onClickLogout} />

View File

@@ -64,6 +64,50 @@ export const StyledCreateWorkspaceCard = styled('div')(() => {
},
};
});
export const StyledCreateWorkspaceCardPillContainer = styled('div')(() => {
return {
padding: '12px',
borderRadius: '10px',
display: 'flex',
margin: '-8px -4px',
flexFlow: 'column',
gap: '12px',
background: 'var(--affine-background-overlay-panel-color)',
};
});
export const StyledCreateWorkspaceCardPill = styled('div')(() => {
return {
borderRadius: '5px',
display: 'flex',
boxShadow: '0px 0px 6px 0px rgba(0, 0, 0, 0.1)',
background: 'var(--affine-background-primary-color)',
};
});
export const StyledCreateWorkspaceCardPillContent = styled('div')(() => {
return {
display: 'flex',
gap: '12px',
alignItems: 'center',
justifyContent: 'space-between',
};
});
export const StyledCreateWorkspaceCardPillIcon = styled('div')(() => {
return {
fontSize: '20px',
width: '1em',
height: '1em',
};
});
export const StyledCreateWorkspaceCardPillTextSecondary = styled('div')(() => {
return {
fontSize: '12px',
color: 'var(--affine-text-secondary-color)',
};
});
export const StyledModalHeaderLeft = styled('div')(() => {
return { ...displayFlex('flex-start', 'center') };