1
0
Fork 0
mirror of synced 2024-09-30 09:07:25 +13:00

builder side panel changes to support inviting creators

This commit is contained in:
Peter Clement 2023-08-29 14:41:56 +01:00
parent e88efe2d1a
commit 8b8bce186c
3 changed files with 395 additions and 241 deletions

View file

@ -1,5 +1,5 @@
<script>
import { Select } from "@budibase/bbui"
import { Select, FancySelect } from "@budibase/bbui"
import { roles } from "stores/backend"
import { licensing } from "stores/portal"
@ -18,6 +18,7 @@
export let footer = null
export let allowedRoles = null
export let allowCreator = false
export let fancySelect = false
const dispatch = createEventDispatcher()
const RemoveID = "remove"
@ -47,7 +48,7 @@
{
_id: CreatorID,
name: "Creator",
tag: $licensing.perAppBuildersEnabled && null,
tag: !$licensing.perAppBuildersEnabled && "Business",
},
...newRoles,
]
@ -82,7 +83,6 @@
}
const onChange = e => {
console.log(e.detail)
if (allowRemove && e.detail === RemoveID) {
dispatch("remove")
} else if (e.detail === CreatorID) {
@ -93,6 +93,32 @@
}
</script>
{#if fancySelect}
<FancySelect
{autoWidth}
{quiet}
{disabled}
{align}
{footer}
bind:value
on:change={onChange}
{options}
label="Access on this app"
getOptionLabel={role => role.name}
getOptionValue={role => role._id}
getOptionColour={getColor}
getOptionIcon={getIcon}
isOptionEnabled={option => {
if (option._id == CreatorID && !$licensing.perAppBuildersEnabled) {
return false
} else {
return true
}
}}
{placeholder}
{error}
/>
{:else}
<Select
{autoWidth}
{quiet}
@ -116,3 +142,4 @@
{placeholder}
{error}
/>
{/if}

View file

@ -1,6 +1,7 @@
<script>
import {
Icon,
Divider,
Heading,
Layout,
Input,
@ -9,6 +10,10 @@
ActionButton,
CopyInput,
Modal,
FancyForm,
FancyInput,
Button,
FancySelect,
} from "@budibase/bbui"
import { store } from "builderStore"
import { groups, licensing, apps, users, auth, admin } from "stores/portal"
@ -31,11 +36,17 @@
let loaded = false
let inviting = false
let searchFocus = false
let invitingFlow = false
// Initially filter entities without app access
// Show all when false
let filterByAppAccess = false
let email
let error
let form
let creationRoleType = "appUser"
let creationAccessType = "BASIC"
let appInvites = []
let filteredInvites = []
let filteredUsers = []
@ -54,7 +65,6 @@
query
)
$: isOwner = $auth.accountPortalAccess && $admin.cloud
const showInvite = (invites, users, groups, query) => {
return !invites?.length && !users?.length && !groups?.length && query
}
@ -292,7 +302,6 @@
$: filteredGroups = searchGroups(enrichedGroups, query)
$: groupUsers = buildGroupUsers(filteredGroups, filteredUsers)
$: allUsers = [...filteredUsers, ...groupUsers]
$: console.log(filteredGroups)
/*
Create pseudo users from the "users" attribute on app groups.
These users will appear muted in the UI and show the ROLE
@ -348,11 +357,20 @@
const payload = [
{
email: newUserEmail,
builder: false,
admin: false,
apps: { [prodAppId]: Constants.Roles.BASIC },
builder:
creationRoleType === Constants.BudibaseRoles.Admin ? true : false,
admin:
creationRoleType === Constants.BudibaseRoles.Admin ? true : false,
},
]
if (creationAccessType === Constants.Roles.CREATOR) {
payload[0].appBuilder = prodAppId
} else {
payload[0].apps = {
[prodAppId]: creationAccessType,
}
}
let userInviteResponse
try {
userInviteResponse = await users.onboard(payload)
@ -364,6 +382,10 @@
return userInviteResponse
}
const openInviteFlow = () => {
invitingFlow = true
}
const onInviteUser = async () => {
userOnboardResponse = await inviteUser()
const originalQuery = query + ""
@ -391,6 +413,7 @@
notifications.error(inviteFailureResponse)
}
userOnboardResponse = null
invitingFlow = false
}
const onUpdateUserInvite = async (invite, role) => {
@ -476,7 +499,17 @@
}}
>
<div class="builder-side-panel-header">
<Heading size="S">Users</Heading>
<div
on:click={() => {
invitingFlow = false
}}
class="header"
>
{#if invitingFlow}
<Icon name="BackAndroid" />
{/if}
<Heading size="S">{invitingFlow ? "Invite new user" : "Users"}</Heading>
</div>
<Icon
color="var(--spectrum-global-color-gray-600)"
name="RailRightClose"
@ -489,6 +522,7 @@
}}
/>
</div>
{#if !invitingFlow}
<div class="search" class:focused={searchFocus}>
<span class="search-input">
<Input
@ -539,7 +573,7 @@
disabled={!queryIsEmail || inviting}
on:click={$licensing.userLimitReached
? userLimitReachedModal.show
: onInviteUser}
: openInviteFlow}
>
Add user
</ActionButton>
@ -568,7 +602,11 @@
value={invite.info.apps?.[prodAppId]}
allowRemove={invite.info.apps?.[prodAppId]}
allowPublic={false}
allowCreator={true}
quiet={true}
on:addcreator={() => {
onUpdateUserInvite(invite, Constants.Roles.CREATOR)
}}
on:change={e => {
onUpdateUserInvite(invite, e.detail)
}}
@ -689,8 +727,8 @@
<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.
Email invites are not available without SMTP configuration. Here
is the password that has been generated for this user.
</div>
</div>
<div>
@ -702,6 +740,62 @@
</Layout>
{/if}
</div>
{:else}
<Divider />
<div class="body">
<Layout gap="L" noPadding>
<div class="user-form">
<FancyForm bind:this={form}>
<FancyInput
disabled={false}
label="Email"
value={query}
on:change={e => {
email = e.detail
}}
validate={() => {
if (!email) {
return "Please enter an email"
}
return null
}}
{error}
/>
<FancySelect
bind:value={creationRoleType}
options={sdk.users.isAdmin($auth.user)
? Constants.BudibaseRoleOptionsNew
: Constants.BudibaseRoleOptionsNew.filter(
option => option.value !== Constants.BudibaseRoles.Admin
)}
label="Role"
/>
{#if creationRoleType !== "ADMIN"}
<RoleSelect
placeholder={false}
bind:value={creationAccessType}
allowPublic={false}
allowCreator={true}
quiet={true}
autoWidth
align="right"
fancySelect
/>
{/if}
</FancyForm>
{#if creationRoleType === Constants.Roles.ADMIN}
<div class="admin-info">
<Icon name="Info" />
Admins will get full access to all apps and settings
</div>
{/if}
<span class="add-user">
<Button newStyles cta on:click={onInviteUser}>Add user</Button>
</span>
</div>
</Layout>
</div>
{/if}
<Modal bind:this={userLimitReachedModal}>
<UpgradeModal {isOwner} />
</Modal>
@ -717,6 +811,22 @@
align-items: center;
}
.add-user {
padding-top: var(--spacing-xl);
width: 100%;
display: grid;
}
.admin-info {
padding: var(--spacing-l) var(--spacing-l) var(--spacing-xs)
var(--spacing-l);
display: flex;
align-items: center;
gap: var(--spacing-xl);
height: 50px;
background-color: var(--background-alt);
}
.search-input {
flex: 1;
}
@ -856,6 +966,16 @@
flex-direction: column;
}
.header {
display: flex;
align-items: center;
gap: var(--spacing-lf);
}
.user-form {
padding: var(--spacing-xl);
}
.body {
display: flex;
flex-direction: column;

View file

@ -266,14 +266,17 @@ export const onboardUsers = async (ctx: Ctx<InviteUsersRequest>) => {
// Temp password to be passed to the user.
createdPasswords[invite.email] = password
let builder: { global: boolean; apps?: string[] } = { global: false }
if (invite.userInfo.appBuilder) {
builder.apps = [invite.userInfo.appBuilder]
}
return {
email: invite.email,
password,
forceResetPassword: true,
roles: invite.userInfo.apps,
admin: { global: false },
builder: { global: false },
builder,
tenantId: tenancy.getTenantId(),
}
})
@ -392,7 +395,7 @@ export const inviteAccept = async (
// info is an extension of the user object that was stored by global
const { email, info }: any = await checkInviteCode(inviteCode)
const user = await tenancy.doInTenant(info.tenantId, async () => {
let request = {
let request: any = {
firstName,
lastName,
password,
@ -400,9 +403,13 @@ export const inviteAccept = async (
roles: info.apps,
tenantId: info.tenantId,
}
let builder: { global: boolean; apps?: string[] } = { global: false }
if (info.appBuilder) {
builder.apps = [info.appBuilder]
request.builder = builder
}
delete info.apps
request = {
...request,
...info,