From 10fcca92f65fbf61b395e928a445fa7de69d9223 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 4 May 2023 17:38:04 +0100 Subject: [PATCH] Paginate users on group views --- .../portal/users/groups/[groupId].svelte | 52 +++++++++---------- packages/frontend-core/src/api/groups.js | 14 +++++ .../frontend-core/src/fetch/GroupUserFetch.js | 50 ++++++++++++++++++ packages/frontend-core/src/fetch/fetchData.js | 2 + .../types/src/documents/global/userGroup.ts | 8 +++ packages/types/src/sdk/db.ts | 1 + 6 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 packages/frontend-core/src/fetch/GroupUserFetch.js diff --git a/packages/builder/src/pages/builder/portal/users/groups/[groupId].svelte b/packages/builder/src/pages/builder/portal/users/groups/[groupId].svelte index 1be019b83e..ccd945fc24 100644 --- a/packages/builder/src/pages/builder/portal/users/groups/[groupId].svelte +++ b/packages/builder/src/pages/builder/portal/users/groups/[groupId].svelte @@ -11,9 +11,11 @@ ActionMenu, MenuItem, Modal, + Pagination, } from "@budibase/bbui" + import { fetchData } from "@budibase/frontend-core" + import { API } from "api" import UserGroupPicker from "components/settings/UserGroupPicker.svelte" - import { createPaginationStore } from "helpers/pagination" import { users, apps, groups, auth, features } from "stores/portal" import { onMount, setContext } from "svelte" import { roles } from "stores/backend" @@ -28,6 +30,18 @@ export let groupId + const fetchUsers = fetchData({ + API, + datasource: { + type: "groupUser", + }, + options: { + query: { + groupId, + }, + }, + }) + $: userSchema = { email: { width: "1fr", @@ -70,17 +84,12 @@ let popoverAnchor let popover let searchTerm = "" - let prevSearch = undefined - let pageInfo = createPaginationStore() let loaded = false let editModal, deleteModal $: scimEnabled = $features.isScimEnabled $: readonly = !$auth.isAdmin || scimEnabled - $: page = $pageInfo.page - $: fetchUsers(page, searchTerm) $: group = $groups.find(x => x._id === groupId) - $: filtered = $users.data $: groupApps = $apps .filter(app => groups.actions @@ -97,25 +106,6 @@ } } - async function fetchUsers(page, search) { - if ($pageInfo.loading) { - return - } - // need to remove the page if they've started searching - if (search && !prevSearch) { - pageInfo.reset() - page = undefined - } - prevSearch = search - try { - pageInfo.loading() - await users.search({ page, email: search }) - pageInfo.fetched($users.hasNextPage, $users.nextPage) - } catch (error) { - notifications.error("Error getting user list") - } - } - async function deleteGroup() { try { await groups.actions.delete(group) @@ -211,7 +201,7 @@ This user group doesn't have any users
+ + diff --git a/packages/frontend-core/src/api/groups.js b/packages/frontend-core/src/api/groups.js index c27f11e0ea..cbc5bfd72a 100644 --- a/packages/frontend-core/src/api/groups.js +++ b/packages/frontend-core/src/api/groups.js @@ -52,6 +52,20 @@ export const buildGroupsEndpoints = API => { }) }, + /** + * Gets a group users by the group id + */ + getGroupUsers: async ({ id, bookmark }) => { + let url = `/api/global/groups/${id}/users?` + if (bookmark) { + url += `bookmark=${bookmark}` + } + + return await API.get({ + url, + }) + }, + /** * Adds users to a group * @param groupId The group to update diff --git a/packages/frontend-core/src/fetch/GroupUserFetch.js b/packages/frontend-core/src/fetch/GroupUserFetch.js new file mode 100644 index 0000000000..b0ca9a5388 --- /dev/null +++ b/packages/frontend-core/src/fetch/GroupUserFetch.js @@ -0,0 +1,50 @@ +import { get } from "svelte/store" +import DataFetch from "./DataFetch.js" +import { TableNames } from "../constants" + +export default class GroupUserFetch extends DataFetch { + constructor(opts) { + super({ + ...opts, + datasource: { + tableId: TableNames.USERS, + }, + }) + } + + determineFeatureFlags() { + return { + supportsSearch: true, + supportsSort: false, + supportsPagination: true, + } + } + + async getDefinition() { + return { + schema: {}, + } + } + + async getData() { + const { query, cursor } = get(this.store) + try { + const res = await this.API.getGroupUsers({ + id: query.groupId, + bookmark: cursor, + }) + + return { + rows: res?.users || [], + hasNextPage: res?.hasNextPage || false, + cursor: res?.bookmark || null, + } + } catch (error) { + return { + rows: [], + hasNextPage: false, + error, + } + } + } +} diff --git a/packages/frontend-core/src/fetch/fetchData.js b/packages/frontend-core/src/fetch/fetchData.js index 4974816496..c4968eabc0 100644 --- a/packages/frontend-core/src/fetch/fetchData.js +++ b/packages/frontend-core/src/fetch/fetchData.js @@ -6,6 +6,7 @@ import NestedProviderFetch from "./NestedProviderFetch.js" import FieldFetch from "./FieldFetch.js" import JSONArrayFetch from "./JSONArrayFetch.js" import UserFetch from "./UserFetch.js" +import GroupUserFetch from "./GroupUserFetch.js" const DataFetchMap = { table: TableFetch, @@ -13,6 +14,7 @@ const DataFetchMap = { query: QueryFetch, link: RelationshipFetch, user: UserFetch, + groupUser: GroupUserFetch, // Client specific datasource types provider: NestedProviderFetch, diff --git a/packages/types/src/documents/global/userGroup.ts b/packages/types/src/documents/global/userGroup.ts index fa48c1636e..b74e59c020 100644 --- a/packages/types/src/documents/global/userGroup.ts +++ b/packages/types/src/documents/global/userGroup.ts @@ -1,3 +1,4 @@ +import { PaginationResponse } from "../../api" import { Document } from "../document" export interface UserGroup extends Document { @@ -26,3 +27,10 @@ export interface SearchGroupRequest {} export interface SearchGroupResponse { data: UserGroup[] } + +export interface SearchUserGroupResponse extends PaginationResponse { + users: { + _id: any + email: any + }[] +} diff --git a/packages/types/src/sdk/db.ts b/packages/types/src/sdk/db.ts index 2cccd3be6a..58b3b7e5bc 100644 --- a/packages/types/src/sdk/db.ts +++ b/packages/types/src/sdk/db.ts @@ -65,6 +65,7 @@ export type DatabaseQueryOpts = { key?: string keys?: string[] group?: boolean + startkey_docid?: string } export const isDocument = (doc: any): doc is Document => {