Skip to content

Commit

Permalink
CB-5511 fix: pagination (#2906)
Browse files Browse the repository at this point in the history
* CB-5511 fix: pagination

* CB-5511 chore: remove unused code

---------

Co-authored-by: Evgenia Bezborodova <[email protected]>
  • Loading branch information
Wroud and EvgeniaBzzz authored Sep 16, 2024
1 parent 6e575d3 commit 9e657d2
Show file tree
Hide file tree
Showing 23 changed files with 377 additions and 144 deletions.
1 change: 0 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"streetsidesoftware.code-spell-checker",
"streetsidesoftware.code-spell-checker-russian",
"syler.sass-indented",
"VisualStudioExptTeam.intellicode-api-usage-examples",
"VisualStudioExptTeam.vscodeintellicode",
"yzhang.markdown-all-in-one",
"GraphQL.vscode-graphql-syntax",
Expand Down
16 changes: 14 additions & 2 deletions webapp/packages/core-authentication/src/UsersResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { runInAction } from 'mobx';

import { injectable } from '@cloudbeaver/core-di';
import {
CACHED_RESOURCE_DEFAULT_PAGE_LIMIT,
Expand Down Expand Up @@ -240,6 +242,7 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
}

const usersList: AdminUser[] = [];
const pages: Parameters<typeof this.offsetPagination.setPage>[] = [];

await ResourceKeyUtils.forEachAsync(originalKey, async key => {
let userId: string | undefined;
Expand Down Expand Up @@ -290,12 +293,21 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso

usersList.push(...users);

this.offsetPagination.setPageEnd(CachedResourceOffsetPageListKey(offset, users.length).setTarget(filterKey), users.length === limit);
pages.push([
CachedResourceOffsetPageListKey(offset, users.length).setParent(filterKey!),
users.map(user => user.userId),
users.length === limit,
]);
}
});

const key = resourceKeyList(usersList.map(user => user.userId));
this.set(key, usersList);
runInAction(() => {
this.set(key, usersList);
for (const pageArgs of pages) {
this.offsetPagination.setPage(...pageArgs);
}
});

return this.data;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import {
CachedMapResource,
CachedResourceOffsetPageKey,
CachedResourceOffsetPageListKey,
CachedResourceOffsetPageTargetKey,
getNextPageOffset,
ICachedResourceOffsetPageOptions,
isResourceAlias,
ResourceKey,
ResourceKeyAlias,
ResourceKeyList,
Expand All @@ -30,7 +32,10 @@ interface IOptions<TKey extends ResourceKey<any>> {
}

interface IOffsetPagination<TKey> {
key: TKey extends ResourceKeyListAlias<any, any> | ResourceKeyList<any>
currentPage: TKey extends ResourceKeyListAlias<any, any> | ResourceKeyList<any>
? ResourceKeyListAlias<any, Readonly<ICachedResourceOffsetPageOptions>>
: ResourceKeyAlias<any, Readonly<ICachedResourceOffsetPageOptions>>;
allPages: TKey extends ResourceKeyListAlias<any, any> | ResourceKeyList<any>
? ResourceKeyListAlias<any, Readonly<ICachedResourceOffsetPageOptions>>
: ResourceKeyAlias<any, Readonly<ICachedResourceOffsetPageOptions>>;
hasNextPage: boolean;
Expand All @@ -42,6 +47,7 @@ interface IOffsetPaginationPrivate<TKey extends ResourceKey<any>> extends IOffse
offset: number;
resource: CachedMapResource<any, any, any, any>;
_key: ResourceKeyAlias<any, Readonly<ICachedResourceOffsetPageOptions>> | ResourceKeyListAlias<any, Readonly<ICachedResourceOffsetPageOptions>>;
_target: TKey | undefined;
}

export function useOffsetPagination<TResource extends CachedMapResource<any, any, any, any>, TKey extends ResourceKey<any>>(
Expand All @@ -61,40 +67,47 @@ export function useOffsetPagination<TResource extends CachedMapResource<any, any
() => ({
offset,
_key: createPageKey(offset, pageSize, targetKey),
get key() {
const pageInfo = resource.offsetPagination.getPageInfo(createPageKey(0, 0, this._key.target));

for (const page of pageInfo?.pages || []) {
if (page.outdated && page.from < this._key.options.offset) {
return createPageKey(page.from, this._key.options.limit, this._key.target);
_target: targetKey,
get currentPage() {
for (let i = 0; i < this.offset; i += this._key.options.limit) {
const key = createPageKey(i, this._key.options.limit, this._target);
if (resource.isOutdated(key)) {
return key;
}
}

return this._key as any;
},
get allPages(): any {
return createPageKey(0, this._key.options.offset + this._key.options.limit, this._target);
},
get hasNextPage(): boolean {
return this.resource.offsetPagination.hasNextPage(this._key);
},
loadMore() {
if (this.hasNextPage) {
this._key = createPageKey(this._key.options.offset + this._key.options.limit, this._key.options.limit, this._key.target);
this._key = createPageKey(this._key.options.offset + this._key.options.limit, this._key.options.limit, this._target);
}
},
refresh() {
this.resource.markOutdated(this._key.target);
this.resource.markOutdated(this._target);
},
}),
{
_key: observable.ref,
key: computed,
offset: observable.ref,
currentPage: computed,
allPages: computed,
hasNextPage: computed,
loadMore: action.bound,
refresh: action.bound,
},
{ resource },
);

if (!resource.isIntersect(targetKey, pagination._key.target)) {
if (!resource.isIntersect(targetKey, pagination._target)) {
pagination._key = createPageKey(offset, pageSize, targetKey);
pagination._target = targetKey;
}

return pagination;
Expand All @@ -103,10 +116,11 @@ export function useOffsetPagination<TResource extends CachedMapResource<any, any
function createPageKey(
offset: number,
limit: number,
target: ResourceKey<any>,
next: ResourceKey<any>,
): ResourceKeyAlias<any, Readonly<ICachedResourceOffsetPageOptions>> | ResourceKeyListAlias<any, Readonly<ICachedResourceOffsetPageOptions>> {
if (target instanceof ResourceKeyList || target instanceof ResourceKeyListAlias) {
return CachedResourceOffsetPageListKey(offset, limit).setTarget(target);
const parent = isResourceAlias(next) ? next : CachedResourceOffsetPageTargetKey(next);
if (next instanceof ResourceKeyList || next instanceof ResourceKeyListAlias) {
return CachedResourceOffsetPageListKey(offset, limit).setParent(parent);
}
return CachedResourceOffsetPageKey(offset, limit).setTarget(target);
return CachedResourceOffsetPageKey(offset, limit).setParent(parent);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
CachedMapResource,
CachedResourceOffsetPageKey,
CachedResourceOffsetPageListKey,
CachedResourceOffsetPageTargetKey,
isResourceAlias,
type ResourceKey,
resourceKeyList,
Expand Down Expand Up @@ -47,7 +48,8 @@ export class DBObjectResource extends CachedMapResource<string, DBObject> {
const pageAlias = this.aliases.isAlias(nodeId, CachedResourceOffsetPageKey) || this.aliases.isAlias(nodeId, CachedResourceOffsetPageListKey);

if (pageAlias) {
this.markOutdated(DBObjectParentKey(pageAlias.target));
const pageTarget = this.aliases.isAlias(nodeId, CachedResourceOffsetPageTargetKey);
this.markOutdated(DBObjectParentKey(pageTarget?.options.target));
}

if (!isResourceAlias(nodeId)) {
Expand All @@ -70,7 +72,9 @@ export class DBObjectResource extends CachedMapResource<string, DBObject> {
}

if (parentKey) {
await this.navTreeResource.load(CachedResourceOffsetPageKey(offset, limit).setTarget(parentKey.options.parentId));
await this.navTreeResource.load(
CachedResourceOffsetPageKey(offset, limit).setParent(CachedResourceOffsetPageTargetKey(parentKey.options.parentId)),
);
return;
}

Expand Down Expand Up @@ -105,14 +109,21 @@ export class DBObjectResource extends CachedMapResource<string, DBObject> {

if (parentKey) {
const nodeId = parentKey.options.parentId;
await this.loadFromChildren(nodeId, offset, limit);
const dbObjects = await this.loadFromChildren(nodeId, offset, limit);

runInAction(() => {
this.offsetPagination.setPageEnd(
CachedResourceOffsetPageKey(offset, limit).setTarget(originalKey),
this.navTreeResource.offsetPagination.hasNextPage(CachedResourceOffsetPageKey(offset, limit).setTarget(nodeId)),
const keys = dbObjects.map(dbObject => dbObject.id);
this.set(resourceKeyList(keys), dbObjects);

this.offsetPagination.setPage(
CachedResourceOffsetPageKey(offset, limit).setParent(CachedResourceOffsetPageTargetKey(originalKey)),
keys,
this.navTreeResource.offsetPagination.hasNextPage(
CachedResourceOffsetPageKey(offset, limit).setParent(CachedResourceOffsetPageTargetKey(nodeId)),
),
);
});

return this.data;
}

Expand All @@ -128,14 +139,14 @@ export class DBObjectResource extends CachedMapResource<string, DBObject> {
return this.data;
}

private async loadFromChildren(parentId: string, offset: number, limit: number) {
private async loadFromChildren(parentId: string, offset: number, limit: number): Promise<DBObject[]> {
const { dbObjects } = await this.graphQLService.sdk.getChildrenDBObjectInfo({
navNodeId: parentId,
offset,
limit,
});

this.set(resourceKeyList(dbObjects.map(dbObject => dbObject.id)), dbObjects);
return dbObjects;
}

private async loadDBObjectInfo(navNodeId: string): Promise<DBObject> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
CachedMapResource,
CachedResourceOffsetPageKey,
CachedResourceOffsetPageListKey,
CachedResourceOffsetPageTargetKey,
type ICachedResourceMetadata,
isResourceAlias,
isResourceKeyList,
Expand Down Expand Up @@ -463,6 +464,7 @@ export class NavTreeResource extends CachedMapResource<string, string[], Record<
const pageKey =
this.aliases.isAlias(originalKey, CachedResourceOffsetPageKey) || this.aliases.isAlias(originalKey, CachedResourceOffsetPageListKey);
const allKey = this.aliases.isAlias(originalKey, CachedMapAllKey);
const pageTarget = this.aliases.isAlias(originalKey, CachedResourceOffsetPageTargetKey);

if (allKey) {
throw new Error('Loading all nodes is prohibited');
Expand All @@ -471,19 +473,27 @@ export class NavTreeResource extends CachedMapResource<string, string[], Record<
const offset = pageKey?.options.offset ?? CACHED_RESOURCE_DEFAULT_PAGE_OFFSET;
const limit = pageKey?.options.limit ?? this.childrenLimit;
const values: NavNodeChildrenQuery[] = [];
const pages: Parameters<typeof this.offsetPagination.setPage>[] = [];

await ResourceKeyUtils.forEachAsync(originalKey, async key => {
const nodeId = pageKey?.target ?? key;
const nodeId = pageTarget?.options?.target ?? key;
const navNodeChildren = await this.loadNodeChildren(nodeId, offset, limit);
values.push(navNodeChildren);

this.offsetPagination.setPageEnd(
CachedResourceOffsetPageKey(offset, navNodeChildren.navNodeChildren.length).setTarget(nodeId),
pages.push([
CachedResourceOffsetPageKey(offset, navNodeChildren.navNodeChildren.length).setParent(CachedResourceOffsetPageTargetKey(nodeId)),
navNodeChildren.navNodeChildren.map(node => node.id),
navNodeChildren.navNodeChildren.length === limit,
);
]);
});

this.setNavObject(values, offset, limit);
runInAction(() => {
this.setNavObject(values, offset, limit);

for (const pageArgs of pages) {
this.offsetPagination.setPage(...pageArgs);
}
});

return this.data;
}
Expand Down
Loading

0 comments on commit 9e657d2

Please sign in to comment.