diff --git a/packages/app/src/components/workspace-modal/index.tsx b/packages/app/src/components/workspace-modal/index.tsx index b86cb67ad..d91ed5259 100644 --- a/packages/app/src/components/workspace-modal/index.tsx +++ b/packages/app/src/components/workspace-modal/index.tsx @@ -9,7 +9,6 @@ import { setActiveWorkspace, Login, User, - getUserInfo, SignOut, updateWorkspaceMeta, } from '@/hooks/mock-data/mock'; @@ -23,6 +22,7 @@ import { import { useConfirm } from '@/providers/confirm-provider'; import { toast } from '@/ui/toast'; import { WorkspaceAvatar } from '@/components/workspace-avatar'; +import useTemporaryHelper from '@/hooks/use-temporary-helper'; interface LoginModalProps { open: boolean; onClose: () => void; @@ -30,23 +30,17 @@ interface LoginModalProps { export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => { const [workspaceList, setWorkspaceList] = useState([]); - const [user, setUser] = useState(); const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false); const { confirm } = useConfirm(); + const { user, login } = useTemporaryHelper(); useEffect(() => { setList(); - setUserInfo(); }, []); const setList = () => { const data = getWorkspaces(); - console.log('data: ', data); setWorkspaceList(data); }; - const setUserInfo = () => { - const data = getUserInfo(); - setUser(data); - }; return (
@@ -153,9 +147,8 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => { {!user ? ( + { + setIsInviteModalShow(false); + }} + onInviteSuccess={() => { + setMembersList(); + setIsInviteModalShow(false); + // refreshMembers(); + }} + workspaceId={workspace.id} + open={isInviteModalShow} + > + + + ) : ( + <> +
+ Collaborating with other members requires AFFiNE Cloud service. +
+
+ +
+ + )} +
+ ); +}; diff --git a/packages/app/src/components/workspace-setting/PublishPage.tsx b/packages/app/src/components/workspace-setting/PublishPage.tsx new file mode 100644 index 000000000..f5136e76b --- /dev/null +++ b/packages/app/src/components/workspace-setting/PublishPage.tsx @@ -0,0 +1,122 @@ +import { + StyledCopyButtonContainer, + StyledPublishContent, + StyledPublishCopyContainer, + StyledPublishExplanation, + StyledSettingH2, +} from './style'; + +import { Button } from '@/ui/button'; +import Input from '@/ui/input'; +import { toast } from '@/ui/toast'; +import { Workspace } from '@/hooks/mock-data/mock'; +import useTemporaryHelper from '@/hooks/use-temporary-helper'; +import { useConfirm } from '@/providers/confirm-provider'; + +export const PublishPage = ({ workspace }: { workspace: Workspace }) => { + const shareUrl = + window.location.host + '/workspace/' + workspace.id + '?share=true'; + + const { login, updateWorkspaceMeta, user, currentWorkspace } = + useTemporaryHelper(); + const { confirm } = useConfirm(); + + const togglePublic = (flag: boolean) => { + updateWorkspaceMeta(currentWorkspace.id, { isPublish: flag }); + }; + + const copyUrl = () => { + navigator.clipboard.writeText(shareUrl); + toast('Copied url to clipboard'); + }; + + const enableAffineCloud = () => { + confirm({ + title: 'Enable AFFiNE Cloud?', + content: `If enabled, the data in this workspace will be backed up and synchronized via AFFiNE Cloud.`, + confirmText: user ? 'Enable' : 'Sign in and Enable', + cancelText: 'Skip', + }).then(confirm => { + if (user) { + updateWorkspaceMeta(currentWorkspace.id, { isPublish: true }); + } else { + confirm && login(); + updateWorkspaceMeta(currentWorkspace.id, { isPublish: true }); + } + }); + }; + return ( + <> + {currentWorkspace.type === 'cloud' ? ( +
+ + {currentWorkspace?.isPublish ? ( + <> + + Publishing to web requires AFFiNE Cloud service . + + + Share with link + + + + + + + + + ) : ( + + After publishing to the web, everyone can view the content of + this workspace through the link. + + )} + + {!currentWorkspace?.isPublish ? ( + + ) : ( + + )} +
+ ) : ( + + <> + + Publishing to web requires AFFiNE Cloud service. + + + + + + + + )} + + ); +}; diff --git a/packages/app/src/components/workspace-setting/SyncPage.tsx b/packages/app/src/components/workspace-setting/SyncPage.tsx new file mode 100644 index 000000000..572a67f77 --- /dev/null +++ b/packages/app/src/components/workspace-setting/SyncPage.tsx @@ -0,0 +1,91 @@ +import { + StyledPublishContent, + StyledPublishCopyContainer, + StyledPublishExplanation, +} from './style'; +import { DownloadIcon } from '@blocksuite/icons'; +import { useEffect, useState } from 'react'; +import { Button } from '@/ui/button'; +import { Menu, MenuItem } from '@/ui/menu'; +import { + deleteMember, + getActiveWorkspace, + updateWorkspaceMeta, + Workspace, +} from '@/hooks/mock-data/mock'; + +export const SyncPage = ({ workspace }: { workspace: Workspace }) => { + const [workspaceType, setWorkspaceType] = useState('local'); + useEffect(() => { + setType(); + }); + const setType = () => { + const ACTIVEworkspace = getActiveWorkspace(); + ACTIVEworkspace && setWorkspaceType(ACTIVEworkspace.type); + }; + return ( +
+ + {workspaceType === 'local' ? ( + <> + + {workspace.name} is Local Workspace. All data is stored on the + current device. You can enable AFFiNE Cloud for this workspace to + keep data in sync with the cloud. + + + + + + + ) : ( + <> + + {workspace.name} is Cloud Workspace. All data will be + synchronized and saved to the AFFiNE + + + + { + deleteMember(workspace.id, 0); + }} + icon={} + > + Download core data to device + + { + deleteMember(workspace.id, 0); + }} + icon={} + > + Download all data to device + + + } + placement="bottom-end" + disablePortal={true} + > + + + + + )} + +
+ ); +}; diff --git a/packages/app/src/components/workspace-setting/general/delete/delete.tsx b/packages/app/src/components/workspace-setting/general/delete/delete.tsx index f5b9e1e86..9594a75aa 100644 --- a/packages/app/src/components/workspace-setting/general/delete/delete.tsx +++ b/packages/app/src/components/workspace-setting/general/delete/delete.tsx @@ -14,20 +14,22 @@ import { Button } from '@/ui/button'; import { getDataCenter } from '@affine/datacenter'; import { useRouter } from 'next/router'; import { useAppState } from '@/providers/app-state-provider'; -import { deleteWorkspace, getWorkspaces } from '@/hooks/mock-data/mock'; +import { + deleteWorkspace, + getWorkspaces, + Workspace, +} from '@/hooks/mock-data/mock'; interface WorkspaceDeleteProps { open: boolean; onClose: () => void; - workspaceName: string; - workspaceId: string; + workspace: Workspace; } export const WorkspaceDelete = ({ open, onClose, - workspaceId, - workspaceName, + workspace, }: WorkspaceDeleteProps) => { const [deleteStr, setDeleteStr] = useState(''); const router = useRouter(); @@ -40,7 +42,7 @@ export const WorkspaceDelete = ({ // const dc = await getDataCenter(); // await dc.apis.deleteWorkspace({ id: workspaceId }); // router.push(`/workspace/${nextWorkSpaceId}`); - deleteWorkspace(workspaceId); + deleteWorkspace(workspace.id); const workspaceList = getWorkspaces(); if (workspaceList.length) { router.push(`/workspace/${workspaceList[0].id}`); @@ -55,11 +57,20 @@ export const WorkspaceDelete = ({ Delete Workspace - - This action cannot be undone. This will permanently delete ( - {workspaceName}) along with - all its content. - + {workspace.type === 'local' ? ( + + Deleting ( + {workspace.name}) cannot + be undone, please proceed with caution. along with all its content. + + ) : ( + + Deleting ( + {workspace.name}) will + delete both local and cloud data, this operation cannot be undone, + please proceed with caution. + + )} { width: '460px', fontWeight: '600', fontSize: '20px;', - textAlign: 'center', + textAlign: 'left', + paddingLeft: '20px', color: theme.colors.popoverColor, }; }); @@ -32,7 +33,7 @@ export const StyledTextContent = styled('div')(() => { fontWeight: '400', fontSize: '18px', lineHeight: '26px', - textAlign: 'center', + textAlign: 'left', }; }); @@ -41,7 +42,7 @@ export const StyledInputContent = styled('div')(() => { display: 'flex', flexDirection: 'row', justifyContent: 'center', - margin: '40px 0 24px 0', + margin: '20px 0 24px 0', }; }); diff --git a/packages/app/src/components/workspace-setting/general/general.tsx b/packages/app/src/components/workspace-setting/general/general.tsx index 5d808d839..1010efb9e 100644 --- a/packages/app/src/components/workspace-setting/general/general.tsx +++ b/packages/app/src/components/workspace-setting/general/general.tsx @@ -77,11 +77,8 @@ export const GeneralPage = ({ workspace }: { workspace: Workspace }) => { return workspace ? (
- Workspace Avatar + Workspace Icon - {/* - AFFiNE - */}
{ {/* TODO: add upload logic */} - {/* {isOwner ? ( - upload - ) : null} */} - {/* */} Workspace Name @@ -122,7 +115,7 @@ export const GeneralPage = ({ workspace }: { workspace: Workspace }) => { ✔️ - {userInfo ? ( + {/* {userInfo ? (
Workspace Owner @@ -136,7 +129,7 @@ export const GeneralPage = ({ workspace }: { workspace: Workspace }) => {
) : ( '' - )} + )} */} Workspace Type @@ -151,8 +144,7 @@ export const GeneralPage = ({ workspace }: { workspace: Workspace }) => { ) : ( diff --git a/packages/app/src/components/workspace-setting/style.ts b/packages/app/src/components/workspace-setting/style.ts index f59125a9f..7cf6ac9fc 100644 --- a/packages/app/src/components/workspace-setting/style.ts +++ b/packages/app/src/components/workspace-setting/style.ts @@ -199,11 +199,12 @@ export const StyledMoreVerticalButton = styled('button')(() => { export const StyledPublishExplanation = styled('div')(() => { return { - marginTop: '56px', paddingRight: '48px', fontWeight: '500', fontSize: '18px', lineHeight: '26px', + flex: 1, + marginTop: '60px', }; }); @@ -213,7 +214,9 @@ export const StyledPublishCopyContainer = styled('div')(() => { display: 'flex', flexDirection: 'row', alignItems: 'center', + height: '38px', + paddingTop: '20px', }; }); @@ -226,5 +229,7 @@ export const StyledCopyButtonContainer = styled('div')(() => { export const StyledPublishContent = styled('div')(() => { return { height: '494px', + display: 'flex', + flexDirection: 'column', }; }); diff --git a/packages/app/src/components/workspace-setting/workspace-setting.tsx b/packages/app/src/components/workspace-setting/workspace-setting.tsx index 13180a580..7d292c9b9 100644 --- a/packages/app/src/components/workspace-setting/workspace-setting.tsx +++ b/packages/app/src/components/workspace-setting/workspace-setting.tsx @@ -1,23 +1,7 @@ import Modal, { ModalCloseButton } from '@/ui/modal'; import { - StyledCopyButtonContainer, - StyledMemberAvatar, - StyledMemberButtonContainer, - StyledMemberEmail, - StyledMemberInfo, - StyledMemberListContainer, - StyledMemberListItem, - StyledMemberName, - StyledMemberNameContainer, - StyledMemberRoleContainer, - StyledMemberTitleContainer, - StyledMoreVerticalButton, - StyledPublishContent, - StyledPublishCopyContainer, - StyledPublishExplanation, StyledSettingContainer, StyledSettingContent, - StyledSettingH2, StyledSettingSidebar, StyledSettingSidebarHeader, StyledSettingTabContainer, @@ -28,34 +12,14 @@ import { EditIcon, UsersIcon, PublishIcon, - MoreVerticalIcon, - EmailIcon, - TrashIcon, - DownloadIcon, CloudInsyncIcon, } from '@blocksuite/icons'; import { useEffect, useState } from 'react'; -import { Button, IconButton } from '@/ui/button'; -import Input from '@/ui/input'; -import { InviteMembers } from '../invite-members/index'; -// import { Member, getDataCenter } from '@affine/datacenter'; -// import { Avatar } from '@mui/material'; -import { Menu, MenuItem } from '@/ui/menu'; -import { toast } from '@/ui/toast'; -import { Empty } from '@/ui/empty'; -// import { useAppState } from '@/providers/app-state-provider'; import { GeneralPage } from './general'; -import { - deleteMember, - getActiveWorkspace, - getMembers, - getUserInfo, - Login, - setWorkspacePublish, - updateWorkspaceMeta, - User, - Workspace, -} from '@/hooks/mock-data/mock'; +import { getActiveWorkspace } from '@/hooks/mock-data/mock'; +import MembersPage from './MembersPage'; +import PublishPage from './PublishPage'; +import SyncPage from './SyncPage'; enum ActiveTab { 'general' = 'general', @@ -192,313 +156,3 @@ export const WorkspaceSetting = ({ ); }; - -const MembersPage = ({ workspace }: { workspace: Workspace }) => { - const [isInviteModalShow, setIsInviteModalShow] = useState(false); - const [members, setMembers] = useState([]); - const [userInfo, setUserInfo] = useState(); - // const refreshMembers = useCallback(() => { - // getDataCenter() - // .then(dc => - // dc.apis.getWorkspaceMembers({ - // id: workspace.id, - // }) - // ) - // .then(data => { - // setMembers(data); - // }) - // .catch(err => { - // console.log(err); - // }); - // }, [workspace.id]); - - useEffect(() => { - setUser(); - setMembersList(); - // refreshMembers(); - }, []); - - const setUser = () => { - const user = getUserInfo(); - user && setUserInfo(user); - }; - const setMembersList = () => { - const members = getMembers(workspace.id); - members && setMembers(members); - }; - - return ( -
- {userInfo ? ( - <> - - - Users({members.length}) - - Access level - - - {members.length === 0 && ( - - )} - {members.length ? ( - members.map((member, index) => { - return ( - - - - - - - - {member.name} - - {member.email} - - - - {/* {member.accepted - ? member.type !== 99 - ? 'Member' - : 'Workspace Owner' - : 'Pending'} */} - Pending - - - - { - deleteMember(workspace.id, 0); - setMembersList(); - // confirm({ - // title: 'Delete Member?', - // content: `will delete member`, - // confirmText: 'Delete', - // confirmType: 'danger', - // }).then(confirm => { - // getDataCenter() - // .then(dc => - // dc.apis.removeMember({ - // permissionId: member.id, - // }) - // ) - // .then(() => { - // // console.log('data: ', data); - // toast('Moved to Trash'); - // // refreshMembers(); - // }); - // }); - }} - icon={} - > - Delete - - - } - placement="bottom-end" - disablePortal={true} - > - - - - - - - ); - }) - ) : ( - <> - )} - - - - { - setIsInviteModalShow(false); - }} - onInviteSuccess={() => { - setMembersList(); - setIsInviteModalShow(false); - // refreshMembers(); - }} - workspaceId={workspace.id} - open={isInviteModalShow} - > - - - ) : ( - <> -
- Collaborating with other members requires AFFiNE Cloud service. -
-
- -
- - )} -
- ); -}; - -const PublishPage = ({ workspace }: { workspace: Workspace }) => { - const shareUrl = - window.location.host + '/workspace/' + workspace.id + '?share=true'; - const [publicStatus, setPublicStatus] = useState( - workspace.isPublish ?? false - ); - const togglePublic = (flag: boolean) => { - const isPublic = setWorkspacePublish(workspace.id, flag); - setPublicStatus(isPublic); - }; - - const copyUrl = () => { - navigator.clipboard.writeText(shareUrl); - toast('Copied url to clipboard'); - }; - return ( -
- - {publicStatus ? ( - <> - - The current workspace has been published to the web, everyone can - view the contents of this workspace through the link. - - Share with link - - - - - - - - ) : ( - - After publishing to the web, everyone can view the content of this - workspace through the link. - - )} - - {!publicStatus ? ( - - ) : ( - - )} -
- ); -}; -const SyncPage = ({ workspace }: { workspace: Workspace }) => { - const [workspaceType, setWorkspaceType] = useState('local'); - useEffect(() => { - setType(); - }); - const setType = () => { - const ACTIVEworkspace = getActiveWorkspace(); - console.log('ACTIVEworkspace: ', ACTIVEworkspace); - ACTIVEworkspace && setWorkspaceType(ACTIVEworkspace.type); - }; - return ( -
- - {workspaceType === 'local' ? ( - <> - - {workspace.name} is Local Workspace. All data is stored on the - current device. You can enable AFFiNE Cloud for this workspace to - keep data in sync with the cloud. - - - - - - - - - ) : ( - - {workspace.name} is Cloud Workspace. All data will be - synchronized and saved to the AFFiNE account -
- - { - deleteMember(workspace.id, 0); - }} - icon={} - > - Download core data to device - - { - deleteMember(workspace.id, 0); - }} - icon={} - > - Download all data to device - - - } - placement="bottom-end" - disablePortal={true} - > - - -
-
- )} -
-
- ); -}; diff --git a/packages/app/src/hooks/use-temporary-helper.ts b/packages/app/src/hooks/use-temporary-helper.ts index 8de0ef88a..c2727f165 100644 --- a/packages/app/src/hooks/use-temporary-helper.ts +++ b/packages/app/src/hooks/use-temporary-helper.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { getWorkspaces, Workspace, User } from './mock-data/mock'; export function getActiveWorkspace(): Workspace { @@ -12,16 +12,19 @@ export const useTemporaryHelper = () => { const [currentWorkspace, setCurrentWorkspace] = useState( JSON.parse(localStorage.getItem('affine-active-workspace') ?? '{}') ); - const [user, setUser] = useState(null); + const [user, setUser] = useState(); return { - updateWorkspaceMeta: (workspaceId: string, workspaceData: Workspace) => { + updateWorkspaceMeta: ( + workspaceId: string, + workspaceData: { name?: string; avatar?: string; isPublish?: boolean } + ) => { const workspacesMeta = getWorkspaces(); const newWorkspacesMeta = workspacesMeta.map((workspace: Workspace) => { if (workspace.id === workspaceId) { workspaceData.name && (workspace.name = workspaceData.name); workspaceData.avatar && (workspace.avatar = workspaceData.avatar); - return workspaceData; + return workspace; } return workspace; }); @@ -94,7 +97,7 @@ export const useTemporaryHelper = () => { avatar: 'string', }; localStorage.setItem('affine-user', JSON.stringify(userInfo)); - + console.log('login'); setUser(userInfo); }, getUserInfo: () => {