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 be1267bb03..3c2ddca459 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -29,7 +29,7 @@ // Initially filter entities without app access // Show all when false - let filterByAppAccess = true + let filterByAppAccess = false let appInvites = [] let filteredInvites = [] @@ -106,31 +106,42 @@ }) await usersFetch.refresh() - filteredUsers = $usersFetch.rows.map(user => { - const isAdminOrGlobalBuilder = sdk.users.isAdminOrGlobalBuilder( - user, - prodAppId - ) - const isAppBuilder = sdk.users.hasAppBuilderPermissions(user, prodAppId) - let role = undefined - if (isAdminOrGlobalBuilder) { - role = Constants.Roles.ADMIN - } else if (isAppBuilder) { - role = Constants.Roles.CREATOR - } else { - const appRole = Object.keys(user.roles).find(x => x === prodAppId) - if (appRole) { - role = user.roles[appRole] + filteredUsers = $usersFetch.rows + .map(user => { + const isAdminOrGlobalBuilder = sdk.users.isAdminOrGlobalBuilder( + user, + prodAppId + ) + const isAppBuilder = sdk.users.hasAppBuilderPermissions(user, prodAppId) + let role = undefined + if (isAdminOrGlobalBuilder) { + role = Constants.Roles.ADMIN + } else if (isAppBuilder) { + role = Constants.Roles.CREATOR + } else { + const appRole = Object.keys(user.roles).find(x => x === prodAppId) + if (appRole) { + role = user.roles[appRole] + } } - } - return { - ...user, - role, - isAdminOrGlobalBuilder, - isAppBuilder, - } - }) + return { + ...user, + role, + isAdminOrGlobalBuilder, + isAppBuilder, + } + }) + .sort((a, b) => { + const roleA = a.role + const roleB = b.role + if (roleA === undefined && roleB !== undefined) { + return 1 + } else if (roleA !== undefined && roleB === undefined) { + return -1 + } + return 0 + }) } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) @@ -201,6 +212,9 @@ return } try { + if (group?.builder?.apps.includes(prodAppId)) { + await removeGroupAppBuilder(group._id) + } await updateAppGroup(group, role) } catch { notifications.error("Group update failed") @@ -242,9 +256,11 @@ const enrichGroupRole = group => { return { ...group, - role: group.roles?.[ - groups.actions.getGroupAppIds(group).find(x => x === prodAppId) - ], + role: group?.builder?.apps.includes(prodAppId) + ? Constants.Roles.CREATOR + : group.roles?.[ + groups.actions.getGroupAppIds(group).find(x => x === prodAppId) + ], } } @@ -257,8 +273,8 @@ $: 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 inherited from their parent group. The users allow assigning of user @@ -393,6 +409,14 @@ await users.removeAppBuilder(userId, prodAppId) } + const addGroupAppBuilder = async groupId => { + await groups.actions.addGroupAppBuilder(groupId, prodAppId) + } + + const removeGroupAppBuilder = async groupId => { + await groups.actions.removeGroupAppBuilder(groupId, prodAppId) + } + const initSidePanel = async sidePaneOpen => { if (sidePaneOpen === true) { await groups.actions.init() @@ -577,9 +601,13 @@ allowRemove={group.role} allowPublic={false} quiet={true} + allowCreator={true} on:change={e => { onUpdateGroup(group, e.detail) }} + on:addcreator={() => { + addGroupAppBuilder(group._id) + }} on:remove={() => { onUpdateGroup(group) }} @@ -612,7 +640,7 @@ value={user.role} allowRemove={user.role && !user.group} allowPublic={false} - allowCreator + allowCreator={true} quiet={true} on:addcreator={() => { addAppBuilder(user._id) diff --git a/packages/builder/src/stores/portal/groups.js b/packages/builder/src/stores/portal/groups.js index c7a54c7e6d..a37a216a7f 100644 --- a/packages/builder/src/stores/portal/groups.js +++ b/packages/builder/src/stores/portal/groups.js @@ -80,6 +80,14 @@ export function createGroupsStore() { getGroupAppIds: group => { return Object.keys(group?.roles || {}) }, + + addGroupAppBuilder: async (groupId, appId) => { + return await API.addGroupAppBuilder({ groupId, appId }) + }, + + removeGroupAppBuilder: async (groupId, appId) => { + return await API.removeGroupAppBuilder({ groupId, appId }) + }, } return { diff --git a/packages/frontend-core/src/api/groups.js b/packages/frontend-core/src/api/groups.js index 72cbe30718..b1be230ac6 100644 --- a/packages/frontend-core/src/api/groups.js +++ b/packages/frontend-core/src/api/groups.js @@ -104,5 +104,27 @@ export const buildGroupsEndpoints = API => { removeAppsFromGroup: async (groupId, appArray) => { return updateGroupResource(groupId, "apps", "remove", appArray) }, + + /** + * Add app builder to group + * @param groupId The group to update + * @param appId The app id where the builder will be added + */ + addGroupAppBuilder: async ({ groupId, appId }) => { + return await API.post({ + url: `/api/global/groups/${groupId}/app/${appId}/builder`, + }) + }, + + /** + * Remove app builder from group + * @param groupId The group to update + * @param appId The app id where the builder will be removed + */ + removeGroupAppBuilder: async ({ groupId, appId }) => { + return await API.delete({ + url: `/api/global/groups/${groupId}/app/${appId}/builder`, + }) + }, } }