mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 19:53:48 +08:00
feat: support pagination for member list (#4231)
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
"react-dom": "18.2.0",
|
||||
"react-error-boundary": "^4.0.11",
|
||||
"react-is": "^18.2.0",
|
||||
"react-paginate": "^8.2.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './accept-invite-page';
|
||||
export * from './invite-modal';
|
||||
export * from './pagination';
|
||||
|
||||
@@ -15,50 +15,6 @@ export interface InviteModalProps {
|
||||
isMutating: boolean;
|
||||
}
|
||||
|
||||
const PermissionMenu = ({
|
||||
currentPermission,
|
||||
onChange,
|
||||
}: {
|
||||
currentPermission: Permission;
|
||||
onChange: (permission: Permission) => void;
|
||||
}) => {
|
||||
console.log('currentPermission', currentPermission);
|
||||
console.log('onChange', onChange);
|
||||
|
||||
return null;
|
||||
// return (
|
||||
// <Menu
|
||||
// trigger="click"
|
||||
// content={
|
||||
// <>
|
||||
// {Object.entries(Permission).map(([permission]) => {
|
||||
// return (
|
||||
// <MenuItem
|
||||
// key={permission}
|
||||
// onClick={() => {
|
||||
// onChange(permission as Permission);
|
||||
// }}
|
||||
// >
|
||||
// {permission}
|
||||
// </MenuItem>
|
||||
// );
|
||||
// })}
|
||||
// </>
|
||||
// }
|
||||
// >
|
||||
// <MenuTrigger
|
||||
// type="plain"
|
||||
// style={{
|
||||
// marginRight: -10,
|
||||
// height: '100%',
|
||||
// }}
|
||||
// >
|
||||
// {currentPermission}
|
||||
// </MenuTrigger>
|
||||
// </Menu>
|
||||
// );
|
||||
};
|
||||
|
||||
export const InviteModal = ({
|
||||
open,
|
||||
setOpen,
|
||||
@@ -67,7 +23,7 @@ export const InviteModal = ({
|
||||
}: InviteModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [inviteEmail, setInviteEmail] = useState('');
|
||||
const [permission, setPermission] = useState(Permission.Write);
|
||||
const [permission] = useState(Permission.Write);
|
||||
const [isValidEmail, setIsValidEmail] = useState(true);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
@@ -125,12 +81,6 @@ export const InviteModal = ({
|
||||
onEnter={handleConfirm}
|
||||
style={{ marginTop: 20 }}
|
||||
size="large"
|
||||
endFix={
|
||||
<PermissionMenu
|
||||
currentPermission={permission}
|
||||
onChange={setPermission}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.inviteModalButtonContainer}>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { ArrowLeftSmallIcon, ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import ReactPaginate from 'react-paginate';
|
||||
|
||||
import * as styles from './styles.css';
|
||||
export interface PaginationProps {
|
||||
totalCount: number;
|
||||
countPerPage: number;
|
||||
onPageChange: (skip: number) => void;
|
||||
}
|
||||
|
||||
export const Pagination = ({
|
||||
totalCount,
|
||||
countPerPage,
|
||||
onPageChange,
|
||||
}: PaginationProps) => {
|
||||
const handlePageClick = useCallback(
|
||||
(e: { selected: number }) => {
|
||||
const newOffset = (e.selected * countPerPage) % totalCount;
|
||||
onPageChange(newOffset);
|
||||
},
|
||||
[countPerPage, onPageChange, totalCount]
|
||||
);
|
||||
|
||||
const pageCount = useMemo(
|
||||
() => Math.ceil(totalCount / countPerPage),
|
||||
[countPerPage, totalCount]
|
||||
);
|
||||
|
||||
return (
|
||||
<ReactPaginate
|
||||
onPageChange={handlePageClick}
|
||||
pageRangeDisplayed={3}
|
||||
marginPagesDisplayed={2}
|
||||
pageCount={pageCount}
|
||||
previousLabel={<ArrowLeftSmallIcon />}
|
||||
nextLabel={<ArrowRightSmallIcon />}
|
||||
pageClassName={styles.pageItem}
|
||||
previousClassName={clsx(styles.pageItem, 'label')}
|
||||
nextClassName={clsx(styles.pageItem, 'label')}
|
||||
breakLabel="..."
|
||||
breakClassName={styles.pageItem}
|
||||
containerClassName={styles.pagination}
|
||||
activeClassName="active"
|
||||
renderOnZeroPageCount={null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
|
||||
export const inviteModalTitle = style({
|
||||
fontWeight: '600',
|
||||
@@ -21,3 +21,48 @@ export const inviteName = style({
|
||||
marginRight: '10px',
|
||||
color: 'var(--affine-black)',
|
||||
});
|
||||
|
||||
export const pagination = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
marginTop: 5,
|
||||
});
|
||||
|
||||
export const pageItem = style({
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
color: 'var(--affine-text-primary-color)',
|
||||
borderRadius: '4px',
|
||||
|
||||
selectors: {
|
||||
'&:hover': {
|
||||
background: 'var(--affine-hover-color)',
|
||||
},
|
||||
'&.active': {
|
||||
color: 'var(--affine-primary-color)',
|
||||
cursor: 'default',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&.label': {
|
||||
color: 'var(--affine-icon-color)',
|
||||
fontSize: '16px',
|
||||
},
|
||||
'&.disabled': {
|
||||
opacity: '.4',
|
||||
cursor: 'default',
|
||||
color: 'var(--affine-disable-color)',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
});
|
||||
globalStyle(`${pageItem} a`, {
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
query getMemberCountByWorkspaceId($workspaceId: String!) {
|
||||
workspace(id: $workspaceId) {
|
||||
memberCount
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
query getMembersByWorkspaceId($workspaceId: String!) {
|
||||
query getMembersByWorkspaceId($workspaceId: String!, $skip: Int!, $take: Int!) {
|
||||
workspace(id: $workspaceId) {
|
||||
members {
|
||||
members(skip: $skip, take: $take) {
|
||||
id
|
||||
name
|
||||
email
|
||||
|
||||
@@ -204,15 +204,28 @@ query getIsOwner($workspaceId: String!) {
|
||||
}`,
|
||||
};
|
||||
|
||||
export const getMemberCountByWorkspaceIdQuery = {
|
||||
id: 'getMemberCountByWorkspaceIdQuery' as const,
|
||||
operationName: 'getMemberCountByWorkspaceId',
|
||||
definitionName: 'workspace',
|
||||
containsFile: false,
|
||||
query: `
|
||||
query getMemberCountByWorkspaceId($workspaceId: String!) {
|
||||
workspace(id: $workspaceId) {
|
||||
memberCount
|
||||
}
|
||||
}`,
|
||||
};
|
||||
|
||||
export const getMembersByWorkspaceIdQuery = {
|
||||
id: 'getMembersByWorkspaceIdQuery' as const,
|
||||
operationName: 'getMembersByWorkspaceId',
|
||||
definitionName: 'workspace',
|
||||
containsFile: false,
|
||||
query: `
|
||||
query getMembersByWorkspaceId($workspaceId: String!) {
|
||||
query getMembersByWorkspaceId($workspaceId: String!, $skip: Int!, $take: Int!) {
|
||||
workspace(id: $workspaceId) {
|
||||
members {
|
||||
members(skip: $skip, take: $take) {
|
||||
id
|
||||
name
|
||||
email
|
||||
|
||||
@@ -206,8 +206,19 @@ export type GetIsOwnerQueryVariables = Exact<{
|
||||
|
||||
export type GetIsOwnerQuery = { __typename?: 'Query'; isOwner: boolean };
|
||||
|
||||
export type GetMemberCountByWorkspaceIdQueryVariables = Exact<{
|
||||
workspaceId: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
export type GetMemberCountByWorkspaceIdQuery = {
|
||||
__typename?: 'Query';
|
||||
workspace: { __typename?: 'WorkspaceType'; memberCount: number };
|
||||
};
|
||||
|
||||
export type GetMembersByWorkspaceIdQueryVariables = Exact<{
|
||||
workspaceId: Scalars['String']['input'];
|
||||
skip: Scalars['Int']['input'];
|
||||
take: Scalars['Int']['input'];
|
||||
}>;
|
||||
|
||||
export type GetMembersByWorkspaceIdQuery = {
|
||||
@@ -493,6 +504,11 @@ export type Queries =
|
||||
variables: GetIsOwnerQueryVariables;
|
||||
response: GetIsOwnerQuery;
|
||||
}
|
||||
| {
|
||||
name: 'getMemberCountByWorkspaceIdQuery';
|
||||
variables: GetMemberCountByWorkspaceIdQueryVariables;
|
||||
response: GetMemberCountByWorkspaceIdQuery;
|
||||
}
|
||||
| {
|
||||
name: 'getMembersByWorkspaceIdQuery';
|
||||
variables: GetMembersByWorkspaceIdQueryVariables;
|
||||
|
||||
@@ -570,5 +570,6 @@
|
||||
"Workspace Settings with name": "{{name}}'s Settings",
|
||||
"Workspace Type": "Workspace Type",
|
||||
"You cannot delete the last workspace": "You cannot delete the last workspace",
|
||||
"Removed successfully": "Removed successfully",
|
||||
"Successfully enabled AFFiNE Cloud": "Successfully enabled AFFiNE Cloud"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user