Update users detail page
This commit is contained in:
parent
7526bc8387
commit
e91ed89d72
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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}
|
||||||
|
|
Loading…
Reference in New Issue