1
0
Fork 0
mirror of synced 2024-08-06 05:38:40 +12:00

Fix adding/removing users to group. Remove add all button

This commit is contained in:
Andrew Kingston 2022-08-04 13:25:44 +01:00
parent 4d475c3cd4
commit 095bb83202
2 changed files with 122 additions and 116 deletions

View file

@ -1,75 +1,109 @@
<script> <script>
import { ActionButton, Icon, Search, Divider, Detail } from "@budibase/bbui" import { Icon, Search, Divider, Layout } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
export let searchTerm = "" export let searchTerm = ""
export let selected export let selected
export let filtered = [] export let list = []
export let addAll export let labelKey
export let select
export let title const dispatch = createEventDispatcher()
export let key
$: enrichedList = enrich(list, selected)
$: sortedList = sort(enrichedList)
const enrich = (list, selected) => {
return list.map(item => {
return {
...item,
selected: selected.find(x => x._id === item._id) != null,
}
})
}
const sort = list => {
let sortedList = list.slice()
sortedList.sort((a, b) => {
if (a.selected === b.selected) {
return a[labelKey] < b[labelKey] ? -1 : 1
} else if (a.selected) {
return -1
} else if (b.selected) {
return 1
}
return 0
})
return sortedList
}
</script> </script>
<div style="padding: var(--spacing-m)"> <div class="container">
<Search placeholder="Search" bind:value={searchTerm} /> <Layout gap="S">
<div class="header sub-header"> <div class="header">
<div> <Search placeholder="Search" bind:value={searchTerm} />
<Detail
>{filtered.length} {title}{filtered.length === 1 ? "" : "s"}</Detail
>
</div> </div>
<div> <Divider noMargin />
<ActionButton on:click={addAll} emphasized size="S">Add all</ActionButton> <div class="items">
</div> {#each sortedList as item}
</div> <div
<Divider noMargin /> on:click={() => {
<div> dispatch(item.selected ? "deselect" : "select", item._id)
{#each filtered as item} }}
<div class="item"
on:click={() => { >
select(item._id) <div class="text">
}} {item[labelKey]}
style="padding-bottom: var(--spacing-m)"
class="selection"
>
<div>
{item[key]}
</div>
{#if selected.includes(item._id)}
<div>
<Icon
color="var(--spectrum-global-color-blue-600);"
name="Checkmark"
/>
</div> </div>
{/if} {#if item.selected}
</div> <div>
{/each} <Icon
</div> color="var(--spectrum-global-color-blue-600);"
name="Checkmark"
/>
</div>
{/if}
</div>
{/each}
</div>
</Layout>
</div> </div>
<style> <style>
.container {
width: 280px;
}
.header { .header {
align-items: center; align-items: center;
padding: var(--spacing-m) 0 var(--spacing-m) 0; display: grid;
display: flex; gap: var(--spacing-m);
justify-content: space-between; grid-template-columns: 1fr;
} }
.items {
.selection { max-height: 242px;
overflow: auto;
overflow-x: hidden;
margin: 0 calc(-1 * var(--spacing-m));
margin-top: -8px;
}
.item {
align-items: end; align-items: end;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
cursor: pointer; cursor: pointer;
padding: var(--spacing-s) var(--spacing-l);
background: var(--spectrum-global-color-gray-50);
transition: background 130ms ease-out;
gap: var(--spacing-xl);
} }
.item:hover {
.selection > :first-child { background: var(--spectrum-global-color-gray-100);
padding-top: var(--spacing-m); cursor: pointer;
} }
.text {
.sub-header { flex: 1 1 auto;
display: flex; width: 0;
justify-content: space-between; overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
</style> </style>

View file

@ -31,7 +31,6 @@
let popoverAnchor let popoverAnchor
let popover let popover
let searchTerm = "" let searchTerm = ""
let selectedUsers = []
let prevSearch = undefined let prevSearch = undefined
let pageInfo = createPaginationStore() let pageInfo = createPaginationStore()
let loaded = false let loaded = false
@ -41,9 +40,7 @@
$: page = $pageInfo.page $: page = $pageInfo.page
$: fetchUsers(page, searchTerm) $: fetchUsers(page, searchTerm)
$: group = $groups.find(x => x._id === groupId) $: group = $groups.find(x => x._id === groupId)
$: filtered = $: filtered = $users.data
$users.data?.filter(x => !group?.users.map(y => y._id).includes(x._id)) ||
[]
$: groupApps = $apps.filter(x => group?.apps.includes(x.appId)) $: groupApps = $apps.filter(x => group?.apps.includes(x.appId))
$: { $: {
if (loaded && !group?._id) { if (loaded && !group?._id) {
@ -51,53 +48,24 @@
} }
} }
async function addAll() { const adduserToGroup = async id => {
selectedUsers = [...selectedUsers, ...filtered.map(u => u._id)] const user = await users.get(id)
if (!user?._id) {
let reducedUserObjects = filtered.map(u => { return
return {
_id: u._id,
email: u.email,
}
})
group.users = [...reducedUserObjects, ...group.users]
await groups.actions.save(group)
$users.data.forEach(async user => {
let userToEdit = await users.get(user._id)
let userGroups = userToEdit.userGroups || []
userGroups.push(groupId)
await users.save({
...userToEdit,
userGroups,
})
})
}
async function selectUser(id) {
let selectedUser = selectedUsers.includes(id)
if (selectedUser) {
selectedUsers = selectedUsers.filter(id => id !== selectedUser)
let newUsers = group.users.filter(user => user._id !== id)
group.users = newUsers
} else {
let enrichedUser = $users.data
.filter(user => user._id === id)
.map(u => {
return {
_id: u._id,
email: u.email,
}
})[0]
selectedUsers = [...selectedUsers, id]
group.users.push(enrichedUser)
} }
await groups.actions.save(group) // Check we haven't already been added
if (group.users?.find(x => x._id === user._id)) {
return
}
let user = await users.get(id) // Update group
await groups.actions.save({
...group,
users: [...group.users, { _id: user._id, email: user.email }],
})
// Update user
let userGroups = user.userGroups || [] let userGroups = user.userGroups || []
userGroups.push(groupId) userGroups.push(groupId)
await users.save({ await users.save({
@ -106,17 +74,23 @@
}) })
} }
async function removeUser(id) { const removeUserFromGroup = async id => {
let newUsers = group.users.filter(user => user._id !== id) const user = await users.get(id)
group.users = newUsers if (!user?._id) {
let user = await users.get(id) return
}
await users.save({ // Update group
...user, await groups.actions.save({
userGroups: [], ...group,
users: group.users.filter(x => x._id !== id),
}) })
await groups.actions.save(group) // Update user
await users.save({
...user,
userGroups: user.userGroups.filter(x => x !== groupId),
})
} }
async function fetchUsers(page, search) { async function fetchUsers(page, search) {
@ -150,7 +124,6 @@
notifications.success("User group deleted successfully") notifications.success("User group deleted successfully")
$goto("./") $goto("./")
} catch (error) { } catch (error) {
console.log(error)
notifications.error(`Failed to delete user group`) notifications.error(`Failed to delete user group`)
} }
} }
@ -216,13 +189,12 @@
</div> </div>
<Popover align="right" bind:this={popover} anchor={popoverAnchor}> <Popover align="right" bind:this={popover} anchor={popoverAnchor}>
<UserGroupPicker <UserGroupPicker
key={"email"}
title={"User"}
bind:searchTerm bind:searchTerm
bind:selected={selectedUsers} labelKey="email"
bind:filtered selected={group.users}
{addAll} list={$users.data}
select={selectUser} on:select={e => adduserToGroup(e.detail)}
on:deselect={e => removeUserFromGroup(e.detail)}
/> />
</Popover> </Popover>
</div> </div>
@ -236,7 +208,7 @@
hoverable hoverable
> >
<Icon <Icon
on:click={() => removeUser(user._id)} on:click={() => removeUserFromGroup(user._id)}
hoverable hoverable
size="S" size="S"
name="Close" name="Close"