take into account pagination
This commit is contained in:
parent
c9d86230d4
commit
b846402d90
|
@ -1,13 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton, Icon, Search, Divider, Detail } from "@budibase/bbui"
|
import { ActionButton, Icon, Search, Divider, Detail } from "@budibase/bbui"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let searchTerm = ""
|
export let searchTerm = ""
|
||||||
export let selected
|
export let selected
|
||||||
export let filtered
|
export let filtered = []
|
||||||
export let addAll
|
export let addAll
|
||||||
export let select
|
export let select
|
||||||
export let title
|
export let title
|
||||||
export let key
|
export let key
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
function onChange(e) {
|
||||||
|
dispatch("change", e.detail)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div style="padding: var(--spacing-m)">
|
<div style="padding: var(--spacing-m)">
|
||||||
|
@ -26,7 +32,9 @@
|
||||||
<div>
|
<div>
|
||||||
{#each filtered as item}
|
{#each filtered as item}
|
||||||
<div
|
<div
|
||||||
on:click={select(item._id)}
|
on:click={() => {
|
||||||
|
select(item._id)
|
||||||
|
}}
|
||||||
style="padding-bottom: var(--spacing-m)"
|
style="padding-bottom: var(--spacing-m)"
|
||||||
class="selection"
|
class="selection"
|
||||||
>
|
>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
StatusLight,
|
StatusLight,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import UserGroupPicker from "components/settings/UserGroupPicker.svelte"
|
import UserGroupPicker from "components/settings/UserGroupPicker.svelte"
|
||||||
|
import { createPaginationStore } from "helpers/pagination"
|
||||||
import { users, apps, groups } from "stores/portal"
|
import { users, apps, groups } from "stores/portal"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { RoleUtils } from "@budibase/frontend-core"
|
import { RoleUtils } from "@budibase/frontend-core"
|
||||||
|
@ -24,24 +24,23 @@
|
||||||
let popover
|
let popover
|
||||||
let searchTerm = ""
|
let searchTerm = ""
|
||||||
let selectedUsers = []
|
let selectedUsers = []
|
||||||
|
let prevSearch = undefined,
|
||||||
|
search = undefined
|
||||||
|
$: page = $pageInfo.page
|
||||||
|
$: fetchUsers(page, search)
|
||||||
$: group = $groups.find(x => x._id === groupId)
|
$: group = $groups.find(x => x._id === groupId)
|
||||||
$: filteredUsers = $users.filter(
|
let pageInfo = createPaginationStore()
|
||||||
user =>
|
|
||||||
selectedUsers &&
|
|
||||||
user?.email?.toLowerCase().includes(searchTerm.toLowerCase())
|
|
||||||
)
|
|
||||||
$: console.log(group)
|
|
||||||
async function addAll() {
|
async function addAll() {
|
||||||
selectedUsers = [...selectedUsers, ...filteredUsers]
|
|
||||||
group.users = selectedUsers
|
group.users = selectedUsers
|
||||||
await groups.actions.save(group)
|
await groups.actions.save(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectUser(id) {
|
async function selectUser(id) {
|
||||||
let selectedUser = selectedUsers.includes(id)
|
let selectedUser = selectedUsers.includes(id)
|
||||||
let enrichedUser = $users.find(user => user._id === id)
|
let enrichedUser = $users.data.find(user => user._id === id)
|
||||||
|
|
||||||
if (selectedUser) {
|
if (selectedUser) {
|
||||||
|
console.log
|
||||||
selectedUsers = selectedUsers.filter(id => id !== selectedUser)
|
selectedUsers = selectedUsers.filter(id => id !== selectedUser)
|
||||||
let newUsers = group.users.filter(user => user._id !== id)
|
let newUsers = group.users.filter(user => user._id !== id)
|
||||||
group.users = newUsers
|
group.users = newUsers
|
||||||
|
@ -52,16 +51,43 @@
|
||||||
|
|
||||||
await groups.actions.save(group)
|
await groups.actions.save(group)
|
||||||
}
|
}
|
||||||
|
$: filtered =
|
||||||
|
$users.data?.filter(x => !group?.users.map(y => y._id).includes(x._id)) ||
|
||||||
|
[]
|
||||||
|
|
||||||
|
$: console.log(filtered)
|
||||||
async function removeUser(id) {
|
async function removeUser(id) {
|
||||||
let newUsers = group.users.filter(user => user._id !== id)
|
let newUsers = group.users.filter(user => user._id !== id)
|
||||||
group.users = newUsers
|
group.users = newUsers
|
||||||
await groups.actions.save(group)
|
await groups.actions.save(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, search })
|
||||||
|
pageInfo.fetched($users.hasNextPage, $users.nextPage)
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error("Error getting user list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
await groups.actions.init()
|
await groups.actions.init()
|
||||||
await users.init()
|
|
||||||
await apps.load()
|
await apps.load()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error fetching User Group data")
|
notifications.error("Error fetching User Group data")
|
||||||
|
@ -91,11 +117,12 @@
|
||||||
</div>
|
</div>
|
||||||
<Popover align="right" bind:this={popover} anchor={popoverAnchor}>
|
<Popover align="right" bind:this={popover} anchor={popoverAnchor}>
|
||||||
<UserGroupPicker
|
<UserGroupPicker
|
||||||
|
on:change={onChange}
|
||||||
key={"email"}
|
key={"email"}
|
||||||
title={"User"}
|
title={"User"}
|
||||||
bind:searchTerm
|
bind:searchTerm
|
||||||
bind:selected={selectedUsers}
|
bind:selected={selectedUsers}
|
||||||
bind:filtered={filteredUsers}
|
bind:filtered
|
||||||
{addAll}
|
{addAll}
|
||||||
select={selectUser}
|
select={selectUser}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -22,13 +22,19 @@
|
||||||
<div class="modal-inner">
|
<div class="modal-inner">
|
||||||
<Body size="XS">Icon</Body>
|
<Body size="XS">Icon</Body>
|
||||||
<div class="modal-spacing">
|
<div class="modal-spacing">
|
||||||
<IconPicker on:change={e => (group.icon = e.detail)} />
|
<IconPicker
|
||||||
|
bind:value={group.icon}
|
||||||
|
on:change={e => (group.icon = e.detail)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-inner">
|
<div class="modal-inner">
|
||||||
<Body size="XS">Color</Body>
|
<Body size="XS">Color</Body>
|
||||||
<div class="modal-spacing">
|
<div class="modal-spacing">
|
||||||
<ColorPicker on:change={e => (group.color = e.detail)} />
|
<ColorPicker
|
||||||
|
bind:value={group.color}
|
||||||
|
on:change={e => (group.color = e.detail)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<CreateEditGroupModal {group} {saveGroup} />
|
<CreateEditGroupModal bind:group {saveGroup} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Icon } from "@budibase/bbui"
|
import { Icon } from "@budibase/bbui"
|
||||||
export let value
|
export let value
|
||||||
$: console.log(value)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="align">
|
<div class="align">
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
import { Icon, Body } from "@budibase/bbui"
|
import { Icon, Body } from "@budibase/bbui"
|
||||||
export let value
|
export let value
|
||||||
|
console.log(value)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="align">
|
<div class="align">
|
||||||
<div class="spacing">
|
<div class="spacing">
|
||||||
<Icon name="UserGroup" />
|
<Icon name="UserGroup" />
|
||||||
</div>
|
</div>
|
||||||
{#if value.length === 0}
|
{#if value?.length === 0}
|
||||||
<div class="opacity">0</div>
|
<div class="opacity">0</div>
|
||||||
{:else if value.length === 1}
|
{:else if value?.length === 1}
|
||||||
<div class="opacity">
|
<div class="opacity">
|
||||||
<Body size="S">{value[0].name}</Body>
|
<Body size="S">{value[0]?.name}</Body>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="opacity">
|
<div class="opacity">
|
||||||
{parseInt(value.length) || 0} groups
|
{parseInt(value?.length) || 0} groups
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -62,8 +62,8 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
let email
|
let email
|
||||||
|
let enrichedUsers = []
|
||||||
let createUserModal,
|
let createUserModal,
|
||||||
basicOnboardingModal,
|
|
||||||
inviteConfirmationModal,
|
inviteConfirmationModal,
|
||||||
onboardingTypeModal,
|
onboardingTypeModal,
|
||||||
passwordModal,
|
passwordModal,
|
||||||
|
@ -74,8 +74,36 @@
|
||||||
search = undefined
|
search = undefined
|
||||||
$: page = $pageInfo.page
|
$: page = $pageInfo.page
|
||||||
$: fetchUsers(page, search)
|
$: fetchUsers(page, search)
|
||||||
$: console.log(page)
|
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if ($users.data) {
|
||||||
|
enrichedUsers = $users.data.map(user => {
|
||||||
|
let userGroups = []
|
||||||
|
let userApps = []
|
||||||
|
$groups.forEach(group => {
|
||||||
|
console.log(group)
|
||||||
|
if (group.users) {
|
||||||
|
group.users?.forEach(y => {
|
||||||
|
if (y._id === user._id) {
|
||||||
|
console.log("hello")
|
||||||
|
userGroups.push(group)
|
||||||
|
userApps = group.apps
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
name: user.firstName ? user.firstName + " " + user.lastName : "",
|
||||||
|
userGroups,
|
||||||
|
apps: [...new Set(Object.keys(user.roles))],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
enrichedUsers = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$: console.log(enrichedUsers)
|
||||||
function showOnboardingTypeModal() {
|
function showOnboardingTypeModal() {
|
||||||
onboardingTypeModal.show()
|
onboardingTypeModal.show()
|
||||||
}
|
}
|
||||||
|
@ -128,6 +156,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
await groups.actions.init()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
notifications.error("Error fetching User Group data")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function fetchUsers(page, search) {
|
async function fetchUsers(page, search) {
|
||||||
if ($pageInfo.loading) {
|
if ($pageInfo.loading) {
|
||||||
return
|
return
|
||||||
|
@ -176,6 +213,22 @@
|
||||||
>Import Users</Button
|
>Import Users</Button
|
||||||
>
|
>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
<Table
|
||||||
|
on:click={({ detail }) => $goto(`./${detail._id}`)}
|
||||||
|
{schema}
|
||||||
|
data={enrichedUsers}
|
||||||
|
allowEditColumns={false}
|
||||||
|
allowEditRows={false}
|
||||||
|
allowSelectRows={true}
|
||||||
|
showHeaderBorder={false}
|
||||||
|
customRenderers={[
|
||||||
|
{ column: "userGroups", component: GroupsTableRenderer },
|
||||||
|
{ column: "apps", component: AppsTableRenderer },
|
||||||
|
{ column: "name", component: NameTableRenderer },
|
||||||
|
{ column: "settings", component: SettingsTableRenderer },
|
||||||
|
{ column: "role", component: RoleTableRenderer },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<Pagination
|
<Pagination
|
||||||
page={$pageInfo.pageNumber}
|
page={$pageInfo.pageNumber}
|
||||||
|
|
|
@ -19,6 +19,7 @@ export function createGroupsStore() {
|
||||||
},
|
},
|
||||||
|
|
||||||
save: async group => {
|
save: async group => {
|
||||||
|
console.log(group)
|
||||||
const response = await API.saveGroup(group)
|
const response = await API.saveGroup(group)
|
||||||
group._id = response._id
|
group._id = response._id
|
||||||
group._rev = response._rev
|
group._rev = response._rev
|
||||||
|
|
|
@ -15,7 +15,9 @@ function buildGroupSaveValidation() {
|
||||||
icon: Joi.string().required(),
|
icon: Joi.string().required(),
|
||||||
name: Joi.string().required(),
|
name: Joi.string().required(),
|
||||||
users: Joi.array().optional(),
|
users: Joi.array().optional(),
|
||||||
apps: Joi.array().optional()
|
apps: Joi.array().optional(),
|
||||||
|
createdAt: Joi.string().optional(),
|
||||||
|
updatedAt: Joi.string().optional(),
|
||||||
}).required())
|
}).required())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue