mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-23 13:02:21 +08:00
feat: connect with datacenter invite function
This commit is contained in:
@@ -1,214 +0,0 @@
|
|||||||
import {
|
|
||||||
StyledMemberAvatar,
|
|
||||||
StyledMemberButtonContainer,
|
|
||||||
StyledMemberEmail,
|
|
||||||
StyledMemberInfo,
|
|
||||||
StyledMemberListContainer,
|
|
||||||
StyledMemberListItem,
|
|
||||||
StyledMemberName,
|
|
||||||
StyledMemberNameContainer,
|
|
||||||
StyledMemberRoleContainer,
|
|
||||||
StyledMemberTitleContainer,
|
|
||||||
StyledMoreVerticalButton,
|
|
||||||
StyledPublishExplanation,
|
|
||||||
} from './style';
|
|
||||||
import { MoreVerticalIcon, EmailIcon, TrashIcon } from '@blocksuite/icons';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Button, IconButton } from '@/ui/button';
|
|
||||||
import { InviteMembers } from '../invite-members/index';
|
|
||||||
import { Menu, MenuItem } from '@/ui/menu';
|
|
||||||
import { Empty } from '@/ui/empty';
|
|
||||||
// import {
|
|
||||||
// deleteMember,
|
|
||||||
// getMembers,
|
|
||||||
// User,
|
|
||||||
// Workspace,
|
|
||||||
// } from '@/hooks/mock-data/mock';
|
|
||||||
import { WorkspaceUnit } from '@affine/datacenter';
|
|
||||||
import { useTemporaryHelper } from '@/providers/temporary-helper-provider';
|
|
||||||
import { StyledMemberWarp } from './general/style';
|
|
||||||
import { useConfirm } from '@/providers/ConfirmProvider';
|
|
||||||
// import { useAppState } from '@/providers/app-state-provider';
|
|
||||||
|
|
||||||
// import { useAppState } from '@/providers/app-state-provider';
|
|
||||||
export const MembersPage = ({ workspace }: { workspace: WorkspaceUnit }) => {
|
|
||||||
const [isInviteModalShow, setIsInviteModalShow] = useState(false);
|
|
||||||
|
|
||||||
const [members, setMembers] = useState<[{ name: string; email: string }?]>(
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
// const getMembers = async () =>{
|
|
||||||
// const members = await dataCenter.
|
|
||||||
// }
|
|
||||||
|
|
||||||
console.log('setMembers: ', setMembers);
|
|
||||||
const { user, login, updateWorkspaceMeta } = useTemporaryHelper();
|
|
||||||
const { confirm } = useConfirm();
|
|
||||||
// const refreshMembers = useCallback(() => {
|
|
||||||
// getDataCenter()
|
|
||||||
// .then(dc =>
|
|
||||||
// dc.apis.getWorkspaceMembers({
|
|
||||||
// id: workspace.id,
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// .then(data => {
|
|
||||||
// setMembers(data);
|
|
||||||
// })
|
|
||||||
// .catch(err => {
|
|
||||||
// console.log(err);
|
|
||||||
// });
|
|
||||||
// }, [workspace.id]);
|
|
||||||
const setMembersList = () => {
|
|
||||||
// setMembers([]);
|
|
||||||
// const members = getMembers(workspace.id);
|
|
||||||
// members && setMembers(members);
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
setMembersList();
|
|
||||||
// refreshMembers();
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{workspace.provider === 'affine' ? (
|
|
||||||
<>
|
|
||||||
<StyledMemberTitleContainer>
|
|
||||||
<StyledMemberNameContainer>
|
|
||||||
Users({members.length})
|
|
||||||
</StyledMemberNameContainer>
|
|
||||||
<StyledMemberRoleContainer>Access level</StyledMemberRoleContainer>
|
|
||||||
</StyledMemberTitleContainer>
|
|
||||||
<StyledMemberListContainer>
|
|
||||||
{members.length ? (
|
|
||||||
members.map((member, index) => {
|
|
||||||
return (
|
|
||||||
<StyledMemberListItem key={index}>
|
|
||||||
<StyledMemberNameContainer>
|
|
||||||
<StyledMemberAvatar alt="member avatar">
|
|
||||||
<EmailIcon></EmailIcon>
|
|
||||||
</StyledMemberAvatar>
|
|
||||||
|
|
||||||
<StyledMemberInfo>
|
|
||||||
<StyledMemberName>{member?.name}</StyledMemberName>
|
|
||||||
|
|
||||||
<StyledMemberEmail>{member?.email}</StyledMemberEmail>
|
|
||||||
</StyledMemberInfo>
|
|
||||||
</StyledMemberNameContainer>
|
|
||||||
<StyledMemberRoleContainer>
|
|
||||||
{/* {member.accepted
|
|
||||||
? member.type !== 99
|
|
||||||
? 'Member'
|
|
||||||
: 'Workspace Owner'
|
|
||||||
: 'Pending'} */}
|
|
||||||
Pending
|
|
||||||
</StyledMemberRoleContainer>
|
|
||||||
<StyledMoreVerticalButton>
|
|
||||||
<Menu
|
|
||||||
content={
|
|
||||||
<>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
// 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={<TrashIcon />}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</MenuItem>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
placement="bottom-end"
|
|
||||||
disablePortal={true}
|
|
||||||
>
|
|
||||||
<IconButton>
|
|
||||||
<MoreVerticalIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Menu>
|
|
||||||
</StyledMoreVerticalButton>
|
|
||||||
</StyledMemberListItem>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<Empty
|
|
||||||
width={648}
|
|
||||||
sx={{ marginTop: '60px' }}
|
|
||||||
height={300}
|
|
||||||
></Empty>
|
|
||||||
)}
|
|
||||||
</StyledMemberListContainer>
|
|
||||||
<StyledMemberButtonContainer>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setIsInviteModalShow(true);
|
|
||||||
}}
|
|
||||||
type="primary"
|
|
||||||
shape="circle"
|
|
||||||
>
|
|
||||||
Invite Members
|
|
||||||
</Button>
|
|
||||||
<InviteMembers
|
|
||||||
onClose={() => {
|
|
||||||
setIsInviteModalShow(false);
|
|
||||||
}}
|
|
||||||
onInviteSuccess={() => {
|
|
||||||
setMembersList();
|
|
||||||
setIsInviteModalShow(false);
|
|
||||||
// refreshMembers();
|
|
||||||
}}
|
|
||||||
workspaceId={workspace.id}
|
|
||||||
open={isInviteModalShow}
|
|
||||||
></InviteMembers>
|
|
||||||
</StyledMemberButtonContainer>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<StyledMemberWarp>
|
|
||||||
<>Collaborating with other members requires AFFiNE Cloud service.</>
|
|
||||||
<StyledPublishExplanation>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
shape="circle"
|
|
||||||
onClick={() => {
|
|
||||||
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 (confirm) {
|
|
||||||
if (user) {
|
|
||||||
updateWorkspaceMeta(workspace.id, { isPublish: true });
|
|
||||||
} else {
|
|
||||||
login();
|
|
||||||
updateWorkspaceMeta(workspace.id, { isPublish: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Enable AFFiNE Cloud
|
|
||||||
</Button>
|
|
||||||
</StyledPublishExplanation>
|
|
||||||
</StyledMemberWarp>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -26,11 +26,3 @@ export const StyledSettingAvatarContent = styled('div')(() => {
|
|||||||
export const StyledSettingAvatar = styled(MuiAvatar)(() => {
|
export const StyledSettingAvatar = styled(MuiAvatar)(() => {
|
||||||
return { height: '72px', width: '72px', marginRight: '24px' };
|
return { height: '72px', width: '72px', marginRight: '24px' };
|
||||||
});
|
});
|
||||||
|
|
||||||
export const StyledMemberWarp = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
padding: '40px 0',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export * from './general';
|
export * from './general';
|
||||||
export * from './ExportPage';
|
export * from './ExportPage';
|
||||||
export * from './MembersPage';
|
export * from './member';
|
||||||
export * from './SyncPage';
|
export * from './SyncPage';
|
||||||
export * from './PublishPage';
|
export * from './PublishPage';
|
||||||
|
|||||||
+14
-43
@@ -4,9 +4,9 @@ import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal';
|
|||||||
import { Button } from '@/ui/button';
|
import { Button } from '@/ui/button';
|
||||||
import Input from '@/ui/input';
|
import Input from '@/ui/input';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
// import { getDataCenter } from '@affine/datacenter';
|
|
||||||
import { Avatar } from '@mui/material';
|
import { Avatar } from '@mui/material';
|
||||||
import { setMember } from '@/hooks/mock-data/mock';
|
import useMembers from '@/hooks/use-members';
|
||||||
|
import { User } from '@affine/datacenter';
|
||||||
interface LoginModalProps {
|
interface LoginModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -43,46 +43,27 @@ export const debounce = <T extends (...args: any) => any>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const gmailReg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@gmail\.com$/;
|
const gmailReg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@gmail\.com$/;
|
||||||
export const InviteMembers = ({
|
export const InviteMemberModal = ({
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
workspaceId,
|
|
||||||
onInviteSuccess,
|
onInviteSuccess,
|
||||||
}: LoginModalProps) => {
|
}: LoginModalProps) => {
|
||||||
const [email, setEmail] = useState<string>('');
|
const [email, setEmail] = useState<string>('');
|
||||||
const [showMember, setShowMember] = useState<boolean>(false);
|
const [showMember, setShowMember] = useState<boolean>(false);
|
||||||
const [showTip, setShowTip] = useState<boolean>(false);
|
const [showTip, setShowTip] = useState<boolean>(false);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const [userData, setUserData] = useState<User | null>(null);
|
||||||
const [userData, setUserData] = useState<any>({});
|
const { inviteMember, getUserByEmail } = useMembers();
|
||||||
const inputChange = (value: string) => {
|
const inputChange = (value: string) => {
|
||||||
setShowMember(true);
|
setShowMember(true);
|
||||||
if (gmailReg.test(value)) {
|
if (gmailReg.test(value)) {
|
||||||
setEmail(value);
|
setEmail(value);
|
||||||
setShowTip(false);
|
setShowTip(false);
|
||||||
setUserData({
|
getUserByEmail(value).then(data => {
|
||||||
name: 'wxl',
|
if (data?.name) {
|
||||||
avatar: 'https://avatars.githubusercontent.com/u/20501502?v=4',
|
setUserData(data);
|
||||||
email: value,
|
setShowTip(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// debounce(
|
|
||||||
// () => {
|
|
||||||
// getDataCenter()
|
|
||||||
// .then(dc =>
|
|
||||||
// dc.apis.getUserByEmail({
|
|
||||||
// email: value,
|
|
||||||
// workspace_id: workspaceId,
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// .then(data => {
|
|
||||||
// if (data?.name) {
|
|
||||||
// setUserData(data);
|
|
||||||
// setShowTip(false);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// 300,
|
|
||||||
// true
|
|
||||||
// )();
|
|
||||||
} else {
|
} else {
|
||||||
setShowTip(true);
|
setShowTip(true);
|
||||||
}
|
}
|
||||||
@@ -118,8 +99,8 @@ export const InviteMembers = ({
|
|||||||
<NoFind>Non-Gmail is not supported</NoFind>
|
<NoFind>Non-Gmail is not supported</NoFind>
|
||||||
) : (
|
) : (
|
||||||
<Member>
|
<Member>
|
||||||
{userData?.avatar_url ? (
|
{userData?.avatar ? (
|
||||||
<Avatar src={userData?.avatar_url}></Avatar>
|
<Avatar src={userData?.avatar}></Avatar>
|
||||||
) : (
|
) : (
|
||||||
<MemberIcon>
|
<MemberIcon>
|
||||||
<EmailIcon></EmailIcon>
|
<EmailIcon></EmailIcon>
|
||||||
@@ -139,19 +120,9 @@ export const InviteMembers = ({
|
|||||||
<Button
|
<Button
|
||||||
shape="circle"
|
shape="circle"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
setMember(workspaceId, userData);
|
await inviteMember(email);
|
||||||
onInviteSuccess();
|
onInviteSuccess();
|
||||||
// getDataCenter()
|
|
||||||
// .then(dc => dc.apis.inviteMember({ id: workspaceId, email }))
|
|
||||||
// .then(() => {
|
|
||||||
// onClose();
|
|
||||||
// onInviteSuccess && onInviteSuccess();
|
|
||||||
// })
|
|
||||||
// .catch(err => {
|
|
||||||
// // toast('Invite failed');
|
|
||||||
// console.log(err);
|
|
||||||
// });
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Invite
|
Invite
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import {
|
||||||
|
StyledMemberAvatar,
|
||||||
|
StyledMemberButtonContainer,
|
||||||
|
StyledMemberEmail,
|
||||||
|
StyledMemberInfo,
|
||||||
|
StyledMemberListContainer,
|
||||||
|
StyledMemberListItem,
|
||||||
|
StyledMemberName,
|
||||||
|
StyledMemberNameContainer,
|
||||||
|
StyledMemberRoleContainer,
|
||||||
|
StyledMemberTitleContainer,
|
||||||
|
StyledMoreVerticalButton,
|
||||||
|
StyledPublishExplanation,
|
||||||
|
StyledMemberWarp,
|
||||||
|
} from './style';
|
||||||
|
import { MoreVerticalIcon, EmailIcon, TrashIcon } from '@blocksuite/icons';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Button, IconButton } from '@/ui/button';
|
||||||
|
import { InviteMemberModal } from './InviteMemberModal';
|
||||||
|
import { Menu, MenuItem } from '@/ui/menu';
|
||||||
|
import { Empty } from '@/ui/empty';
|
||||||
|
import { WorkspaceUnit } from '@affine/datacenter';
|
||||||
|
import { useTemporaryHelper } from '@/providers/temporary-helper-provider';
|
||||||
|
import { useConfirm } from '@/providers/ConfirmProvider';
|
||||||
|
import { toast } from '@/ui/toast';
|
||||||
|
import useMembers from '@/hooks/use-members';
|
||||||
|
import Loading from '@/components/loading';
|
||||||
|
import { Wrapper } from '@/ui/layout';
|
||||||
|
|
||||||
|
export const MembersPage = ({ workspace }: { workspace: WorkspaceUnit }) => {
|
||||||
|
const [isInviteModalShow, setIsInviteModalShow] = useState(false);
|
||||||
|
const { members, removeMember, loaded } = useMembers();
|
||||||
|
|
||||||
|
// FIXME: DELETE THIS
|
||||||
|
const { user, login, updateWorkspaceMeta } = useTemporaryHelper();
|
||||||
|
const { confirm } = useConfirm();
|
||||||
|
|
||||||
|
if (workspace.provider === 'affine') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StyledMemberListContainer>
|
||||||
|
{!loaded && (
|
||||||
|
<Wrapper justifyContent="center">
|
||||||
|
<Loading size={25} />
|
||||||
|
</Wrapper>
|
||||||
|
)}
|
||||||
|
{loaded && members.length === 0 && (
|
||||||
|
<Empty width={648} sx={{ marginTop: '60px' }} height={300} />
|
||||||
|
)}
|
||||||
|
{loaded && members.length && (
|
||||||
|
<>
|
||||||
|
<StyledMemberTitleContainer>
|
||||||
|
<StyledMemberNameContainer>
|
||||||
|
Users({members.length})
|
||||||
|
</StyledMemberNameContainer>
|
||||||
|
<StyledMemberRoleContainer>
|
||||||
|
Access level
|
||||||
|
</StyledMemberRoleContainer>
|
||||||
|
</StyledMemberTitleContainer>
|
||||||
|
{members.map((member, index) => {
|
||||||
|
const user = Object.assign(
|
||||||
|
{
|
||||||
|
avatar_url: '',
|
||||||
|
email: '',
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
member.user
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<StyledMemberListItem key={index}>
|
||||||
|
<StyledMemberNameContainer>
|
||||||
|
<StyledMemberAvatar
|
||||||
|
alt="member avatar"
|
||||||
|
src={user.avatar_url}
|
||||||
|
>
|
||||||
|
<EmailIcon />
|
||||||
|
</StyledMemberAvatar>
|
||||||
|
|
||||||
|
<StyledMemberInfo>
|
||||||
|
<StyledMemberName>{user.name}</StyledMemberName>
|
||||||
|
<StyledMemberEmail>
|
||||||
|
{member.user.email}
|
||||||
|
</StyledMemberEmail>
|
||||||
|
</StyledMemberInfo>
|
||||||
|
</StyledMemberNameContainer>
|
||||||
|
<StyledMemberRoleContainer>
|
||||||
|
{member.accepted
|
||||||
|
? member.type !== 99
|
||||||
|
? 'Member'
|
||||||
|
: 'Workspace Owner'
|
||||||
|
: 'Pending'}
|
||||||
|
</StyledMemberRoleContainer>
|
||||||
|
<StyledMoreVerticalButton>
|
||||||
|
<Menu
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
<MenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
const confirmRemove = await confirm({
|
||||||
|
title: 'Delete Member?',
|
||||||
|
content: `will delete member`,
|
||||||
|
confirmText: 'Delete',
|
||||||
|
confirmType: 'danger',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmRemove) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await removeMember(member.id);
|
||||||
|
toast(`${user.name} has been removed`);
|
||||||
|
}}
|
||||||
|
icon={<TrashIcon />}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
placement="bottom-end"
|
||||||
|
disablePortal={true}
|
||||||
|
>
|
||||||
|
<IconButton>
|
||||||
|
<MoreVerticalIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Menu>
|
||||||
|
</StyledMoreVerticalButton>
|
||||||
|
</StyledMemberListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</StyledMemberListContainer>
|
||||||
|
<StyledMemberButtonContainer>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsInviteModalShow(true);
|
||||||
|
}}
|
||||||
|
type="primary"
|
||||||
|
shape="circle"
|
||||||
|
>
|
||||||
|
Invite Members
|
||||||
|
</Button>
|
||||||
|
<InviteMemberModal
|
||||||
|
onClose={() => {
|
||||||
|
setIsInviteModalShow(false);
|
||||||
|
}}
|
||||||
|
onInviteSuccess={() => {
|
||||||
|
setIsInviteModalShow(false);
|
||||||
|
// refreshMembers();
|
||||||
|
}}
|
||||||
|
workspaceId={workspace.id}
|
||||||
|
open={isInviteModalShow}
|
||||||
|
></InviteMemberModal>
|
||||||
|
</StyledMemberButtonContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledMemberWarp>
|
||||||
|
<>Collaborating with other members requires AFFiNE Cloud service.</>
|
||||||
|
<StyledPublishExplanation>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
shape="circle"
|
||||||
|
onClick={() => {
|
||||||
|
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 (confirm) {
|
||||||
|
if (user) {
|
||||||
|
updateWorkspaceMeta(workspace.id, { isPublish: true });
|
||||||
|
} else {
|
||||||
|
login();
|
||||||
|
updateWorkspaceMeta(workspace.id, { isPublish: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Enable AFFiNE Cloud
|
||||||
|
</Button>
|
||||||
|
</StyledPublishExplanation>
|
||||||
|
</StyledMemberWarp>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './MembersPage';
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import { styled } from '@/styles';
|
||||||
|
import MuiAvatar from '@mui/material/Avatar';
|
||||||
|
import { Button } from '@/ui/button';
|
||||||
|
|
||||||
|
export const StyledMemberTitleContainer = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
marginTop: '60px',
|
||||||
|
fontWeight: '500',
|
||||||
|
flex: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberAvatar = styled(MuiAvatar)(() => {
|
||||||
|
return { height: '40px', width: '40px' };
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberNameContainer = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '402px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberRoleContainer = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '222px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberListContainer = styled('ul')(() => {
|
||||||
|
return {
|
||||||
|
marginTop: '15px',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberListItem = styled('li')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '72px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberInfo = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
paddingLeft: '12px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberName = styled('div')(({ theme }) => {
|
||||||
|
return {
|
||||||
|
fontWeight: '400',
|
||||||
|
fontSize: '18px',
|
||||||
|
lineHeight: '16px',
|
||||||
|
color: theme.colors.textColor,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberEmail = styled('div')(({ theme }) => {
|
||||||
|
return {
|
||||||
|
fontWeight: '400',
|
||||||
|
fontSize: '16px',
|
||||||
|
lineHeight: '22px',
|
||||||
|
color: theme.colors.iconColor,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberButtonContainer = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
marginTop: '14px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMoreVerticalButton = styled('button')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '24px',
|
||||||
|
height: '24px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledPublishExplanation = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
paddingRight: '48px',
|
||||||
|
fontWeight: '500',
|
||||||
|
fontSize: '18px',
|
||||||
|
lineHeight: '26px',
|
||||||
|
flex: 1,
|
||||||
|
marginTop: '60px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const StyledMemberWarp = styled('div')(() => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '40px 0',
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -96,99 +96,6 @@ export const StyledSettingH2 = styled('h2')<{ marginTop?: number }>(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const StyledAvatarUploadBtn = styled(Button)(({ theme }) => {
|
|
||||||
return {
|
|
||||||
backgroundColor: theme.colors.hoverBackground,
|
|
||||||
color: theme.colors.primaryColor,
|
|
||||||
margin: '0 12px 0 24px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberTitleContainer = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
marginTop: '60px',
|
|
||||||
fontWeight: '500',
|
|
||||||
flex: 1,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberAvatar = styled(MuiAvatar)(() => {
|
|
||||||
return { height: '40px', width: '40px' };
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberNameContainer = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '402px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberRoleContainer = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '222px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberListContainer = styled('ul')(() => {
|
|
||||||
return {
|
|
||||||
marginTop: '15px',
|
|
||||||
overflowY: 'scroll',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberListItem = styled('li')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
height: '72px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberInfo = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
paddingLeft: '12px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberName = styled('div')(({ theme }) => {
|
|
||||||
return {
|
|
||||||
fontWeight: '400',
|
|
||||||
fontSize: '18px',
|
|
||||||
lineHeight: '16px',
|
|
||||||
color: theme.colors.textColor,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberEmail = styled('div')(({ theme }) => {
|
|
||||||
return {
|
|
||||||
fontWeight: '400',
|
|
||||||
fontSize: '16px',
|
|
||||||
lineHeight: '22px',
|
|
||||||
color: theme.colors.iconColor,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMemberButtonContainer = styled('div')(() => {
|
|
||||||
return {
|
|
||||||
marginTop: '14px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledMoreVerticalButton = styled('button')(() => {
|
|
||||||
return {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '24px',
|
|
||||||
height: '24px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledPublishExplanation = styled('div')(() => {
|
export const StyledPublishExplanation = styled('div')(() => {
|
||||||
return {
|
return {
|
||||||
paddingRight: '48px',
|
paddingRight: '48px',
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { Member } from '@affine/datacenter';
|
||||||
|
import { useAppState } from '@/providers/app-state-provider';
|
||||||
|
export const useMembers = () => {
|
||||||
|
const { dataCenter, currentWorkspace } = useAppState();
|
||||||
|
const [members, setMembers] = useState<Member[]>([]);
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
const refreshMembers = useCallback(async () => {
|
||||||
|
if (!currentWorkspace || !dataCenter) return;
|
||||||
|
const members = await dataCenter.getMembers(currentWorkspace.id);
|
||||||
|
setMembers(members);
|
||||||
|
}, [dataCenter, currentWorkspace]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const init = async () => {
|
||||||
|
await refreshMembers();
|
||||||
|
setLoaded(true);
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}, [refreshMembers]);
|
||||||
|
|
||||||
|
const inviteMember = async (email: string) => {
|
||||||
|
currentWorkspace &&
|
||||||
|
dataCenter &&
|
||||||
|
(await dataCenter.inviteMember(currentWorkspace?.id, email));
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeMember = async (permissionId: number) => {
|
||||||
|
if (!currentWorkspace || !dataCenter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoaded(false);
|
||||||
|
await dataCenter.removeMember(currentWorkspace.id, permissionId);
|
||||||
|
await refreshMembers();
|
||||||
|
setLoaded(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserByEmail = async (email: string) => {
|
||||||
|
if (!currentWorkspace) return null;
|
||||||
|
return dataCenter?.getUserByEmail(currentWorkspace.id, email);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
members,
|
||||||
|
removeMember,
|
||||||
|
inviteMember,
|
||||||
|
getUserByEmail,
|
||||||
|
loaded,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useMembers;
|
||||||
@@ -56,16 +56,10 @@ export const useWorkspaceHelper = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const inviteMember = async (email: string) => {
|
|
||||||
currentWorkspace &&
|
|
||||||
(await dataCenter.inviteMember(currentWorkspace?.id, email));
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createWorkspace,
|
createWorkspace,
|
||||||
publishWorkspace,
|
publishWorkspace,
|
||||||
updateWorkspace,
|
updateWorkspace,
|
||||||
enableWorkspace,
|
enableWorkspace,
|
||||||
inviteMember,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ export const AppStateProvider = ({
|
|||||||
children,
|
children,
|
||||||
}: PropsWithChildren<AppStateContextProps>) => {
|
}: PropsWithChildren<AppStateContextProps>) => {
|
||||||
const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue);
|
const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initState = async () => {
|
const initState = async () => {
|
||||||
const dataCenter = await getDataCenter();
|
const dataCenter = await getDataCenter();
|
||||||
|
|
||||||
// Ensure datacenter has at least one workspace
|
// Ensure datacenter has at least one workspace
|
||||||
if (dataCenter.workspaces.length === 0) {
|
if (dataCenter.workspaces.length === 0) {
|
||||||
await createDefaultWorkspace(dataCenter);
|
await createDefaultWorkspace(dataCenter);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const _initializeDataCenter = () => {
|
|||||||
export const getDataCenter = _initializeDataCenter();
|
export const getDataCenter = _initializeDataCenter();
|
||||||
|
|
||||||
export type { DataCenter };
|
export type { DataCenter };
|
||||||
export type { AccessTokenMessage } from './provider/affine/apis';
|
export * from './provider/affine/apis';
|
||||||
export { WorkspaceUnit } from './workspace-unit';
|
export { WorkspaceUnit } from './workspace-unit';
|
||||||
export { getLogger } from './logger';
|
export { getLogger } from './logger';
|
||||||
export * from './message';
|
export * from './message';
|
||||||
|
|||||||
Reference in New Issue
Block a user