mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-27 23:37:03 +03:00
feat: connect with datacenter invite function
This commit is contained in:
parent
e2a9c6c552
commit
0152172dd1
@ -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)(() => {
|
||||
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 './ExportPage';
|
||||
export * from './MembersPage';
|
||||
export * from './member';
|
||||
export * from './SyncPage';
|
||||
export * from './PublishPage';
|
||||
|
@ -4,9 +4,9 @@ import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal';
|
||||
import { Button } from '@/ui/button';
|
||||
import Input from '@/ui/input';
|
||||
import { useState } from 'react';
|
||||
// import { getDataCenter } from '@affine/datacenter';
|
||||
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 {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@ -43,46 +43,27 @@ export const debounce = <T extends (...args: any) => any>(
|
||||
};
|
||||
|
||||
const gmailReg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@gmail\.com$/;
|
||||
export const InviteMembers = ({
|
||||
export const InviteMemberModal = ({
|
||||
open,
|
||||
onClose,
|
||||
workspaceId,
|
||||
onInviteSuccess,
|
||||
}: LoginModalProps) => {
|
||||
const [email, setEmail] = useState<string>('');
|
||||
const [showMember, setShowMember] = useState<boolean>(false);
|
||||
const [showTip, setShowTip] = useState<boolean>(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [userData, setUserData] = useState<any>({});
|
||||
const [userData, setUserData] = useState<User | null>(null);
|
||||
const { inviteMember, getUserByEmail } = useMembers();
|
||||
const inputChange = (value: string) => {
|
||||
setShowMember(true);
|
||||
if (gmailReg.test(value)) {
|
||||
setEmail(value);
|
||||
setShowTip(false);
|
||||
setUserData({
|
||||
name: 'wxl',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/20501502?v=4',
|
||||
email: value,
|
||||
getUserByEmail(value).then(data => {
|
||||
if (data?.name) {
|
||||
setUserData(data);
|
||||
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 {
|
||||
setShowTip(true);
|
||||
}
|
||||
@ -118,8 +99,8 @@ export const InviteMembers = ({
|
||||
<NoFind>Non-Gmail is not supported</NoFind>
|
||||
) : (
|
||||
<Member>
|
||||
{userData?.avatar_url ? (
|
||||
<Avatar src={userData?.avatar_url}></Avatar>
|
||||
{userData?.avatar ? (
|
||||
<Avatar src={userData?.avatar}></Avatar>
|
||||
) : (
|
||||
<MemberIcon>
|
||||
<EmailIcon></EmailIcon>
|
||||
@ -139,19 +120,9 @@ export const InviteMembers = ({
|
||||
<Button
|
||||
shape="circle"
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setMember(workspaceId, userData);
|
||||
onClick={async () => {
|
||||
await inviteMember(email);
|
||||
onInviteSuccess();
|
||||
// getDataCenter()
|
||||
// .then(dc => dc.apis.inviteMember({ id: workspaceId, email }))
|
||||
// .then(() => {
|
||||
// onClose();
|
||||
// onInviteSuccess && onInviteSuccess();
|
||||
// })
|
||||
// .catch(err => {
|
||||
// // toast('Invite failed');
|
||||
// console.log(err);
|
||||
// });
|
||||
}}
|
||||
>
|
||||
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';
|
107
packages/app/src/components/workspace-setting/member/style.ts
Normal file
107
packages/app/src/components/workspace-setting/member/style.ts
Normal file
@ -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')(() => {
|
||||
return {
|
||||
paddingRight: '48px',
|
||||
|
51
packages/app/src/hooks/use-members.ts
Normal file
51
packages/app/src/hooks/use-members.ts
Normal file
@ -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 {
|
||||
createWorkspace,
|
||||
publishWorkspace,
|
||||
updateWorkspace,
|
||||
enableWorkspace,
|
||||
inviteMember,
|
||||
};
|
||||
};
|
||||
|
@ -20,11 +20,9 @@ export const AppStateProvider = ({
|
||||
children,
|
||||
}: PropsWithChildren<AppStateContextProps>) => {
|
||||
const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue);
|
||||
|
||||
useEffect(() => {
|
||||
const initState = async () => {
|
||||
const dataCenter = await getDataCenter();
|
||||
|
||||
// Ensure datacenter has at least one workspace
|
||||
if (dataCenter.workspaces.length === 0) {
|
||||
await createDefaultWorkspace(dataCenter);
|
||||
|
@ -26,7 +26,7 @@ const _initializeDataCenter = () => {
|
||||
export const getDataCenter = _initializeDataCenter();
|
||||
|
||||
export type { DataCenter };
|
||||
export type { AccessTokenMessage } from './provider/affine/apis';
|
||||
export * from './provider/affine/apis';
|
||||
export { WorkspaceUnit } from './workspace-unit';
|
||||
export { getLogger } from './logger';
|
||||
export * from './message';
|
||||
|
Loading…
Reference in New Issue
Block a user