From 5dff2f30173a32cf122b20b96dd40635577c4bd5 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 14:16:36 +0100 Subject: [PATCH 01/51] Added pending users to user portal screen --- .../builder/portal/users/users/index.svelte | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index 984ecd46ff..0c69e2c213 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -110,6 +110,27 @@ } }) } + let invitesLoaded = false + let pendingInvites = [] + let parsedInvites = [] + + const invitesToSchema = invites => { + return invites.map(invite => { + const { admin, builder, userGroups, apps } = invite.info + + return { + email: invite.email, + builder, + admin, + userGroups: userGroups, + apps: apps ? [...new Set(Object.keys(apps))] : undefined, + } + }) + } + $: parsedInvites = invitesToSchema(pendingInvites) + $: console.log("parsed invites ", parsedInvites) + // $: console.log(pendingInvites) + $: console.log(enrichedUsers) const updateFetch = email => { fetch.update({ @@ -232,6 +253,9 @@ try { await groups.actions.init() groupsLoaded = true + + pendingInvites = await users.getInvites() + invitesLoaded = true } catch (error) { notifications.error("Error fetching user group data") } @@ -326,6 +350,23 @@ + + + Pending invitations + A list of all pending user invitations + + + + + + From 785b6f50ae7619bf9fcc82389e7635697ae7c399 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 14:53:31 +0100 Subject: [PATCH 02/51] Removed console debugging --- .../builder/src/pages/builder/portal/users/users/index.svelte | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index 0c69e2c213..19beb67773 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -128,9 +128,6 @@ }) } $: parsedInvites = invitesToSchema(pendingInvites) - $: console.log("parsed invites ", parsedInvites) - // $: console.log(pendingInvites) - $: console.log(enrichedUsers) const updateFetch = email => { fetch.update({ From 4f8e293dc9dec147d66de0fb4e0703f52c472346 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 16:42:27 +0100 Subject: [PATCH 03/51] Refresh pending invites after inviting a new user in the portal user menu --- .../builder/src/pages/builder/portal/users/users/index.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index 19beb67773..ff5ad2356e 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -162,6 +162,7 @@ })) try { inviteUsersResponse = await users.invite(payload) + pendingInvites = await users.getInvites() inviteConfirmationModal.show() } catch (error) { notifications.error("Error inviting user") From 4093516a0db895c684e448ee9b4ae420b972dbb0 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 27 Apr 2023 12:46:40 +0100 Subject: [PATCH 04/51] Initial commit of filter UX behaviour --- .../_components/BuilderSidePanel.svelte | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 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 9a6d9ea1d3..b31488e492 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,6 +28,10 @@ let inviting = false let searchFocus = false + //Or searching = true? + let filtered = true + $: console.log("filtering enabled ", filtered) + let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -52,15 +56,31 @@ } const filterInvites = async query => { - appInvites = await getInvites() - if (!query || query == "") { - filteredInvites = appInvites + if (!prodAppId) { return } - filteredInvites = appInvites.filter(invite => invite.email.includes(query)) + + appInvites = await getInvites() + + //On Focus behaviour + if (!filtered && (!query || query == "")) { + filteredInvites = [...appInvites] + return + } + + filteredInvites = appInvites.filter(invite => { + const inviteInfo = invite.info?.apps + if ((!query || query == "") && inviteInfo && prodAppId) { + return Object.keys(inviteInfo).includes(prodAppId) + } + return invite.email.includes(query) + }) } - $: filterInvites(query) + $: filtered, prodAppId, filterInvites(query) + $: if (searchFocus === true) { + filtered = false + } const usersFetch = fetchData({ API, @@ -351,7 +371,7 @@ onMount(() => { rendered = true - searchFocus = true + // searchFocus = true }) function handleKeyDown(evt) { @@ -417,7 +437,6 @@ autocomplete="off" disabled={inviting} value={query} - autofocus on:input={e => { query = e.target.value.trim() }} @@ -428,16 +447,20 @@ { + if (!filtered) { + filtered = true + } if (!query) { return } query = null userOnboardResponse = null + filtered = true }} > - + @@ -481,6 +504,8 @@
+ + +
{/each} From bb981603174bfc4f79b3e85b0bd703c1bb7965f9 Mon Sep 17 00:00:00 2001 From: Dean Date: Tue, 2 May 2023 14:35:15 +0100 Subject: [PATCH 05/51] On focus search behaviour renders to 100 invites, all groups and the first page of current users --- .../_components/BuilderSidePanel.svelte | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 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 b31488e492..7341dcd35c 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,9 +28,9 @@ let inviting = false let searchFocus = false - //Or searching = true? - let filtered = true - $: console.log("filtering enabled ", filtered) + // Initially filter entities without app access + // Show all when false + let filterByAppAccess = true let appInvites = [] let filteredInvites = [] @@ -38,7 +38,6 @@ let filteredGroups = [] let selectedGroup let userOnboardResponse = null - let userLimitReachedModal $: queryIsEmail = emailValidator(query) === true @@ -63,8 +62,9 @@ appInvites = await getInvites() //On Focus behaviour - if (!filtered && (!query || query == "")) { - filteredInvites = [...appInvites] + if (!filterByAppAccess && (!query || query == "")) { + filteredInvites = + appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return } @@ -77,9 +77,9 @@ }) } - $: filtered, prodAppId, filterInvites(query) + $: filterByAppAccess, prodAppId, filterInvites(query) $: if (searchFocus === true) { - filtered = false + filterByAppAccess = false } const usersFetch = fetchData({ @@ -99,9 +99,9 @@ } await usersFetch.update({ query: { - appId: query ? null : prodAppId, + appId: query || !filterByAppAccess ? null : prodAppId, email: query, - paginated: query ? null : false, + paginated: query || !filterByAppAccess ? null : false, }, }) await usersFetch.refresh() @@ -127,7 +127,12 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded) + $: debouncedUpdateFetch( + query, + $store.builderSidePanel, + loaded, + filterByAppAccess + ) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -202,9 +207,10 @@ } const searchGroups = (userGroups, query) => { - let filterGroups = query?.length - ? userGroups - : getAppGroups(userGroups, prodAppId) + let filterGroups = + query?.length || !filterByAppAccess + ? userGroups + : getAppGroups(userGroups, prodAppId) return filterGroups .filter(group => { if (!query?.length) { @@ -234,7 +240,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups) + $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -246,7 +252,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query) { + if (query || !filterByAppAccess) { return [] } // Must exclude users who have explicit privileges @@ -371,7 +377,6 @@ onMount(() => { rendered = true - // searchFocus = true }) function handleKeyDown(evt) { @@ -447,20 +452,20 @@ { - if (!filtered) { - filtered = true + if (!filterByAppAccess) { + filterByAppAccess = true } if (!query) { return } query = null userOnboardResponse = null - filtered = true + filterByAppAccess = true }} > - + @@ -581,7 +586,7 @@ {#if filteredUsers?.length}
-
+
Users
Access
From 19ed0ec3f59270c6c7418e0ea7870e9055f1bbbe Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 3 May 2023 11:22:38 +0100 Subject: [PATCH 06/51] Feedback updates and a fix for z-index issue in user side panel --- .../components/backend/DataTable/Table.svelte | 2 ++ .../_components/BuilderSidePanel.svelte | 4 ++-- .../builder/portal/users/users/index.svelte | 22 ++++++++++--------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index 4df6e9a306..460a02a9b1 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -22,6 +22,7 @@ export let rowCount export let disableSorting = false export let customPlaceholder = false + export let allowClickRows const dispatch = createEventDispatcher() @@ -110,6 +111,7 @@ {disableSorting} {customPlaceholder} showAutoColumns={!hideAutocolumns} + {allowClickRows} on:clickrelationship={e => selectRelationship(e.detail)} on:sort > 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 9a6d9ea1d3..be8237f616 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -555,7 +555,7 @@ {#if filteredUsers?.length}
-
+
Users
Access
@@ -696,7 +696,7 @@ max-width: calc(100vw - 40px); background: var(--background); border-left: var(--border-light); - z-index: 3; + z-index: 999; display: flex; flex-direction: column; overflow-y: auto; diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index ff5ad2356e..4053ef5ff3 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -88,6 +88,16 @@ }, } + const getPendingSchema = tblSchema => { + if (!tblSchema) { + return {} + } + let pendingSchema = JSON.parse(JSON.stringify(tblSchema)) + pendingSchema.email.displayName = "Pending Invites" + return pendingSchema + } + + $: pendingSchema = getPendingSchema(schema) $: userData = [] $: inviteUsersResponse = { successful: [], unsuccessful: [] } $: { @@ -346,22 +356,14 @@ goToNextPage={fetch.nextPage} />
- - - - - Pending invitations - A list of all pending user invitations - - -
From 20885a708d56969502c4c4505f95a32f3c8eeabd Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 3 May 2023 12:23:21 +0100 Subject: [PATCH 07/51] Feedback updates --- .../_components/BuilderSidePanel.svelte | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 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 7341dcd35c..5b35e65ed9 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,10 +28,6 @@ let inviting = false let searchFocus = false - // Initially filter entities without app access - // Show all when false - let filterByAppAccess = true - let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -62,7 +58,7 @@ appInvites = await getInvites() //On Focus behaviour - if (!filterByAppAccess && (!query || query == "")) { + if (searchFocus && !query) { filteredInvites = appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return @@ -77,10 +73,7 @@ }) } - $: filterByAppAccess, prodAppId, filterInvites(query) - $: if (searchFocus === true) { - filterByAppAccess = false - } + $: searchFocus, prodAppId, filterInvites(query) const usersFetch = fetchData({ API, @@ -99,9 +92,9 @@ } await usersFetch.update({ query: { - appId: query || !filterByAppAccess ? null : prodAppId, + appId: query || searchFocus ? null : prodAppId, email: query, - paginated: query || !filterByAppAccess ? null : false, + paginated: query || searchFocus ? null : false, }, }) await usersFetch.refresh() @@ -127,12 +120,7 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch( - query, - $store.builderSidePanel, - loaded, - filterByAppAccess - ) + $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded, searchFocus) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -208,7 +196,7 @@ const searchGroups = (userGroups, query) => { let filterGroups = - query?.length || !filterByAppAccess + query?.length || searchFocus ? userGroups : getAppGroups(userGroups, prodAppId) return filterGroups @@ -240,7 +228,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) + $: enrichedGroups = getEnrichedGroups($groups, searchFocus) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -252,7 +240,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query || !filterByAppAccess) { + if (query || searchFocus) { return [] } // Must exclude users who have explicit privileges @@ -452,20 +440,19 @@ { - if (!filterByAppAccess) { - filterByAppAccess = true + if (searchFocus) { + searchFocus = false } if (!query) { return } query = null userOnboardResponse = null - filterByAppAccess = true }} > - + @@ -509,8 +496,6 @@
- - -
{/each} From 5cf0e57eec977074c1c7e804b56d85ad2465f405 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 4 May 2023 16:01:34 +0100 Subject: [PATCH 08/51] Feedback updates and a fix pass the current query after updating a user invite --- .../_components/BuilderSidePanel.svelte | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 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 5b35e65ed9..9dce1fdf9b 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,6 +28,10 @@ let inviting = false let searchFocus = false + // Initially filter entities without app access + // Show all when false + let filterByAppAccess = true + let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -58,7 +62,7 @@ appInvites = await getInvites() //On Focus behaviour - if (searchFocus && !query) { + if (!filterByAppAccess && !query) { filteredInvites = appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return @@ -66,14 +70,17 @@ filteredInvites = appInvites.filter(invite => { const inviteInfo = invite.info?.apps - if ((!query || query == "") && inviteInfo && prodAppId) { + if (!query && inviteInfo && prodAppId) { return Object.keys(inviteInfo).includes(prodAppId) } return invite.email.includes(query) }) } - $: searchFocus, prodAppId, filterInvites(query) + $: filterByAppAccess, prodAppId, filterInvites(query) + $: if (searchFocus === true) { + filterByAppAccess = false + } const usersFetch = fetchData({ API, @@ -92,9 +99,9 @@ } await usersFetch.update({ query: { - appId: query || searchFocus ? null : prodAppId, + appId: query || !filterByAppAccess ? null : prodAppId, email: query, - paginated: query || searchFocus ? null : false, + paginated: query || !filterByAppAccess ? null : false, }, }) await usersFetch.refresh() @@ -120,7 +127,12 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded, searchFocus) + $: debouncedUpdateFetch( + query, + $store.builderSidePanel, + loaded, + filterByAppAccess + ) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -196,7 +208,7 @@ const searchGroups = (userGroups, query) => { let filterGroups = - query?.length || searchFocus + query?.length || !filterByAppAccess ? userGroups : getAppGroups(userGroups, prodAppId) return filterGroups @@ -228,7 +240,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups, searchFocus) + $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -240,7 +252,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query || searchFocus) { + if (query || !filterByAppAccess) { return [] } // Must exclude users who have explicit privileges @@ -335,12 +347,12 @@ [prodAppId]: role, }, }) - await filterInvites() + await filterInvites(query) } const onUninviteAppUser = async invite => { await uninviteAppUser(invite) - await filterInvites() + await filterInvites(query) } // Purge only the app from the invite or recind the invite if only 1 app remains? @@ -440,19 +452,20 @@ { - if (searchFocus) { - searchFocus = false + if (!filterByAppAccess) { + filterByAppAccess = true } if (!query) { return } query = null userOnboardResponse = null + filterByAppAccess = true }} > - + From 80d3b99b90dba2d1e7b4c3bd16a573c63b814f78 Mon Sep 17 00:00:00 2001 From: jvcalderon Date: Mon, 8 May 2023 13:26:00 +0200 Subject: [PATCH 09/51] Provide some functions to check the path in the context --- .../src/utils/tests/utils.spec.ts | 77 +++++++++++++++++++ packages/backend-core/src/utils/utils.ts | 19 ++++- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/packages/backend-core/src/utils/tests/utils.spec.ts b/packages/backend-core/src/utils/tests/utils.spec.ts index ededa48628..bea0bfa52b 100644 --- a/packages/backend-core/src/utils/tests/utils.spec.ts +++ b/packages/backend-core/src/utils/tests/utils.spec.ts @@ -5,6 +5,8 @@ import * as db from "../../db" import { Header } from "../../constants" import { newid } from "../../utils" import env from "../../environment" +import { beforeEach } from "@jest/globals" +import { BBContext } from "@budibase/types" describe("utils", () => { const config = new DBTestConfiguration() @@ -106,4 +108,79 @@ describe("utils", () => { expect(actual).toBe(undefined) }) }) + + describe("isServingBuilder", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isServingBuilder(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path is in builder", async () => { + ctx.path = "/builder/app/app_" + expectResult(true) + }) + + it("returns false if current path is not in builder", async () => { + ctx.path = "/builder/app" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) + + describe("isServingBuilderPreview", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isServingBuilderPreview(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path is in builder preview", async () => { + ctx.path = "/app/preview/xx" + expectResult(true) + }) + + it("returns false if current path is not in builder preview", async () => { + ctx.path = "/builder" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) + + describe("isPublicAPIRequest", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isPublicApiRequest(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path remains to public API", async () => { + ctx.path = "/api/public/v1/invoices" + expectResult(true) + + ctx.path = "/api/public/v1" + expectResult(true) + }) + + it("returns false if current path doesn't remain to public API", async () => { + ctx.path = "/api/public" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) }) diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 75b098093b..6cbd1fc406 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,10 +1,9 @@ -import { getAllApps, queryGlobalView } from "../db" +import { getAllApps } from "../db" import { Header, MAX_VALID_DATE, DocumentType, SEPARATOR, - ViewName, } from "../constants" import env from "../environment" import * as tenancy from "../tenancy" @@ -23,7 +22,9 @@ const APP_PREFIX = DocumentType.APP + SEPARATOR const PROD_APP_PREFIX = "/app/" const BUILDER_PREVIEW_PATH = "/app/preview" -const BUILDER_REFERER_PREFIX = "/builder/app/" +const BUILDER_PREFIX = "/builder" +const BUILDER_REFERER_PREFIX = `${BUILDER_PREFIX}/app/` +const PUBLIC_API_PREFIX = "/api/public/v1" function confirmAppId(possibleAppId: string | undefined) { return possibleAppId && possibleAppId.startsWith(APP_PREFIX) @@ -69,6 +70,18 @@ export function isServingApp(ctx: Ctx) { return false } +export function isServingBuilder(ctx: Ctx): boolean { + return ctx.path.startsWith(BUILDER_REFERER_PREFIX) +} + +export function isServingBuilderPreview(ctx: Ctx): boolean { + return ctx.path.startsWith(BUILDER_PREVIEW_PATH) +} + +export function isPublicApiRequest(ctx: Ctx): boolean { + return ctx.path.startsWith(PUBLIC_API_PREFIX) +} + /** * Given a request tries to find the appId, which can be located in various places * @param {object} ctx The main request body to look through. From d4d1bc03b31324c530b7f589cbd1ec402fdf739f Mon Sep 17 00:00:00 2001 From: jvcalderon Date: Mon, 8 May 2023 13:42:26 +0200 Subject: [PATCH 10/51] Fix ESLint --- packages/backend-core/src/utils/utils.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 6cbd1fc406..aee672042b 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,10 +1,5 @@ import { getAllApps } from "../db" -import { - Header, - MAX_VALID_DATE, - DocumentType, - SEPARATOR, -} from "../constants" +import { Header, MAX_VALID_DATE, DocumentType, SEPARATOR } from "../constants" import env from "../environment" import * as tenancy from "../tenancy" import * as context from "../context" From d33a06c89c810e0348e44d71084c39a8aa73901a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 8 May 2023 14:54:43 +0200 Subject: [PATCH 11/51] Send search term to api call --- .../groups/_components/GroupUsers.svelte | 21 +++++++++++++++++-- packages/frontend-core/src/api/groups.js | 7 +++++-- .../frontend-core/src/fetch/GroupUserFetch.js | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte b/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte index 9c18008e44..fbc3dd5ac1 100644 --- a/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte +++ b/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte @@ -1,7 +1,7 @@
- Users {#if !scimEnabled} {:else} {/if} -
-
- +
+ +
Date: Wed, 10 May 2023 16:00:12 +0100 Subject: [PATCH 22/51] Add grid menu items to copy row ID and rev --- .../grid/overlays/MenuOverlay.svelte | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte b/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte index 89e4d3503b..d0379edee6 100644 --- a/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte +++ b/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte @@ -1,5 +1,11 @@ {#if $menu.visible} @@ -64,6 +75,22 @@ > Edit row in modal + copyToClipboard($focusedRow?._id)} + on:click={menu.actions.close} + > + Copy row _id + + copyToClipboard($focusedRow?._rev)} + on:click={menu.actions.close} + > + Copy row _rev + Date: Wed, 10 May 2023 16:00:27 +0100 Subject: [PATCH 23/51] Fix not properly updating row state for formula columns --- packages/frontend-core/src/components/grid/stores/rows.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/frontend-core/src/components/grid/stores/rows.js b/packages/frontend-core/src/components/grid/stores/rows.js index 694b66629b..b6dc8c05d0 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.js +++ b/packages/frontend-core/src/components/grid/stores/rows.js @@ -338,15 +338,11 @@ export const deriveStores = context => { ...state, [rowId]: true, })) - const newRow = { ...row, ...get(rowChangeCache)[rowId] } - const saved = await API.saveRow(newRow) + const saved = await API.saveRow({ ...row, ...get(rowChangeCache)[rowId] }) // Update state after a successful change rows.update(state => { - state[index] = { - ...newRow, - _rev: saved._rev, - } + state[index] = saved return state.slice() }) rowChangeCache.update(state => { From d146aae08421048081df090d0d9f19fe704fb8eb Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 10 May 2023 16:02:00 +0100 Subject: [PATCH 24/51] Treat formula cell as readonly! --- packages/frontend-core/src/components/grid/cells/DataCell.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte index 0aa0cd54f4..f39b820632 100644 --- a/packages/frontend-core/src/components/grid/cells/DataCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte @@ -32,6 +32,7 @@ $: readonly = column.schema.autocolumn || column.schema.disabled || + column.schema.type === "formula" || (!$config.allowEditRows && row._id) // Register this cell API if the row is focused From 59ea4460f9ce211694468789e3adf23b661b3dca Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 11 May 2023 10:51:44 +0100 Subject: [PATCH 25/51] Fix multiple issues with keypresses and date cells due to flatpickr --- packages/bbui/src/Form/Core/DatePicker.svelte | 16 ++++++++-- .../src/components/grid/cells/DateCell.svelte | 29 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/packages/bbui/src/Form/Core/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker.svelte index 2c89a538a3..ad39136142 100644 --- a/packages/bbui/src/Form/Core/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker.svelte @@ -18,10 +18,14 @@ export let ignoreTimezones = false export let time24hr = false export let range = false + export let flatpickr + export let useKeyboardShortcuts = true + const dispatch = createEventDispatcher() const flatpickrId = `${uuid()}-wrapper` + let open = false - let flatpickr, flatpickrOptions + let flatpickrOptions // Another classic flatpickr issue. Errors were randomly being thrown due to // flatpickr internal code. Making sure that "destroy" is a valid function @@ -59,6 +63,8 @@ dispatch("change", timestamp.toISOString()) } }, + onOpen: () => dispatch("open"), + onClose: () => dispatch("close"), } $: redrawOptions = { @@ -113,12 +119,16 @@ const onOpen = () => { open = true - document.addEventListener("keyup", clearDateOnBackspace) + if (useKeyboardShortcuts) { + document.addEventListener("keyup", clearDateOnBackspace) + } } const onClose = () => { open = false - document.removeEventListener("keyup", clearDateOnBackspace) + if (useKeyboardShortcuts) { + document.removeEventListener("keyup", clearDateOnBackspace) + } // Manually blur all input fields since flatpickr creates a second // duplicate input field. diff --git a/packages/frontend-core/src/components/grid/cells/DateCell.svelte b/packages/frontend-core/src/components/grid/cells/DateCell.svelte index 0112bcda15..f5b1acb1c8 100644 --- a/packages/frontend-core/src/components/grid/cells/DateCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/DateCell.svelte @@ -1,12 +1,17 @@
@@ -42,6 +67,10 @@ {timeOnly} time24hr ignoreTimezones={schema.ignoreTimezones} + bind:flatpickr + on:open={() => (isOpen = true)} + on:close={() => (isOpen = false)} + useKeyboardShortcuts={false} />
{/if} From 5a0ae3ff01f1dc72c03d12e31c1ab0379dca884d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 11 May 2023 11:58:26 +0100 Subject: [PATCH 26/51] Disable most context menu options for cells in the new row --- .../src/components/grid/overlays/MenuOverlay.svelte | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte b/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte index d0379edee6..15ca08dbdf 100644 --- a/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte +++ b/packages/frontend-core/src/components/grid/overlays/MenuOverlay.svelte @@ -7,6 +7,7 @@ notifications, } from "@budibase/bbui" import { getContext } from "svelte" + import { NewRowID } from "../lib/constants" const { focusedRow, @@ -20,9 +21,11 @@ clipboard, dispatch, focusedCellAPI, + focusedRowId, } = getContext("grid") $: style = makeStyle($menu) + $: isNewRow = $focusedRowId === NewRowID const makeStyle = menu => { return `left:${menu.left}px; top:${menu.top}px;` @@ -69,7 +72,7 @@
dispatch("edit-row", $focusedRow)} on:click={menu.actions.close} > @@ -77,7 +80,7 @@ copyToClipboard($focusedRow?._id)} on:click={menu.actions.close} > @@ -85,7 +88,7 @@ copyToClipboard($focusedRow?._rev)} on:click={menu.actions.close} > @@ -93,14 +96,14 @@ Duplicate row Delete row From 1ebd1c274f49060edd63ca988497559933562f6f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 11 May 2023 13:32:46 +0200 Subject: [PATCH 27/51] Undo key changes --- packages/types/src/sdk/db.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/sdk/db.ts b/packages/types/src/sdk/db.ts index 023f6382e7..58b3b7e5bc 100644 --- a/packages/types/src/sdk/db.ts +++ b/packages/types/src/sdk/db.ts @@ -57,8 +57,8 @@ export type DatabaseDeleteIndexOpts = { export type DatabaseQueryOpts = { include_docs?: boolean - startkey?: string | string[] - endkey?: string | string[] + startkey?: string + endkey?: string limit?: number skip?: number descending?: boolean From 14906e762cec874d6534bef36b4baafee5a31643 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 11 May 2023 16:26:40 +0000 Subject: [PATCH 28/51] Bump version to 2.6.8-alpha.8 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 5988c50af4..c9e10d93a6 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.6.8-alpha.7", + "version": "2.6.8-alpha.8", "npmClient": "yarn", "packages": [ "packages/backend-core", From 395cf4a667aa01319e668c41f151ffbd5781bbe5 Mon Sep 17 00:00:00 2001 From: melohagan <101575380+melohagan@users.noreply.github.com> Date: Thu, 11 May 2023 17:49:33 +0100 Subject: [PATCH 29/51] Add JSON payload support for Make and Zapier (#10529) * Rename Integromat to Make. Update logo. * Add JSON type for automations * Support deprecated values in JSON * Fix json query editor width bug * Push body to schema if missing * Support JSON body * Add JSON payload support for Zapier * Update packages/server/src/automations/steps/make.ts Co-authored-by: Martin McKeaveney * July -> November * Add unit tests --------- Co-authored-by: Martin McKeaveney --- .../SetupPanel/AutomationBlockSetup.svelte | 76 ++++++++++++++++++- .../components/integration/QueryEditor.svelte | 6 +- packages/server/src/automations/steps/make.ts | 19 ++++- .../server/src/automations/steps/zapier.ts | 19 ++++- .../server/src/automations/tests/make.spec.ts | 54 +++++++++++++ .../src/automations/tests/zapier.spec.js | 27 ------- .../src/automations/tests/zapier.spec.ts | 56 ++++++++++++++ .../types/src/documents/app/automation.ts | 1 + 8 files changed, 227 insertions(+), 31 deletions(-) create mode 100644 packages/server/src/automations/tests/make.spec.ts delete mode 100644 packages/server/src/automations/tests/zapier.spec.js create mode 100644 packages/server/src/automations/tests/zapier.spec.ts diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 70cb56c77d..35c9c6ad6d 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -61,11 +61,63 @@ $: isTrigger = block?.type === "TRIGGER" $: isUpdateRow = stepId === ActionStepID.UPDATE_ROW + /** + * TODO - Remove after November 2023 + * ******************************* + * Code added to provide backwards compatibility between Values 1,2,3,4,5 + * and the new JSON body. + */ + let deprecatedSchemaProperties + $: { + if (block?.stepId === "integromat" || block?.stepId === "zapier") { + deprecatedSchemaProperties = schemaProperties.filter( + prop => !prop[0].startsWith("value") + ) + if (!deprecatedSchemaProperties.map(entry => entry[0]).includes("body")) { + deprecatedSchemaProperties.push([ + "body", + { + title: "Payload", + type: "json", + }, + ]) + } + } else { + deprecatedSchemaProperties = schemaProperties + } + } + /****************************************************/ + const getInputData = (testData, blockInputs) => { let newInputData = testData || blockInputs if (block.event === "app:trigger" && !newInputData?.fields) { newInputData = cloneDeep(blockInputs) } + + /** + * TODO - Remove after November 2023 + * ******************************* + * Code added to provide backwards compatibility between Values 1,2,3,4,5 + * and the new JSON body. + */ + if ( + (block?.stepId === "integromat" || block?.stepId === "zapier") && + !newInputData?.body?.value + ) { + let deprecatedValues = { + ...newInputData, + } + delete deprecatedValues.url + delete deprecatedValues.body + newInputData = { + url: newInputData.url, + body: { + value: JSON.stringify(deprecatedValues), + }, + } + } + /**********************************/ + inputData = newInputData setDefaultEnumValues() } @@ -239,7 +291,7 @@
- {#each schemaProperties as [key, value]} + {#each deprecatedSchemaProperties as [key, value]}
{#if key !== "fields"}