fix(admin): frequent query requests in the search (#7854)
This commit is contained in:
@@ -4,7 +4,13 @@ import { useQuery } from '@affine/core/hooks/use-query';
|
|||||||
import { getUserByEmailQuery } from '@affine/graphql';
|
import { getUserByEmailQuery } from '@affine/graphql';
|
||||||
import { PlusIcon } from 'lucide-react';
|
import { PlusIcon } from 'lucide-react';
|
||||||
import type { SetStateAction } from 'react';
|
import type { SetStateAction } from 'react';
|
||||||
import { startTransition, useCallback, useEffect, useState } from 'react';
|
import {
|
||||||
|
startTransition,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
import { useRightPanel } from '../../layout';
|
import { useRightPanel } from '../../layout';
|
||||||
import { DiscardChanges } from './discard-changes';
|
import { DiscardChanges } from './discard-changes';
|
||||||
@@ -15,6 +21,21 @@ interface DataTableToolbarProps<TData> {
|
|||||||
setDataTable: (data: TData[]) => void;
|
setDataTable: (data: TData[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useSearch = () => {
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
const { data } = useQuery({
|
||||||
|
query: getUserByEmailQuery,
|
||||||
|
variables: { email: value },
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = useMemo(() => data?.userByEmail, [data]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
result,
|
||||||
|
query: setValue,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function useDebouncedValue<T>(value: T, delay: number): T {
|
function useDebouncedValue<T>(value: T, delay: number): T {
|
||||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||||
|
|
||||||
@@ -37,9 +58,10 @@ export function DataTableToolbar<TData>({
|
|||||||
}: DataTableToolbarProps<TData>) {
|
}: DataTableToolbarProps<TData>) {
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState('');
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const debouncedValue = useDebouncedValue(value, 500);
|
const debouncedValue = useDebouncedValue(value, 1000);
|
||||||
const { setRightPanelContent, openPanel, closePanel, isOpen } =
|
const { setRightPanelContent, openPanel, closePanel, isOpen } =
|
||||||
useRightPanel();
|
useRightPanel();
|
||||||
|
const { result, query } = useSearch();
|
||||||
|
|
||||||
const handleConfirm = useCallback(() => {
|
const handleConfirm = useCallback(() => {
|
||||||
setRightPanelContent(<CreateUserForm onComplete={closePanel} />);
|
setRightPanelContent(<CreateUserForm onComplete={closePanel} />);
|
||||||
@@ -51,12 +73,9 @@ export function DataTableToolbar<TData>({
|
|||||||
}
|
}
|
||||||
}, [setRightPanelContent, closePanel, dialogOpen, isOpen, openPanel]);
|
}, [setRightPanelContent, closePanel, dialogOpen, isOpen, openPanel]);
|
||||||
|
|
||||||
const result = useQuery({
|
useEffect(() => {
|
||||||
query: getUserByEmailQuery,
|
query(debouncedValue);
|
||||||
variables: {
|
}, [debouncedValue, query]);
|
||||||
email: value,
|
|
||||||
},
|
|
||||||
}).data.userByEmail;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
@@ -68,13 +87,11 @@ export function DataTableToolbar<TData>({
|
|||||||
setDataTable([]);
|
setDataTable([]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [data, debouncedValue, result, setDataTable, value]);
|
}, [data, debouncedValue, result, setDataTable]);
|
||||||
|
|
||||||
const onValueChange = useCallback(
|
const onValueChange = useCallback(
|
||||||
(e: { currentTarget: { value: SetStateAction<string> } }) => {
|
(e: { currentTarget: { value: SetStateAction<string> } }) => {
|
||||||
startTransition(() => {
|
setValue(e.currentTarget.value);
|
||||||
setValue(e.currentTarget.value);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import {
|
|||||||
TableCell,
|
TableCell,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '@affine/admin/components/ui/table';
|
} from '@affine/admin/components/ui/table';
|
||||||
import { useQuery } from '@affine/core/hooks/use-query';
|
|
||||||
import { getUsersCountQuery } from '@affine/graphql';
|
|
||||||
import type { ColumnDef, PaginationState } from '@tanstack/react-table';
|
import type { ColumnDef, PaginationState } from '@tanstack/react-table';
|
||||||
import {
|
import {
|
||||||
flexRender,
|
flexRender,
|
||||||
@@ -17,6 +15,7 @@ import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
|
|||||||
|
|
||||||
import { DataTablePagination } from './data-table-pagination';
|
import { DataTablePagination } from './data-table-pagination';
|
||||||
import { DataTableToolbar } from './data-table-toolbar';
|
import { DataTableToolbar } from './data-table-toolbar';
|
||||||
|
import { useUserCount } from './use-user-management';
|
||||||
|
|
||||||
interface DataTableProps<TData, TValue> {
|
interface DataTableProps<TData, TValue> {
|
||||||
columns: ColumnDef<TData, TValue>[];
|
columns: ColumnDef<TData, TValue>[];
|
||||||
@@ -36,11 +35,7 @@ export function DataTable<TData, TValue>({
|
|||||||
pagination,
|
pagination,
|
||||||
onPaginationChange,
|
onPaginationChange,
|
||||||
}: DataTableProps<TData, TValue>) {
|
}: DataTableProps<TData, TValue>) {
|
||||||
const {
|
const usersCount = useUserCount();
|
||||||
data: { usersCount },
|
|
||||||
} = useQuery({
|
|
||||||
query: getUsersCountQuery,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [tableData, setTableData] = useState(data);
|
const [tableData, setTableData] = useState(data);
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import {
|
|||||||
useMutateQueryResource,
|
useMutateQueryResource,
|
||||||
useMutation,
|
useMutation,
|
||||||
} from '@affine/core/hooks/use-mutation';
|
} from '@affine/core/hooks/use-mutation';
|
||||||
|
import { useQuery } from '@affine/core/hooks/use-query';
|
||||||
import {
|
import {
|
||||||
createChangePasswordUrlMutation,
|
createChangePasswordUrlMutation,
|
||||||
createUserMutation,
|
createUserMutation,
|
||||||
deleteUserMutation,
|
deleteUserMutation,
|
||||||
|
getUsersCountQuery,
|
||||||
listUsersQuery,
|
listUsersQuery,
|
||||||
updateAccountFeaturesMutation,
|
updateAccountFeaturesMutation,
|
||||||
updateAccountMutation,
|
updateAccountMutation,
|
||||||
@@ -159,3 +161,12 @@ export const useDeleteUser = () => {
|
|||||||
|
|
||||||
return deleteById;
|
return deleteById;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useUserCount = () => {
|
||||||
|
const {
|
||||||
|
data: { usersCount },
|
||||||
|
} = useQuery({
|
||||||
|
query: getUsersCountQuery,
|
||||||
|
});
|
||||||
|
return usersCount;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,27 +1,11 @@
|
|||||||
import { Separator } from '@affine/admin/components/ui/separator';
|
import { Separator } from '@affine/admin/components/ui/separator';
|
||||||
import { useQuery } from '@affine/core/hooks/use-query';
|
|
||||||
import { listUsersQuery } from '@affine/graphql';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
import { columns } from './components/columns';
|
import { columns } from './components/columns';
|
||||||
import { DataTable } from './components/data-table';
|
import { DataTable } from './components/data-table';
|
||||||
|
import { useUserList } from './use-user-list';
|
||||||
|
|
||||||
export function AccountPage() {
|
export function AccountPage() {
|
||||||
const [pagination, setPagination] = useState({
|
const { users, pagination, setPagination } = useUserList();
|
||||||
pageIndex: 0,
|
|
||||||
pageSize: 10,
|
|
||||||
});
|
|
||||||
const {
|
|
||||||
data: { users },
|
|
||||||
} = useQuery({
|
|
||||||
query: listUsersQuery,
|
|
||||||
variables: {
|
|
||||||
filter: {
|
|
||||||
first: pagination.pageSize,
|
|
||||||
skip: pagination.pageIndex * pagination.pageSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className=" h-screen flex-1 flex-col flex">
|
<div className=" h-screen flex-1 flex-col flex">
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { useQuery } from '@affine/core/hooks/use-query';
|
||||||
|
import { listUsersQuery } from '@affine/graphql';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
export const useUserList = () => {
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
data: { users },
|
||||||
|
} = useQuery({
|
||||||
|
query: listUsersQuery,
|
||||||
|
variables: {
|
||||||
|
filter: {
|
||||||
|
first: pagination.pageSize,
|
||||||
|
skip: pagination.pageIndex * pagination.pageSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
users,
|
||||||
|
pagination,
|
||||||
|
setPagination,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -6,36 +6,14 @@ import {
|
|||||||
} from '@affine/admin/components/ui/card';
|
} from '@affine/admin/components/ui/card';
|
||||||
import { ScrollArea } from '@affine/admin/components/ui/scroll-area';
|
import { ScrollArea } from '@affine/admin/components/ui/scroll-area';
|
||||||
import { Separator } from '@affine/admin/components/ui/separator';
|
import { Separator } from '@affine/admin/components/ui/separator';
|
||||||
import { useQueryImmutable } from '@affine/core/hooks/use-query';
|
|
||||||
import { getServerServiceConfigsQuery } from '@affine/graphql';
|
|
||||||
|
|
||||||
import { AboutAFFiNE } from './about';
|
import { AboutAFFiNE } from './about';
|
||||||
|
import type {
|
||||||
type ServerConfig = {
|
DatabaseConfig,
|
||||||
externalUrl: string;
|
MailerConfig,
|
||||||
https: boolean;
|
ServerConfig,
|
||||||
host: string;
|
} from './use-server-service-configs';
|
||||||
port: number;
|
import { useServerServiceConfigs } from './use-server-service-configs';
|
||||||
path: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type MailerConfig = {
|
|
||||||
host: string;
|
|
||||||
port: number;
|
|
||||||
sender: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type DatabaseConfig = {
|
|
||||||
host: string;
|
|
||||||
port: number;
|
|
||||||
user: string;
|
|
||||||
database: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ServerServiceConfig = {
|
|
||||||
name: string;
|
|
||||||
config: ServerConfig | MailerConfig | DatabaseConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ConfigPage() {
|
export function ConfigPage() {
|
||||||
return (
|
return (
|
||||||
@@ -166,22 +144,8 @@ const MailerCard = ({ mailerConfig }: { mailerConfig?: MailerConfig }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function ServerServiceConfig() {
|
export function ServerServiceConfig() {
|
||||||
const { data } = useQueryImmutable({
|
const { serverConfig, mailerConfig, databaseConfig } =
|
||||||
query: getServerServiceConfigsQuery,
|
useServerServiceConfigs();
|
||||||
});
|
|
||||||
const server = data.serverServiceConfigs.find(
|
|
||||||
(service: ServerServiceConfig) => service.name === 'server'
|
|
||||||
);
|
|
||||||
const mailer = data.serverServiceConfigs.find(
|
|
||||||
(service: ServerServiceConfig) => service.name === 'mailer'
|
|
||||||
);
|
|
||||||
const database = data.serverServiceConfigs.find(
|
|
||||||
(service: ServerServiceConfig) => service.name === 'database'
|
|
||||||
);
|
|
||||||
|
|
||||||
const serverConfig = server?.config as ServerConfig | undefined;
|
|
||||||
const mailerConfig = mailer?.config as MailerConfig | undefined;
|
|
||||||
const databaseConfig = database?.config as DatabaseConfig | undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col py-5 px-6">
|
<div className="flex flex-col py-5 px-6">
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { useQueryImmutable } from '@affine/core/hooks/use-query';
|
||||||
|
import { getServerServiceConfigsQuery } from '@affine/graphql';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export type ServerConfig = {
|
||||||
|
externalUrl: string;
|
||||||
|
https: boolean;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MailerConfig = {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
sender: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DatabaseConfig = {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
user: string;
|
||||||
|
database: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerServiceConfig = {
|
||||||
|
name: string;
|
||||||
|
config: ServerConfig | MailerConfig | DatabaseConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useServerServiceConfigs = () => {
|
||||||
|
const { data } = useQueryImmutable({
|
||||||
|
query: getServerServiceConfigsQuery,
|
||||||
|
});
|
||||||
|
const server = useMemo(
|
||||||
|
() =>
|
||||||
|
data.serverServiceConfigs.find(
|
||||||
|
(service: ServerServiceConfig) => service.name === 'server'
|
||||||
|
),
|
||||||
|
[data.serverServiceConfigs]
|
||||||
|
);
|
||||||
|
const mailer = useMemo(
|
||||||
|
() =>
|
||||||
|
data.serverServiceConfigs.find(
|
||||||
|
(service: ServerServiceConfig) => service.name === 'mailer'
|
||||||
|
),
|
||||||
|
[data.serverServiceConfigs]
|
||||||
|
);
|
||||||
|
const database = useMemo(
|
||||||
|
() =>
|
||||||
|
data.serverServiceConfigs.find(
|
||||||
|
(service: ServerServiceConfig) => service.name === 'database'
|
||||||
|
),
|
||||||
|
[data.serverServiceConfigs]
|
||||||
|
);
|
||||||
|
|
||||||
|
const serverConfig = server?.config as ServerConfig | undefined;
|
||||||
|
const mailerConfig = mailer?.config as MailerConfig | undefined;
|
||||||
|
const databaseConfig = database?.config as DatabaseConfig | undefined;
|
||||||
|
|
||||||
|
return { serverConfig, mailerConfig, databaseConfig };
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user