Support observable grid queries and file filters
This commit is contained in:
@@ -126,11 +126,16 @@ type DataGridBaseProps<T> = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Query ownership is deliberately explicit: client grids receive all rows and
|
* Query ownership is deliberately explicit: client grids receive all rows and
|
||||||
* DataGrid queries them locally; server grids receive one page and must handle
|
* DataGrid queries them locally, while optional `onQueryChange` observers can
|
||||||
* the complete query through `onQueryChange`.
|
* explain the current match. Server grids receive one page and must handle the
|
||||||
|
* complete query through `onQueryChange`.
|
||||||
*/
|
*/
|
||||||
export type DataGridProps<T> = DataGridBaseProps<T> & (
|
export type DataGridProps<T> = DataGridBaseProps<T> & (
|
||||||
| {pagination?: DataGridClientPagination;onQueryChange?: never;}
|
| {
|
||||||
|
pagination?: DataGridClientPagination;
|
||||||
|
/** Observe client-side filters and sorting without taking ownership of them. */
|
||||||
|
onQueryChange?: (query: DataGridQueryState) => void;
|
||||||
|
}
|
||||||
| {pagination: DataGridServerPagination;onQueryChange: (query: DataGridQueryState) => void;}
|
| {pagination: DataGridServerPagination;onQueryChange: (query: DataGridQueryState) => void;}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -256,7 +261,7 @@ export default function DataGrid<T>({
|
|||||||
const serverQueryMode = pagination?.mode === "server";
|
const serverQueryMode = pagination?.mode === "server";
|
||||||
const onQueryChangeRef = useRef(onQueryChange);
|
const onQueryChangeRef = useRef(onQueryChange);
|
||||||
const serverPaginationRef = useRef<DataGridServerPagination | null>(serverQueryMode ? pagination : null);
|
const serverPaginationRef = useRef<DataGridServerPagination | null>(serverQueryMode ? pagination : null);
|
||||||
const lastServerQueryRef = useRef<DataGridQueryState | null>(null);
|
const lastQueryRef = useRef<DataGridQueryState | null>(null);
|
||||||
const lastLayoutSignatureRef = useRef<string | null>(null);
|
const lastLayoutSignatureRef = useRef<string | null>(null);
|
||||||
const lastContainerWidthRef = useRef<number | undefined>(undefined);
|
const lastContainerWidthRef = useRef<number | undefined>(undefined);
|
||||||
const [measuredWidths, setMeasuredWidths] = useState<Record<string, number>>({});
|
const [measuredWidths, setMeasuredWidths] = useState<Record<string, number>>({});
|
||||||
@@ -265,7 +270,6 @@ export default function DataGrid<T>({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
serverPaginationRef.current = serverQueryMode ? pagination as DataGridServerPagination : null;
|
serverPaginationRef.current = serverQueryMode ? pagination as DataGridServerPagination : null;
|
||||||
if (!serverQueryMode) lastServerQueryRef.current = null;
|
|
||||||
}, [pagination, serverQueryMode]);
|
}, [pagination, serverQueryMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -510,18 +514,23 @@ export default function DataGrid<T>({
|
|||||||
}, [openFilterColumnId]);
|
}, [openFilterColumnId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!serverQueryMode) return;
|
const nextQuery = {
|
||||||
const query = {
|
|
||||||
sort: state.sort ?? null,
|
sort: state.sort ?? null,
|
||||||
filters: { ...(state.filters ?? {}) }
|
filters: { ...(state.filters ?? {}) }
|
||||||
};
|
};
|
||||||
const previousQuery = lastServerQueryRef.current;
|
const previousQuery = lastQueryRef.current;
|
||||||
lastServerQueryRef.current = query;
|
lastQueryRef.current = nextQuery;
|
||||||
const serverPagination = serverPaginationRef.current;
|
const serverPagination = serverPaginationRef.current;
|
||||||
if (previousQuery && !dataGridQueriesEqual(previousQuery, query) && serverPagination && serverPagination.page !== 1) {
|
if (
|
||||||
|
serverQueryMode &&
|
||||||
|
previousQuery &&
|
||||||
|
!dataGridQueriesEqual(previousQuery, nextQuery) &&
|
||||||
|
serverPagination &&
|
||||||
|
serverPagination.page !== 1
|
||||||
|
) {
|
||||||
serverPagination.onPageChange(1);
|
serverPagination.onPageChange(1);
|
||||||
}
|
}
|
||||||
onQueryChangeRef.current?.(query);
|
onQueryChangeRef.current?.(nextQuery);
|
||||||
}, [serverQueryMode, state.sort, state.filters]);
|
}, [serverQueryMode, state.sort, state.filters]);
|
||||||
|
|
||||||
const filterTypes = useMemo(() => {
|
const filterTypes = useMemo(() => {
|
||||||
|
|||||||
@@ -857,7 +857,7 @@ export type FilesFileFolder = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type FilesFileSpacesResponse = { spaces: FilesFileSpace[] };
|
export type FilesFileSpacesResponse = { spaces: FilesFileSpace[] };
|
||||||
export type FilesFileListResponse = { files: FilesManagedFile[]; cursor?: string | null; next_cursor?: string | null };
|
export type FilesFileListResponse = { files: FilesManagedFile[]; total: number; cursor?: string | null; next_cursor?: string | null };
|
||||||
export type FilesFileFoldersResponse = { folders: FilesFileFolder[]; cursor?: string | null; next_cursor?: string | null };
|
export type FilesFileFoldersResponse = { folders: FilesFileFolder[]; cursor?: string | null; next_cursor?: string | null };
|
||||||
export type FilesFileDeltaResponse = {
|
export type FilesFileDeltaResponse = {
|
||||||
files: FilesManagedFile[];
|
files: FilesManagedFile[];
|
||||||
@@ -917,7 +917,7 @@ export type FilesFileExplorerUiCapability = {
|
|||||||
FolderTree: ComponentType<FilesFolderTreeProps>;
|
FolderTree: ComponentType<FilesFolderTreeProps>;
|
||||||
ManagedFileChooser?: ComponentType<FilesManagedFileChooserProps>;
|
ManagedFileChooser?: ComponentType<FilesManagedFileChooserProps>;
|
||||||
listFileSpaces?: (settings: ApiSettings) => Promise<FilesFileSpacesResponse>;
|
listFileSpaces?: (settings: ApiSettings) => Promise<FilesFileSpacesResponse>;
|
||||||
listFiles?: (settings: ApiSettings, params?: { owner_type?: FilesOwnerType | string; owner_id?: string; campaign_id?: string; path_prefix?: string; page_size?: number; cursor?: string | null }) => Promise<FilesFileListResponse>;
|
listFiles?: (settings: ApiSettings, params?: { owner_type?: FilesOwnerType | string; owner_id?: string; campaign_id?: string; path_prefix?: string; campaign_usage?: "linked" | "unlinked"; audit_relevant?: boolean; page_size?: number; cursor?: string | null }) => Promise<FilesFileListResponse>;
|
||||||
listFilesDelta?: (settings: ApiSettings, params?: { owner_type?: FilesOwnerType | string; owner_id?: string; campaign_id?: string; path_prefix?: string; since?: string | null; limit?: number }) => Promise<FilesFileDeltaResponse>;
|
listFilesDelta?: (settings: ApiSettings, params?: { owner_type?: FilesOwnerType | string; owner_id?: string; campaign_id?: string; path_prefix?: string; since?: string | null; limit?: number }) => Promise<FilesFileDeltaResponse>;
|
||||||
listFolders?: (settings: ApiSettings, params: { owner_type: FilesOwnerType; owner_id: string; page_size?: number; cursor?: string | null }) => Promise<FilesFileFoldersResponse>;
|
listFolders?: (settings: ApiSettings, params: { owner_type: FilesOwnerType; owner_id: string; page_size?: number; cursor?: string | null }) => Promise<FilesFileFoldersResponse>;
|
||||||
resolveFilePatterns?: (
|
resolveFilePatterns?: (
|
||||||
|
|||||||
Reference in New Issue
Block a user