From 6bbdf0e4744e2a42283eeeb36d2c4cd0e9d0f2bc Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 18 Apr 2024 17:04:26 +0100 Subject: [PATCH 01/53] Bindings support for views and table row searches --- .../buttons/TableFilterButton.svelte | 71 ++++++++++++------- .../controls/FilterEditor/FilterDrawer.svelte | 1 + .../controls/FilterEditor/FilterUsers.svelte | 21 +++--- .../server/src/api/controllers/row/index.ts | 15 +++- .../src/api/controllers/row/utils/utils.ts | 41 ++++++++++- .../server/src/api/controllers/row/views.ts | 14 +++- 6 files changed, 122 insertions(+), 41 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte index 91456da655..26b6624160 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte @@ -1,7 +1,9 @@ - + {text} - - dispatch("change", tempValue)} - > -
- (tempValue = e.detail)} - /> -
-
-
- + + + (tempValue = e.detail)} + {bindings} + /> + diff --git a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte index 7f1ee8010d..74c081cd5b 100644 --- a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte @@ -304,6 +304,7 @@ OperatorOptions.ContainsAny.value, ].includes(filter.operator)} disabled={filter.noValue} + type={filter.valueType} /> {:else} diff --git a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterUsers.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterUsers.svelte index 88383ba170..4613b8c40f 100644 --- a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterUsers.svelte +++ b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterUsers.svelte @@ -1,7 +1,6 @@ - option.email} - getOptionValue={option => option._id} - {disabled} -/> +
+ option.email} + getOptionValue={option => option._id} + {disabled} + /> +
diff --git a/packages/server/src/api/controllers/row/index.ts b/packages/server/src/api/controllers/row/index.ts index c3d1f2cb47..7f99105ea4 100644 --- a/packages/server/src/api/controllers/row/index.ts +++ b/packages/server/src/api/controllers/row/index.ts @@ -2,7 +2,7 @@ import stream from "stream" import archiver from "archiver" import { quotas } from "@budibase/pro" -import { objectStore } from "@budibase/backend-core" +import { objectStore, context } from "@budibase/backend-core" import * as internal from "./internal" import * as external from "./external" import { isExternalTableID } from "../../../integrations/utils" @@ -198,8 +198,21 @@ export async function destroy(ctx: UserCtx) { export async function search(ctx: Ctx) { const tableId = utils.getTableId(ctx) + // Current user context for bindable search + const { _id, _rev, firstName, lastName, email, status, roleId } = ctx.user + + await context.ensureSnippetContext() + + const enrichedQuery = await utils.enrichSearchContext( + { ...ctx.request.body.query }, + { + user: { _id, _rev, firstName, lastName, email, status, roleId }, + } + ) + const searchParams: RowSearchParams = { ...ctx.request.body, + query: enrichedQuery, tableId, } diff --git a/packages/server/src/api/controllers/row/utils/utils.ts b/packages/server/src/api/controllers/row/utils/utils.ts index f387a468cf..503f139783 100644 --- a/packages/server/src/api/controllers/row/utils/utils.ts +++ b/packages/server/src/api/controllers/row/utils/utils.ts @@ -7,6 +7,8 @@ import { FieldType, RelationshipsJson, Row, + SearchRowRequest, + SearchRowResponse, Table, UserCtx, } from "@budibase/types" @@ -22,7 +24,7 @@ import { getInternalRowId, } from "./basic" import sdk from "../../../../sdk" - +import { processStringSync } from "@budibase/string-templates" import validateJs from "validate.js" validateJs.extend(validateJs.validators.datetime, { @@ -187,3 +189,40 @@ export async function sqlOutputProcessing( export function isUserMetadataTable(tableId: string) { return tableId === InternalTables.USER_METADATA } + +export async function enrichSearchContext( + fields: Record, + inputs = {}, + helpers = true +): Promise> { + const enrichedQuery: Record = {} + if (!fields || !inputs) { + return enrichedQuery + } + const parameters = { ...inputs } + // enrich the fields with dynamic parameters + for (let key of Object.keys(fields)) { + if (fields[key] == null) { + continue + } + if (typeof fields[key] === "object") { + // enrich nested fields object + enrichedQuery[key] = await enrichSearchContext( + fields[key], + parameters, + helpers + ) + } else if (typeof fields[key] === "string") { + // enrich string value as normal + enrichedQuery[key] = processStringSync(fields[key], parameters, { + noEscaping: true, + noHelpers: !helpers, + escapeNewlines: true, + }) + } else { + enrichedQuery[key] = fields[key] + } + } + + return enrichedQuery +} diff --git a/packages/server/src/api/controllers/row/views.ts b/packages/server/src/api/controllers/row/views.ts index 2644446d82..18953ebe88 100644 --- a/packages/server/src/api/controllers/row/views.ts +++ b/packages/server/src/api/controllers/row/views.ts @@ -9,7 +9,8 @@ import { } from "@budibase/types" import { dataFilters } from "@budibase/shared-core" import sdk from "../../../sdk" -import { db } from "@budibase/backend-core" +import { db, context } from "@budibase/backend-core" +import { enrichSearchContext, userSearchFromContext } from "./utils" export async function searchView( ctx: UserCtx @@ -56,10 +57,19 @@ export async function searchView( }) } + // Current user search context. + const { _id, _rev, firstName, lastName, email, status, roleId } = ctx.user + + await context.ensureSnippetContext() + + const enrichedQuery = await enrichSearchContext(query, { + user: { _id, _rev, firstName, lastName, email, status, roleId }, + }) + const searchOptions: RequiredKeys & RequiredKeys> = { tableId: view.tableId, - query, + query: enrichedQuery, fields: viewFields, ...getSortOptions(body, view), limit: body.limit, From bdf15b21b1f62cea09a3c03d5e0b8c7fc9260d66 Mon Sep 17 00:00:00 2001 From: Dean Date: Fri, 19 Apr 2024 11:49:20 +0100 Subject: [PATCH 02/53] Fixes for filter drawer padding --- .../buttons/TableFilterButton.svelte | 19 ++++++++++--------- .../src/components/FilterBuilder.svelte | 1 - 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte index 0fc3fd505e..140cac1533 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte @@ -1,6 +1,6 @@ + + + { + if (get(auth).user) { + try { + await API.updateSelf({ + freeTrialConfirmedAt: new Date().toISOString(), + }) + // Update the cached user + await auth.getSelf() + } finally { + freeTrialModal.hide() + } + } + }} + > +

Experience all of Budibase with a free 14-day trial

+
+ We've upgraded you to a free 14-day trial that allows you to try all our + features before deciding which plan is right for you. +

+ At the end of your trial, we'll automatically downgrade you to the Free + plan unless you choose to upgrade. +

+
+ +
+
+ + diff --git a/packages/builder/src/helpers/planTitle.js b/packages/builder/src/helpers/planTitle.js index 79f2bc2382..c08b8bf3fe 100644 --- a/packages/builder/src/helpers/planTitle.js +++ b/packages/builder/src/helpers/planTitle.js @@ -20,6 +20,9 @@ export function getFormattedPlanName(userPlanType) { case PlanType.ENTERPRISE: planName = "Enterprise" break + case PlanType.ENTERPRISE_BASIC_TRIAL: + planName = "Trial" + break default: planName = "Free" // Default to "Free" if the type is not explicitly handled } diff --git a/packages/builder/src/pages/builder/app/[application]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/_layout.svelte index fd6a97560d..60c45fd2e4 100644 --- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte @@ -32,6 +32,7 @@ import { UserAvatars } from "@budibase/frontend-core" import { TOUR_KEYS } from "components/portal/onboarding/tours.js" import PreviewOverlay from "./_components/PreviewOverlay.svelte" + import EnterpriseBasicTrialModal from "components/portal/onboarding/EnterpriseBasicTrialModal.svelte" export let application @@ -192,6 +193,8 @@ + + diff --git a/packages/builder/src/components/portal/licensing/EnterpriseBasicTrialBanner.svelte b/packages/builder/src/components/portal/licensing/EnterpriseBasicTrialBanner.svelte new file mode 100644 index 0000000000..111f0481b9 --- /dev/null +++ b/packages/builder/src/components/portal/licensing/EnterpriseBasicTrialBanner.svelte @@ -0,0 +1,43 @@ + + + + + + + diff --git a/packages/builder/src/components/portal/licensing/licensingBanners.js b/packages/builder/src/components/portal/licensing/licensingBanners.js index 34558e98e2..34b22c934b 100644 --- a/packages/builder/src/components/portal/licensing/licensingBanners.js +++ b/packages/builder/src/components/portal/licensing/licensingBanners.js @@ -12,7 +12,7 @@ const defaultCacheFn = key => { const upgradeAction = key => { return defaultNavigateAction( key, - "Upgrade Plan", + "Upgrade", `${get(admin).accountPortalUrl}/portal/upgrade` ) } diff --git a/packages/builder/src/components/portal/onboarding/EnterpriseBasicTrialModal.svelte b/packages/builder/src/components/portal/onboarding/EnterpriseBasicTrialModal.svelte index fa789311d1..6652bd4104 100644 --- a/packages/builder/src/components/portal/onboarding/EnterpriseBasicTrialModal.svelte +++ b/packages/builder/src/components/portal/onboarding/EnterpriseBasicTrialModal.svelte @@ -5,6 +5,7 @@ import { auth, licensing } from "stores/portal" import { API } from "api" import { PlanType } from "@budibase/types" + import { sdk } from "@budibase/shared-core" let freeTrialModal @@ -14,7 +15,8 @@ const showFreeTrialModal = (planType, freeTrialModal) => { if ( planType === PlanType.ENTERPRISE_BASIC_TRIAL && - !$auth.user?.freeTrialConfirmedAt + !$auth.user?.freeTrialConfirmedAt && + sdk.users.isAdmin($auth.user) ) { freeTrialModal?.show() } diff --git a/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte b/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte index 59a791538a..1e67bc2140 100644 --- a/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte +++ b/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte @@ -6,7 +6,7 @@ import { sdk } from "@budibase/shared-core" -{#if isEnabled(TENANT_FEATURE_FLAGS.LICENSING) && !$licensing.isEnterprisePlan} +{#if isEnabled(TENANT_FEATURE_FLAGS.LICENSING) && !$licensing.isEnterprisePlan && !$licensing.isEnterpriseTrial} {#if $admin.cloud && $auth?.user?.accountPortalAccess}