Update users detail page

This commit is contained in:
Andrew Kingston 2022-12-21 11:53:16 +00:00
parent 7526bc8387
commit e91ed89d72
4 changed files with 134 additions and 63 deletions

View File

@ -18,20 +18,63 @@
Modal, Modal,
notifications, notifications,
Banner, Banner,
StatusLight, Table,
} from "@budibase/bbui" } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount, setContext } from "svelte"
import { users, auth, groups, apps, licensing } from "stores/portal" import { users, auth, groups, apps, licensing } from "stores/portal"
import { roles } from "stores/backend" import { roles } from "stores/backend"
import ForceResetPasswordModal from "./_components/ForceResetPasswordModal.svelte" import ForceResetPasswordModal from "./_components/ForceResetPasswordModal.svelte"
import UserGroupPicker from "components/settings/UserGroupPicker.svelte" import UserGroupPicker from "components/settings/UserGroupPicker.svelte"
import DeleteUserModal from "./_components/DeleteUserModal.svelte" import DeleteUserModal from "./_components/DeleteUserModal.svelte"
import GroupIcon from "../groups/_components/GroupIcon.svelte" import GroupIcon from "../groups/_components/GroupIcon.svelte"
import { Constants, RoleUtils } from "@budibase/frontend-core" import { Constants } from "@budibase/frontend-core"
import { Breadcrumbs, Breadcrumb } from "components/portal/page" import { Breadcrumbs, Breadcrumb } from "components/portal/page"
import RemoveGroupTableRenderer from "./_components/RemoveGroupTableRenderer.svelte"
import GroupNameTableRenderer from "../groups/_components/GroupNameTableRenderer.svelte"
import AppNameTableRenderer from "./_components/AppNameTableRenderer.svelte"
import AppRoleTableRenderer from "./_components/AppRoleTableRenderer.svelte"
export let userId export let userId
const groupSchema = {
name: {
width: "1fr",
},
_id: {
displayName: "",
width: "auto",
borderLeft: true,
},
}
const appSchema = {
name: {
width: "2fr",
},
role: {
width: "1fr",
},
}
const customGroupTableRenderers = [
{
column: "name",
component: GroupNameTableRenderer,
},
{
column: "_id",
component: RemoveGroupTableRenderer,
},
]
const customAppTableRenderers = [
{
column: "name",
component: AppNameTableRenderer,
},
{
column: "role",
component: AppRoleTableRenderer,
},
]
let deleteModal let deleteModal
let resetPasswordModal let resetPasswordModal
let popoverAnchor let popoverAnchor
@ -113,11 +156,6 @@
.join("") .join("")
} }
const getRoleLabel = roleId => {
const role = $roles.find(x => x._id === roleId)
return role?.name || "Custom role"
}
async function updateUserFirstName(evt) { async function updateUserFirstName(evt) {
try { try {
await users.save({ ...user, firstName: evt.target.value }) await users.save({ ...user, firstName: evt.target.value })
@ -172,6 +210,10 @@
await fetchUser() await fetchUser()
} }
setContext("groups", {
removeGroup,
})
onMount(async () => { onMount(async () => {
try { try {
await Promise.all([ await Promise.all([
@ -272,61 +314,43 @@
/> />
</Popover> </Popover>
</div> </div>
<List> <Table
{#if userGroups.length} schema={groupSchema}
{#each userGroups as group} data={userGroups}
<ListItem allowEditRows={false}
title={group.name} customPlaceholder
icon={group.icon} customRenderers={customGroupTableRenderers}
iconBackground={group.color} on:click={e => $goto(`../groups/${e.detail._id}`)}
hoverable
on:click={() => $goto(`../groups/${group._id}`)}
> >
<Icon <div class="placeholder" slot="placeholder">
on:click={e => { <Heading size="S">This user is not in any groups</Heading>
removeGroup(group._id) </div>
e.stopPropagation() </Table>
}}
hoverable
size="S"
name="Close"
/>
</ListItem>
{/each}
{:else}
<ListItem icon="UserGroup" title="This user is in no user groups" />
{/if}
</List>
</Layout> </Layout>
{/if} {/if}
<Layout gap="S" noPadding> <Layout gap="S" noPadding>
<Heading size="S">Apps</Heading> <Heading size="S">Apps</Heading>
<List>
{#if privileged} {#if privileged}
<Banner showCloseButton={false}> <Banner showCloseButton={false}>
This user's role grants admin access to all apps This user's role grants admin access to all apps
</Banner> </Banner>
{:else if availableApps.length}
{#each availableApps as app}
<ListItem
title={app.name}
iconColor={app?.icon?.color}
icon={app?.icon?.name || "Apps"}
hoverable
on:click={() => $goto(`../../overview/${app.devId}`)}
>
<div class="title ">
<StatusLight square color={RoleUtils.getRoleColour(app.role)}>
{getRoleLabel(app.role)}
</StatusLight>
</div>
</ListItem>
{/each}
{:else} {:else}
<ListItem icon="Apps" title="This user has access to no apps" /> <Table
schema={appSchema}
data={availableApps}
customPlaceholder
allowEditRows={false}
customRenderers={customAppTableRenderers}
on:click={e => $goto(`../../overview/${e.detail.devId}`)}
>
<div class="placeholder" slot="placeholder">
<Heading size="S">
This user doesn't have access to any apps
</Heading>
</div>
</Table>
{/if} {/if}
</List>
</Layout> </Layout>
</Layout> </Layout>
{/if} {/if}
@ -348,19 +372,16 @@
grid-template-columns: 120px 1fr; grid-template-columns: 120px 1fr;
align-items: center; align-items: center;
} }
.title { .title {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.tableTitle { .tableTitle {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-end; align-items: flex-end;
} }
.subtitle { .subtitle {
padding: 0 0 0 var(--spacing-m); padding: 0 0 0 var(--spacing-m);
display: flex; display: flex;
@ -368,4 +389,8 @@
justify-content: center; justify-content: center;
align-items: stretch; align-items: stretch;
} }
.placeholder {
width: 100%;
text-align: center;
}
</style> </style>

View File

@ -0,0 +1,30 @@
<script>
import { IconAvatar } from "@budibase/bbui"
export let value
export let row
</script>
<div class="align">
<IconAvatar icon={row?.icon?.name || "Apps"} color={row?.icon?.color} />
<div class="text">
{value}
</div>
</div>
<style>
.align {
display: flex;
align-items: center;
overflow: hidden;
gap: var(--spacing-m);
max-width: var(--max-cell-width);
flex: 1 1 auto;
width: 0;
}
.text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>

View File

@ -0,0 +1,16 @@
<script>
import { StatusLight } from "@budibase/bbui"
import { RoleUtils } from "@budibase/frontend-core"
import { roles } from "stores/backend"
export let value
const getRoleLabel = roleId => {
const role = $roles.find(x => x._id === roleId)
return role?.name || "Custom role"
}
</script>
<StatusLight square color={RoleUtils.getRoleColour(value)}>
{getRoleLabel(value)}
</StatusLight>

View File

@ -1,6 +1,6 @@
<script> <script>
import { Body, ModalContent, Table, Icon } from "@budibase/bbui" import { Body, ModalContent, Table, Icon } from "@budibase/bbui"
import PasswordCopyRenderer from "./PasswordCopyRenderer.svelte" import PasswordCopyTableRenderer from "./PasswordCopyTableRenderer.svelte"
import { parseToCsv } from "helpers/data/utils" import { parseToCsv } from "helpers/data/utils"
import { onMount } from "svelte" import { onMount } from "svelte"
@ -138,7 +138,7 @@
allowEditRows={false} allowEditRows={false}
allowSelectRows={false} allowSelectRows={false}
customRenderers={[ customRenderers={[
{ column: "password", component: PasswordCopyRenderer }, { column: "password", component: PasswordCopyTableRenderer },
]} ]}
/> />
{/if} {/if}