Paginate users on group views
This commit is contained in:
parent
bbd0690518
commit
10fcca92f6
|
@ -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">
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
Loading…
Reference in New Issue