mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-30 00:29:46 +08:00
feat: create workspace from loading existing exported file (#2122)
Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
// import { styled } from '@affine/component';
|
||||
// import { FlexWrapper } from '@affine/component';
|
||||
|
||||
import { globalStyle, style, styleVariants } from '@vanilla-extract/css';
|
||||
|
||||
export const container = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '52px 52px 0 52px',
|
||||
height: 'calc(100vh - 52px)',
|
||||
});
|
||||
|
||||
export const sidebar = style({
|
||||
marginTop: '52px',
|
||||
});
|
||||
|
||||
export const content = style({
|
||||
overflow: 'auto',
|
||||
flex: 1,
|
||||
marginTop: '40px',
|
||||
});
|
||||
|
||||
const baseAvatar = style({
|
||||
position: 'relative',
|
||||
marginRight: '20px',
|
||||
cursor: 'pointer',
|
||||
});
|
||||
|
||||
globalStyle(`${baseAvatar} .camera-icon`, {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
display: 'none',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: 'rgba(60, 61, 63, 0.5)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
zIndex: 10,
|
||||
});
|
||||
|
||||
globalStyle(`${baseAvatar}:hover .camera-icon`, {
|
||||
display: 'flex',
|
||||
});
|
||||
|
||||
export const avatar = styleVariants({
|
||||
disabled: [
|
||||
baseAvatar,
|
||||
{
|
||||
cursor: 'default',
|
||||
},
|
||||
],
|
||||
enabled: [
|
||||
baseAvatar,
|
||||
{
|
||||
cursor: 'pointer',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const baseTagItem = style({
|
||||
display: 'flex',
|
||||
margin: '0 48px 0 0',
|
||||
height: '34px',
|
||||
fontWeight: '500',
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
lineHeight: 'var(--affine-line-height)',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.15s ease',
|
||||
});
|
||||
|
||||
export const tagItem = styleVariants({
|
||||
active: [
|
||||
baseTagItem,
|
||||
{
|
||||
color: 'var(--affine-primary-color)',
|
||||
},
|
||||
],
|
||||
inactive: [
|
||||
baseTagItem,
|
||||
{
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const settingKey = style({
|
||||
width: '140px',
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
fontWeight: 500,
|
||||
marginRight: '56px',
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const settingItemLabel = style({
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
fontWeight: 600,
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const settingItemLabelHint = style({
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
fontWeight: 400,
|
||||
flexShrink: 0,
|
||||
marginTop: '4px',
|
||||
});
|
||||
|
||||
export const row = style({
|
||||
padding: '40px 0',
|
||||
display: 'flex',
|
||||
gap: '60px',
|
||||
selectors: {
|
||||
'&': {
|
||||
borderBottom: '1px solid var(--affine-border-color)',
|
||||
},
|
||||
'&:first-child': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const col = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
flexShrink: 0,
|
||||
selectors: {
|
||||
[`${row} &:nth-child(1)`]: {
|
||||
flex: 3,
|
||||
},
|
||||
[`${row} &:nth-child(2)`]: {
|
||||
flex: 5,
|
||||
},
|
||||
[`${row} &:nth-child(3)`]: {
|
||||
flex: 2,
|
||||
alignItems: 'flex-end',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const workspaceName = style({
|
||||
fontWeight: '400',
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
});
|
||||
|
||||
export const indicator = style({
|
||||
height: '2px',
|
||||
background: 'var(--affine-primary-color)',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
bottom: '0',
|
||||
transition: 'left .3s, width .3s',
|
||||
});
|
||||
|
||||
export const tabButtonWrapper = style({
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
export const storageTypeWrapper = style({
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
padding: '12px',
|
||||
borderRadius: '10px',
|
||||
gap: '12px',
|
||||
boxShadow: 'var(--affine-shadow-1)',
|
||||
cursor: 'pointer',
|
||||
selectors: {
|
||||
'&:hover': {
|
||||
boxShadow: 'var(--affine-shadow-2)',
|
||||
},
|
||||
'&:not(:last-child)': {
|
||||
marginBottom: '12px',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const storageTypeLabelWrapper = style({
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export const storageTypeLabel = style({
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
});
|
||||
|
||||
export const storageTypeLabelHint = style({
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
});
|
||||
@@ -9,18 +9,12 @@ import { preload } from 'swr';
|
||||
import { useIsWorkspaceOwner } from '../../../hooks/affine/use-is-workspace-owner';
|
||||
import { fetcher, QueryKey } from '../../../plugins/affine/fetcher';
|
||||
import type { AffineOfficialWorkspace } from '../../../shared';
|
||||
import * as style from './index.css';
|
||||
import { CollaborationPanel } from './panel/collaboration';
|
||||
import { ExportPanel } from './panel/export';
|
||||
import { GeneralPanel } from './panel/general';
|
||||
import { PublishPanel } from './panel/publish';
|
||||
import { SyncPanel } from './panel/sync';
|
||||
import {
|
||||
StyledIndicator,
|
||||
StyledSettingContainer,
|
||||
StyledSettingContent,
|
||||
StyledTabButtonWrapper,
|
||||
WorkspaceSettingTagItem,
|
||||
} from './style';
|
||||
|
||||
export type WorkspaceSettingDetailProps = {
|
||||
workspace: AffineOfficialWorkspace;
|
||||
@@ -133,39 +127,43 @@ export const WorkspaceSettingDetail: React.FC<
|
||||
);
|
||||
const Component = useMemo(() => panelMap[currentTab].ui, [currentTab]);
|
||||
return (
|
||||
<StyledSettingContainer
|
||||
<div
|
||||
className={style.container}
|
||||
aria-label="workspace-setting-detail"
|
||||
ref={containerRef}
|
||||
>
|
||||
<StyledTabButtonWrapper>
|
||||
<div className={style.tabButtonWrapper}>
|
||||
{Object.entries(panelMap).map(([key, value]) => {
|
||||
if ('enable' in value && !value.enable(workspace.flavour)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<WorkspaceSettingTagItem
|
||||
<div
|
||||
className={
|
||||
style.tagItem[currentTab === key ? 'active' : 'inactive']
|
||||
}
|
||||
key={key}
|
||||
isActive={currentTab === key}
|
||||
data-tab-key={key}
|
||||
onClick={handleTabClick}
|
||||
>
|
||||
{t[value.name]()}
|
||||
</WorkspaceSettingTagItem>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<StyledIndicator
|
||||
<div
|
||||
className={style.indicator}
|
||||
ref={ref => {
|
||||
indicatorRef.current = ref;
|
||||
startTransaction();
|
||||
}}
|
||||
/>
|
||||
</StyledTabButtonWrapper>
|
||||
<StyledSettingContent>
|
||||
</div>
|
||||
<div className={style.content}>
|
||||
{/* todo: add skeleton */}
|
||||
<Suspense fallback="loading panel...">
|
||||
<Component {...props} key={currentTab} data-tab-ui={currentTab} />
|
||||
</Suspense>
|
||||
</StyledSettingContent>
|
||||
</StyledSettingContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Button, Wrapper } from '@affine/component';
|
||||
import { Button, toast, Wrapper } from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { rootCurrentWorkspaceIdAtom } from '@affine/workspace/atom';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
||||
export const ExportPanel = () => {
|
||||
const id = useAtomValue(rootCurrentWorkspaceIdAtom);
|
||||
const t = useAFFiNEI18N();
|
||||
return (
|
||||
<>
|
||||
@@ -9,9 +12,12 @@ export const ExportPanel = () => {
|
||||
<Button
|
||||
type="light"
|
||||
shape="circle"
|
||||
disabled={!environment.isDesktop}
|
||||
onClick={() => {
|
||||
window.apis.openSaveDBFileDialog();
|
||||
disabled={!environment.isDesktop || !id}
|
||||
data-testid="export-affine-backup"
|
||||
onClick={async () => {
|
||||
if (id && (await window.apis?.dialog.saveDBFileAs(id))) {
|
||||
toast(t['Export success']());
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t['Export AFFiNE backup file']()}
|
||||
|
||||
+8
-4
@@ -37,11 +37,15 @@ export const WorkspaceDeleteModal = ({
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
onDeleteWorkspace().then(() => {
|
||||
toast(t['Successfully deleted'](), {
|
||||
portal: document.body,
|
||||
onDeleteWorkspace()
|
||||
.then(() => {
|
||||
toast(t['Successfully deleted'](), {
|
||||
portal: document.body,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
// ignore error
|
||||
});
|
||||
});
|
||||
}, [onDeleteWorkspace, t]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
import { Button, FlexWrapper, MuiFade } from '@affine/component';
|
||||
import { Button, toast } from '@affine/component';
|
||||
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import {
|
||||
ArrowRightSmallIcon,
|
||||
DeleteIcon,
|
||||
FolderIcon,
|
||||
MoveToIcon,
|
||||
SaveIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
|
||||
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
||||
import clsx from 'clsx';
|
||||
import type React from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useIsWorkspaceOwner } from '../../../../../hooks/affine/use-is-workspace-owner';
|
||||
import { Upload } from '../../../../pure/file-upload';
|
||||
import {
|
||||
CloudWorkspaceIcon,
|
||||
JoinedWorkspaceIcon,
|
||||
LocalWorkspaceIcon,
|
||||
} from '../../../../pure/icons';
|
||||
import type { PanelProps } from '../../index';
|
||||
import { StyledRow, StyledSettingKey } from '../../style';
|
||||
import * as style from '../../index.css';
|
||||
import { WorkspaceDeleteModal } from './delete';
|
||||
import { CameraIcon } from './icons';
|
||||
import { WorkspaceLeave } from './leave';
|
||||
import {
|
||||
StyledAvatar,
|
||||
StyledEditButton,
|
||||
StyledInput,
|
||||
StyledWorkspaceInfo,
|
||||
} from './style';
|
||||
import { StyledInput } from './style';
|
||||
|
||||
export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
workspace,
|
||||
@@ -37,11 +34,11 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
);
|
||||
const [input, setInput] = useState<string>(name);
|
||||
const isOwner = useIsWorkspaceOwner(workspace);
|
||||
const [showEditInput, setShowEditInput] = useState(false);
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const handleUpdateWorkspaceName = (name: string) => {
|
||||
setName(name);
|
||||
toast(t['Update workspace name success']());
|
||||
};
|
||||
|
||||
const [, update] = useBlockSuiteWorkspaceAvatarUrl(
|
||||
@@ -49,187 +46,189 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<StyledRow>
|
||||
<StyledSettingKey>{t['Workspace Avatar']()}</StyledSettingKey>
|
||||
<StyledAvatar disabled={!isOwner}>
|
||||
{isOwner ? (
|
||||
<Upload
|
||||
accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"
|
||||
fileChange={update}
|
||||
data-testid="upload-avatar"
|
||||
<div data-testid="avatar-row" className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>
|
||||
{t['Workspace Avatar']()}
|
||||
</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Change avatar hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx(style.col)}>
|
||||
<div className={style.avatar[isOwner ? 'enabled' : 'disabled']}>
|
||||
{isOwner ? (
|
||||
<Upload
|
||||
accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"
|
||||
fileChange={update}
|
||||
data-testid="upload-avatar"
|
||||
>
|
||||
<>
|
||||
<div className="camera-icon">
|
||||
<CameraIcon></CameraIcon>
|
||||
</div>
|
||||
<WorkspaceAvatar size={72} workspace={workspace} />
|
||||
</>
|
||||
</Upload>
|
||||
) : (
|
||||
<WorkspaceAvatar size={72} workspace={workspace} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx(style.col)}></div>
|
||||
</div>
|
||||
|
||||
<div data-testid="workspace-name-row" className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>{t['Workspace Name']()}</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Change workspace name hint']()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.col}>
|
||||
<StyledInput
|
||||
width={284}
|
||||
height={38}
|
||||
value={input}
|
||||
data-testid="workspace-name-input"
|
||||
placeholder={t['Workspace Name']()}
|
||||
maxLength={50}
|
||||
minLength={0}
|
||||
onChange={newName => {
|
||||
setInput(newName);
|
||||
}}
|
||||
></StyledInput>
|
||||
</div>
|
||||
|
||||
<div className={style.col}>
|
||||
<Button
|
||||
type="light"
|
||||
size="middle"
|
||||
data-testid="save-workspace-name"
|
||||
icon={<SaveIcon />}
|
||||
disabled={input === workspace.blockSuiteWorkspace.meta.name}
|
||||
onClick={() => {
|
||||
handleUpdateWorkspaceName(input);
|
||||
}}
|
||||
>
|
||||
{t['Save']()}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{environment.isDesktop && (
|
||||
<div className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>
|
||||
{t['Storage Folder']()}
|
||||
</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Storage Folder Hint']()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.col}>
|
||||
<div
|
||||
className={style.storageTypeWrapper}
|
||||
onClick={() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.dialog.revealDBFile(workspace.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<>
|
||||
<div className="camera-icon">
|
||||
<CameraIcon></CameraIcon>
|
||||
<FolderIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>
|
||||
{t['Open folder']()}
|
||||
</div>
|
||||
<WorkspaceAvatar size={72} workspace={workspace} />
|
||||
</>
|
||||
</Upload>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Open folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="move-folder"
|
||||
className={style.storageTypeWrapper}
|
||||
onClick={async () => {
|
||||
if (await window.apis?.dialog.moveDBFile(workspace.id)) {
|
||||
toast(t['Move folder success']());
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MoveToIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>
|
||||
{t['Move folder']()}
|
||||
</div>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Move folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.col}></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>
|
||||
{t['Delete Workspace']()}
|
||||
</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Delete Workspace Label Hint']()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.col}></div>
|
||||
<div className={style.col}>
|
||||
{isOwner ? (
|
||||
<>
|
||||
<Button
|
||||
type="warning"
|
||||
data-testid="delete-workspace-button"
|
||||
size="middle"
|
||||
icon={<DeleteIcon />}
|
||||
onClick={() => {
|
||||
setShowDelete(true);
|
||||
}}
|
||||
>
|
||||
{t['Delete']()}
|
||||
</Button>
|
||||
<WorkspaceDeleteModal
|
||||
onDeleteWorkspace={onDeleteWorkspace}
|
||||
open={showDelete}
|
||||
onClose={() => {
|
||||
setShowDelete(false);
|
||||
}}
|
||||
workspace={workspace}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<WorkspaceAvatar size={72} workspace={workspace} />
|
||||
)}
|
||||
</StyledAvatar>
|
||||
</StyledRow>
|
||||
|
||||
<StyledRow>
|
||||
<StyledSettingKey>{t['Workspace Name']()}</StyledSettingKey>
|
||||
|
||||
<div style={{ position: 'relative' }}>
|
||||
<MuiFade in={!showEditInput}>
|
||||
<FlexWrapper>
|
||||
{name}
|
||||
{isOwner && (
|
||||
<StyledEditButton
|
||||
onClick={() => {
|
||||
setShowEditInput(true);
|
||||
}}
|
||||
>
|
||||
{t['Edit']()}
|
||||
</StyledEditButton>
|
||||
)}
|
||||
</FlexWrapper>
|
||||
</MuiFade>
|
||||
|
||||
{isOwner && (
|
||||
<MuiFade in={showEditInput}>
|
||||
<FlexWrapper style={{ position: 'absolute', top: 0, left: 0 }}>
|
||||
<StyledInput
|
||||
width={284}
|
||||
height={38}
|
||||
value={input}
|
||||
placeholder={t['Workspace Name']()}
|
||||
maxLength={50}
|
||||
minLength={0}
|
||||
onChange={newName => {
|
||||
setInput(newName);
|
||||
}}
|
||||
></StyledInput>
|
||||
<Button
|
||||
type="light"
|
||||
shape="circle"
|
||||
style={{ marginLeft: '24px' }}
|
||||
disabled={input === workspace.blockSuiteWorkspace.meta.name}
|
||||
onClick={() => {
|
||||
handleUpdateWorkspaceName(input);
|
||||
setShowEditInput(false);
|
||||
}}
|
||||
>
|
||||
{t['Confirm']()}
|
||||
</Button>
|
||||
<Button
|
||||
type="default"
|
||||
shape="circle"
|
||||
style={{ marginLeft: '24px' }}
|
||||
onClick={() => {
|
||||
setInput(workspace.blockSuiteWorkspace.meta.name ?? '');
|
||||
setShowEditInput(false);
|
||||
}}
|
||||
>
|
||||
{t['Cancel']()}
|
||||
</Button>
|
||||
</FlexWrapper>
|
||||
</MuiFade>
|
||||
<>
|
||||
<Button
|
||||
type="warning"
|
||||
size="middle"
|
||||
onClick={() => {
|
||||
setShowLeave(true);
|
||||
}}
|
||||
>
|
||||
{t['Leave']()}
|
||||
</Button>
|
||||
<WorkspaceLeave
|
||||
open={showLeave}
|
||||
onClose={() => {
|
||||
setShowLeave(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</StyledRow>
|
||||
|
||||
{/* fixme(himself65): how to know a workspace owner by api? */}
|
||||
{/*{!isOwner && (*/}
|
||||
{/* <StyledRow>*/}
|
||||
{/* <StyledSettingKey>{t('Workspace Owner')}</StyledSettingKey>*/}
|
||||
{/* <FlexWrapper alignItems="center">*/}
|
||||
{/* <MuiAvatar*/}
|
||||
{/* sx={{ width: 72, height: 72, marginRight: '12px' }}*/}
|
||||
{/* alt="owner avatar"*/}
|
||||
{/* // src={currentWorkspace?.owner?.avatar}*/}
|
||||
{/* >*/}
|
||||
{/* <EmailIcon />*/}
|
||||
{/* </MuiAvatar>*/}
|
||||
{/* /!*<span>{currentWorkspace?.owner?.name}</span>*!/*/}
|
||||
{/* </FlexWrapper>*/}
|
||||
{/* </StyledRow>*/}
|
||||
{/*)}*/}
|
||||
{/*{!isOwner && (*/}
|
||||
{/* <StyledRow>*/}
|
||||
{/* <StyledSettingKey>{t('Members')}</StyledSettingKey>*/}
|
||||
{/* <FlexWrapper alignItems="center">*/}
|
||||
{/* /!*<span>{currentWorkspace?.memberCount}</span>*!/*/}
|
||||
{/* </FlexWrapper>*/}
|
||||
{/* </StyledRow>*/}
|
||||
{/*)}*/}
|
||||
|
||||
<StyledRow
|
||||
onClick={() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis.openDBFolder();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<StyledSettingKey>{t['Workspace Type']()}</StyledSettingKey>
|
||||
{isOwner ? (
|
||||
workspace.flavour === WorkspaceFlavour.LOCAL ? (
|
||||
<StyledWorkspaceInfo>
|
||||
<LocalWorkspaceIcon />
|
||||
<span>{t['Local Workspace']()}</span>
|
||||
</StyledWorkspaceInfo>
|
||||
) : (
|
||||
<StyledWorkspaceInfo>
|
||||
<CloudWorkspaceIcon />
|
||||
<span>{t['Cloud Workspace']()}</span>
|
||||
</StyledWorkspaceInfo>
|
||||
)
|
||||
) : (
|
||||
<StyledWorkspaceInfo>
|
||||
<JoinedWorkspaceIcon />
|
||||
<span>{t['Joined Workspace']()}</span>
|
||||
</StyledWorkspaceInfo>
|
||||
)}
|
||||
</StyledRow>
|
||||
|
||||
<StyledRow>
|
||||
<StyledSettingKey> {t['Delete Workspace']()}</StyledSettingKey>
|
||||
{isOwner ? (
|
||||
<>
|
||||
<Button
|
||||
type="warning"
|
||||
shape="circle"
|
||||
style={{ borderRadius: '40px' }}
|
||||
data-testid="delete-workspace-button"
|
||||
onClick={() => {
|
||||
setShowDelete(true);
|
||||
}}
|
||||
>
|
||||
{t['Delete Workspace']()}
|
||||
</Button>
|
||||
<WorkspaceDeleteModal
|
||||
onDeleteWorkspace={onDeleteWorkspace}
|
||||
open={showDelete}
|
||||
onClose={() => {
|
||||
setShowDelete(false);
|
||||
}}
|
||||
workspace={workspace}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
type="warning"
|
||||
shape="circle"
|
||||
onClick={() => {
|
||||
setShowLeave(true);
|
||||
}}
|
||||
>
|
||||
{t['Leave Workspace']()}
|
||||
</Button>
|
||||
<WorkspaceLeave
|
||||
open={showLeave}
|
||||
onClose={() => {
|
||||
setShowLeave(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</StyledRow>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Input } from '@affine/component';
|
||||
export const StyledInput = styled(Input)(() => {
|
||||
return {
|
||||
border: '1px solid var(--affine-border-color)',
|
||||
borderRadius: '10px',
|
||||
borderRadius: '8px',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import { styled } from '@affine/component';
|
||||
import { FlexWrapper } from '@affine/component';
|
||||
export const StyledSettingContainer = styled('div')(() => {
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '52px 0 0 52px',
|
||||
height: 'calc(100vh - 52px)',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledSettingSidebar = styled('div')(() => {
|
||||
{
|
||||
return {
|
||||
marginTop: '52px',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const StyledSettingContent = styled('div')(() => {
|
||||
return {
|
||||
overflow: 'auto',
|
||||
flex: 1,
|
||||
paddingTop: '48px',
|
||||
};
|
||||
});
|
||||
|
||||
export const WorkspaceSettingTagItem = styled('li')<{ isActive?: boolean }>(
|
||||
({ isActive }) => {
|
||||
{
|
||||
return {
|
||||
display: 'flex',
|
||||
margin: '0 48px 0 0',
|
||||
height: '34px',
|
||||
color: isActive
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'var(--affine-text-primary-color)',
|
||||
fontWeight: '500',
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
lineHeight: 'var(--affine-line-height)',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.15s ease',
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const StyledSettingKey = styled('div')(() => {
|
||||
return {
|
||||
width: '140px',
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
fontWeight: 500,
|
||||
marginRight: '56px',
|
||||
flexShrink: 0,
|
||||
};
|
||||
});
|
||||
export const StyledRow = styled(FlexWrapper)(() => {
|
||||
return {
|
||||
marginBottom: '42px',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledWorkspaceName = styled('span')(() => {
|
||||
return {
|
||||
fontWeight: '400',
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledIndicator = styled('div')(() => {
|
||||
return {
|
||||
height: '2px',
|
||||
background: 'var(--affine-primary-color)',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
bottom: '0',
|
||||
transition: 'left .3s, width .3s',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledTabButtonWrapper = styled('div')(() => {
|
||||
return {
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
};
|
||||
});
|
||||
|
||||
// export const StyledDownloadCard = styled('div')<{ active?: boolean }>(
|
||||
// ({ theme, active }) => {
|
||||
// return {
|
||||
// width: '240px',
|
||||
// height: '86px',
|
||||
// border: '1px solid',
|
||||
// borderColor: active
|
||||
// ? 'var(--affine-primary-color)'
|
||||
// : 'var(--affine-border-color)',
|
||||
// borderRadius: '10px',
|
||||
// padding: '8px 12px',
|
||||
// position: 'relative',
|
||||
// ':not(:last-of-type)': {
|
||||
// marginRight: '24px',
|
||||
// },
|
||||
// svg: {
|
||||
// display: active ? 'block' : 'none',
|
||||
// ...positionAbsolute({ top: '-12px', right: '-12px' }),
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
// );
|
||||
// export const StyledDownloadCardDes = styled('div')(({ theme }) => {
|
||||
// return {
|
||||
// fontSize: 'var(--affine-font-sm)',
|
||||
// color: 'var(--affine-icon-color)',
|
||||
// };
|
||||
// });
|
||||
Reference in New Issue
Block a user