Paginate users on group views

This commit is contained in:
Adria Navarro 2023-05-04 17:38:04 +01:00
parent bbd0690518
commit 10fcca92f6
6 changed files with 101 additions and 26 deletions

View File

@ -11,9 +11,11 @@
ActionMenu, ActionMenu,
MenuItem, MenuItem,
Modal, Modal,
Pagination,
} from "@budibase/bbui" } from "@budibase/bbui"
import { fetchData } from "@budibase/frontend-core"
import { API } from "api"
import UserGroupPicker from "components/settings/UserGroupPicker.svelte" import UserGroupPicker from "components/settings/UserGroupPicker.svelte"
import { createPaginationStore } from "helpers/pagination"
import { users, apps, groups, auth, features } from "stores/portal" import { users, apps, groups, auth, features } from "stores/portal"
import { onMount, setContext } from "svelte" import { onMount, setContext } from "svelte"
import { roles } from "stores/backend" import { roles } from "stores/backend"
@ -28,6 +30,18 @@
export let groupId export let groupId
const fetchUsers = fetchData({
API,
datasource: {
type: "groupUser",
},
options: {
query: {
groupId,
},
},
})
$: userSchema = { $: userSchema = {
email: { email: {
width: "1fr", width: "1fr",
@ -70,17 +84,12 @@
let popoverAnchor let popoverAnchor
let popover let popover
let searchTerm = "" let searchTerm = ""
let prevSearch = undefined
let pageInfo = createPaginationStore()
let loaded = false let loaded = false
let editModal, deleteModal let editModal, deleteModal
$: scimEnabled = $features.isScimEnabled $: scimEnabled = $features.isScimEnabled
$: readonly = !$auth.isAdmin || scimEnabled $: readonly = !$auth.isAdmin || scimEnabled
$: page = $pageInfo.page
$: fetchUsers(page, searchTerm)
$: group = $groups.find(x => x._id === groupId) $: group = $groups.find(x => x._id === groupId)
$: filtered = $users.data
$: groupApps = $apps $: groupApps = $apps
.filter(app => .filter(app =>
groups.actions 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() { async function deleteGroup() {
try { try {
await groups.actions.delete(group) await groups.actions.delete(group)
@ -211,7 +201,7 @@
<Table <Table
schema={userSchema} schema={userSchema}
data={group?.users} data={$fetchUsers.rows}
allowEditRows={false} allowEditRows={false}
customPlaceholder customPlaceholder
customRenderers={customUserTableRenderers} customRenderers={customUserTableRenderers}
@ -221,6 +211,16 @@
<Heading size="S">This user group doesn't have any users</Heading> <Heading size="S">This user group doesn't have any users</Heading>
</div> </div>
</Table> </Table>
<div class="pagination">
<Pagination
page={$fetchUsers.pageNumber + 1}
hasPrevPage={$fetchUsers.loading ? false : $fetchUsers.hasPrevPage}
hasNextPage={$fetchUsers.loading ? false : $fetchUsers.hasNextPage}
goToPrevPage={$fetchUsers.loading ? null : fetchUsers.prevPage}
goToNextPage={$fetchUsers.loading ? null : fetchUsers.nextPage}
/>
</div>
</Layout> </Layout>
<Layout noPadding gap="S"> <Layout noPadding gap="S">

View File

@ -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 * Adds users to a group
* @param groupId The group to update * @param groupId The group to update

View File

@ -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,
}
}
}
}

View File

@ -6,6 +6,7 @@ import NestedProviderFetch from "./NestedProviderFetch.js"
import FieldFetch from "./FieldFetch.js" import FieldFetch from "./FieldFetch.js"
import JSONArrayFetch from "./JSONArrayFetch.js" import JSONArrayFetch from "./JSONArrayFetch.js"
import UserFetch from "./UserFetch.js" import UserFetch from "./UserFetch.js"
import GroupUserFetch from "./GroupUserFetch.js"
const DataFetchMap = { const DataFetchMap = {
table: TableFetch, table: TableFetch,
@ -13,6 +14,7 @@ const DataFetchMap = {
query: QueryFetch, query: QueryFetch,
link: RelationshipFetch, link: RelationshipFetch,
user: UserFetch, user: UserFetch,
groupUser: GroupUserFetch,
// Client specific datasource types // Client specific datasource types
provider: NestedProviderFetch, provider: NestedProviderFetch,

View File

@ -1,3 +1,4 @@
import { PaginationResponse } from "../../api"
import { Document } from "../document" import { Document } from "../document"
export interface UserGroup extends Document { export interface UserGroup extends Document {
@ -26,3 +27,10 @@ export interface SearchGroupRequest {}
export interface SearchGroupResponse { export interface SearchGroupResponse {
data: UserGroup[] data: UserGroup[]
} }
export interface SearchUserGroupResponse extends PaginationResponse {
users: {
_id: any
email: any
}[]
}

View File

@ -65,6 +65,7 @@ export type DatabaseQueryOpts = {
key?: string key?: string
keys?: string[] keys?: string[]
group?: boolean group?: boolean
startkey_docid?: string
} }
export const isDocument = (doc: any): doc is Document => { export const isDocument = (doc: any): doc is Document => {