mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat: create workspace from loading existing exported file (#2122)
Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
@@ -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',
|
||||
};
|
||||
});
|
||||
@@ -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} />
|
||||
|
||||
@@ -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') };
|
||||
|
||||
Reference in New Issue
Block a user