mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-24 05:07:06 +08:00
fix(server): member loading (#15156)
#### PR Dependency Tree * **PR #15156** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed Stripe subscription syncing for Team plans to update the correct existing local subscription (avoiding duplicates) while refreshing quantity and billing/trial period details. * **UI/UX Improvements** * Improved workspace member list loading/error states with shared UI components and steadier pagination behavior. * Refined fallback styling for cleaner, more stable layout. * **Tests** * Expanded subscription and projection coverage and adjusted seat-allocation/e2e assertions to be more robust. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
+3
-33
@@ -1,4 +1,4 @@
|
||||
import { Button, Loading, notify, useConfirmModal } from '@affine/component';
|
||||
import { Button, notify, useConfirmModal } from '@affine/component';
|
||||
import {
|
||||
InviteTeamMemberModal,
|
||||
type InviteTeamMemberModalProps,
|
||||
@@ -31,7 +31,7 @@ import { nanoid } from 'nanoid';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import type { SettingState } from '../../types';
|
||||
import { MemberList } from './member-list';
|
||||
import { MemberList, MemberListError, MemberListFallback } from './member-list';
|
||||
import * as styles from './styles.css';
|
||||
|
||||
const parseCSV = async (blob: Blob): Promise<string[]> => {
|
||||
@@ -290,13 +290,7 @@ export const CloudWorkspaceMembersPanel = ({
|
||||
if (isLoading) {
|
||||
return <MembersPanelFallback />;
|
||||
} else {
|
||||
return (
|
||||
<span className={styles.errorStyle}>
|
||||
{error
|
||||
? UserFriendlyError.fromAny(error).message
|
||||
: 'Failed to load members'}
|
||||
</span>
|
||||
);
|
||||
return <MemberListError error={error} memberCount={1} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,30 +352,6 @@ export const MembersPanelFallback = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const MemberListFallback = ({ memberCount }: { memberCount?: number }) => {
|
||||
// prevent page jitter
|
||||
const height = useMemo(() => {
|
||||
if (memberCount) {
|
||||
// height and margin-bottom
|
||||
return memberCount * 58 + (memberCount - 1) * 6;
|
||||
}
|
||||
return 'auto';
|
||||
}, [memberCount]);
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height,
|
||||
}}
|
||||
className={styles.membersFallback}
|
||||
>
|
||||
<Loading size={20} />
|
||||
<span>{t['com.affine.settings.member.loading']()}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ImportCSV = ({ onImport }: { onImport: (file: File) => void }) => {
|
||||
const t = useI18n();
|
||||
|
||||
|
||||
+42
-14
@@ -45,7 +45,6 @@ export const MemberList = ({
|
||||
const handlePageChange = useCallback(
|
||||
(_: number, pageNum: number) => {
|
||||
membersService.members.setPageNum(pageNum);
|
||||
membersService.members.revalidate();
|
||||
},
|
||||
[membersService]
|
||||
);
|
||||
@@ -57,7 +56,7 @@ export const MemberList = ({
|
||||
return (
|
||||
<div>
|
||||
{pageMembers === undefined ? (
|
||||
isLoading ? (
|
||||
isLoading || !error ? (
|
||||
<MemberListFallback
|
||||
memberCount={
|
||||
memberCount
|
||||
@@ -70,11 +69,7 @@ export const MemberList = ({
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<span className={styles.errorStyle}>
|
||||
{error
|
||||
? UserFriendlyError.fromAny(error).message
|
||||
: 'Failed to load members'}
|
||||
</span>
|
||||
<MemberListError error={error} />
|
||||
)
|
||||
) : (
|
||||
pageMembers?.map(member => (
|
||||
@@ -278,19 +273,24 @@ const getMemberStatus = (member: Member): I18nString => {
|
||||
}
|
||||
};
|
||||
|
||||
const getMembersFallbackHeight = (memberCount?: number) => {
|
||||
if (memberCount) {
|
||||
// height and margin-bottom
|
||||
return memberCount * 58 + (memberCount - 1) * 6;
|
||||
}
|
||||
return 'auto';
|
||||
};
|
||||
|
||||
export const MemberListFallback = ({
|
||||
memberCount,
|
||||
}: {
|
||||
memberCount?: number;
|
||||
}) => {
|
||||
// prevent page jitter
|
||||
const height = useMemo(() => {
|
||||
if (memberCount) {
|
||||
// height and margin-bottom
|
||||
return memberCount * 58 + (memberCount - 1) * 6;
|
||||
}
|
||||
return 'auto';
|
||||
}, [memberCount]);
|
||||
const height = useMemo(
|
||||
() => getMembersFallbackHeight(memberCount),
|
||||
[memberCount]
|
||||
);
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
@@ -305,3 +305,31 @@ export const MemberListFallback = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MemberListError = ({
|
||||
error,
|
||||
memberCount,
|
||||
}: {
|
||||
error?: unknown;
|
||||
memberCount?: number;
|
||||
}) => {
|
||||
const height = useMemo(
|
||||
() => getMembersFallbackHeight(memberCount),
|
||||
[memberCount]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height,
|
||||
}}
|
||||
className={styles.membersFallback}
|
||||
>
|
||||
<span className={styles.errorStyle}>
|
||||
{error
|
||||
? UserFriendlyError.fromAny(error).message
|
||||
: 'Failed to load members'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+3
-2
@@ -55,11 +55,12 @@ export const errorStyle = style({
|
||||
export const membersFallback = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flexStart',
|
||||
alignItems: 'center',
|
||||
color: cssVarV2('text/secondary'),
|
||||
gap: '4px',
|
||||
padding: '8px',
|
||||
padding: '16px 8px',
|
||||
fontSize: cssVar('fontXs'),
|
||||
textAlign: 'center',
|
||||
});
|
||||
|
||||
export const memberListItem = style({
|
||||
|
||||
@@ -66,8 +66,9 @@ export class WorkspaceMembers extends Entity {
|
||||
}
|
||||
|
||||
private async requestMembers(signal: AbortSignal) {
|
||||
this.pageMembers$.setValue(undefined);
|
||||
this.isLoading$.setValue(true);
|
||||
this.error$.setValue(null);
|
||||
this.pageMembers$.setValue(undefined);
|
||||
try {
|
||||
const pageNum = this.pageNum$.value;
|
||||
return await this.store.fetchMembers(
|
||||
|
||||
Reference in New Issue
Block a user