From 98c486655b71ac397666d1d4dd8194d6677ceffc Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 29 Jun 2022 19:11:00 +0100 Subject: [PATCH 1/5] Adding user pagination, removing usages of the global user list from builder and replacing with direct user lookups where possible, still need to apply filtering to username/email serverside. --- packages/backend-core/src/db/utils.ts | 27 +++++++++++- packages/builder/src/helpers/pagination.js | 31 ++++++++++++++ .../builder/portal/manage/users/index.svelte | 42 +++++++++++++++---- .../overview/_components/OverviewTab.svelte | 30 ++++--------- packages/builder/src/stores/portal/users.js | 26 +++++++++--- packages/frontend-core/src/api/user.js | 15 ++++++- .../src/api/controllers/global/users.ts | 7 ++-- packages/worker/src/sdk/users/users.ts | 15 +++++++ 8 files changed, 150 insertions(+), 43 deletions(-) create mode 100644 packages/builder/src/helpers/pagination.js diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts index dc7a0454c3..fc4094ad9f 100644 --- a/packages/backend-core/src/db/utils.ts +++ b/packages/backend-core/src/db/utils.ts @@ -93,13 +93,17 @@ export function generateGlobalUserID(id?: any) { /** * Gets parameters for retrieving users. */ -export function getGlobalUserParams(globalId: any, otherProps = {}) { +export function getGlobalUserParams(globalId: any, otherProps: any = {}) { if (!globalId) { globalId = "" } + const startkey = otherProps?.startkey return { ...otherProps, - startkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}`, + // need to include this incase pagination + startkey: startkey + ? startkey + : `${DocumentTypes.USER}${SEPARATOR}${globalId}`, endkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}${UNICODE_MAX}`, } } @@ -434,6 +438,25 @@ export const getPlatformUrl = async (opts = { tenantAware: true }) => { return platformUrl } +export function pagination( + response: any, + pageSize: number, + paginate: boolean = true +) { + const data = response.rows.map((row: any) => { + return row.doc ? row.doc : row + }) + if (!paginate) { + return { data, hasNextPage: false } + } + const hasNextPage = data.length > pageSize + return { + data: data.slice(0, pageSize), + hasNextPage, + nextPage: hasNextPage ? data[pageSize]?._id : undefined, + } +} + export async function getScopedConfig(db: any, params: any) { const configDoc = await getScopedFullConfig(db, params) return configDoc && configDoc.config ? configDoc.config : configDoc diff --git a/packages/builder/src/helpers/pagination.js b/packages/builder/src/helpers/pagination.js new file mode 100644 index 0000000000..8f524d8d9f --- /dev/null +++ b/packages/builder/src/helpers/pagination.js @@ -0,0 +1,31 @@ +export class PageInfo { + constructor(fetch) { + this.reset() + this.fetch = fetch + } + + async goToNextPage() { + this.pageNumber++ + this.prevPage = this.page + this.page = this.nextPage + this.hasPrevPage = this.pageNumber > 1 + await this.fetch(this.page) + } + + async goToPrevPage() { + this.pageNumber-- + this.nextPage = this.page + this.page = this.prevPage + this.hasPrevPage = this.pageNumber > 1 + await this.fetch(this.page) + } + + reset() { + this.prevPage = null + this.nextPage = null + this.page = undefined + this.hasPrevPage = false + this.hasNextPage = false + this.pageNumber = 1 + } +} diff --git a/packages/builder/src/pages/builder/portal/manage/users/index.svelte b/packages/builder/src/pages/builder/portal/manage/users/index.svelte index 1d9c245480..ef1ba2a24a 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/index.svelte @@ -12,25 +12,26 @@ Layout, Modal, notifications, + Pagination, } from "@budibase/bbui" import TagsRenderer from "./_components/TagsTableRenderer.svelte" import AddUserModal from "./_components/AddUserModal.svelte" import { users } from "stores/portal" + import { PageInfo } from "helpers/pagination" import { onMount } from "svelte" const schema = { email: {}, developmentAccess: { displayName: "Development Access", type: "boolean" }, adminAccess: { displayName: "Admin Access", type: "boolean" }, - // role: { type: "options" }, group: {}, - // access: {}, - // group: {} } + let pageInfo = new PageInfo(fetchUsers) let search - $: filteredUsers = $users - .filter(user => user.email.includes(search || "")) + $: checkRefreshed($users.page) + $: filteredUsers = $users.data + ?.filter(user => user?.email?.includes(search || "")) .map(user => ({ ...user, group: ["All users"], @@ -40,12 +41,28 @@ let createUserModal - onMount(async () => { + async function checkRefreshed(page) { + // the users have been reset, go back to first page + if (!page && pageInfo.page) { + pageInfo.reset() + pageInfo.pageNumber = pageInfo.pageNumber + pageInfo.hasNextPage = $users.hasNextPage + pageInfo.nextPage = $users.nextPage + } + } + + async function fetchUsers(page) { try { - await users.init() + await users.fetch(page) + pageInfo.hasNextPage = $users.hasNextPage + pageInfo.nextPage = $users.nextPage } catch (error) { notifications.error("Error getting user list") } + } + + onMount(async () => { + await fetchUsers() }) @@ -75,12 +92,21 @@ $goto(`./${detail._id}`)} {schema} - data={filteredUsers || $users} + data={filteredUsers || $users.data} allowEditColumns={false} allowEditRows={false} allowSelectRows={false} customRenderers={[{ column: "group", component: TagsRenderer }]} /> + diff --git a/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte index 7b7258cada..6957f2ea9a 100644 --- a/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte +++ b/packages/builder/src/pages/builder/portal/overview/_components/OverviewTab.svelte @@ -1,14 +1,7 @@ @@ -92,7 +69,7 @@
$goto(`./${detail._id}`)} {schema} - data={filteredUsers || $users.data} + data={$users.data} allowEditColumns={false} allowEditRows={false} allowSelectRows={false} @@ -100,18 +77,23 @@ /> - + { + pageInfo.reset() + await fetchUsers() + }} + />