Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): optimize team workspace member management #9737

Merged
merged 1 commit into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const AuthPageContainer: FC<
<div className="wrapper">
<div className="content">
<p className="title">{title}</p>
<p className="subtitle">{subtitle}</p>
<div className="subtitle">{subtitle}</div>
{children}
</div>
<div className={hideInSmallScreen}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './accept-invite-page';
export * from './invite-modal';
export * from './invite-team-modal';
export * from './join-failed-page';
export * from './member-limit-modal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { AuthPageContainer } from '@affine/component/auth-components';
import {
ErrorNames,
type GetInviteInfoQuery,
UserFriendlyError,
} from '@affine/graphql';
import { Trans, useI18n } from '@affine/i18n';

import { Avatar } from '../../ui/avatar';
import * as styles from './styles.css';

export const JoinFailedPage = ({
inviteInfo,
error,
}: {
inviteInfo: GetInviteInfoQuery['getInviteInfo'];
error?: any;
}) => {
const userFriendlyError = UserFriendlyError.fromAnyError(error);
const t = useI18n();
return (
<AuthPageContainer
title={t['com.affine.fail-to-join-workspace.title']()}
subtitle={
userFriendlyError.name === ErrorNames.MEMBER_QUOTA_EXCEEDED ? (
<div className={styles.content}>
<Trans
i18nKey={'com.affine.fail-to-join-workspace.description-1'}
components={{
1: (
<Avatar
url={`data:image/png;base64,${inviteInfo.workspace.avatar}`}
name={inviteInfo.workspace.name}
size={20}
style={{ marginLeft: 4 }}
colorfulFallback
/>
),
2: <span className={styles.inviteName} />,
}}
values={{
workspaceName: inviteInfo.workspace.name,
}}
/>
<div>{t['com.affine.fail-to-join-workspace.description-2']()}</div>
</div>
) : (
<div>{t['error.' + userFriendlyError.name]()}</div>
)
}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import illustrationLight from '../affine-other-page-layout/assets/other-page.lig
import type { User } from '../auth-components';
import {
illustration,
info,
largeButtonEffect,
notFoundPageContainer,
wrapper,
Expand All @@ -35,6 +36,30 @@ export const NoPermissionOrNotFound = ({
<div className={notFoundPageContainer} data-testid="not-found">
{user ? (
<>
<div className={info}>
<p className={wrapper}>{t['404.hint']()}</p>
<div className={wrapper}>
<Button
variant="primary"
size="extraLarge"
onClick={onBack}
className={largeButtonEffect}
>
{t['404.back']()}
</Button>
</div>
<div className={wrapper}>
<Avatar url={user.avatar ?? user.image} name={user.label} />
<span style={{ margin: '0 12px' }}>{user.email}</span>
<IconButton
onClick={onSignOut}
size="20"
tooltip={t['404.signOut']()}
>
<SignOutIcon />
</IconButton>
</div>
</div>
<div className={wrapper}>
<ThemedImg
draggable={false}
Expand All @@ -43,28 +68,6 @@ export const NoPermissionOrNotFound = ({
darkSrc={illustrationDark}
/>
</div>
<p className={wrapper}>{t['404.hint']()}</p>
<div className={wrapper}>
<Button
variant="primary"
size="extraLarge"
onClick={onBack}
className={largeButtonEffect}
>
{t['404.back']()}
</Button>
</div>
<div className={wrapper}>
<Avatar url={user.avatar ?? user.image} name={user.label} />
<span style={{ margin: '0 12px' }}>{user.email}</span>
<IconButton
onClick={onSignOut}
size="20"
tooltip={t['404.signOut']()}
>
<SignOutIcon />
</IconButton>
</div>
</>
) : (
signInComponent
Expand All @@ -84,6 +87,32 @@ export const NotFoundPage = ({
return (
<AffineOtherPageLayout>
<div className={notFoundPageContainer} data-testid="not-found">
<div className={info}>
<p className={wrapper}>{t['404.hint']()}</p>
<div className={wrapper}>
<Button
variant="primary"
size="extraLarge"
onClick={onBack}
className={largeButtonEffect}
>
{t['404.back']()}
</Button>
</div>
{user ? (
<div className={wrapper}>
<Avatar url={user.avatar ?? user.image} name={user.label} />
<span style={{ margin: '0 12px' }}>{user.email}</span>
<IconButton
onClick={onSignOut}
size="20"
tooltip={t['404.signOut']()}
>
<SignOutIcon />
</IconButton>
</div>
) : null}
</div>
<div className={wrapper}>
<ThemedImg
draggable={false}
Expand All @@ -92,31 +121,6 @@ export const NotFoundPage = ({
darkSrc={illustrationDark}
/>
</div>
<p className={wrapper}>{t['404.hint']()}</p>
<div className={wrapper}>
<Button
variant="primary"
size="extraLarge"
onClick={onBack}
className={largeButtonEffect}
>
{t['404.back']()}
</Button>
</div>

{user ? (
<div className={wrapper}>
<Avatar url={user.avatar ?? user.image} name={user.label} />
<span style={{ margin: '0 12px' }}>{user.email}</span>
<IconButton
onClick={onSignOut}
size="20"
tooltip={t['404.signOut']()}
>
<SignOutIcon />
</IconButton>
</div>
) : null}
</div>
</AffineOtherPageLayout>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,29 @@ import { style } from '@vanilla-extract/css';
export const notFoundPageContainer = style({
fontSize: cssVar('fontBase'),
color: cssVar('textPrimaryColor'),
height: '100vh',
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
padding: '0 20px',
});
export const wrapper = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '24px auto 0',
margin: '0 auto',
});
export const info = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: '24px',
textAlign: 'center',
marginTop: 'auto',
paddingTop: '120px',
marginBottom: 'auto',
});
export const largeButtonEffect = style({
boxShadow: `${cssVar('largeButtonEffect')} !important`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { notify } from '@affine/component';
import { useDowngradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
import { getDowngradeQuestionnaireLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { SubscriptionPlan } from '@affine/graphql';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { useLiveData, useService } from '@toeverything/infra';
import { nanoid } from 'nanoid';
Expand Down Expand Up @@ -231,6 +233,7 @@ export const TeamResumeAction = ({
const [idempotencyKey, setIdempotencyKey] = useState(nanoid());
const [isMutating, setIsMutating] = useState(false);
const subscription = useService(WorkspaceSubscriptionService).subscription;
const t = useI18n();

const resume = useAsyncCallback(async () => {
try {
Expand All @@ -243,10 +246,14 @@ export const TeamResumeAction = ({
// refresh idempotency key
setIdempotencyKey(nanoid());
onOpenChange(false);
notify.success({
title: t['com.affine.payment.resume.success.title'](),
message: t['com.affine.payment.resume.success.team.message'](),
});
} finally {
setIsMutating(false);
}
}, [subscription, idempotencyKey, onOpenChange]);
}, [subscription, idempotencyKey, onOpenChange, t]);

return (
<>
Expand Down
Loading
Loading