Skip to content

Commit

Permalink
feat(core): add CRUD function of workspace member permission
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmFly committed Dec 5, 2024
1 parent fd45731 commit 58d1a5e
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 114 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ import {
MemberLimitModal,
} from '@affine/component/member-components';
import { SettingRow } from '@affine/component/setting-components';
import { useInviteMember } from '@affine/core/components/hooks/affine/use-invite-member';
import { useRevokeMemberPermission } from '@affine/core/components/hooks/affine/use-revoke-member-permission';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { ServerService, SubscriptionService } from '@affine/core/modules/cloud';
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
import { copyTextToClipboard } from '@affine/core/utils/clipboard';
import { UserFriendlyError } from '@affine/graphql';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
import { useLiveData, useService } from '@toeverything/infra';
import { useCallback, useEffect, useMemo, useState } from 'react';

import type { SettingState } from '../../../types';
Expand All @@ -35,7 +32,6 @@ export const CloudWorkspaceMembersPanel = ({
const hasPaymentFeature = useLiveData(
serverService.server.features$.map(f => f?.payment)
);
const workspace = useService(WorkspaceService).workspace;

const permissionService = useService(WorkspacePermissionService);
const isOwner = useLiveData(permissionService.permission.isOwner$);
Expand All @@ -60,21 +56,20 @@ export const CloudWorkspaceMembersPanel = ({
: null;

const t = useI18n();
const { invite, isMutating } = useInviteMember(workspace.id);
const revokeMemberPermission = useRevokeMemberPermission(workspace.id);

const [open, setOpen] = useState(false);
const [isMutating, setIsMutating] = useState(false);

const openModal = useCallback(() => {
setOpen(true);
}, []);

const onInviteConfirm = useCallback<InviteModalProps['onConfirm']>(
async ({ email, permission }) => {
const success = await invite(
setIsMutating(true);
const success = await permissionService.permission.inviteMember(
email,
permission,
// send invite email
true
);
if (success) {
Expand All @@ -84,8 +79,9 @@ export const CloudWorkspaceMembersPanel = ({
});
setOpen(false);
}
setIsMutating(false);
},
[invite, t]
[permissionService.permission, t]
);

const handleUpgradeConfirm = useCallback(() => {
Expand All @@ -98,16 +94,6 @@ export const CloudWorkspaceMembersPanel = ({
});
}, [onChangeSettingState]);

const onRevoke = useAsyncCallback(
async (memberId: string) => {
const res = await revokeMemberPermission(memberId);
if (res?.revoke) {
notify.success({ title: t['Removed successfully']() });
}
},
[revokeMemberPermission, t]
);

const desc = useMemo(() => {
if (!workspaceQuota) return null;

Expand Down Expand Up @@ -188,7 +174,7 @@ export const CloudWorkspaceMembersPanel = ({
</SettingRow>

<div className={styles.membersPanel}>
<MemberList isOwner={!!isOwner} onRevoke={onRevoke} />
<MemberList isOwner={!!isOwner} />
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ import { ConfirmAssignModal } from './confirm-assign-modal';
import { MemberOptions } from './member-option';
import * as styles from './styles.css';

export const MemberList = ({
isOwner,
onRevoke,
}: {
isOwner: boolean;
onRevoke: (memberId: string) => void;
}) => {
export const MemberList = ({ isOwner }: { isOwner: boolean }) => {
const membersService = useService(WorkspaceMembersService);
const memberCount = useLiveData(membersService.members.memberCount$);
const pageNum = useLiveData(membersService.members.pageNum$);
Expand Down Expand Up @@ -80,7 +74,6 @@ export const MemberList = ({
key={member.id}
member={member}
isOwner={isOwner}
onRevoke={onRevoke}
/>
))
)}
Expand All @@ -101,12 +94,10 @@ const MemberItem = ({
member,
isOwner,
currentAccount,
onRevoke,
}: {
member: Member;
isOwner: boolean;
currentAccount: AuthAccountInfo;
onRevoke: (memberId: string) => void;
}) => {
const t = useI18n();
const [open, setOpen] = useState(false);
Expand Down Expand Up @@ -164,7 +155,6 @@ const MemberItem = ({
items={
<MemberOptions
member={member}
onRevoke={onRevoke}
openAssignModal={handleOpenAssignModal}
/>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
import { MenuItem, notify } from '@affine/component';
import type { Member } from '@affine/core/modules/permissions';
import {
type Member,
WorkspacePermissionService,
} from '@affine/core/modules/permissions';
import { useI18n } from '@affine/i18n';
import { useService } from '@toeverything/infra';
import { useCallback, useMemo } from 'react';

export const MemberOptions = ({
member,
onRevoke,
openAssignModal,
}: {
member: Member;
onRevoke: (memberId: string) => void;
openAssignModal: () => void;
}) => {
const t = useI18n();
const permission = useService(WorkspacePermissionService).permission;

const handleAssignOwner = useCallback(() => {
openAssignModal();
}, [openAssignModal]);

const handleRevoke = useCallback(() => {
onRevoke(member.id);
notify.success({
title: t['com.affine.payment.member.team.revoke.notify.title'](),
message: t['com.affine.payment.member.team.revoke.notify.message']({
name: member.name || member.email || member.id,
}),
});
}, [onRevoke, member, t]);
permission
.revokeMember(member.id)
.then(result => {
if (result) {
notify.success({
title: t['com.affine.payment.member.team.revoke.notify.title'](),
message: t['com.affine.payment.member.team.revoke.notify.message']({
name: member.name || member.email || member.id,
}),
});
}
})
.catch(error => {
notify.error({
title: 'Operation failed',
message: error.message,
});
});
}, [permission, member, t]);
const handleApprove = useCallback(() => {
notify.success({
title: t['com.affine.payment.member.team.approve.notify.title'](),
Expand All @@ -35,6 +49,7 @@ export const MemberOptions = ({
}),
});
}, [member, t]);

const handleDecline = useCallback(() => {
notify.success({
title: t['com.affine.payment.member.team.decline.notify.title'](),
Expand All @@ -43,15 +58,28 @@ export const MemberOptions = ({
}),
});
}, [member.email, member.id, member.name, t]);

const handleRemove = useCallback(() => {
onRevoke(member.id);
notify.success({
title: t['com.affine.payment.member.team.remove.notify.title'](),
message: t['com.affine.payment.member.team.remove.notify.message']({
name: member.name || member.email || member.id,
}),
});
}, [member, onRevoke, t]);
permission
.revokeMember(member.id)
.then(result => {
if (result) {
notify.success({
title: t['com.affine.payment.member.team.remove.notify.title'](),
message: t['com.affine.payment.member.team.remove.notify.message']({
name: member.name || member.email || member.id,
}),
});
}
})
.catch(error => {
notify.error({
title: 'Operation failed',
message: error.message,
});
});
}, [member, permission, t]);

const handleChangeToAdmin = useCallback(() => {
notify.success({
title: t['com.affine.payment.member.team.change.notify.title'](),
Expand Down
35 changes: 26 additions & 9 deletions packages/frontend/core/src/desktop/pages/upgrade-to-team/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const Component = () => {
open={openUpgrade}
onOpenChange={setOpenUpgrade}
workspaceName={name}
workspaceId={selectedWorkspace?.id ?? ''}
/>
<CreateAndUpgradeDialog
open={openCreate}
Expand All @@ -129,9 +130,11 @@ const UpgradeDialog = ({
open,
onOpenChange,
workspaceName,
workspaceId,
}: {
open: boolean;
workspaceName: string;
workspaceId: string;
onOpenChange: (open: boolean) => void;
}) => {
const t = useI18n();
Expand Down Expand Up @@ -162,6 +165,11 @@ const UpgradeDialog = ({
recurring={SubscriptionRecurring.Monthly}
plan={SubscriptionPlan.Team}
onCheckoutSuccess={onClose}
checkoutInput={{
args: {
workspaceId,
},
}}
>
{t['com.affine.payment.upgrade']()}
</Upgrade>
Expand Down Expand Up @@ -239,21 +247,25 @@ const CreateAndUpgradeDialog = ({
const onClose = useCallback(() => {
onOpenChange(false);
}, [onOpenChange]);
const [loading, setLoading] = useState(false);
const [name, setName] = useState('');
const workspacesService = useService(WorkspacesService);
const [newWorkspaceId, setNewWorkspaceId] = useState<string | null>(null);

const onConfirmName = useAsyncCallback(async () => {
if (loading) return;
setLoading(true);

await buildShowcaseWorkspace(workspacesService, 'affine-cloud', name);
const onCreate = useCallback(async () => {
const newWorkspace = await buildShowcaseWorkspace(
workspacesService,
'affine-cloud',
name
);
notify.success({
title: 'Workspace Created',
});
setNewWorkspaceId(newWorkspace.meta.id);
}, [name, workspacesService]);

setLoading(false);
}, [loading, name, workspacesService]);
const onBeforeCheckout = useAsyncCallback(async () => {
await onCreate();
}, [onCreate]);

return (
<Modal width={480} open={open} onOpenChange={onOpenChange}>
Expand Down Expand Up @@ -286,7 +298,12 @@ const CreateAndUpgradeDialog = ({
recurring={SubscriptionRecurring.Monthly}
plan={SubscriptionPlan.Team}
onCheckoutSuccess={onClose}
onBeforeCheckout={onConfirmName}
onBeforeCheckout={onBeforeCheckout}
checkoutInput={{
args: {
workspaceId: newWorkspaceId,
},
}}
>
{t[
'com.affine.upgrade-to-team-page.create-and-upgrade-confirm.confirm'
Expand Down
Loading

0 comments on commit 58d1a5e

Please sign in to comment.