From 8d5f6cf7af9a7efec7f2f28b78e55c0b152ede78 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 24 Aug 2023 11:38:12 +0100 Subject: [PATCH 01/33] add api for per app builder and help function --- packages/frontend-core/src/api/user.js | 22 +++++++++++++++++++ packages/frontend-core/src/constants.js | 2 ++ .../shared-core/src/sdk/documents/users.ts | 7 ++++++ 3 files changed, 31 insertions(+) diff --git a/packages/frontend-core/src/api/user.js b/packages/frontend-core/src/api/user.js index d8723a649c..d0560239ba 100644 --- a/packages/frontend-core/src/api/user.js +++ b/packages/frontend-core/src/api/user.js @@ -250,4 +250,26 @@ export const buildUserEndpoints = API => ({ url: `/api/global/users/count/${appId}`, }) }, + + /** + * Adds a per app builder to the selected app + * @param appId the applications id + * @param userId The id of the user to add as a builder + */ + addAppBuilder: async ({ userId, appId }) => { + return await API.post({ + url: `/api/global/users/${userId}/app/${appId}/builder`, + }) + }, + + /** + * Removes a per app builder to the selected app + * @param appId the applications id + * @param userId The id of the user to remove as a builder + */ + removeAppBuilder: async ({ userId, appId }) => { + return await API.delete({ + url: `/api/global/users/${userId}/app/${appId}/builder`, + }) + }, }) diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index 0497a392f3..2a04886762 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -71,6 +71,7 @@ export const Features = { BRANDING: "branding", SCIM: "scim", SYNC_AUTOMATIONS: "syncAutomations", + APP_BUILDERS: "appBuilders", } // Role IDs @@ -80,6 +81,7 @@ export const Roles = { BASIC: "BASIC", PUBLIC: "PUBLIC", BUILDER: "BUILDER", + CREATOR: "CREATOR", } export const Themes = [ diff --git a/packages/shared-core/src/sdk/documents/users.ts b/packages/shared-core/src/sdk/documents/users.ts index 0f0983c6f7..1be8845656 100644 --- a/packages/shared-core/src/sdk/documents/users.ts +++ b/packages/shared-core/src/sdk/documents/users.ts @@ -35,6 +35,13 @@ export function isAdminOrBuilder( return isBuilder(user, appId) || isAdmin(user) } +export function isAdminOrGlobalBuilder( + user: User | ContextUser, + appId?: string +): boolean { + return isGlobalBuilder(user) || isAdmin(user) +} + // check if they are a builder within an app (not necessarily a global builder) export function hasAppBuilderPermissions(user?: User | ContextUser): boolean { if (!user) { From f7e43a766dc1c5167ba65f0099bd77ce34f3ea88 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 24 Aug 2023 11:38:50 +0100 Subject: [PATCH 02/33] add tag support to picker --- packages/bbui/src/Form/Core/Picker.svelte | 20 +++++++++++++++++++- packages/bbui/src/Form/Core/Select.svelte | 3 ++- packages/bbui/src/Form/Select.svelte | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/bbui/src/Form/Core/Picker.svelte b/packages/bbui/src/Form/Core/Picker.svelte index aada17b318..6658ab0df5 100644 --- a/packages/bbui/src/Form/Core/Picker.svelte +++ b/packages/bbui/src/Form/Core/Picker.svelte @@ -8,6 +8,8 @@ import Icon from "../../Icon/Icon.svelte" import StatusLight from "../../StatusLight/StatusLight.svelte" import Popover from "../../Popover/Popover.svelte" + import Tags from "../../Tags/Tags.svelte" + import Tag from "../../Tags/Tag.svelte" export let id = null export let disabled = false @@ -37,6 +39,7 @@ export let customPopoverHeight export let align = "left" export let footer = null + export let tag = null const dispatch = createEventDispatcher() @@ -99,7 +102,7 @@ bind:this={button} > {#if fieldIcon} - {#if !useOptionIconImage} + {#if !useOptionIconImage}x @@ -217,6 +220,13 @@ {getOptionLabel(option, idx)} + {#if option.tag} + + + {option.tag} + + + {/if} .spectrum-Icon) { + margin-top: 2px; + } diff --git a/packages/bbui/src/Form/Core/Select.svelte b/packages/bbui/src/Form/Core/Select.svelte index 2fad886910..e79ead7e8c 100644 --- a/packages/bbui/src/Form/Core/Select.svelte +++ b/packages/bbui/src/Form/Core/Select.svelte @@ -21,7 +21,7 @@ export let sort = false export let align export let footer = null - + export let tag = null const dispatch = createEventDispatcher() let open = false @@ -83,6 +83,7 @@ {isOptionEnabled} {autocomplete} {sort} + {tag} isPlaceholder={value == null || value === ""} placeholderOption={placeholder === false ? null : placeholder} isOptionSelected={option => option === value} diff --git a/packages/bbui/src/Form/Select.svelte b/packages/bbui/src/Form/Select.svelte index e87496652d..a9214320f9 100644 --- a/packages/bbui/src/Form/Select.svelte +++ b/packages/bbui/src/Form/Select.svelte @@ -25,7 +25,7 @@ export let customPopoverHeight export let align export let footer = null - + export let tag = null const dispatch = createEventDispatcher() const onChange = e => { value = e.detail @@ -61,6 +61,7 @@ {isOptionEnabled} {autocomplete} {customPopoverHeight} + {tag} on:change={onChange} on:click /> From 6b14353dcbd59a79fab19a7d817d12841e719497 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 24 Aug 2023 11:40:00 +0100 Subject: [PATCH 03/33] update side panel to enable selecting of creator role --- .../src/components/common/RoleSelect.svelte | 42 ++++++++++++++-- .../_components/BuilderSidePanel.svelte | 49 ++++++++++++------- .../builder/src/stores/portal/licensing.js | 4 ++ packages/builder/src/stores/portal/users.js | 10 ++++ 4 files changed, 83 insertions(+), 22 deletions(-) diff --git a/packages/builder/src/components/common/RoleSelect.svelte b/packages/builder/src/components/common/RoleSelect.svelte index 09a67cb6fe..62be915dcb 100644 --- a/packages/builder/src/components/common/RoleSelect.svelte +++ b/packages/builder/src/components/common/RoleSelect.svelte @@ -1,6 +1,8 @@
{user.email}
-
- {userTitle(user)} -
{ + addAppBuilder(user._id) + }} on:change={e => { onUpdateUser(user, e.detail) }} @@ -614,7 +625,7 @@ }} autoWidth align="right" - allowedRoles={user.isAdminOrBuilder + allowedRoles={user.isAdminOrGlobalBuilder ? [Constants.Roles.ADMIN] : null} /> diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js index 4a59f29f52..c42a2006c3 100644 --- a/packages/builder/src/stores/portal/licensing.js +++ b/packages/builder/src/stores/portal/licensing.js @@ -125,6 +125,9 @@ export const createLicensingStore = () => { const syncAutomationsEnabled = license.features.includes( Constants.Features.SYNC_AUTOMATIONS ) + const perAppBuildersEnabled = license.features.includes( + Constants.Features.APP_BUILDERS + ) store.update(state => { return { ...state, @@ -140,6 +143,7 @@ export const createLicensingStore = () => { auditLogsEnabled, enforceableSSO, syncAutomationsEnabled, + perAppBuildersEnabled, } }) }, diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index 992f6a5418..9cd5ed54ea 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -112,6 +112,14 @@ export function createUsersStore() { return await API.saveUser(user) } + async function addAppBuilder(userId, appId) { + return await API.addAppBuilder({ userId, appId }) + } + + async function removeAppBuilder(userId, appId) { + return await API.removeAppBuilder({ userId, appId }) + } + const getUserRole = user => sdk.users.isAdmin(user) ? "admin" @@ -139,6 +147,8 @@ export function createUsersStore() { getInvites, updateInvite, getUserCountByApp, + addAppBuilder, + removeAppBuilder, // any operation that adds or deletes users acceptInvite, create: refreshUsage(create), From d5aa9755937aae72b2b4a9b458fba9598d9709cf Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 24 Aug 2023 15:42:32 +0100 Subject: [PATCH 04/33] add per app builder support when adding groups --- .../_components/BuilderSidePanel.svelte | 88 ++++++++++++------- packages/builder/src/stores/portal/groups.js | 8 ++ packages/frontend-core/src/api/groups.js | 22 +++++ 3 files changed, 88 insertions(+), 30 deletions(-) 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`, + }) + }, } } From 5226f7389bb2576abda1d7eb6d7aed47545c4c6d Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 24 Aug 2023 16:41:52 +0100 Subject: [PATCH 05/33] fix bug with app not being shown to per app builder --- packages/builder/src/pages/builder/apps/index.svelte | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/pages/builder/apps/index.svelte b/packages/builder/src/pages/builder/apps/index.svelte index ca3617b589..7ccc98d78a 100644 --- a/packages/builder/src/pages/builder/apps/index.svelte +++ b/packages/builder/src/pages/builder/apps/index.svelte @@ -39,7 +39,7 @@ return publishedApps } return publishedApps.filter(app => { - if (sdk.users.isBuilder(user, app.appId)) { + if (sdk.users.isBuilder(user, app.prodId)) { return true } if (!Object.keys(user?.roles).length && user?.userGroups) { @@ -142,7 +142,12 @@
{#each userApps as app (app.appId)} - +
{app.name} From d2284c2f0aba7d1450b4bf199ca15adb500b011d Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 25 Aug 2023 09:44:29 +0100 Subject: [PATCH 06/33] fix sorting of users and groups --- .../_components/BuilderSidePanel.svelte | 41 ++++++++++++++----- packages/frontend-core/src/utils/roles.js | 7 ++-- 2 files changed, 34 insertions(+), 14 deletions(-) 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 3c2ddca459..bf405dbc52 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -12,7 +12,12 @@ } from "@budibase/bbui" import { store } from "builderStore" import { groups, licensing, apps, users, auth, admin } from "stores/portal" - import { fetchData, Constants, Utils } from "@budibase/frontend-core" + import { + fetchData, + Constants, + Utils, + RoleUtils, + } from "@budibase/frontend-core" import { sdk } from "@budibase/shared-core" import { API } from "api" import GroupIcon from "../../../portal/users/groups/_components/GroupIcon.svelte" @@ -132,16 +137,29 @@ 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 - }) + .sort(sortRoles) + } + + const sortRoles = (a, b) => { + const roleA = a.role + const roleB = b.role + + const priorityA = RoleUtils.getRolePriority(roleA) + const priorityB = RoleUtils.getRolePriority(roleB) + + if (roleA === undefined && roleB !== undefined) { + return 1 + } else if (roleA !== undefined && roleB === undefined) { + return -1 + } + + if (priorityA < priorityB) { + return 1 + } else if (priorityA > priorityB) { + return -1 + } + + return 0 } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) @@ -251,6 +269,7 @@ return nameMatch }) .map(enrichGroupRole) + .sort(sortRoles) } const enrichGroupRole = group => { diff --git a/packages/frontend-core/src/utils/roles.js b/packages/frontend-core/src/utils/roles.js index dc9138455d..9190d41c12 100644 --- a/packages/frontend-core/src/utils/roles.js +++ b/packages/frontend-core/src/utils/roles.js @@ -1,7 +1,8 @@ import { Roles } from "../constants" const RolePriorities = { - [Roles.ADMIN]: 4, + [Roles.ADMIN]: 5, + [Roles.CREATOR]: 4, [Roles.POWER]: 3, [Roles.BASIC]: 2, [Roles.PUBLIC]: 1, @@ -13,8 +14,8 @@ const RoleColours = { [Roles.PUBLIC]: "var(--spectrum-global-color-static-blue-400)", } -export const getRolePriority = roleId => { - return RolePriorities[roleId] ?? 0 +export const getRolePriority = role => { + return RolePriorities[role] ?? 0 } export const getRoleColour = roleId => { From ac2389c445b3dbbe5127e2dc8ea8ab4d37a46b15 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 29 Aug 2023 14:40:56 +0100 Subject: [PATCH 07/33] update api to take a per app builder --- packages/frontend-core/src/api/user.js | 3 ++- packages/frontend-core/src/constants.js | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/frontend-core/src/api/user.js b/packages/frontend-core/src/api/user.js index d0560239ba..8f3d50f3ee 100644 --- a/packages/frontend-core/src/api/user.js +++ b/packages/frontend-core/src/api/user.js @@ -156,13 +156,14 @@ export const buildUserEndpoints = API => ({ return await API.post({ url: "/api/global/users/onboard", body: payload.map(invite => { - const { email, admin, builder, apps } = invite + const { email, admin, builder, apps, appBuilder } = invite return { email, userInfo: { admin: admin ? { global: true } : undefined, builder: builder ? { global: true } : undefined, apps: apps ? apps : undefined, + appBuilder: appBuilder ? appBuilder : undefined, }, } }), diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index 2a04886762..4a77f5a43b 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -28,6 +28,19 @@ export const BudibaseRoleOptions = [ { label: "Admin", value: BudibaseRoles.Admin }, ] +export const BudibaseRoleOptionsNew = [ + { + label: "Admin", + value: "admin", + subtitle: "Has full access to all apps and settings in your account", + }, + { + label: "Member", + value: "appUser", + subtitle: "Can only view apps they have access to", + }, +] + export const BuilderRoleDescriptions = [ { value: BudibaseRoles.AppUser, From e88efe2d1a27a1bd4d736b20e51817477b9c9b6e Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 29 Aug 2023 14:41:34 +0100 Subject: [PATCH 08/33] update picker to allow only popover --- .../bbui/src/FancyForm/FancySelect.svelte | 102 ++++++++-------- packages/bbui/src/Form/Core/Picker.svelte | 115 ++++++++++-------- 2 files changed, 116 insertions(+), 101 deletions(-) diff --git a/packages/bbui/src/FancyForm/FancySelect.svelte b/packages/bbui/src/FancyForm/FancySelect.svelte index ee43ecc3ca..aa75a25f42 100644 --- a/packages/bbui/src/FancyForm/FancySelect.svelte +++ b/packages/bbui/src/FancyForm/FancySelect.svelte @@ -2,8 +2,9 @@ import { createEventDispatcher } from "svelte" import FancyField from "./FancyField.svelte" import Icon from "../Icon/Icon.svelte" - import Popover from "../Popover/Popover.svelte" import FancyFieldLabel from "./FancyFieldLabel.svelte" + import StatusLight from "../StatusLight/StatusLight.svelte" + import Picker from "../Form/Core/Picker.svelte" export let label export let value @@ -11,18 +12,30 @@ export let error = null export let validate = null export let options = [] + export let isOptionEnabled = () => true export let getOptionLabel = option => extractProperty(option, "label") export let getOptionValue = option => extractProperty(option, "value") - + export let getOptionSubtitle = option => extractProperty(option, "subtitle") + export let getOptionColour = () => null const dispatch = createEventDispatcher() let open = false - let popover let wrapper $: placeholder = !value $: selectedLabel = getSelectedLabel(value) + $: fieldColour = getFieldAttribute(getOptionColour, value, options) + const getFieldAttribute = (getAttribute, value, options) => { + // Wait for options to load if there is a value but no options + if (!options?.length) { + return "" + } + const index = options.findIndex( + (option, idx) => getOptionValue(option, idx) === value + ) + return index !== -1 ? getAttribute(options[index], index) : null + } const extractProperty = (value, property) => { if (value && typeof value === "object") { return value[property] @@ -64,44 +77,38 @@ {label} {/if} + {#if fieldColour} + + + + {/if} +
{selectedLabel || ""}
-
+
- (open = false)} - useAnchorWidth={true} - maxWidth={null} -> -
- {#if options.length} - {#each options as option, idx} -
onChange(getOptionValue(option, idx))} - > - - {getOptionLabel(option, idx)} - - {#if value === getOptionValue(option, idx)} - - {/if} -
- {/each} - {/if} -
-
+ option === value} +/> diff --git a/packages/bbui/src/Form/Core/Picker.svelte b/packages/bbui/src/Form/Core/Picker.svelte index 6658ab0df5..1aa709478c 100644 --- a/packages/bbui/src/Form/Core/Picker.svelte +++ b/packages/bbui/src/Form/Core/Picker.svelte @@ -28,6 +28,7 @@ export let getOptionIcon = () => null export let useOptionIconImage = false export let getOptionColour = () => null + export let getOptionSubtitle = () => null export let open = false export let readonly = false export let quiet = false @@ -39,8 +40,8 @@ export let customPopoverHeight export let align = "left" export let footer = null - export let tag = null - + export let onlyPopover = false + export let customAnchor = null const dispatch = createEventDispatcher() let searchTerm = null @@ -90,61 +91,62 @@ } - - + +{/if} {/if} + {#if getOptionSubtitle(option, idx)} + {getOptionSubtitle(option, idx)} + {/if} + {getOptionLabel(option, idx)} {#if option.tag} @@ -252,6 +260,17 @@ width: 100%; box-shadow: none; } + + .subtitle-text { + font-size: 12px; + line-height: 15px; + font-weight: 500; + top: 10px; + color: var(--spectrum-global-color-gray-600); + display: block; + margin-bottom: var(--spacing-s); + } + .spectrum-Picker-label.auto-width { margin-right: var(--spacing-xs); } From 8b8bce186c6c7f9b77e6ba73babc0d2af292ea11 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 29 Aug 2023 14:41:56 +0100 Subject: [PATCH 09/33] builder side panel changes to support inviting creators --- .../src/components/common/RoleSelect.svelte | 79 ++- .../_components/BuilderSidePanel.svelte | 542 +++++++++++------- .../src/api/controllers/global/users.ts | 15 +- 3 files changed, 395 insertions(+), 241 deletions(-) diff --git a/packages/builder/src/components/common/RoleSelect.svelte b/packages/builder/src/components/common/RoleSelect.svelte index 62be915dcb..cef032f7c5 100644 --- a/packages/builder/src/components/common/RoleSelect.svelte +++ b/packages/builder/src/components/common/RoleSelect.svelte @@ -1,5 +1,5 @@ - 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} + /> +{/if} 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 bf405dbc52..5bb8676ec0 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -1,6 +1,7 @@ diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/AppsTableRenderer.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/AppsTableRenderer.svelte index 55cad9b93b..b454d2668c 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/AppsTableRenderer.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/AppsTableRenderer.svelte @@ -7,7 +7,11 @@ export let row $: priviliged = sdk.users.isAdminOrBuilder(row) - $: count = priviliged ? $apps.length : value?.length || 0 + $: count = priviliged + ? $apps.length + : sdk.users.hasAppBuilderPermissions(row) + ? row?.builder?.apps?.length + : value?.length || 0
diff --git a/packages/frontend-core/src/utils/roles.js b/packages/frontend-core/src/utils/roles.js index 9190d41c12..1ae9d3ac14 100644 --- a/packages/frontend-core/src/utils/roles.js +++ b/packages/frontend-core/src/utils/roles.js @@ -9,6 +9,7 @@ const RolePriorities = { } const RoleColours = { [Roles.ADMIN]: "var(--spectrum-global-color-static-red-400)", + [Roles.CREATOR]: "var(--spectrum-global-color-static-magenta-600)", [Roles.POWER]: "var(--spectrum-global-color-static-orange-400)", [Roles.BASIC]: "var(--spectrum-global-color-static-green-400)", [Roles.PUBLIC]: "var(--spectrum-global-color-static-blue-400)", From 84571e36c20b168d297901a33e597c8387b42097 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 30 Aug 2023 10:50:49 +0100 Subject: [PATCH 16/33] use display to hide picker button instead of prop --- .../bbui/src/FancyForm/FancySelect.svelte | 39 ++++---- packages/bbui/src/Form/Core/Picker.svelte | 93 +++++++++---------- .../_components/BuilderSidePanel.svelte | 2 + 3 files changed, 69 insertions(+), 65 deletions(-) diff --git a/packages/bbui/src/FancyForm/FancySelect.svelte b/packages/bbui/src/FancyForm/FancySelect.svelte index aa75a25f42..811b53c2be 100644 --- a/packages/bbui/src/FancyForm/FancySelect.svelte +++ b/packages/bbui/src/FancyForm/FancySelect.svelte @@ -92,25 +92,30 @@
- option === value} -/> +
+ option === value} + /> +