Update spacing, borders and sizing
This commit is contained in:
parent
dd08845a44
commit
862ba6ce92
|
@ -33,6 +33,8 @@
|
||||||
export let sort = false
|
export let sort = false
|
||||||
export let fetchTerm = null
|
export let fetchTerm = null
|
||||||
export let customPopoverHeight
|
export let customPopoverHeight
|
||||||
|
export let align = "left"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let searchTerm = null
|
let searchTerm = null
|
||||||
|
@ -131,7 +133,7 @@
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
anchor={button}
|
anchor={button}
|
||||||
align="left"
|
align={align || "left"}
|
||||||
bind:this={popover}
|
bind:this={popover}
|
||||||
{open}
|
{open}
|
||||||
on:close={() => (open = false)}
|
on:close={() => (open = false)}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
export let autoWidth = false
|
export let autoWidth = false
|
||||||
export let autocomplete = false
|
export let autocomplete = false
|
||||||
export let sort = false
|
export let sort = false
|
||||||
|
export let align
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
{fieldColour}
|
{fieldColour}
|
||||||
{options}
|
{options}
|
||||||
{autoWidth}
|
{autoWidth}
|
||||||
|
{align}
|
||||||
{getOptionLabel}
|
{getOptionLabel}
|
||||||
{getOptionValue}
|
{getOptionValue}
|
||||||
{getOptionIcon}
|
{getOptionIcon}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
export let tooltip = ""
|
export let tooltip = ""
|
||||||
export let autocomplete = false
|
export let autocomplete = false
|
||||||
export let customPopoverHeight
|
export let customPopoverHeight
|
||||||
|
export let align
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = e => {
|
const onChange = e => {
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
{placeholder}
|
{placeholder}
|
||||||
{autoWidth}
|
{autoWidth}
|
||||||
{sort}
|
{sort}
|
||||||
|
{align}
|
||||||
{getOptionLabel}
|
{getOptionLabel}
|
||||||
{getOptionValue}
|
{getOptionValue}
|
||||||
{getOptionIcon}
|
{getOptionIcon}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let allowPublic = true
|
export let allowPublic = true
|
||||||
export let allowRemove = false
|
export let allowRemove = false
|
||||||
|
export let disabled = false
|
||||||
|
export let align
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const RemoveID = "remove"
|
const RemoveID = "remove"
|
||||||
|
@ -59,6 +61,8 @@
|
||||||
<Select
|
<Select
|
||||||
{autoWidth}
|
{autoWidth}
|
||||||
{quiet}
|
{quiet}
|
||||||
|
{disabled}
|
||||||
|
{align}
|
||||||
bind:value
|
bind:value
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
{options}
|
{options}
|
||||||
|
|
|
@ -81,7 +81,16 @@
|
||||||
await usersFetch.refresh()
|
await usersFetch.refresh()
|
||||||
|
|
||||||
filteredUsers = $usersFetch.rows.map(user => {
|
filteredUsers = $usersFetch.rows.map(user => {
|
||||||
const appRole = Object.keys(user.roles).find(x => x === prodAppId)
|
const isBuilderOrAdmin = user.admin?.global || user.builder?.global
|
||||||
|
let role = undefined
|
||||||
|
if (isBuilderOrAdmin) {
|
||||||
|
role = "ADMIN"
|
||||||
|
} else {
|
||||||
|
const appRole = Object.keys(user.roles).find(x => x === prodAppId)
|
||||||
|
if (appRole) {
|
||||||
|
role = user.roles[appRole]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if (
|
// if (
|
||||||
// !appRole &&
|
// !appRole &&
|
||||||
|
@ -94,7 +103,8 @@
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...user,
|
...user,
|
||||||
role: !appRole ? undefined : user.roles[appRole],
|
role,
|
||||||
|
isBuilderOrAdmin,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -423,167 +433,172 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if promptInvite && !userOnboardResponse}
|
<div class="body">
|
||||||
<Layout gap="S" paddingX="XL">
|
{#if promptInvite && !userOnboardResponse}
|
||||||
<div class="invite-header">
|
<Layout gap="S" paddingX="XL">
|
||||||
<Heading size="XS">No user found</Heading>
|
<div class="invite-header">
|
||||||
<div class="invite-directions">
|
<Heading size="XS">No user found</Heading>
|
||||||
Add a valid email to invite a new user
|
<div class="invite-directions">
|
||||||
</div>
|
Add a valid email to invite a new user
|
||||||
</div>
|
|
||||||
<div class="invite-form">
|
|
||||||
<span>{query || ""}</span>
|
|
||||||
<ActionButton
|
|
||||||
icon="UserAdd"
|
|
||||||
disabled={!queryIsEmail || inviting}
|
|
||||||
on:click={onInviteUser}
|
|
||||||
>
|
|
||||||
Add user
|
|
||||||
</ActionButton>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if !promptInvite}
|
|
||||||
<Layout gap="L" noPadding>
|
|
||||||
{#if filteredInvites?.length}
|
|
||||||
<Layout noPadding gap="XS">
|
|
||||||
<div class="auth-entity-header">
|
|
||||||
<div class="auth-entity-title">Pending invites</div>
|
|
||||||
<div class="auth-entity-access-title">Access</div>
|
|
||||||
</div>
|
</div>
|
||||||
{#each filteredInvites as invite}
|
|
||||||
<div class="auth-entity">
|
|
||||||
<div class="details">
|
|
||||||
<div class="user-email" title={invite.email}>
|
|
||||||
{invite.email}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="auth-entity-access">
|
|
||||||
<RoleSelect
|
|
||||||
placeholder={false}
|
|
||||||
value={invite.info.apps?.[prodAppId]}
|
|
||||||
allowRemove={invite.info.apps?.[prodAppId]}
|
|
||||||
allowPublic={false}
|
|
||||||
quiet={true}
|
|
||||||
on:change={e => {
|
|
||||||
onUpdateUserInvite(invite, e.detail)
|
|
||||||
}}
|
|
||||||
on:remove={() => {
|
|
||||||
onUninviteAppUser(invite)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</Layout>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if $licensing.groupsEnabled && filteredGroups?.length}
|
|
||||||
<Layout noPadding gap="XS">
|
|
||||||
<div class="auth-entity-header">
|
|
||||||
<div class="auth-entity-title">Groups</div>
|
|
||||||
<div class="auth-entity-access-title">Access</div>
|
|
||||||
</div>
|
|
||||||
{#each filteredGroups as group}
|
|
||||||
<div
|
|
||||||
class="auth-entity group"
|
|
||||||
on:click={() => {
|
|
||||||
if (selectedGroup != group._id) {
|
|
||||||
selectedGroup = group._id
|
|
||||||
} else {
|
|
||||||
selectedGroup = null
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:keydown={() => {}}
|
|
||||||
>
|
|
||||||
<div class="details">
|
|
||||||
<GroupIcon {group} size="S" />
|
|
||||||
<div>
|
|
||||||
{group.name}
|
|
||||||
</div>
|
|
||||||
<div class="auth-entity-meta">
|
|
||||||
{`${group.users?.length} user${
|
|
||||||
group.users?.length != 1 ? "s" : ""
|
|
||||||
}`}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="auth-entity-access">
|
|
||||||
<RoleSelect
|
|
||||||
placeholder={false}
|
|
||||||
value={group.role}
|
|
||||||
allowRemove={group.role}
|
|
||||||
allowPublic={false}
|
|
||||||
quiet={true}
|
|
||||||
on:change={e => {
|
|
||||||
onUpdateGroup(group, e.detail)
|
|
||||||
}}
|
|
||||||
on:remove={() => {
|
|
||||||
onUpdateGroup(group)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</Layout>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if filteredUsers?.length}
|
|
||||||
<div class="auth-entity-section">
|
|
||||||
<div class="auth-entity-header ">
|
|
||||||
<div class="auth-entity-title">Users</div>
|
|
||||||
<div class="auth-entity-access-title">Access</div>
|
|
||||||
</div>
|
|
||||||
{#each allUsers as user}
|
|
||||||
<div class="auth-entity">
|
|
||||||
<div class="details">
|
|
||||||
<div class="user-email" title={user.email}>
|
|
||||||
{user.email}
|
|
||||||
</div>
|
|
||||||
<div class="auth-entity-meta">
|
|
||||||
{userTitle(user)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="auth-entity-access" class:muted={user.group}>
|
|
||||||
<RoleSelect
|
|
||||||
note={roleNote(user)}
|
|
||||||
placeholder={false}
|
|
||||||
value={user.role}
|
|
||||||
allowRemove={user.role && !user.group}
|
|
||||||
allowPublic={false}
|
|
||||||
quiet={true}
|
|
||||||
on:change={e => {
|
|
||||||
onUpdateUser(user, e.detail)
|
|
||||||
}}
|
|
||||||
on:remove={() => {
|
|
||||||
onUpdateUser(user)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="invite-form">
|
||||||
</Layout>
|
<span>{query || ""}</span>
|
||||||
{/if}
|
<ActionButton
|
||||||
|
icon="UserAdd"
|
||||||
{#if userOnboardResponse?.created}
|
disabled={!queryIsEmail || inviting}
|
||||||
<Layout gap="S" paddingX="XL">
|
on:click={onInviteUser}
|
||||||
<div class="invite-header">
|
>
|
||||||
<Heading size="XS">User added!</Heading>
|
Add user
|
||||||
<div class="invite-directions">
|
</ActionButton>
|
||||||
Email invites are not available without SMTP configuration. Here is
|
|
||||||
the password that has been generated for this user.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Layout>
|
||||||
<div>
|
{/if}
|
||||||
<CopyInput
|
|
||||||
value={userOnboardResponse.successful[0]?.password}
|
{#if !promptInvite}
|
||||||
label="Password"
|
<Layout gap="L" noPadding>
|
||||||
/>
|
{#if filteredInvites?.length}
|
||||||
</div>
|
<Layout noPadding gap="XS">
|
||||||
</Layout>
|
<div class="auth-entity-header">
|
||||||
{/if}
|
<div class="auth-entity-title">Pending invites</div>
|
||||||
|
<div class="auth-entity-access-title">Access</div>
|
||||||
|
</div>
|
||||||
|
{#each filteredInvites as invite}
|
||||||
|
<div class="auth-entity">
|
||||||
|
<div class="details">
|
||||||
|
<div class="user-email" title={invite.email}>
|
||||||
|
{invite.email}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="auth-entity-access">
|
||||||
|
<RoleSelect
|
||||||
|
placeholder={false}
|
||||||
|
value={invite.info.apps?.[prodAppId]}
|
||||||
|
allowRemove={invite.info.apps?.[prodAppId]}
|
||||||
|
allowPublic={false}
|
||||||
|
quiet={true}
|
||||||
|
on:change={e => {
|
||||||
|
onUpdateUserInvite(invite, e.detail)
|
||||||
|
}}
|
||||||
|
on:remove={() => {
|
||||||
|
onUninviteAppUser(invite)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $licensing.groupsEnabled && filteredGroups?.length}
|
||||||
|
<Layout noPadding gap="XS">
|
||||||
|
<div class="auth-entity-header">
|
||||||
|
<div class="auth-entity-title">Groups</div>
|
||||||
|
<div class="auth-entity-access-title">Access</div>
|
||||||
|
</div>
|
||||||
|
{#each filteredGroups as group}
|
||||||
|
<div
|
||||||
|
class="auth-entity group"
|
||||||
|
on:click={() => {
|
||||||
|
if (selectedGroup != group._id) {
|
||||||
|
selectedGroup = group._id
|
||||||
|
} else {
|
||||||
|
selectedGroup = null
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:keydown={() => {}}
|
||||||
|
>
|
||||||
|
<div class="details">
|
||||||
|
<GroupIcon {group} size="S" />
|
||||||
|
<div>
|
||||||
|
{group.name}
|
||||||
|
</div>
|
||||||
|
<div class="auth-entity-meta">
|
||||||
|
{`${group.users?.length} user${
|
||||||
|
group.users?.length != 1 ? "s" : ""
|
||||||
|
}`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="auth-entity-access">
|
||||||
|
<RoleSelect
|
||||||
|
placeholder={false}
|
||||||
|
value={group.role}
|
||||||
|
allowRemove={group.role}
|
||||||
|
allowPublic={false}
|
||||||
|
quiet={true}
|
||||||
|
on:change={e => {
|
||||||
|
onUpdateGroup(group, e.detail)
|
||||||
|
}}
|
||||||
|
on:remove={() => {
|
||||||
|
onUpdateGroup(group)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if filteredUsers?.length}
|
||||||
|
<div class="auth-entity-section">
|
||||||
|
<div class="auth-entity-header ">
|
||||||
|
<div class="auth-entity-title">Users</div>
|
||||||
|
<div class="auth-entity-access-title">Access</div>
|
||||||
|
</div>
|
||||||
|
{#each allUsers as user}
|
||||||
|
<div class="auth-entity">
|
||||||
|
<div class="details">
|
||||||
|
<div class="user-email" title={user.email}>
|
||||||
|
{user.email}
|
||||||
|
</div>
|
||||||
|
<div class="auth-entity-meta">
|
||||||
|
{userTitle(user)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="auth-entity-access" class:muted={user.group}>
|
||||||
|
<RoleSelect
|
||||||
|
note={roleNote(user)}
|
||||||
|
placeholder={false}
|
||||||
|
value={user.role}
|
||||||
|
allowRemove={user.role && !user.group}
|
||||||
|
allowPublic={false}
|
||||||
|
quiet={true}
|
||||||
|
on:change={e => {
|
||||||
|
onUpdateUser(user, e.detail)
|
||||||
|
}}
|
||||||
|
on:remove={() => {
|
||||||
|
onUpdateUser(user)
|
||||||
|
}}
|
||||||
|
disabled={user.isBuilderOrAdmin}
|
||||||
|
autoWidth
|
||||||
|
align="right"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if userOnboardResponse?.created}
|
||||||
|
<Layout gap="S" paddingX="XL">
|
||||||
|
<div class="invite-header">
|
||||||
|
<Heading size="XS">User added!</Heading>
|
||||||
|
<div class="invite-directions">
|
||||||
|
Email invites are not available without SMTP configuration. Here is
|
||||||
|
the password that has been generated for this user.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<CopyInput
|
||||||
|
value={userOnboardResponse.successful[0]?.password}
|
||||||
|
label="Password"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -617,6 +632,9 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.auth-entity-access {
|
||||||
|
margin-right: var(--spacing-m);
|
||||||
|
}
|
||||||
.auth-entity-access.muted :global(.spectrum-Picker-label),
|
.auth-entity-access.muted :global(.spectrum-Picker-label),
|
||||||
.auth-entity-access.muted :global(.spectrum-StatusLight) {
|
.auth-entity-access.muted :global(.spectrum-StatusLight) {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
@ -634,7 +652,7 @@
|
||||||
.auth-entity,
|
.auth-entity,
|
||||||
.auth-entity-header {
|
.auth-entity-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 65% auto;
|
grid-template-columns: 1fr 100px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-xl);
|
gap: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
|
@ -657,10 +675,8 @@
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
border-left: var(--border-light);
|
border-left: var(--border-light);
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
padding: var(--spacing-xl) 0px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--spacing-xl);
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
transition: transform 130ms ease-out;
|
transition: transform 130ms ease-out;
|
||||||
|
@ -689,8 +705,10 @@
|
||||||
#builder-side-panel-container .search {
|
#builder-side-panel-container .search {
|
||||||
padding-top: var(--spacing-m);
|
padding-top: var(--spacing-m);
|
||||||
padding-bottom: var(--spacing-m);
|
padding-bottom: var(--spacing-m);
|
||||||
border-top: 1px solid var(--spectrum-alias-border-color-mid);
|
border-top: var(--border-light);
|
||||||
border-bottom: 1px solid var(--spectrum-alias-border-color-mid);
|
border-bottom: var(--border-light);
|
||||||
|
border-left: 2px solid transparent;
|
||||||
|
border-right: 2px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#builder-side-panel-container .search :global(input) {
|
#builder-side-panel-container .search :global(input) {
|
||||||
|
@ -721,6 +739,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.builder-side-panel-header {
|
.builder-side-panel-header {
|
||||||
|
height: 58px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -732,4 +751,11 @@
|
||||||
gap: var(--spacing-s);
|
gap: var(--spacing-s);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
padding: var(--spacing-xl) 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue