mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix(server): wrong member count query (#4506)
This commit is contained in:
@@ -21,7 +21,14 @@ import { Tooltip } from '@toeverything/components/tooltip';
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { Suspense, useCallback, useMemo, useState } from 'react';
|
import {
|
||||||
|
Suspense,
|
||||||
|
useCallback,
|
||||||
|
useLayoutEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { ErrorBoundary } from 'react-error-boundary';
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
|
|
||||||
import type { CheckedUser } from '../../../hooks/affine/use-current-user';
|
import type { CheckedUser } from '../../../hooks/affine/use-current-user';
|
||||||
@@ -96,6 +103,20 @@ export const CloudWorkspaceMembersPanel = ({
|
|||||||
[invite, pushNotification, t]
|
[invite, pushNotification, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const listContainerRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const [memberListHeight, setMemberListHeight] = useState<number | null>(null);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (
|
||||||
|
memberCount > COUNT_PER_PAGE &&
|
||||||
|
listContainerRef.current &&
|
||||||
|
memberListHeight === null
|
||||||
|
) {
|
||||||
|
const rect = listContainerRef.current.getBoundingClientRect();
|
||||||
|
setMemberListHeight(rect.height);
|
||||||
|
}
|
||||||
|
}, [listContainerRef, memberCount, memberListHeight]);
|
||||||
|
|
||||||
const onRevoke = useCallback<OnRevoke>(
|
const onRevoke = useCallback<OnRevoke>(
|
||||||
async memberId => {
|
async memberId => {
|
||||||
const res = await revokeMemberPermission(memberId);
|
const res = await revokeMemberPermission(memberId);
|
||||||
@@ -129,7 +150,11 @@ export const CloudWorkspaceMembersPanel = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
|
|
||||||
<div className={style.membersPanel}>
|
<div
|
||||||
|
className={style.membersPanel}
|
||||||
|
ref={listContainerRef}
|
||||||
|
style={memberListHeight ? { height: memberListHeight } : {}}
|
||||||
|
>
|
||||||
<Suspense fallback={<MemberListFallback memberCount={memberCount} />}>
|
<Suspense fallback={<MemberListFallback memberCount={memberCount} />}>
|
||||||
<MemberList
|
<MemberList
|
||||||
workspaceId={workspaceId}
|
workspaceId={workspaceId}
|
||||||
@@ -139,11 +164,13 @@ export const CloudWorkspaceMembersPanel = ({
|
|||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
|
{memberCount > COUNT_PER_PAGE && (
|
||||||
<Pagination
|
<Pagination
|
||||||
totalCount={memberCount}
|
totalCount={memberCount}
|
||||||
countPerPage={COUNT_PER_PAGE}
|
countPerPage={COUNT_PER_PAGE}
|
||||||
onPageChange={onPageChange}
|
onPageChange={onPageChange}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -186,7 +213,7 @@ const MemberList = ({
|
|||||||
const currentUser = useCurrentUser();
|
const currentUser = useCurrentUser();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={style.memberList}>
|
||||||
{members.map(member => (
|
{members.map(member => (
|
||||||
<MemberItem
|
<MemberItem
|
||||||
key={member.id}
|
key={member.id}
|
||||||
@@ -196,7 +223,7 @@ const MemberList = ({
|
|||||||
onRevoke={onRevoke}
|
onRevoke={onRevoke}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -225,8 +252,11 @@ const MemberItem = ({
|
|||||||
}, [currentUser.id, isOwner, member.id, t]);
|
}, [currentUser.id, isOwner, member.id, t]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
<div key={member.id} className={style.listItem} data-testid="member-item">
|
key={member.id}
|
||||||
|
className={style.memberListItem}
|
||||||
|
data-testid="member-item"
|
||||||
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
size={36}
|
size={36}
|
||||||
url={member.avatarUrl}
|
url={member.avatarUrl}
|
||||||
@@ -272,7 +302,6 @@ const MemberItem = ({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -93,14 +93,17 @@ export const membersFallback = style({
|
|||||||
color: 'var(--affine-primary-color)',
|
color: 'var(--affine-primary-color)',
|
||||||
});
|
});
|
||||||
export const membersPanel = style({
|
export const membersPanel = style({
|
||||||
marginTop: '24px',
|
|
||||||
padding: '4px',
|
padding: '4px',
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
background: 'var(--affine-background-primary-color)',
|
background: 'var(--affine-background-primary-color)',
|
||||||
border: '1px solid var(--affine-border-color)',
|
border: '1px solid var(--affine-border-color)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-between',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const listItem = style({
|
export const memberList = style({});
|
||||||
|
export const memberListItem = style({
|
||||||
padding: '0 4px 0 16px',
|
padding: '0 4px 0 16px',
|
||||||
height: '58px',
|
height: '58px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -155,7 +158,7 @@ export const memberEmail = style({
|
|||||||
});
|
});
|
||||||
export const iconButton = style({});
|
export const iconButton = style({});
|
||||||
|
|
||||||
globalStyle(`${listItem}:hover ${iconButton}`, {
|
globalStyle(`${memberListItem}:hover ${iconButton}`, {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
pointerEvents: 'all',
|
pointerEvents: 'all',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,6 +174,9 @@ export class WorkspaceResolver {
|
|||||||
return this.prisma.userWorkspacePermission.count({
|
return this.prisma.userWorkspacePermission.count({
|
||||||
where: {
|
where: {
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
|
userId: {
|
||||||
|
not: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -214,6 +217,9 @@ export class WorkspaceResolver {
|
|||||||
const data = await this.prisma.userWorkspacePermission.findMany({
|
const data = await this.prisma.userWorkspacePermission.findMany({
|
||||||
where: {
|
where: {
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
|
userId: {
|
||||||
|
not: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
skip,
|
skip,
|
||||||
take: take || 8,
|
take: take || 8,
|
||||||
|
|||||||
@@ -173,6 +173,15 @@ type Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
signUp(name: String!, email: String!, password: String!): UserType!
|
||||||
|
signIn(email: String!, password: String!): UserType!
|
||||||
|
changePassword(token: String!, newPassword: String!): UserType!
|
||||||
|
changeEmail(token: String!): UserType!
|
||||||
|
sendChangePasswordEmail(email: String!, callbackUrl: String!): Boolean!
|
||||||
|
sendSetPasswordEmail(email: String!, callbackUrl: String!): Boolean!
|
||||||
|
sendChangeEmail(email: String!, callbackUrl: String!): Boolean!
|
||||||
|
sendVerifyChangeEmail(token: String!, email: String!, callbackUrl: String!): Boolean!
|
||||||
|
|
||||||
"""Create a new workspace"""
|
"""Create a new workspace"""
|
||||||
createWorkspace(init: Upload!): WorkspaceType!
|
createWorkspace(init: Upload!): WorkspaceType!
|
||||||
|
|
||||||
@@ -196,14 +205,6 @@ type Mutation {
|
|||||||
removeAvatar: RemoveAvatar!
|
removeAvatar: RemoveAvatar!
|
||||||
deleteAccount: DeleteAccount!
|
deleteAccount: DeleteAccount!
|
||||||
addToNewFeaturesWaitingList(type: NewFeaturesKind!, email: String!): AddToNewFeaturesWaitingList!
|
addToNewFeaturesWaitingList(type: NewFeaturesKind!, email: String!): AddToNewFeaturesWaitingList!
|
||||||
signUp(name: String!, email: String!, password: String!): UserType!
|
|
||||||
signIn(email: String!, password: String!): UserType!
|
|
||||||
changePassword(token: String!, newPassword: String!): UserType!
|
|
||||||
changeEmail(token: String!): UserType!
|
|
||||||
sendChangePasswordEmail(email: String!, callbackUrl: String!): Boolean!
|
|
||||||
sendSetPasswordEmail(email: String!, callbackUrl: String!): Boolean!
|
|
||||||
sendChangeEmail(email: String!, callbackUrl: String!): Boolean!
|
|
||||||
sendVerifyChangeEmail(token: String!, email: String!, callbackUrl: String!): Boolean!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"""The `Upload` scalar type represents a file upload."""
|
"""The `Upload` scalar type represents a file upload."""
|
||||||
|
|||||||
Reference in New Issue
Block a user