feat:mock workspace-setting

This commit is contained in:
DiamondThree
2023-01-05 16:05:54 +08:00
parent 5f729464a2
commit 4dc61165b2
9 changed files with 160 additions and 122 deletions

View File

@@ -2,7 +2,11 @@ import { styled } from '@/styles';
import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal'; import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal';
import { Button } from '@/ui/button'; import { Button } from '@/ui/button';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { getWorkspaceList, Workspace } from '@/hooks/mock-data/mock'; import {
getWorkspaces,
Workspace,
setActiveWorkspace,
} from '@/hooks/mock-data/mock';
import { CreateWorkspaceModal } from '../create-workspace'; import { CreateWorkspaceModal } from '../create-workspace';
interface LoginModalProps { interface LoginModalProps {
@@ -19,7 +23,7 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
}, []); }, []);
const getList = () => { const getList = () => {
const data = getWorkspaceList(); const data = getWorkspaces();
setWorkspaceList(data); setWorkspaceList(data);
}; };
return ( return (
@@ -40,11 +44,16 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
<WorkspaceList> <WorkspaceList>
{workspaceList.map(item => { {workspaceList.map(item => {
return ( return (
<WorkspaceItem key={item.id}> <WorkspaceItem
<span></span> onClick={() => {
setActiveWorkspace(item);
onClose();
}}
key={item.id}
>
<span>{item.name}</span>/ <span>{item.name}</span>/
{item.type === 'local' && <b>local</b>} {item.type === 'local' && <b>local</b>}
{item.type === 'share' && <b>share</b>}/ {item.type === 'join' && <b>join</b>}/
{item.isPublish ? 'isPublish' : 'isPrivate'}/ {item.isPublish ? 'isPublish' : 'isPrivate'}/
{item.isLocal ? 'isLocal' : ''}/ {item.isLocal ? 'isLocal' : ''}/
</WorkspaceItem> </WorkspaceItem>
@@ -70,6 +79,7 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
onClose={() => { onClose={() => {
setCreateWorkspaceOpen(false); setCreateWorkspaceOpen(false);
getList(); getList();
onClose();
}} }}
></CreateWorkspaceModal> ></CreateWorkspaceModal>
</ModalWrapper> </ModalWrapper>

View File

@@ -9,25 +9,22 @@ import { StyledSettingH2 } from '../style';
import { useState } from 'react'; import { useState } from 'react';
import { Button } from '@/ui/button'; import { Button } from '@/ui/button';
import Input from '@/ui/input'; import Input from '@/ui/input';
import { getDataCenter, Workspace, WorkspaceType } from '@affine/datacenter'; import { getDataCenter } from '@affine/datacenter';
import { useAppState } from '@/providers/app-state-provider'; import { useAppState } from '@/providers/app-state-provider';
import { WorkspaceDetails } from '@/components/workspace-slider-bar/WorkspaceSelector/SelectorPopperContent';
import { WorkspaceDelete } from './delete'; import { WorkspaceDelete } from './delete';
import { Workspace as StoreWorkspace } from '@blocksuite/store'; import { Workspace as StoreWorkspace } from '@blocksuite/store';
import { debounce } from '@/utils'; import { debounce } from '@/utils';
import { WorkspaceLeave } from './leave'; import { WorkspaceLeave } from './leave';
import { Upload } from '@/components/file-upload'; import { Upload } from '@/components/file-upload';
import { Workspace } from '@/hooks/mock-data/mock';
export const GeneralPage = ({ export const GeneralPage = ({
workspace, workspace,
owner,
}: { }: {
workspace: Workspace; workspace: Workspace;
owner: WorkspaceDetails[string]['owner'];
workspaces: Record<string, StoreWorkspace | null>; workspaces: Record<string, StoreWorkspace | null>;
}) => { }) => {
const { const {
user,
currentWorkspace, currentWorkspace,
workspacesMeta, workspacesMeta,
workspaces, workspaces,
@@ -36,14 +33,11 @@ export const GeneralPage = ({
const [showDelete, setShowDelete] = useState<boolean>(false); const [showDelete, setShowDelete] = useState<boolean>(false);
const [showLeave, setShowLeave] = useState<boolean>(false); const [showLeave, setShowLeave] = useState<boolean>(false);
const [uploading, setUploading] = useState<boolean>(false); const [uploading, setUploading] = useState<boolean>(false);
const [workspaceName, setWorkspaceName] = useState<string>( const [workspaceName, setWorkspaceName] = useState<string>('');
workspaces[workspace.id]?.meta.name ||
(workspace.type === WorkspaceType.Private && user ? user.name : '')
);
const debouncedRefreshWorkspacesMeta = debounce(() => { const debouncedRefreshWorkspacesMeta = debounce(() => {
refreshWorkspacesMeta(); refreshWorkspacesMeta();
}, 100); }, 100);
const isOwner = user && owner.id === user.id; const isOwner = true;
const handleChangeWorkSpaceName = (newName: string) => { const handleChangeWorkSpaceName = (newName: string) => {
setWorkspaceName(newName); setWorkspaceName(newName);
currentWorkspace?.meta.setName(newName); currentWorkspace?.meta.setName(newName);
@@ -119,7 +113,6 @@ export const GeneralPage = ({
width={327} width={327}
value={workspaceName} value={workspaceName}
placeholder="Workspace Name" placeholder="Workspace Name"
disabled={!isOwner}
maxLength={14} maxLength={14}
minLength={1} minLength={1}
onChange={handleChangeWorkSpaceName} onChange={handleChangeWorkSpaceName}
@@ -130,7 +123,7 @@ export const GeneralPage = ({
<Input <Input
width={327} width={327}
disabled disabled
value={owner.name} // value={owner.name}
placeholder="Workspace Owner" placeholder="Workspace Owner"
></Input> ></Input>
</StyledSettingInputContainer> </StyledSettingInputContainer>

View File

@@ -36,14 +36,14 @@ import { useCallback, useEffect, useState } from 'react';
import { Button, IconButton } from '@/ui/button'; import { Button, IconButton } from '@/ui/button';
import Input from '@/ui/input'; import Input from '@/ui/input';
import { InviteMembers } from '../invite-members/index'; import { InviteMembers } from '../invite-members/index';
import { Workspace, Member, getDataCenter } from '@affine/datacenter'; import { Member, getDataCenter } from '@affine/datacenter';
import { Avatar } from '@mui/material'; import { Avatar } from '@mui/material';
import { Menu, MenuItem } from '@/ui/menu'; import { Menu, MenuItem } from '@/ui/menu';
import { toast } from '@/ui/toast'; import { toast } from '@/ui/toast';
import { Empty } from '@/ui/empty'; import { Empty } from '@/ui/empty';
import { useAppState } from '@/providers/app-state-provider'; import { useAppState } from '@/providers/app-state-provider';
import { WorkspaceDetails } from '../workspace-slider-bar/WorkspaceSelector/SelectorPopperContent';
import { GeneralPage } from './general'; import { GeneralPage } from './general';
import { getActiveWorkspace, Workspace } from '@/hooks/mock-data/mock';
enum ActiveTab { enum ActiveTab {
'general' = 'general', 'general' = 'general',
@@ -59,8 +59,6 @@ type SettingTabProps = {
type WorkspaceSettingProps = { type WorkspaceSettingProps = {
isShow: boolean; isShow: boolean;
onClose?: () => void; onClose?: () => void;
workspace: Workspace;
owner: WorkspaceDetails[string]['owner'];
}; };
const WorkspaceSettingTab = ({ activeTab, onTabChange }: SettingTabProps) => { const WorkspaceSettingTab = ({ activeTab, onTabChange }: SettingTabProps) => {
@@ -106,18 +104,18 @@ const WorkspaceSettingTab = ({ activeTab, onTabChange }: SettingTabProps) => {
export const WorkspaceSetting = ({ export const WorkspaceSetting = ({
isShow, isShow,
onClose, onClose,
workspace,
owner,
}: WorkspaceSettingProps) => { }: WorkspaceSettingProps) => {
const { user, workspaces } = useAppState(); const { workspaces } = useAppState();
const [activeTab, setActiveTab] = useState<ActiveTab>(ActiveTab.general); const [activeTab, setActiveTab] = useState<ActiveTab>(ActiveTab.general);
const handleTabChange = (tab: ActiveTab) => { const handleTabChange = (tab: ActiveTab) => {
setActiveTab(tab); setActiveTab(tab);
}; };
const workspace = getActiveWorkspace();
const handleClickClose = () => { const handleClickClose = () => {
onClose && onClose(); onClose && onClose();
}; };
const isOwner = user && owner.id === user.id; const isOwner = true;
useEffect(() => { useEffect(() => {
// reset tab when modal is closed // reset tab when modal is closed
if (!isShow) { if (!isShow) {
@@ -125,7 +123,7 @@ export const WorkspaceSetting = ({
} }
}, [isShow]); }, [isShow]);
return ( return (
<Modal open={isShow}> <Modal open={false}>
<StyledSettingContainer> <StyledSettingContainer>
<ModalCloseButton onClick={handleClickClose} /> <ModalCloseButton onClick={handleClickClose} />
{isOwner ? ( {isOwner ? (
@@ -141,11 +139,7 @@ export const WorkspaceSetting = ({
) : null} ) : null}
<StyledSettingContent> <StyledSettingContent>
{activeTab === ActiveTab.general && ( {activeTab === ActiveTab.general && (
<GeneralPage <GeneralPage workspace={workspace} workspaces={workspaces} />
workspace={workspace}
owner={owner}
workspaces={workspaces}
/>
)} )}
{activeTab === ActiveTab.members && workspace && ( {activeTab === ActiveTab.members && workspace && (
<MembersPage workspace={workspace} /> <MembersPage workspace={workspace} />
@@ -295,7 +289,7 @@ const MembersPage = ({ workspace }: { workspace: Workspace }) => {
const PublishPage = ({ workspace }: { workspace: Workspace }) => { const PublishPage = ({ workspace }: { workspace: Workspace }) => {
const shareUrl = window.location.host + '/workspace/' + workspace.id; const shareUrl = window.location.host + '/workspace/' + workspace.id;
const [publicStatus, setPublicStatus] = useState<boolean | null>( const [publicStatus, setPublicStatus] = useState<boolean | null>(
workspace.public workspace.isPublish ?? false
); );
const togglePublic = (flag: boolean) => { const togglePublic = (flag: boolean) => {
getDataCenter() getDataCenter()

View File

@@ -130,16 +130,16 @@ export const SelectorPopperContent = ({
<CreateWorkspaceItem /> <CreateWorkspaceItem />
{settingWorkspace ? ( {settingWorkspace ? (
<WorkspaceSetting <WorkspaceSetting
isShow={Boolean(settingWorkspaceId)} isShow={false}
onClose={handleCloseWorkSpace} onClose={handleCloseWorkSpace}
workspace={settingWorkspace} // workspace={settingWorkspace}
owner={ // owner={
(settingWorkspaceId && // (settingWorkspaceId &&
workSpaceDetails[settingWorkspaceId]?.owner) || { // workSpaceDetails[settingWorkspaceId]?.owner) || {
id: user.id, // id: user.id,
name: user.name, // name: user.name,
} // }
} // }
/> />
) : null} ) : null}
<StyledDivider /> <StyledDivider />

View File

@@ -1,53 +1,46 @@
import { Popper } from '@/ui/popper';
import { Avatar, WorkspaceName, SelectorWrapper } from './styles'; import { Avatar, WorkspaceName, SelectorWrapper } from './styles';
import { SelectorPopperContent } from './SelectorPopperContent'; import { useEffect, useState } from 'react';
import { useState } from 'react';
import { useAppState } from '@/providers/app-state-provider';
import { WorkspaceType } from '@affine/datacenter';
import { AffineIcon } from '../icons/icons'; import { AffineIcon } from '../icons/icons';
import { WorkspaceModal } from '@/components/workspace-modal';
import { getActiveWorkspace } from '@/hooks/mock-data/mock';
export const WorkspaceSelector = () => { export const WorkspaceSelector = () => {
const [isShow, setIsShow] = useState(false); const [workspaceListShow, setWorkspaceListShow] = useState(false);
const { currentWorkspace, workspacesMeta, currentWorkspaceId, user } = const [workspace, setWorkSpace] = useState(getActiveWorkspace());
useAppState(); useEffect(() => {
const workspaceMeta = workspacesMeta.find( getWorkspace();
meta => String(meta.id) === String(currentWorkspaceId) }, [workspaceListShow]);
); const getWorkspace = () => {
const workspace = getActiveWorkspace();
setWorkSpace(workspace);
};
return ( return (
<Popper <>
content={<SelectorPopperContent isShow={isShow} />} <SelectorWrapper
zIndex={1000} onClick={() => {
placement="bottom-start" setWorkspaceListShow(true);
trigger="click" }}
onVisibleChange={setIsShow} data-testid="current-workspace"
> >
<SelectorWrapper data-testid="current-workspace">
<Avatar <Avatar
alt="Affine" alt="Affine"
data-testid="workspace-avatar" data-testid="workspace-avatar"
src={ src={workspace.avatar}
workspaceMeta?.type === WorkspaceType.Private
? user
? user.avatar_url
: ''
: currentWorkspace?.meta.avatar &&
`/api/blob/${currentWorkspace?.meta.avatar}`
}
> >
{workspaceMeta?.type === WorkspaceType.Private && user ? (
user?.name[0]
) : (
<AffineIcon /> <AffineIcon />
)}
</Avatar> </Avatar>
<WorkspaceName data-testid="workspace-name"> <WorkspaceName data-testid="workspace-name">
{workspaceMeta?.type === WorkspaceType.Private {workspace?.name ?? 'AFFiNE'}
? user
? user.name
: 'AFFiNE'
: currentWorkspace?.meta.name || 'AFFiNE'}
</WorkspaceName> </WorkspaceName>
</SelectorWrapper> </SelectorWrapper>
</Popper> <WorkspaceModal
open={workspaceListShow}
onClose={() => {
setWorkspaceListShow(false);
getWorkspace();
}}
></WorkspaceModal>
</>
); );
}; };

View File

@@ -21,6 +21,7 @@ import {
ImportIcon, ImportIcon,
TrashIcon, TrashIcon,
AddIcon, AddIcon,
SettingsIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import Link from 'next/link'; import Link from 'next/link';
import { Tooltip } from '@/ui/tooltip'; import { Tooltip } from '@/ui/tooltip';
@@ -31,6 +32,7 @@ import { IconButton } from '@/ui/button';
import useLocalStorage from '@/hooks/use-local-storage'; import useLocalStorage from '@/hooks/use-local-storage';
import usePageMetaList from '@/hooks/use-page-meta-list'; import usePageMetaList from '@/hooks/use-page-meta-list';
import { usePageHelper } from '@/hooks/use-page-helper'; import { usePageHelper } from '@/hooks/use-page-helper';
import { WorkspaceSetting } from '@/components/workspace-setting';
const FavoriteList = ({ showList }: { showList: boolean }) => { const FavoriteList = ({ showList }: { showList: boolean }) => {
const { openPage } = usePageHelper(); const { openPage } = usePageHelper();
@@ -146,6 +148,20 @@ export const WorkSpaceSliderBar = () => {
</IconButton> </IconButton>
</StyledListItem> </StyledListItem>
<FavoriteList showList={showSubFavorite} /> <FavoriteList showList={showSubFavorite} />
<StyledListItem
onClick={() => {
console.log('ttt');
}}
>
<SettingsIcon /> Setting
</StyledListItem>
<WorkspaceSetting
isShow={true}
onClose={() => {
console.log(1231231);
}}
/>
<StyledListItem <StyledListItem
onClick={() => { onClick={() => {

View File

@@ -4,7 +4,7 @@ export interface Workspace {
isPublish?: boolean; // 是否公开 isPublish?: boolean; // 是否公开
isLocal?: boolean; // 是否全部数据都在本地 isLocal?: boolean; // 是否全部数据都在本地
avatar?: string; // 封面 avatar?: string; // 封面
type: 'local' | 'cloud' | 'share'; // cloud: 云端(本次暂不支持),local: 本地,share: 分享 type: 'local' | 'cloud' | 'join'; // cloud: 云端(本次暂不支持),local: 本地,join : 加入别人的
workspaceOwner?: User; // 本地工作空间的拥有者 workspaceOwner?: User; // 本地工作空间的拥有者
} }
@@ -15,45 +15,15 @@ interface User {
avatar: string; avatar: string;
} }
export function getWorkspaceList(): Workspace[] { export function updateWorkspaceMeta(
const workspacesMeta = JSON.parse(
localStorage.getItem('affine-workspace') ?? '[]'
);
return workspacesMeta;
}
export function getPagesByWorkspaceId(workspaceId: string) {
if (!workspaceId) return [];
const workspacesMeta = [];
for (let i = 0; i < 10; i++) {
workspacesMeta.push({
id: 'page-' + i,
name: 'page ' + i,
});
}
}
export function addWorkSpace(workspaceData: Workspace) {
const workspacesMeta = getWorkspaceList();
workspacesMeta.push(workspaceData);
localStorage.setItem('affine-workspace', JSON.stringify(workspacesMeta));
}
export function deleteWorkspaceById(workspaceId: string) {
const workspacesMeta = getWorkspaceList();
const newWorkspacesMeta = workspacesMeta.filter(() => {
return workspaceId !== workspaceId;
});
localStorage.setItem('affine-workspace', JSON.stringify(newWorkspacesMeta));
}
export function updateWorkspaceById(
workspaceId: string, workspaceId: string,
workspaceData: Workspace workspaceData: Workspace
) { ) {
const workspacesMeta = getWorkspaceList(); const workspacesMeta = getWorkspaces();
const newWorkspacesMeta = workspacesMeta.map((workspace: Workspace) => { const newWorkspacesMeta = workspacesMeta.map((workspace: Workspace) => {
if (workspace.id === workspaceId) { if (workspace.id === workspaceId) {
workspaceData.name && (workspace.name = workspaceData.name);
workspaceData.avatar && (workspace.avatar = workspaceData.avatar);
return workspaceData; return workspaceData;
} }
return workspace; return workspace;
@@ -69,7 +39,73 @@ export function createWorkspace(workspaceName: string) {
avatar: '', avatar: '',
type: 'local', type: 'local',
} as Workspace; } as Workspace;
const workspacesMeta = getWorkspaceList(); const workspacesMeta = getWorkspaces();
workspacesMeta.push(workspaceData); workspacesMeta.push(workspaceData);
localStorage.setItem('affine-workspace', JSON.stringify(workspacesMeta)); localStorage.setItem('affine-workspace', JSON.stringify(workspacesMeta));
setActiveWorkspace(workspaceData);
}
export function getWorkspaces(): Workspace[] {
const workspacesMeta = JSON.parse(
localStorage.getItem('affine-workspace') ?? '[]'
);
return workspacesMeta;
}
export function deleteWorkspace(workspaceId: string) {
const workspacesMeta = getWorkspaces();
const newWorkspacesMeta = workspacesMeta.filter(() => {
return workspaceId !== workspaceId;
});
localStorage.setItem('affine-workspace', JSON.stringify(newWorkspacesMeta));
}
export function getMembers(id: string): User[] {
const memberMap = JSON.parse(localStorage.getItem('affine-member') ?? '{}');
return memberMap[id] || [];
}
export function leaveWorkspace(id: string) {
return true;
}
export function setWorkspacePublish(id: string, isPublish: boolean): boolean {
const workspacesMeta = getWorkspaces();
const newWorkspacesMeta = workspacesMeta.map((workspace: Workspace) => {
if (workspace.id === id) {
workspace.isPublish = isPublish;
}
return workspace;
});
localStorage.setItem('affine-workspace', JSON.stringify(newWorkspacesMeta));
return isPublish;
}
export function getWorkspaceById(id: string) {
const workspacesMeta = getWorkspaces();
return workspacesMeta.find((workspace: Workspace) => {
return workspace.id === id;
});
}
export function getPagesByWorkspaceId(workspaceId: string) {
if (!workspaceId) return [];
const workspacesMeta = [];
for (let i = 0; i < 10; i++) {
workspacesMeta.push({
id: 'page-' + i,
name: 'page ' + i,
});
}
}
export function getActiveWorkspace(): Workspace {
return JSON.parse(localStorage.getItem('affine-active-workspace') ?? '{}');
}
export function setActiveWorkspace(workspaceData: Workspace) {
localStorage.setItem(
'affine-active-workspace',
JSON.stringify(workspaceData)
);
} }

View File

@@ -1,14 +1,14 @@
import { WorkspaceModal } from '@/components/workspace-modal'; import { WorkspaceModal } from '@/components/workspace-modal';
import { getWorkspaceList } from '@/hooks/mock-data/mock'; import { getWorkspaces } from '@/hooks/mock-data/mock';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { styled } from '@/styles'; import { styled } from '@/styles';
import Button from '@/ui/button/Button'; import Button from '@/ui/button/Button';
const Page = () => { const Page = () => {
const [open, setOpen] = useState<boolean>(true); const [open, setOpen] = useState<boolean>(false);
useEffect(() => { useEffect(() => {
const data = getWorkspaceList(); const data = getWorkspaces();
if (!data.length) { if (!data.length) {
setOpen(true); setOpen(true);
} }

View File

@@ -40,14 +40,10 @@ export interface AppStateContext extends AppStateValue {
export const AppState = createContext<AppStateContext>({ export const AppState = createContext<AppStateContext>({
user: null, user: null,
workspacesMeta: [], workspacesMeta: [],
currentWorkspaceId: '', currentWorkspaceId: '',
currentWorkspace: null, currentWorkspace: null,
currentPage: null, currentPage: null,
editor: null, editor: null,
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
setState: () => {}, setState: () => {},
createEditor: undefined, createEditor: undefined,