diff --git a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte index a832be83f6..b304140a8d 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -39,7 +39,6 @@ // Initially filter entities without app access // Show all when false let filterByAppAccess = false - let email let error let form @@ -55,7 +54,7 @@ let userLimitReachedModal let inviteFailureResponse = "" - $: queryIsEmail = emailValidator(query) === true + $: validEmail = emailValidator(email) === true $: prodAppId = apps.getProdAppID($store.appId) $: promptInvite = showInvite( filteredInvites, @@ -152,16 +151,13 @@ } const sortInviteRoles = (a, b) => { - const aIsEmpty = !a.info.apps || Object.keys(a.info.apps).length === 0 - const bIsEmpty = !b.info.apps || Object.keys(b.info.apps).length === 0 + const aEmpty = + !a.info?.appBuilders?.length && Object.keys(a.info.apps).length === 0 + const bEmpty = + !b.info?.appBuilders?.length && Object.keys(b.info.apps).length === 0 - return aIsEmpty - ? bIsEmpty - ? 0 - : 1 // Put items with empty "apps" at the bottom - : bIsEmpty - ? -1 - : 0 // Put items with non-empty "apps" above the empty ones + if (aEmpty && !bEmpty) return 1 + if (!aEmpty && bEmpty) return -1 } const sortRoles = (a, b) => { @@ -361,11 +357,11 @@ } async function inviteUser() { - if (!queryIsEmail) { + if (!validEmail) { notifications.error("Email is not valid") return } - const newUserEmail = query + "" + const newUserEmail = email + "" inviting = true const payload = [ @@ -377,7 +373,7 @@ ] if (creationAccessType === Constants.Roles.CREATOR) { - payload[0].appBuilder = prodAppId + payload[0].appBuilders = [prodAppId] } else { payload[0].apps = { [prodAppId]: creationAccessType, @@ -395,20 +391,22 @@ } const openInviteFlow = () => { - invitingFlow = true + $licensing.userLimitReached + ? userLimitReachedModal.show() + : (invitingFlow = true) } const onInviteUser = async () => { form.validate() userOnboardResponse = await inviteUser() - const originalQuery = query + "" - query = null + const originalQuery = email + "" + email = null const newUser = userOnboardResponse?.successful.find( user => user.email === originalQuery ) if (newUser) { - query = originalQuery + email = originalQuery notifications.success( userOnboardResponse.created ? "User created successfully" @@ -427,16 +425,26 @@ } userOnboardResponse = null invitingFlow = false + // trigger reload of the users + query = "" } const onUpdateUserInvite = async (invite, role) => { - await users.updateInvite({ + let updateBody = { code: invite.code, apps: { ...invite.apps, [prodAppId]: role, }, - }) + } + + if (role === Constants.Roles.CREATOR) { + updateBody.appBuilders = [...(updateBody.appBuilders ?? []), prodAppId] + delete updateBody?.apps?.[prodAppId] + } else if (role !== Constants.Roles.CREATOR && invite?.appBuilders) { + invite.appBuilders = [] + } + await users.updateInvite(updateBody) await filterInvites(query) } @@ -482,7 +490,7 @@ $: initSidePanel($store.builderSidePanel) function handleKeyDown(evt) { - if (evt.key === "Enter" && queryIsEmail && !inviting) { + if (evt.key === "Enter" && validEmail && !inviting) { onInviteUser() } } @@ -524,9 +532,7 @@ {invitingFlow ? "Invite new user" : "Users"}
- + Try searching a different email or invite a new userinvite a new user
@@ -606,7 +610,9 @@
{ email = e.detail - query = e.detail }} validate={() => { if (!email) { diff --git a/packages/frontend-core/src/api/user.js b/packages/frontend-core/src/api/user.js index 8f3d50f3ee..27b17ca60b 100644 --- a/packages/frontend-core/src/api/user.js +++ b/packages/frontend-core/src/api/user.js @@ -156,14 +156,14 @@ export const buildUserEndpoints = API => ({ return await API.post({ url: "/api/global/users/onboard", body: payload.map(invite => { - const { email, admin, builder, apps, appBuilder } = invite + const { email, admin, builder, apps, appBuilders } = invite return { email, userInfo: { admin: admin ? { global: true } : undefined, builder: builder ? { global: true } : undefined, apps: apps ? apps : undefined, - appBuilder: appBuilder ? appBuilder : undefined, + appBuilders: appBuilders ? appBuilders : undefined, }, } }), @@ -176,10 +176,12 @@ export const buildUserEndpoints = API => ({ * @param invite the invite code sent in the email */ updateUserInvite: async invite => { + console.log(invite) await API.post({ url: `/api/global/users/invite/update/${invite.code}`, body: { apps: invite.apps, + appBuilders: invite.appBuilders ? invite.appBuilders : undefined, }, }) }, diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index e7d40f5879..5cf6bf857f 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -267,8 +267,8 @@ export const onboardUsers = async (ctx: Ctx) => { // 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] + if (invite.userInfo.appBuilders) { + builder.apps = invite.userInfo.appBuilders } return { email: invite.email, @@ -371,6 +371,15 @@ export const updateInvite = async (ctx: any) => { ...invite, } + if (!updateBody?.appBuilders || !updateBody.appBuilders?.length) { + updated.info.appBuilders = [] + } else { + updated.info.appBuilders = [ + ...(invite.info.appBuilders ?? []), + ...updateBody.appBuilders, + ] + } + if (!updateBody?.apps || !Object.keys(updateBody?.apps).length) { updated.info.apps = [] } else { @@ -405,8 +414,8 @@ export const inviteAccept = async ( } let builder: { global: boolean; apps?: string[] } = { global: false } - if (info.appBuilder) { - builder.apps = [info.appBuilder] + if (info.appBuilders) { + builder.apps = info.appBuilders request.builder = builder } delete info.apps