1
0
Fork 0
mirror of synced 2024-09-08 21:51:58 +12:00

Update user and group details pages with new tables

This commit is contained in:
Andrew Kingston 2022-12-21 16:33:25 +00:00
parent e91ed89d72
commit 3dd5916f24
8 changed files with 155 additions and 131 deletions

View file

@ -1,6 +1,7 @@
<script>
import Field from "./Field.svelte"
import Select from "./Core/Select.svelte"
import { createEventDispatcher } from "svelte"
export let value = null
export let label = undefined
@ -20,6 +21,12 @@
export let sort = false
export let tooltip = ""
const dispatch = createEventDispatcher()
const onChange = e => {
value = e.detail
dispatch("change", e.detail)
}
const extractProperty = (value, property) => {
if (value && typeof value === "object") {
return value[property]
@ -44,7 +51,7 @@
{getOptionIcon}
{getOptionColour}
{isOptionEnabled}
on:change
on:change={onChange}
on:click
/>
</Field>

View file

@ -14,8 +14,8 @@
quiet
allowRemove
allowPublic={false}
on:change={e => rolesContext.updateUserRole(e.detail, row._id)}
on:remove={() => rolesContext.removeUserRole(row._id)}
on:change={e => rolesContext.updateRole(e.detail, row._id)}
on:remove={() => rolesContext.removeRole(row._id)}
/>
</div>

View file

@ -1,26 +0,0 @@
<script>
import RoleSelect from "components/common/RoleSelect.svelte"
import { getContext } from "svelte"
const rolesContext = getContext("roles")
export let value
export let row
</script>
<div>
<RoleSelect
{value}
quiet
allowRemove
allowPublic={false}
on:change={e => rolesContext.updateGroupRole(e.detail, row._id)}
on:remove={() => rolesContext.removeGroupRole(row._id)}
/>
</div>
<style>
div {
width: 100%;
}
</style>

View file

@ -16,15 +16,14 @@
import { roles } from "stores/backend"
import { API } from "api"
import { fetchData } from "@budibase/frontend-core"
import UserRoleRenderer from "./_components/UserRoleRenderer.svelte"
import GroupRoleRenderer from "./_components/GroupRoleRenderer.svelte"
import EditableRoleRenderer from "./_components/EditableRoleRenderer.svelte"
const userSchema = {
email: {
type: "string",
width: "1fr",
},
userAppRole: {
role: {
displayName: "Access",
width: "150px",
borderLeft: true,
@ -35,7 +34,7 @@
type: "string",
width: "1fr",
},
groupAppRole: {
role: {
displayName: "Access",
width: "150px",
borderLeft: true,
@ -43,12 +42,8 @@
}
const customRenderers = [
{
column: "userAppRole",
component: UserRoleRenderer,
},
{
column: "groupAppRole",
component: GroupRoleRenderer,
column: "role",
component: EditableRoleRenderer,
},
]
@ -76,7 +71,7 @@
const getAppUsers = (users, appId) => {
return users.map(user => ({
...user,
userAppRole: user.roles[Object.keys(user.roles).find(x => x === appId)],
role: user.roles[Object.keys(user.roles).find(x => x === appId)],
}))
}
@ -90,13 +85,30 @@
})
.map(group => ({
...group,
groupAppRole:
group.roles[
groups.actions.getGroupAppIds(group).find(x => x === appId)
],
role: group.roles[
groups.actions.getGroupAppIds(group).find(x => x === appId)
],
}))
}
const updateRole = async (role, id) => {
// Check if this is a user or a group
if ($usersFetch.rows.some(user => user._id === id)) {
await updateUserRole(role, id)
} else {
await updateGroupRole(role, id)
}
}
const removeRole = async id => {
// Check if this is a user or a group
if ($usersFetch.rows.some(user => user._id === id)) {
await removeUserRole(id)
} else {
await removeGroupRole(id)
}
}
const updateUserRole = async (role, userId) => {
const user = $usersFetch.rows.find(user => user._id === userId)
if (!user) {
@ -142,10 +154,8 @@
}
setContext("roles", {
updateUserRole,
removeUserRole,
updateGroupRole,
removeGroupRole,
updateRole,
removeRole,
})
onMount(async () => {

View file

@ -2,6 +2,8 @@
import { url, isActive } from "@roxi/routify"
import { Page } from "@budibase/bbui"
import { Content, SideNav, SideNavItem } from "components/portal/page"
$: narrow = !$isActive("./users/index") && !$isActive("./groups/index")
</script>
<Page narrow>

View file

@ -7,10 +7,7 @@
Icon,
Popover,
notifications,
List,
ListItem,
StatusLight,
Divider,
Table,
ActionMenu,
MenuItem,
Modal,
@ -18,32 +15,76 @@
import UserGroupPicker from "components/settings/UserGroupPicker.svelte"
import { createPaginationStore } from "helpers/pagination"
import { users, apps, groups } from "stores/portal"
import { onMount } from "svelte"
import { RoleUtils } from "@budibase/frontend-core"
import { onMount, setContext } from "svelte"
import { roles } from "stores/backend"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import CreateEditGroupModal from "./_components/CreateEditGroupModal.svelte"
import GroupIcon from "./_components/GroupIcon.svelte"
import AppAddModal from "./_components/AppAddModal.svelte"
import { Breadcrumbs, Breadcrumb } from "components/portal/page"
import AppNameTableRenderer from "../users/_components/AppNameTableRenderer.svelte"
import RemoveUserTableRenderer from "./_components/RemoveUserTableRenderer.svelte"
import AppRoleTableRenderer from "../users/_components/AppRoleTableRenderer.svelte"
export let groupId
const userSchema = {
email: {
width: "1fr",
},
_id: {
displayName: "",
width: "auto",
borderLeft: true,
},
}
const appSchema = {
name: {
width: "2fr",
},
role: {
width: "1fr",
},
}
const customUserTableRenderers = [
{
column: "_id",
component: RemoveUserTableRenderer,
},
]
const customAppTableRenderers = [
{
column: "name",
component: AppNameTableRenderer,
},
{
column: "role",
component: AppRoleTableRenderer,
},
]
let popoverAnchor
let popover
let searchTerm = ""
let prevSearch = undefined
let pageInfo = createPaginationStore()
let loaded = false
let editModal, deleteModal, appAddModal
let editModal, deleteModal
$: page = $pageInfo.page
$: fetchUsers(page, searchTerm)
$: group = $groups.find(x => x._id === groupId)
$: filtered = $users.data
$: groupApps = $apps.filter(app =>
groups.actions.getGroupAppIds(group).includes(apps.getProdAppID(app.devId))
)
$: groupApps = $apps
.filter(app =>
groups.actions
.getGroupAppIds(group)
.includes(apps.getProdAppID(app.devId))
)
.map(app => ({
...app,
role: group?.roles?.[apps.getProdAppID(app.devId)],
}))
$: console.log(groupApps)
$: {
if (loaded && !group?._id) {
$goto("./")
@ -93,6 +134,22 @@
}
}
const removeUser = async id => {
await groups.actions.removeUser(groupId, id)
}
const removeApp = async app => {
await groups.actions.removeApp(groupId, apps.getProdAppID(app.devId))
}
setContext("users", {
removeUser,
})
setContext("roles", {
updateRole: () => {},
removeRole: removeApp,
})
onMount(async () => {
try {
await Promise.all([groups.actions.init(), apps.load(), roles.fetch()])
@ -143,76 +200,35 @@
/>
</Popover>
</div>
<List>
{#if group?.users.length}
{#each group.users as user}
<ListItem
title={user.email}
on:click={() => $goto(`../users/${user._id}`)}
hoverable
>
<Icon
on:click={e => {
groups.actions.removeUser(groupId, user._id)
e.stopPropagation()
}}
hoverable
size="S"
name="Close"
/>
</ListItem>
{/each}
{:else}
<ListItem icon="UserGroup" title="This user group has no users" />
{/if}
</List>
<Table
schema={userSchema}
data={group?.users}
allowEditRows={false}
customPlaceholder
customRenderers={customUserTableRenderers}
on:click={e => $goto(`../users/${e.detail._id}`)}
>
<div class="placeholder" slot="placeholder">
<Heading size="S">This user group doesn't have any users</Heading>
</div>
</Table>
</Layout>
<Layout noPadding gap="S">
<div class="header">
<Heading size="S">Apps</Heading>
<div>
<Button on:click={appAddModal.show()} secondary>Add app</Button>
<Heading size="S">Apps</Heading>
<Table
schema={appSchema}
data={groupApps}
customPlaceholder
allowEditRows={false}
customRenderers={customAppTableRenderers}
on:click={e => $goto(`../../overview/${e.detail.devId}`)}
>
<div class="placeholder" slot="placeholder">
<Heading size="S">This group doesn't have access to any apps</Heading>
</div>
</div>
<List>
{#if groupApps.length}
{#each groupApps as app}
<ListItem
title={app.name}
icon={app?.icon?.name || "Apps"}
iconColor={app?.icon?.color || ""}
on:click={() => $goto(`../../overview/${app.devId}`)}
hoverable
>
<div class="title ">
<StatusLight
square
color={RoleUtils.getRoleColour(
group.roles[apps.getProdAppID(app.devId)]
)}
>
{getRoleLabel(app.devId)}
</StatusLight>
</div>
<Icon
on:click={e => {
groups.actions.removeApp(
groupId,
apps.getProdAppID(app.devId)
)
e.stopPropagation()
}}
hoverable
size="S"
name="Close"
/>
</ListItem>
{/each}
{:else}
<ListItem icon="Apps" title="This user group has access to no apps" />
{/if}
</List>
</Table>
</Layout>
</Layout>
{/if}
@ -221,10 +237,6 @@
<CreateEditGroupModal {group} {saveGroup} />
</Modal>
<Modal bind:this={appAddModal}>
<AppAddModal {group} />
</Modal>
<ConfirmDialog
bind:this={deleteModal}
title="Delete user group"
@ -245,4 +257,8 @@
.header :global(.spectrum-Heading) {
flex: 1 1 auto;
}
.placeholder {
width: 100%;
text-align: center;
}
</style>

View file

@ -14,10 +14,10 @@
<ModalContent
onConfirm={() => saveGroup(group)}
size="M"
title="Create User Group"
title={group?._rev ? "Edit group" : "Create group"}
confirmText="Save"
>
<Input bind:value={group.name} label="Team name" />
<Input bind:value={group.name} label="Name" />
<div class="modal-format">
<div class="modal-inner">
<Body size="XS">Icon</Body>

View file

@ -0,0 +1,15 @@
<script>
import { ActionButton } from "@budibase/bbui"
import { getContext } from "svelte"
export let value
const userContext = getContext("users")
const onClick = e => {
e.stopPropagation()
userContext.removeUser(value)
}
</script>
<ActionButton size="S" on:click={onClick}>Remove</ActionButton>