From 6b566d8b7ad81cb69fe21c009cfcdee27851b5c4 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 29 Jan 2025 16:58:49 +0000 Subject: [PATCH 01/76] TS conversions of components required to create generic deletion component. --- packages/bbui/src/Form/Core/TextField.svelte | 27 +-- packages/bbui/src/Form/Field.svelte | 10 +- packages/bbui/src/Form/Input.svelte | 11 +- packages/bbui/src/Link/Link.svelte | 2 +- .../modals/DeleteDataConfirmationModal.svelte | 164 ++++++++++++++++++ packages/types/src/ui/common.ts | 3 + packages/types/src/ui/index.ts | 1 + 7 files changed, 193 insertions(+), 25 deletions(-) create mode 100644 packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte create mode 100644 packages/types/src/ui/common.ts diff --git a/packages/bbui/src/Form/Core/TextField.svelte b/packages/bbui/src/Form/Core/TextField.svelte index 917bb2a452..a4f614ce29 100644 --- a/packages/bbui/src/Form/Core/TextField.svelte +++ b/packages/bbui/src/Form/Core/TextField.svelte @@ -1,8 +1,9 @@ - diff --git a/packages/bbui/src/Form/Input.svelte b/packages/bbui/src/Form/Input.svelte index 47962720af..39055237f0 100644 --- a/packages/bbui/src/Form/Input.svelte +++ b/packages/bbui/src/Form/Input.svelte @@ -1,12 +1,12 @@ - + + +
+

+ Are you sure you wish to delete the table + + + + {source?.name} + ? + +

+ +

All table data will be deleted{viewsMessage}.

+

This action cannot be undone.

+ + {#if affectedScreens.length > 0} +
+ +
    + {#each affectedScreens as item} +
  • + {item.text} +
  • + {/each} +
+
+
+ {/if} +

+ Please enter the "{source?.name}" below to confirm. +

+ +
+
+ + diff --git a/packages/types/src/ui/common.ts b/packages/types/src/ui/common.ts new file mode 100644 index 0000000000..2f5d864ca0 --- /dev/null +++ b/packages/types/src/ui/common.ts @@ -0,0 +1,3 @@ +export type UIEvent = Event & { + currentTarget: EventTarget & HTMLInputElement +} & { key?: string } & { target?: any } diff --git a/packages/types/src/ui/index.ts b/packages/types/src/ui/index.ts index 6e5f37608c..9c4ba93058 100644 --- a/packages/types/src/ui/index.ts +++ b/packages/types/src/ui/index.ts @@ -3,3 +3,4 @@ export * from "./bindings" export * from "./components" export * from "./dataFetch" export * from "./datasource" +export * from "./common" From 795df854af65be542c70deb1cc05a49698e5ec0c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 29 Jan 2025 17:09:40 +0000 Subject: [PATCH 02/76] More TS fixes. --- packages/bbui/src/Form/Core/TextField.svelte | 8 ++++---- packages/bbui/src/Form/Input.svelte | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/bbui/src/Form/Core/TextField.svelte b/packages/bbui/src/Form/Core/TextField.svelte index a4f614ce29..2de310cd25 100644 --- a/packages/bbui/src/Form/Core/TextField.svelte +++ b/packages/bbui/src/Form/Core/TextField.svelte @@ -4,7 +4,7 @@ import type { UIEvent } from "@budibase/types" export let value: string | null = null - export let placeholder = null + export let placeholder: string | null = null export let type = "text" export let disabled = false export let id = null @@ -12,8 +12,8 @@ export let updateOnChange = true export let quiet = false export let align: string | null = null - export let autofocus = false - export let autocomplete = null + export let autofocus: boolean | null = false + export let autocomplete: string | null = null const dispatch = createEventDispatcher() @@ -71,7 +71,7 @@ onMount(async () => { if (disabled) return - focus = autofocus + focus = autofocus || false if (focus) { await tick() field.focus() diff --git a/packages/bbui/src/Form/Input.svelte b/packages/bbui/src/Form/Input.svelte index 39055237f0..f141e85a51 100644 --- a/packages/bbui/src/Form/Input.svelte +++ b/packages/bbui/src/Form/Input.svelte @@ -13,8 +13,8 @@ export let error = null export let updateOnChange = true export let quiet = false - export let autofocus - export let autocomplete + export let autofocus: boolean | null = null + export let autocomplete: string | null = null export let helpText = null const dispatch = createEventDispatcher() From b8e5512f307a5bb03adcab66ad35bad56da59dc8 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 29 Jan 2025 17:40:45 +0000 Subject: [PATCH 03/76] Remove table word, pass this in instead --- .../modals/DeleteDataConfirmationModal.svelte | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 64c70f0dd0..d9e55a4cf2 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -5,6 +5,7 @@ import type { Table, View, Datasource, Query } from "@budibase/types" export let source: Table | View | Datasource | Query | undefined + export let type: "table" | "view" | "datasource" | "query" export let deleteSourceFn: () => Promise let confirmDeleteDialog: any @@ -54,7 +55,7 @@

- Are you sure you wish to delete the table - + Are you sure you wish to delete the {type} + {source?.name} @@ -71,13 +72,13 @@

-

All table data will be deleted{viewsMessage}.

+

All {type} data will be deleted{viewsMessage}.

This action cannot be undone.

{#if affectedScreens.length > 0}
    {#each affectedScreens as item} @@ -109,7 +110,7 @@ max-width: 100%; } - .tableNameLine { + .sourceNameLine { display: inline-flex; max-width: 100%; vertical-align: bottom; From 1b8a229e8508548fecdae8a1072003960dc3088c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 30 Jan 2025 16:36:44 +0000 Subject: [PATCH 04/76] Functions to get source type and usage endpoint for screens. --- packages/backend-core/src/docIds/params.ts | 6 +++++- packages/server/src/api/controllers/screen.ts | 7 +++++++ packages/server/src/api/routes/screen.ts | 5 +++++ packages/server/src/sdk/app/common/index.ts | 1 + packages/server/src/sdk/app/common/utils.ts | 15 +++++++++++++++ packages/server/src/sdk/index.ts | 2 ++ packages/types/src/api/web/app/screen.ts | 7 +++++++ packages/types/src/documents/app/datasource.ts | 7 +++++++ 8 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 packages/server/src/sdk/app/common/index.ts create mode 100644 packages/server/src/sdk/app/common/utils.ts diff --git a/packages/backend-core/src/docIds/params.ts b/packages/backend-core/src/docIds/params.ts index 016604b69b..5f1c053bde 100644 --- a/packages/backend-core/src/docIds/params.ts +++ b/packages/backend-core/src/docIds/params.ts @@ -83,11 +83,15 @@ export function isViewId(id: string): boolean { /** * Check if a given ID is that of a datasource or datasource plus. */ -export const isDatasourceId = (id: string): boolean => { +export function isDatasourceId(id: string): boolean { // this covers both datasources and datasource plus return !!id && id.startsWith(`${DocumentType.DATASOURCE}${SEPARATOR}`) } +export function isQueryId(id: string): boolean { + return !!id && id.startsWith(`${DocumentType.QUERY}${SEPARATOR}`) +} + /** * Gets parameters for retrieving workspaces. */ diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index ad000871fe..99a6b5ab52 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -16,8 +16,10 @@ import { SaveScreenRequest, SaveScreenResponse, DeleteScreenResponse, + UsageScreenResponse, } from "@budibase/types" import { builderSocket } from "../../websockets" +import sdk from "../../sdk" export async function fetch(ctx: UserCtx) { const db = context.getAppDB() @@ -140,3 +142,8 @@ function findPlugins(component: ScreenProps, foundPlugins: string[]) { } component._children.forEach(child => findPlugins(child, foundPlugins)) } + +export async function usage(ctx: UserCtx) { + const sourceId = ctx.params.sourceId + const sourceType = sdk.common.getSourceType(sourceId) +} diff --git a/packages/server/src/api/routes/screen.ts b/packages/server/src/api/routes/screen.ts index 7caa37bbfc..6329175fb6 100644 --- a/packages/server/src/api/routes/screen.ts +++ b/packages/server/src/api/routes/screen.ts @@ -19,5 +19,10 @@ router authorized(permissions.BUILDER), controller.destroy ) + .post( + "/api/screens/usage/:sourceId", + authorized(permissions.BUILDER), + controller.usage + ) export default router diff --git a/packages/server/src/sdk/app/common/index.ts b/packages/server/src/sdk/app/common/index.ts new file mode 100644 index 0000000000..3eeaeaa90c --- /dev/null +++ b/packages/server/src/sdk/app/common/index.ts @@ -0,0 +1 @@ +export * from "./utils" diff --git a/packages/server/src/sdk/app/common/utils.ts b/packages/server/src/sdk/app/common/utils.ts new file mode 100644 index 0000000000..ed4e4c9a4f --- /dev/null +++ b/packages/server/src/sdk/app/common/utils.ts @@ -0,0 +1,15 @@ +import { SourceType } from "@budibase/types" +import { docIds } from "@budibase/backend-core" + +export function getSourceType(sourceId: string): SourceType { + if (docIds.isTableId(sourceId)) { + return SourceType.TABLE + } else if (docIds.isViewId(sourceId)) { + return SourceType.VIEW + } else if (docIds.isDatasourceId(sourceId)) { + return SourceType.DATASOURCE + } else if (docIds.isQueryId(sourceId)) { + return SourceType.QUERY + } + throw new Error("Unknown source type - cannot find document type") +} diff --git a/packages/server/src/sdk/index.ts b/packages/server/src/sdk/index.ts index a871546b60..91dd3dffff 100644 --- a/packages/server/src/sdk/index.ts +++ b/packages/server/src/sdk/index.ts @@ -11,6 +11,7 @@ import { default as plugins } from "./plugins" import * as views from "./app/views" import * as permissions from "./app/permissions" import * as rowActions from "./app/rowActions" +import * as common from "./app/common" const sdk = { backups, @@ -26,6 +27,7 @@ const sdk = { permissions, links, rowActions, + common, } // default export for TS diff --git a/packages/types/src/api/web/app/screen.ts b/packages/types/src/api/web/app/screen.ts index 372d1ba2ea..f7cd5c0bf7 100644 --- a/packages/types/src/api/web/app/screen.ts +++ b/packages/types/src/api/web/app/screen.ts @@ -15,3 +15,10 @@ export interface SaveScreenResponse extends Screen {} export interface DeleteScreenResponse { message: string } + +export interface UsageScreenResponse { + screens: { + url: string + _id: string + }[] +} diff --git a/packages/types/src/documents/app/datasource.ts b/packages/types/src/documents/app/datasource.ts index a0be7bd80d..46d2a81de0 100644 --- a/packages/types/src/documents/app/datasource.ts +++ b/packages/types/src/documents/app/datasource.ts @@ -57,3 +57,10 @@ export interface RestConfig { } dynamicVariables?: DynamicVariable[] } + +export enum SourceType { + DATASOURCE = "datasource", + QUERY = "query", + TABLE = "table", + VIEW = "view", +} From 47fdd0f64ffd0ccd3ec80b8e04031565fbcffe2b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 30 Jan 2025 17:55:53 +0000 Subject: [PATCH 05/76] Still requires tests, but main body of endpoint to check screen usage. --- packages/server/src/api/controllers/screen.ts | 28 ++++++++++++------- packages/server/src/sdk/app/screens/index.ts | 1 + .../server/src/sdk/app/screens/screens.ts | 15 ++++++++++ packages/server/src/sdk/index.ts | 2 ++ .../shared-core/src/sdk/documents/index.ts | 1 + .../shared-core/src/sdk/documents/screens.ts | 24 ++++++++++++++++ packages/shared-core/src/utils.ts | 17 +++++++++++ packages/types/src/api/web/app/screen.ts | 15 ++++++---- 8 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 packages/server/src/sdk/app/screens/index.ts create mode 100644 packages/server/src/sdk/app/screens/screens.ts create mode 100644 packages/shared-core/src/sdk/documents/screens.ts diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index 99a6b5ab52..403059efde 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -1,4 +1,4 @@ -import { getScreenParams, generateScreenID, DocumentType } from "../../db/utils" +import { generateScreenID, DocumentType } from "../../db/utils" import { events, context, @@ -17,20 +17,14 @@ import { SaveScreenResponse, DeleteScreenResponse, UsageScreenResponse, + ScreenUsage, } from "@budibase/types" import { builderSocket } from "../../websockets" import sdk from "../../sdk" +import { sdk as sharedSdk } from "@budibase/shared-core" export async function fetch(ctx: UserCtx) { - const db = context.getAppDB() - - const screens = ( - await db.allDocs( - getScreenParams(null, { - include_docs: true, - }) - ) - ).rows.map((el: any) => el.doc) + const screens = await sdk.screens.fetch() const roleId = ctx.user?.role?._id as string if (!roleId) { @@ -146,4 +140,18 @@ function findPlugins(component: ScreenProps, foundPlugins: string[]) { export async function usage(ctx: UserCtx) { const sourceId = ctx.params.sourceId const sourceType = sdk.common.getSourceType(sourceId) + const allScreens = await sdk.screens.fetch() + const response: ScreenUsage[] = [] + for (let screen of allScreens) { + if (sharedSdk.screens.findInSettings(screen, sourceId)) { + response.push({ + url: screen.routing.route, + _id: screen._id!, + }) + } + } + ctx.body = { + sourceType, + screens: response, + } } diff --git a/packages/server/src/sdk/app/screens/index.ts b/packages/server/src/sdk/app/screens/index.ts new file mode 100644 index 0000000000..84f4bad6bb --- /dev/null +++ b/packages/server/src/sdk/app/screens/index.ts @@ -0,0 +1 @@ +export * from "./screens" diff --git a/packages/server/src/sdk/app/screens/screens.ts b/packages/server/src/sdk/app/screens/screens.ts new file mode 100644 index 0000000000..c600825efb --- /dev/null +++ b/packages/server/src/sdk/app/screens/screens.ts @@ -0,0 +1,15 @@ +import { getScreenParams } from "../../../db/utils" +import { context } from "@budibase/backend-core" +import { Screen } from "@budibase/types" + +export async function fetch(): Promise { + const db = context.getAppDB() + + return ( + await db.allDocs( + getScreenParams(null, { + include_docs: true, + }) + ) + ).rows.map(el => el.doc!) +} diff --git a/packages/server/src/sdk/index.ts b/packages/server/src/sdk/index.ts index 91dd3dffff..e3e88c25c4 100644 --- a/packages/server/src/sdk/index.ts +++ b/packages/server/src/sdk/index.ts @@ -11,6 +11,7 @@ import { default as plugins } from "./plugins" import * as views from "./app/views" import * as permissions from "./app/permissions" import * as rowActions from "./app/rowActions" +import * as screens from "./app/screens" import * as common from "./app/common" const sdk = { @@ -23,6 +24,7 @@ const sdk = { datasources, queries, plugins, + screens, views, permissions, links, diff --git a/packages/shared-core/src/sdk/documents/index.ts b/packages/shared-core/src/sdk/documents/index.ts index 4b17c1ea08..502e968a15 100644 --- a/packages/shared-core/src/sdk/documents/index.ts +++ b/packages/shared-core/src/sdk/documents/index.ts @@ -1,3 +1,4 @@ export * as applications from "./applications" export * as automations from "./automations" export * as users from "./users" +export * as screens from "./screens" diff --git a/packages/shared-core/src/sdk/documents/screens.ts b/packages/shared-core/src/sdk/documents/screens.ts new file mode 100644 index 0000000000..8fdd7087c8 --- /dev/null +++ b/packages/shared-core/src/sdk/documents/screens.ts @@ -0,0 +1,24 @@ +import { Screen } from "@budibase/types" +import { flattenObject } from "../../utils" + +export function findInSettings(screen: Screen, toFind: string) { + const flattened = flattenObject(screen.props) + const foundIn: { setting: string; value: string }[] = [] + for (let key of Object.keys(flattened)) { + let found = false + if (typeof flattened[key] === "string") { + found = flattened[key].includes(toFind) + } else if (Array.isArray(flattened[key])) { + found = flattened[key].find( + (el: any) => typeof el === "string" && el.includes(toFind) + ) + } + if (found) { + foundIn.push({ + setting: key, + value: flattened[key], + }) + } + } + return foundIn +} diff --git a/packages/shared-core/src/utils.ts b/packages/shared-core/src/utils.ts index fac8fa61ee..afc1c8872b 100644 --- a/packages/shared-core/src/utils.ts +++ b/packages/shared-core/src/utils.ts @@ -173,3 +173,20 @@ export function processSearchFilters( ], } } + +export function flattenObject( + obj: Record, + parentKey: string = "", + state: Record = {} +) { + for (const key of Object.keys(obj)) { + const newKey = parentKey.length ? `${parentKey}.${key}` : key + const value = obj[key] + if (value && typeof value === "object" && !Array.isArray(value)) { + flattenObject(value, newKey, state) + } else { + state[newKey] = value + } + } + return state +} diff --git a/packages/types/src/api/web/app/screen.ts b/packages/types/src/api/web/app/screen.ts index f7cd5c0bf7..280c623216 100644 --- a/packages/types/src/api/web/app/screen.ts +++ b/packages/types/src/api/web/app/screen.ts @@ -1,4 +1,4 @@ -import { ScreenRoutingJson, Screen } from "../../../documents" +import { ScreenRoutingJson, Screen, SourceType } from "../../../documents" export interface FetchScreenRoutingResponse { routes: ScreenRoutingJson @@ -16,9 +16,12 @@ export interface DeleteScreenResponse { message: string } -export interface UsageScreenResponse { - screens: { - url: string - _id: string - }[] +export interface ScreenUsage { + url: string + _id: string +} + +export interface UsageScreenResponse { + sourceType: SourceType + screens: ScreenUsage[] } From 4626d0d16b69c5148c39865ac187affd23c4ebdb Mon Sep 17 00:00:00 2001 From: mikesealey Date: Fri, 31 Jan 2025 15:08:25 +0000 Subject: [PATCH 06/76] replaces broken link --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 26ad9f80c2..552a849581 100644 --- a/README.md +++ b/README.md @@ -54,17 +54,21 @@

    + ## ✨ Features -### Build and ship real software +### Build and ship real software + Unlike other platforms, with Budibase you build and ship single page applications. Budibase applications have performance baked in and can be designed responsively, providing users with a great experience.

    ### Open source and extensible + Budibase is open-source - licensed as GPL v3. This should fill you with confidence that Budibase will always be around. You can also code against Budibase or fork it and make changes as you please, providing a developer-friendly experience.

    ### Load data or start from scratch + Budibase pulls data from multiple sources, including MongoDB, CouchDB, PostgreSQL, MariaDB, MySQL, Airtable, S3, DynamoDB, or a REST API. And unlike other platforms, with Budibase you can start from scratch and create business apps with no data sources. [Request new datasources](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).

    @@ -82,10 +86,12 @@ Budibase comes out of the box with beautifully designed, powerful components whi

    ### Automate processes, integrate with other tools and connect to webhooks + Save time by automating manual processes and workflows. From connecting to webhooks to automating emails, simply tell Budibase what to do and let it work for you. You can easily [create new automations for Budibase here](https://github.com/Budibase/automations) or [Request new automation](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).

    ### Integrate with your favorite tools + Budibase integrates with a number of popular tools allowing you to build apps that perfectly fit your stack.

    @@ -94,6 +100,7 @@ Budibase integrates with a number of popular tools allowing you to build apps th

    ### Deploy with confidence and security + Budibase is made to scale. With Budibase, you can self-host on your own infrastructure and globally manage users, onboarding, SMTP, apps, groups, theming and more. You can also provide users/groups with an app portal and disseminate user management to the group manager. - Checkout the promo video: https://youtu.be/xoljVpty_Kw @@ -104,15 +111,15 @@ Budibase is made to scale. With Budibase, you can self-host on your own infrastr
    - ## Budibase Public API + As with anything that we build in Budibase, our new public API is simple to use, flexible, and introduces new extensibility. To summarize, the Budibase API enables: - Budibase as a backend - Interoperability - #### Docs + You can learn more about the Budibase API at the following places: - [General documentation](https://docs.budibase.com/docs/public-api): Learn how to get your API key, how to use spec, and how to use Postman @@ -132,10 +139,8 @@ Deploy Budibase using Docker, Kubernetes, and Digital Ocean on your existing inf - [Digital Ocean](https://docs.budibase.com/docs/digitalocean) - [Portainer](https://docs.budibase.com/docs/portainer) - ### [Get started with Budibase Cloud](https://budibase.com) -

    ## 🎓 Learning Budibase @@ -143,7 +148,6 @@ Deploy Budibase using Docker, Kubernetes, and Digital Ocean on your existing inf The Budibase documentation [lives here](https://docs.budibase.com/docs).
    -

    ## 💬 Community @@ -152,25 +156,24 @@ If you have a question or would like to talk with other Budibase users and join


    - ## ❗ Code of conduct Budibase is dedicated to providing everyone a welcoming, diverse, and harassment-free experience. We expect everyone in the Budibase community to abide by our [**Code of Conduct**](https://github.com/Budibase/budibase/blob/HEAD/docs/CODE_OF_CONDUCT.md). Please read it.
    -

    - ## 🙌 Contributing to Budibase From opening a bug report to creating a pull request: every contribution is appreciated and welcomed. If you're planning to implement a new feature or change the API, please create an issue first. This way, we can ensure your work is not in vain. Environment setup instructions are available [here](https://github.com/Budibase/budibase/tree/HEAD/docs/CONTRIBUTING.md). ### Not Sure Where to Start? -A good place to start contributing is the [First time issues project](https://github.com/Budibase/budibase/projects/22). + +A good place to start contributing is by looking for the [good first issue](https://github.com/Budibase/budibase/labels/good%20first%20issue) tag. ### How the repository is organized + Budibase is a monorepo managed by lerna. Lerna manages the building and publishing of the budibase packages. At a high level, here are the packages that make up Budibase. - [packages/builder](https://github.com/Budibase/budibase/tree/HEAD/packages/builder) - contains code for the budibase builder client-side svelte application. @@ -183,7 +186,6 @@ For more information, see [CONTRIBUTING.md](https://github.com/Budibase/budibase

    - ## 📝 License Budibase is open-source, licensed as [GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html). The client and component libraries are licensed as [MPL](https://directory.fsf.org/wiki/License:MPL-2.0) - so the apps you build can be licensed however you like. @@ -202,7 +204,6 @@ If you are having issues between updates of the builder, please use the guide [h Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): - From d6fb87dce04008d7a12a4e2f38481d605161b4b2 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 31 Jan 2025 17:46:43 +0000 Subject: [PATCH 07/76] Creating structures for testing usage endpoint. --- .../src/api/routes/tests/screen.spec.ts | 10 +- packages/server/src/constants/screens.ts | 176 +++++++++++++++++- .../server/src/tests/utilities/structures.ts | 20 +- 3 files changed, 203 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index 82a550f2fd..7d3049faca 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -3,7 +3,8 @@ import * as setup from "./utilities" import { events, roles } from "@budibase/backend-core" import { Screen, Role, BuiltinPermissionID } from "@budibase/types" -const { basicScreen } = setup.structures +const { basicScreen, tableScreen, viewScreen, queryScreen, basicTable } = + setup.structures describe("/screens", () => { let config = setup.getConfig() @@ -186,4 +187,11 @@ describe("/screens", () => { }) }) }) + + describe("usage", () => { + it("should find table usage", async () => { + const table = await config.api.table.save(basicTable(), { status: 200 }) + const tableScreen = await config.api.screen.save(tableScreen()) + }) + }) }) diff --git a/packages/server/src/constants/screens.ts b/packages/server/src/constants/screens.ts index 1107289ea0..52f0b3d9ff 100644 --- a/packages/server/src/constants/screens.ts +++ b/packages/server/src/constants/screens.ts @@ -1,6 +1,6 @@ import { roles } from "@budibase/backend-core" import { BASE_LAYOUT_PROP_IDS } from "./layouts" -import { Screen } from "@budibase/types" +import { Screen, Table, Query, ViewV2 } from "@budibase/types" export function createHomeScreen( config: { @@ -53,3 +53,177 @@ export function createHomeScreen( name: "home-screen", } } + +function heading(text: string) { + return { + _id: "c1bff24cd821e41d18c894ac77a80ef99", + _component: "@budibase/standard-components/heading", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _instanceName: "Table heading", + _children: [], + text, + } +} + +export function createTableScreen( + datasourceName: string, + table: Table +): Screen { + return { + props: { + _id: "cad0a0904cacd4678a2ac094e293db1a5", + _component: "@budibase/standard-components/container", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _children: [ + heading("table"), + { + _id: "ca6304be2079147bb9933092c4f8ce6fa", + _component: "@budibase/standard-components/gridblock", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _instanceName: "table - Table", + _children: [], + table: { + label: table.name, + tableId: table._id!, + type: "table", + datasourceName, + }, + }, + ], + _instanceName: "table - List", + layout: "grid", + direction: "column", + hAlign: "stretch", + vAlign: "top", + size: "grow", + gap: "M", + }, + routing: { + route: "/table", + roleId: "ADMIN", + homeScreen: false, + }, + name: "screen-id", + } +} + +export function createViewScreen(datasourceName: string, view: ViewV2): Screen { + return { + props: { + _id: "cc359092bbd6c4e10b57827155edb7872", + _component: "@budibase/standard-components/container", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _children: [ + heading("view"), + { + _id: "ccb4a9e3734794864b5c65b012a0bdc5a", + _component: "@budibase/standard-components/gridblock", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _instanceName: "view - Table", + _children: [], + table: { + ...view, + name: view.name, + tableId: view.tableId, + id: view.id, + label: view.name, + type: "viewV2", + }, + }, + ], + _instanceName: "view - List", + layout: "grid", + direction: "column", + hAlign: "stretch", + vAlign: "top", + size: "grow", + gap: "M", + }, + routing: { + route: "/view", + roleId: "ADMIN", + homeScreen: false, + }, + name: "view-id", + } +} + +export function createQueryScreen(datasourceId: string, query: Query): Screen { + return { + props: { + _id: "cc59b217aed264939a6c5249eee39cb25", + _component: "@budibase/standard-components/container", + _styles: { + normal: {}, + hover: {}, + active: {}, + selected: {}, + }, + _children: [ + { + _id: "c33a4a6e3cb5343158a08625c06b5cd7c", + _component: "@budibase/standard-components/gridblock", + _styles: { + normal: {}, + hover: {}, + active: {}, + }, + _instanceName: "New Table", + table: { + ...query, + label: query.name, + _id: query._id!, + name: query.name, + datasourceId: datasourceId, + type: "query", + }, + initialSortOrder: "Ascending", + allowAddRows: true, + allowEditRows: true, + allowDeleteRows: true, + stripeRows: false, + quiet: false, + columns: null, + }, + ], + _instanceName: "Blank screen", + layout: "grid", + direction: "column", + hAlign: "stretch", + vAlign: "top", + size: "grow", + gap: "M", + }, + routing: { + route: "/query", + roleId: "BASIC", + homeScreen: false, + }, + name: "screen-id", + } +} diff --git a/packages/server/src/tests/utilities/structures.ts b/packages/server/src/tests/utilities/structures.ts index 0c74a0faa2..79b1773afe 100644 --- a/packages/server/src/tests/utilities/structures.ts +++ b/packages/server/src/tests/utilities/structures.ts @@ -1,5 +1,10 @@ import { roles, utils } from "@budibase/backend-core" -import { createHomeScreen } from "../../constants/screens" +import { + createHomeScreen, + createTableScreen, + createQueryScreen, + createViewScreen, +} from "../../constants/screens" import { EMPTY_LAYOUT } from "../../constants/layouts" import { cloneDeep } from "lodash/fp" import { @@ -35,6 +40,7 @@ import { WebhookActionType, BuiltinPermissionID, DeepPartial, + ViewV2, } from "@budibase/types" import { LoopInput } from "../../definitions/automations" import { merge } from "lodash" @@ -599,6 +605,18 @@ export function basicScreen(route = "/") { }) } +export function tableScreen(datasourceName: string, table: Table) { + return createTableScreen(datasourceName, table) +} + +export function viewScreen(datasourceName: string, view: ViewV2) { + return createViewScreen(datasourceName, view) +} + +export function queryScreen(datasourceId: string, query: Query) { + return createQueryScreen(datasourceId, query) +} + export function powerScreen(route = "/") { return createHomeScreen({ roleId: BUILTIN_ROLE_IDS.POWER, From 5a737ff5c4299cc0792f9e69d8b7a3074e72f826 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 31 Jan 2025 18:39:48 +0000 Subject: [PATCH 08/76] Completing test cases for usage endpoint. --- packages/server/src/api/controllers/screen.ts | 3 +- .../src/api/routes/tests/screen.spec.ts | 86 ++++++++++++++++++- .../server/src/tests/utilities/api/screen.ts | 11 ++- .../shared-core/src/sdk/documents/screens.ts | 31 ++++--- packages/shared-core/src/utils.ts | 17 ---- 5 files changed, 109 insertions(+), 39 deletions(-) diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index 403059efde..93a70d5e36 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -143,7 +143,8 @@ export async function usage(ctx: UserCtx) { const allScreens = await sdk.screens.fetch() const response: ScreenUsage[] = [] for (let screen of allScreens) { - if (sharedSdk.screens.findInSettings(screen, sourceId)) { + const found = sharedSdk.screens.findInSettings(screen, sourceId) + if (found.length !== 0) { response.push({ url: screen.routing.route, _id: screen._id!, diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index 7d3049faca..610c07f36a 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -1,10 +1,24 @@ import { checkBuilderEndpoint } from "./utilities/TestFunctions" import * as setup from "./utilities" import { events, roles } from "@budibase/backend-core" -import { Screen, Role, BuiltinPermissionID } from "@budibase/types" +import { + Screen, + Role, + BuiltinPermissionID, + SourceType, + UsageScreenResponse, +} from "@budibase/types" -const { basicScreen, tableScreen, viewScreen, queryScreen, basicTable } = - setup.structures +const { + basicScreen, + tableScreen, + viewScreen, + queryScreen, + basicTable, + viewV2, + basicQuery, + basicDatasource, +} = setup.structures describe("/screens", () => { let config = setup.getConfig() @@ -189,9 +203,73 @@ describe("/screens", () => { }) describe("usage", () => { + beforeEach(async () => { + await config.init() + await config.api.screen.save(basicScreen(), { + status: 200, + }) + }) + + function confirmScreen(usage: UsageScreenResponse, screen: Screen) { + expect(usage.screens.length).toEqual(1) + expect(usage.screens[0].url).toEqual(screen.routing.route) + expect(usage.screens[0]._id).toEqual(screen._id!) + } + it("should find table usage", async () => { const table = await config.api.table.save(basicTable(), { status: 200 }) - const tableScreen = await config.api.screen.save(tableScreen()) + const screen = await config.api.screen.save( + tableScreen("BudibaseDB", table), + { status: 200 } + ) + const usage = await config.api.screen.usage(table._id!, { status: 200 }) + expect(usage.sourceType).toEqual(SourceType.TABLE) + confirmScreen(usage, screen) + }) + + it("should find view usage", async () => { + const table = await config.api.table.save(basicTable(), { status: 200 }) + const view = await config.api.viewV2.create( + viewV2.createRequest(table._id!), + { status: 201 } + ) + const screen = await config.api.screen.save( + viewScreen("BudibaseDB", view), + { + status: 200, + } + ) + const usage = await config.api.screen.usage(view.id, { status: 200 }) + expect(usage.sourceType).toEqual(SourceType.VIEW) + confirmScreen(usage, screen) + }) + + it("should find datasource/query usage", async () => { + const datasource = await config.api.datasource.create( + basicDatasource().datasource, + { + status: 200, + } + ) + const query = await config.api.query.save(basicQuery(datasource._id!), { + status: 200, + }) + const screen = await config.api.screen.save( + queryScreen(datasource._id!, query), + { + status: 200, + } + ) + const dsUsage = await config.api.screen.usage(datasource._id!, { + status: 200, + }) + expect(dsUsage.sourceType).toEqual(SourceType.DATASOURCE) + confirmScreen(dsUsage, screen) + const queryUsage = await config.api.screen.usage(query._id!, { + status: 200, + }) + expect(queryUsage.sourceType).toEqual(SourceType.QUERY) + confirmScreen(queryUsage, screen) }) }) }) diff --git a/packages/server/src/tests/utilities/api/screen.ts b/packages/server/src/tests/utilities/api/screen.ts index 8b7d7f92c1..7f7f73fb84 100644 --- a/packages/server/src/tests/utilities/api/screen.ts +++ b/packages/server/src/tests/utilities/api/screen.ts @@ -1,4 +1,4 @@ -import { Screen } from "@budibase/types" +import { Screen, UsageScreenResponse } from "@budibase/types" import { Expectations, TestAPI } from "./base" export class ScreenAPI extends TestAPI { @@ -28,4 +28,13 @@ export class ScreenAPI extends TestAPI { } ) } + + usage = async ( + sourceId: string, + expectations?: Expectations + ): Promise => { + return this._post(`/api/screens/usage/${sourceId}`, { + expectations, + }) + } } diff --git a/packages/shared-core/src/sdk/documents/screens.ts b/packages/shared-core/src/sdk/documents/screens.ts index 8fdd7087c8..8b6ea276b2 100644 --- a/packages/shared-core/src/sdk/documents/screens.ts +++ b/packages/shared-core/src/sdk/documents/screens.ts @@ -1,24 +1,23 @@ import { Screen } from "@budibase/types" -import { flattenObject } from "../../utils" export function findInSettings(screen: Screen, toFind: string) { - const flattened = flattenObject(screen.props) const foundIn: { setting: string; value: string }[] = [] - for (let key of Object.keys(flattened)) { - let found = false - if (typeof flattened[key] === "string") { - found = flattened[key].includes(toFind) - } else if (Array.isArray(flattened[key])) { - found = flattened[key].find( - (el: any) => typeof el === "string" && el.includes(toFind) - ) - } - if (found) { - foundIn.push({ - setting: key, - value: flattened[key], - }) + function recurse(props: Record, parentKey = "") { + for (let key of Object.keys(props)) { + if (!props[key]) { + continue + } + if (typeof props[key] === "string" && props[key].includes(toFind)) { + foundIn.push({ + setting: parentKey ? `${parentKey}.${key}` : key, + value: props[key], + }) + } else if (typeof props[key] === "object") { + recurse(props[key], key) + } } } + + recurse(screen.props) return foundIn } diff --git a/packages/shared-core/src/utils.ts b/packages/shared-core/src/utils.ts index afc1c8872b..fac8fa61ee 100644 --- a/packages/shared-core/src/utils.ts +++ b/packages/shared-core/src/utils.ts @@ -173,20 +173,3 @@ export function processSearchFilters( ], } } - -export function flattenObject( - obj: Record, - parentKey: string = "", - state: Record = {} -) { - for (const key of Object.keys(obj)) { - const newKey = parentKey.length ? `${parentKey}.${key}` : key - const value = obj[key] - if (value && typeof value === "object" && !Array.isArray(value)) { - flattenObject(value, newKey, state) - } else { - state[newKey] = value - } - } - return state -} From b214019dbe53049cffdf3c9d08b3410160f8c90e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 3 Feb 2025 14:14:08 +0000 Subject: [PATCH 09/76] Frontend usage of API. --- packages/frontend-core/src/api/screens.ts | 8 ++++++++ packages/server/src/api/controllers/screen.ts | 4 ++-- packages/server/src/api/routes/tests/screen.spec.ts | 4 ++-- packages/server/src/tests/utilities/api/screen.ts | 13 ++++++++----- packages/types/src/api/web/app/screen.ts | 2 +- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/frontend-core/src/api/screens.ts b/packages/frontend-core/src/api/screens.ts index bdb01e1427..8147db738d 100644 --- a/packages/frontend-core/src/api/screens.ts +++ b/packages/frontend-core/src/api/screens.ts @@ -2,12 +2,14 @@ import { DeleteScreenResponse, SaveScreenRequest, SaveScreenResponse, + UsageOfScreensResponse, } from "@budibase/types" import { BaseAPIClient } from "./types" export interface ScreenEndpoints { saveScreen: (screen: SaveScreenRequest) => Promise deleteScreen: (id: string, rev: string) => Promise + usageOfScreens: (sourceId: string) => Promise } export const buildScreenEndpoints = (API: BaseAPIClient): ScreenEndpoints => ({ @@ -32,4 +34,10 @@ export const buildScreenEndpoints = (API: BaseAPIClient): ScreenEndpoints => ({ url: `/api/screens/${id}/${rev}`, }) }, + + usageOfScreens: async sourceId => { + return await API.post({ + url: `/api/screens/usage/${sourceId}`, + }) + }, }) diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index 93a70d5e36..1bf800691c 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -16,7 +16,7 @@ import { SaveScreenRequest, SaveScreenResponse, DeleteScreenResponse, - UsageScreenResponse, + UsageOfScreensResponse, ScreenUsage, } from "@budibase/types" import { builderSocket } from "../../websockets" @@ -137,7 +137,7 @@ function findPlugins(component: ScreenProps, foundPlugins: string[]) { component._children.forEach(child => findPlugins(child, foundPlugins)) } -export async function usage(ctx: UserCtx) { +export async function usage(ctx: UserCtx) { const sourceId = ctx.params.sourceId const sourceType = sdk.common.getSourceType(sourceId) const allScreens = await sdk.screens.fetch() diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index 610c07f36a..90ec4a567f 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -6,7 +6,7 @@ import { Role, BuiltinPermissionID, SourceType, - UsageScreenResponse, + UsageOfScreensResponse, } from "@budibase/types" const { @@ -210,7 +210,7 @@ describe("/screens", () => { }) }) - function confirmScreen(usage: UsageScreenResponse, screen: Screen) { + function confirmScreen(usage: UsageOfScreensResponse, screen: Screen) { expect(usage.screens.length).toEqual(1) expect(usage.screens[0].url).toEqual(screen.routing.route) expect(usage.screens[0]._id).toEqual(screen._id!) diff --git a/packages/server/src/tests/utilities/api/screen.ts b/packages/server/src/tests/utilities/api/screen.ts index 7f7f73fb84..bbbe704a29 100644 --- a/packages/server/src/tests/utilities/api/screen.ts +++ b/packages/server/src/tests/utilities/api/screen.ts @@ -1,4 +1,4 @@ -import { Screen, UsageScreenResponse } from "@budibase/types" +import { Screen, UsageOfScreensResponse } from "@budibase/types" import { Expectations, TestAPI } from "./base" export class ScreenAPI extends TestAPI { @@ -32,9 +32,12 @@ export class ScreenAPI extends TestAPI { usage = async ( sourceId: string, expectations?: Expectations - ): Promise => { - return this._post(`/api/screens/usage/${sourceId}`, { - expectations, - }) + ): Promise => { + return this._post( + `/api/screens/usage/${sourceId}`, + { + expectations, + } + ) } } diff --git a/packages/types/src/api/web/app/screen.ts b/packages/types/src/api/web/app/screen.ts index 280c623216..0550c5206a 100644 --- a/packages/types/src/api/web/app/screen.ts +++ b/packages/types/src/api/web/app/screen.ts @@ -21,7 +21,7 @@ export interface ScreenUsage { _id: string } -export interface UsageScreenResponse { +export interface UsageOfScreensResponse { sourceType: SourceType screens: ScreenUsage[] } From a1409f43faea7046c74e5ab5a6f5d5aa7141b4a6 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 3 Feb 2025 14:34:54 +0000 Subject: [PATCH 10/76] implementing usage API in the modal. --- .../modals/DeleteDataConfirmationModal.svelte | 21 ++++++++++++++----- .../builder/src/stores/builder/screens.ts | 7 +++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index d9e55a4cf2..62d55d2283 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -1,10 +1,10 @@ - - -

    -

    - Are you sure you wish to delete the table - - - - {table.name} - ? - -

    - -

    All table data will be deleted{viewsMessage}.

    -

    This action cannot be undone.

    - - {#if screensPossiblyAffected.length > 0} -
    - -
      - {#each screensPossiblyAffected as item} -
    • - {item.text} -
    • - {/each} -
    -
    -
    - {/if} -

    Please enter the table name below to confirm.

    - -
    - - - diff --git a/packages/builder/src/components/backend/TableNavigator/TableNavItem/TableNavItem.svelte b/packages/builder/src/components/backend/TableNavigator/TableNavItem/TableNavItem.svelte index f3deccb3c9..fe9d02af40 100644 --- a/packages/builder/src/components/backend/TableNavigator/TableNavItem/TableNavItem.svelte +++ b/packages/builder/src/components/backend/TableNavigator/TableNavItem/TableNavItem.svelte @@ -8,7 +8,7 @@ import NavItem from "@/components/common/NavItem.svelte" import { isActive } from "@roxi/routify" import EditModal from "./EditModal.svelte" - import DeleteConfirmationModal from "./DeleteConfirmationModal.svelte" + import DeleteConfirmationModal from "../../modals/DeleteDataConfirmationModal.svelte" import { Icon } from "@budibase/bbui" import { DB_TYPE_EXTERNAL } from "@/constants/backend" @@ -65,4 +65,4 @@ {/if} - + diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 62d55d2283..033358b7b3 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -1,16 +1,24 @@

    - Are you sure you wish to delete the {type} + Are you sure you wish to delete the {sourceType} @@ -83,13 +141,15 @@

    -

    All {type} data will be deleted{viewsMessage}.

    +

    + All {sourceType} data will be deleted{viewsMessage}. +

    This action cannot be undone.

    {#if affectedScreens.length > 0}
      {#each affectedScreens as item} diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/DeleteViewModal.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/DeleteViewModal.svelte deleted file mode 100644 index 5a23c976f8..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/DeleteViewModal.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/ViewNavBar.svelte b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/ViewNavBar.svelte index e9c5745cc6..f32767451a 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/ViewNavBar.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/table/[tableId]/_components/ViewNavBar.svelte @@ -10,9 +10,8 @@ import { Icon, ActionButton, ActionMenu, MenuItem } from "@budibase/bbui" import { params, url } from "@roxi/routify" import EditViewModal from "./EditViewModal.svelte" - import DeleteViewModal from "./DeleteViewModal.svelte" import EditTableModal from "@/components/backend/TableNavigator/TableNavItem/EditModal.svelte" - import DeleteTableModal from "@/components/backend/TableNavigator/TableNavItem/DeleteConfirmationModal.svelte" + import DeleteConfirmationModal from "@/components/backend/modals/DeleteDataConfirmationModal.svelte" import { UserAvatars } from "@budibase/frontend-core" import { DB_TYPE_EXTERNAL } from "@/constants/backend" import { TableNames } from "@/constants" @@ -314,12 +313,12 @@ {#if table && tableEditable} - + {/if} {#if editableView} - + {/if} diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 033358b7b3..ace6dd696f 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -3,6 +3,7 @@ import { appStore, datasources, + queries, screenStore, tables, views, @@ -106,6 +107,20 @@ } } + async function deleteQuery(query: Query) { + try { + // Go back to the datasource if we are deleting the active query + if ($queries.selectedQueryId === query._id) { + $goto(`./datasource/${query.datasourceId}`) + } + await queries.delete(query) + await datasources.fetch() + notifications.success("Query deleted") + } catch (error) { + notifications.error("Error deleting query") + } + } + async function deleteSource() { if (!source || !sourceType) { throw new Error("Unable to delete - no data source found.") @@ -116,8 +131,9 @@ return await deleteTable(source as Table) case SourceType.VIEW: return await deleteView(source as ViewV2) - case SourceType.DATASOURCE: case SourceType.QUERY: + return await deleteQuery(source as Query) + case SourceType.DATASOURCE: } } @@ -164,7 +180,9 @@
    {/if}

    - Please enter the "{source?.name}" below to confirm. + Please enter the "{source?.name}" below to confirm.

    From 9b6c8c74f3698728446a2c5935510c67861ba02c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Feb 2025 10:32:56 +0100 Subject: [PATCH 13/76] Add error button --- .../design/[screenId]/_components/AppPanel.svelte | 11 ++++++++++- packages/builder/src/stores/builder/index.js | 2 ++ .../builder/src/stores/builder/screenComponent.ts | 14 ++++++++++++++ packages/types/src/ui/components/errors.ts | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte index b04cd8b956..98a3f129a2 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte @@ -1,8 +1,13 @@
    @@ -15,6 +20,10 @@ {#if $appStore.clientFeatures.devicePreview} {/if} + + {}} + >Errors ({$screenComponentErrorList.length})
diff --git a/packages/builder/src/stores/builder/index.js b/packages/builder/src/stores/builder/index.js index c6dc631e5c..5856a394e0 100644 --- a/packages/builder/src/stores/builder/index.js +++ b/packages/builder/src/stores/builder/index.js @@ -20,6 +20,7 @@ import { screenComponents, screenComponentErrors, findComponentsBySettingsType, + screenComponentErrorList, } from "./screenComponent" // Backend @@ -75,6 +76,7 @@ export { screenComponents, screenComponentErrors, findComponentsBySettingsType, + screenComponentErrorList, } export const reset = () => { diff --git a/packages/builder/src/stores/builder/screenComponent.ts b/packages/builder/src/stores/builder/screenComponent.ts index 62bc97cc27..0ee64501f0 100644 --- a/packages/builder/src/stores/builder/screenComponent.ts +++ b/packages/builder/src/stores/builder/screenComponent.ts @@ -115,6 +115,7 @@ function getInvalidDatasources( const friendlyTypeName = friendlyNameByType[type] ?? type result[component._id!] = [ { + componentId: component._id!, key: setting.key, message: `The ${friendlyTypeName} named "${label}" could not be found`, errorType: "setting", @@ -174,6 +175,7 @@ function getMissingRequiredSettings( if (missingRequiredSettings?.length) { result[component._id!] = missingRequiredSettings.map((s: any) => ({ + componentId: component._id!, key: s.key, message: `Add the ${s.label} setting to start using your component`, errorType: "setting", @@ -214,6 +216,7 @@ function getMissingAncestors( result[component._id!] = missingAncestors.map(ancestor => { const ancestorDefinition = definitions[`${BudibasePrefix}${ancestor}`] return { + componentId: component._id!, message: `${pluralise(definition.name)} need to be inside a ${ancestorDefinition.name}`, errorType: "ancestor-setting", @@ -270,6 +273,17 @@ export function findComponentsBySettingsType( return result } +export const screenComponentErrorList = derived( + [screenComponentErrors], + ([$screenComponentErrors]): UIComponentError[] => { + if (!featureFlag.isEnabled("CHECK_COMPONENT_SETTINGS_ERRORS")) { + return [] + } + + return Object.values($screenComponentErrors).flatMap(errors => errors) + } +) + export const screenComponents = derived( [selectedScreen], ([$selectedScreen]) => { diff --git a/packages/types/src/ui/components/errors.ts b/packages/types/src/ui/components/errors.ts index 9725ed8a33..58c36c7248 100644 --- a/packages/types/src/ui/components/errors.ts +++ b/packages/types/src/ui/components/errors.ts @@ -1,4 +1,5 @@ interface BaseUIComponentError { + componentId: string message: string } From 6d984243230e02a10bd15fbeb710fd8847345b63 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Feb 2025 10:47:50 +0100 Subject: [PATCH 14/76] Show popover --- .../design/[screenId]/_components/AppPanel.svelte | 12 +++--------- .../_components/ScreenErrorsButton.svelte | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte index 98a3f129a2..120d9eeeeb 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte @@ -1,13 +1,9 @@
@@ -21,9 +17,7 @@ {/if} - {}} - >Errors ({$screenComponentErrorList.length}) +
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte new file mode 100644 index 0000000000..8fd23d47c8 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -0,0 +1,14 @@ + + +
+ popover.show()} + >Errors ({$screenComponentErrorList.length}) +
+TODO From 4d732dd142563d1d35366c2f7ae3f5d1eecc83f5 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Feb 2025 11:05:14 +0100 Subject: [PATCH 15/76] Display errors --- .../_components/ScreenErrorsButton.svelte | 41 +++++++++++++++++-- .../builder/src/stores/builder/components.ts | 2 +- .../src/stores/builder/screenComponent.ts | 12 ++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index 8fd23d47c8..3766c2794c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -1,6 +1,10 @@
- popover.show()} - >Errors ({$screenComponentErrorList.length}) + popover.show()}> +
+ Errors + {#if $screenComponentErrorList.length} +
+ {$screenComponentErrorList.length} +
+ {/if} +
+
- +
{#each $screenComponentErrorList as error}
@@ -24,8 +27,11 @@ color="var(--spectrum-global-color-static-red-600)" />
- {$screenComponents[error.componentId]._instanceName}: - {error.message} + + {$screenComponents[error.componentId]._instanceName}: + + + {@html error.message}
{/each} @@ -33,6 +39,21 @@ From 7b0a8165ea325ef4a0ae4adb02ab854fe3d13560 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Feb 2025 12:36:46 +0100 Subject: [PATCH 17/76] Styling --- .../_components/ScreenErrorsButton.svelte | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index 8bd8220a1a..95dd3cf85f 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -6,12 +6,12 @@ let popover: any -
+
popover.show()}> -
+
Errors {#if $screenComponentErrorList.length} -
+
{$screenComponentErrorList.length}
{/if} @@ -19,7 +19,7 @@
-
+
{#each $screenComponentErrorList as error}
diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index 0f2ed24177..f5eeba2e81 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -11,6 +11,8 @@ Body, Divider, Button, + ActionButton, + Popover, } from "@budibase/bbui" import { capitalise } from "@/helpers" import AccessLevelSelect from "./AccessLevelSelect.svelte" @@ -23,6 +25,7 @@ import ExtraQueryConfig from "./ExtraQueryConfig.svelte" import QueryViewerSavePromptModal from "./QueryViewerSavePromptModal.svelte" import { Utils } from "@budibase/frontend-core" + import ConnectedQueryScreens from "./ConnectedQueryScreens.svelte" export let query let queryHash @@ -44,6 +47,9 @@ let rows = [] let keys = {} + let popover + let anchor + const parseQuery = query => { modified = false @@ -170,6 +176,13 @@
+ + popover.show()}>Screens +
+ + + + From a31eeef87b00c160ff28245eeac16cad6538a33a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Feb 2025 16:25:43 +0100 Subject: [PATCH 39/76] Fix scrolling --- .../components/design/settings/controls/PropertyControl.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte index c8a1f94402..8ba32c47cf 100644 --- a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte +++ b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte @@ -82,7 +82,7 @@ }) } - $: isHighlighted && scrollToElement(domElement) + $: highlightedProp && isHighlighted && scrollToElement(domElement)
Date: Tue, 4 Feb 2025 16:34:54 +0100 Subject: [PATCH 40/76] Fix gaps --- .../design/[screenId]/_components/ScreenErrorsButton.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index cf89a21415..f97d0ec062 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -108,7 +108,7 @@ .error-popover .error { display: inline-flex; flex-direction: row; - padding: var(--spacing-xl) var(--spacing-m); + padding: var(--spacing-m); gap: var(--spacing-s); align-items: start; } From 1051faef1d79e4e1b92a42443914fe6e433bfc46 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 4 Feb 2025 15:44:43 +0000 Subject: [PATCH 41/76] pull in query usage --- packages/bbui/src/List/ListItem.svelte | 18 +-- .../components/common/DetailPopover.svelte | 17 +-- .../integration/ConnectedQueryScreens.svelte | 131 +++++++----------- .../components/integration/QueryViewer.svelte | 17 +-- .../integration/RestQueryViewer.svelte | 25 ++-- packages/types/src/ui/components/index.ts | 1 + packages/types/src/ui/components/popover.ts | 6 + 7 files changed, 87 insertions(+), 128 deletions(-) create mode 100644 packages/types/src/ui/components/popover.ts diff --git a/packages/bbui/src/List/ListItem.svelte b/packages/bbui/src/List/ListItem.svelte index e979b2b684..87deb2eb86 100644 --- a/packages/bbui/src/List/ListItem.svelte +++ b/packages/bbui/src/List/ListItem.svelte @@ -1,15 +1,15 @@ - + -
-
-

Screens

- -
-

The following screens are connected to this data.

-
- {#each screens as screen} - - {/each} -
-
+ + + + Screens + + + + {#if !screens.length} +
+

No screens are using this data.

+
+ {:else} +

The following screens are connected to this data.

+ + + {#each screens as screen} + + {/each} + + {/if} +
diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index f5eeba2e81..7a1410e53e 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -11,8 +11,6 @@ Body, Divider, Button, - ActionButton, - Popover, } from "@budibase/bbui" import { capitalise } from "@/helpers" import AccessLevelSelect from "./AccessLevelSelect.svelte" @@ -47,9 +45,6 @@ let rows = [] let keys = {} - let popover - let anchor - const parseQuery = query => { modified = false @@ -176,13 +171,7 @@
- - popover.show()}>Screens - +
- - - - diff --git a/packages/builder/src/components/integration/ConnectedQueryScreens.svelte b/packages/builder/src/components/integration/ConnectedQueryScreens.svelte index e97017df96..2a24088dc4 100644 --- a/packages/builder/src/components/integration/ConnectedQueryScreens.svelte +++ b/packages/builder/src/components/integration/ConnectedQueryScreens.svelte @@ -1,10 +1,9 @@ - - - - Screens - - - - {#if !screens.length} -
-

No screens are using this data.

-
- {:else} -

The following screens are connected to this data.

- - - {#each screens as screen} - - {/each} - - {/if} -
- - + From 47a014789f01b3d3aad00195c70b7fcd1e6cf345 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 5 Feb 2025 10:23:07 +0100 Subject: [PATCH 47/76] Change the errors button to an icon --- packages/bbui/src/Divider/Divider.svelte | 4 +- .../[screenId]/_components/AppPanel.svelte | 5 ++- .../_components/ScreenErrorsButton.svelte | 37 +------------------ 3 files changed, 6 insertions(+), 40 deletions(-) diff --git a/packages/bbui/src/Divider/Divider.svelte b/packages/bbui/src/Divider/Divider.svelte index f6837ca97c..5373b1fa16 100644 --- a/packages/bbui/src/Divider/Divider.svelte +++ b/packages/bbui/src/Divider/Divider.svelte @@ -1,7 +1,7 @@ -
@@ -16,7 +17,7 @@ {#if $appStore.clientFeatures.devicePreview} {/if} - +
@@ -65,7 +66,7 @@ flex-direction: row; justify-content: flex-start; align-items: center; - gap: var(--spacing-xl); + gap: var(--spacing-l); } .content { flex: 1 1 auto; diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index f97d0ec062..85f6aaf13d 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -37,16 +37,7 @@
- popover.show()} size="M"> -
- Errors - {#if $screenComponentErrorList.length} -
- {$screenComponentErrorList.length} -
- {/if} -
-
+ popover.show()} size="M" icon="Alert" />
From 2ade11174d902da2e52bcebe125cc301ecc185bf Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 5 Feb 2025 11:54:08 +0100 Subject: [PATCH 50/76] Add indicator --- .../common/Icons/CircleIndicator.svelte | 27 +++++++++++++++++-- .../_components/ScreenErrorsButton.svelte | 17 ++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/common/Icons/CircleIndicator.svelte b/packages/builder/src/components/common/Icons/CircleIndicator.svelte index 35938fb7e9..d322425db7 100644 --- a/packages/builder/src/components/common/Icons/CircleIndicator.svelte +++ b/packages/builder/src/components/common/Icons/CircleIndicator.svelte @@ -1,3 +1,26 @@ - - + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index 9bf3ffb016..3471953dbe 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -13,6 +13,7 @@ Popover, PopoverAlignment, } from "@budibase/bbui" + import CircleIndicator from "@/components/common/Icons/CircleIndicator.svelte" let button: any let popover: any @@ -46,6 +47,14 @@ size="M" icon="Alert" /> + {#if hasErrors} +
+ +
+ {/if}
From 877f30b7a0abf6c398e820057e979f7d1042060c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 5 Feb 2025 16:29:21 +0000 Subject: [PATCH 53/76] No input required for deletion. --- .../modals/DeleteDataConfirmationModal.svelte | 82 ++++++++----------- .../components/common/ConfirmDialog.svelte | 2 +- 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 2e7c8d5078..db13558713 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -1,5 +1,5 @@ - -
-

- - {@html buildMessage()} -

+{#if sourceType} + +
+

+ + {@html buildMessage()} +

- {#if affectedScreens.length > 0} -
- -
    - {#each affectedScreens as item} -
  • - {item.text} -
  • - {/each} -
-
-
- {/if} -
-
+ {#if affectedScreens.length > 0} +
+ +
    + {#each affectedScreens as item} +
  • + {item.text} +
  • + {/each} +
+
+
+ {/if} +
+
+{/if} From 880f27e0ff6193c913015e0dd8dde1f65b312933 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 5 Feb 2025 17:39:31 +0000 Subject: [PATCH 55/76] Changing how messaging is generated. --- .../modals/DeleteDataConfirmationModal.svelte | 74 +++++++++---------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 0649e40c09..4d2a60d2f5 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -25,22 +25,7 @@ $: isInternalTable = isInternal && sourceType === SourceType.TABLE - const getViewsMessage = () => { - if (!source || !("views" in source)) { - return "" - } - const views = Object.values(source?.views ?? []) - if (views.length < 1) { - return "" - } - if (views.length === 1) { - return "1 view" - } - - return `${views.length} views` - } - - const getQueriesMessage = () => { + const getDatasourceQueries = () => { if (sourceType !== SourceType.DATASOURCE) { return "" } @@ -48,14 +33,7 @@ const queryList = get(queries).list.filter( query => query.datasourceId === sourceId ) - if (queryList.length < 1) { - return "" - } - if (queryList.length === 1) { - return "1 query" - } - - return `${queryList.length} queries` + return queryList } function getSourceID(): string { @@ -168,21 +146,35 @@ } } - function buildMessage() { - let message = "" - if (isInternalTable) { - message = `All ${sourceType} data will also be deleted` - const viewsMessage = getViewsMessage() - if (viewsMessage) { - message += `, including ${viewsMessage}. ` - } else { - message += ". " + function buildMessage(sourceType: string) { + if (!source) { + return "" + } + let message = `Removing ${source?.name} ` + let initialLength = message.length + if (sourceType === SourceType.TABLE) { + const views = "views" in source ? Object.values(source?.views ?? []) : [] + if (isInternalTable) { + message += `will delete its data${ + views.length ? `, views (${views.length})` : "" + }` + } else if (views.length) { + message += `will delete its views (${views.length})` } } else if (sourceType === SourceType.DATASOURCE) { - const queriesMessage = getQueriesMessage() - message = `This will include deleting ${queriesMessage}. ` + const queryList = getDatasourceQueries() + if (queryList.length) { + message += `will delete its queries (${queryList.length})` + } + } + if (affectedScreens.length) { + message += + initialLength !== message.length + ? ", and break connected screens:" + : "will break connected screens:" + } else { + message += "." } - message += "This action cannot be undone." return message } @@ -192,12 +184,12 @@ okText="Delete" onOk={deleteSource} onCancel={hideDeleteDialog} - title={`Are you sure you want to delete ${source?.name}?`} + title={`Are you sure you want to delete this ${sourceType}?`} >
- {#if affectedScreens.length > 0} + {#if affectedScreens.length > 0 && sourceType}

- Removing this {sourceType} will break the following screens: + {buildMessage(sourceType)} {#each affectedScreens as item, idx} {/if}

- - {@html buildMessage()} + This action cannot be undone.

@@ -228,6 +219,7 @@ .screens { display: flex; flex-direction: row; + padding-bottom: var(--spacing-l); gap: var(--spacing-xs); } From fdf82a62760fa79e2f74edf3a1f7e50f37319595 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 15:30:30 +0000 Subject: [PATCH 56/76] Some updates, deleting external tables does delete data so warn about this. --- .../modals/DeleteDataConfirmationModal.svelte | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 4d2a60d2f5..0ef177db64 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -150,24 +150,23 @@ if (!source) { return "" } + const screenCount = affectedScreens.length let message = `Removing ${source?.name} ` let initialLength = message.length if (sourceType === SourceType.TABLE) { const views = "views" in source ? Object.values(source?.views ?? []) : [] - if (isInternalTable) { - message += `will delete its data${ - views.length ? `, views (${views.length})` : "" - }` - } else if (views.length) { - message += `will delete its views (${views.length})` - } + message += `will delete its data${ + views.length + ? `${screenCount ? "," : " and"} views (${views.length})` + : "" + }` } else if (sourceType === SourceType.DATASOURCE) { const queryList = getDatasourceQueries() if (queryList.length) { message += `will delete its queries (${queryList.length})` } } - if (affectedScreens.length) { + if (screenCount) { message += initialLength !== message.length ? ", and break connected screens:" @@ -187,16 +186,20 @@ title={`Are you sure you want to delete this ${sourceType}?`} >
- {#if affectedScreens.length > 0 && sourceType} + {#if sourceType}

{buildMessage(sourceType)} - - {#each affectedScreens as item, idx} - {item.text}{idx !== affectedScreens.length - 1 ? "," : ""} - {/each} - + {#if affectedScreens.length > 0} + + {#each affectedScreens as item, idx} + {item.text}{idx !== affectedScreens.length - 1 + ? "," + : ""} + {/each} + + {/if}

{/if}

From 399cf0ef6c9189553bb31ca508ad5da910682892 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 16:48:17 +0000 Subject: [PATCH 57/76] Removing unused elements. --- .../backend/modals/DeleteDataConfirmationModal.svelte | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 0ef177db64..39832cd491 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -1,5 +1,5 @@ From e8c79bc72008d757e8cbef488c66c96f9384c27f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 17:24:04 +0000 Subject: [PATCH 58/76] Most PR comments. --- .../modals/DeleteDataConfirmationModal.svelte | 7 +- .../src/api/routes/tests/screen.spec.ts | 99 +++++++------------ packages/server/src/constants/screens.ts | 4 +- packages/server/src/sdk/app/common/utils.ts | 2 +- .../shared-core/src/sdk/documents/screens.ts | 12 +-- 5 files changed, 46 insertions(+), 78 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index 39832cd491..f55e0e7013 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -10,6 +10,7 @@ viewsV2, } from "@/stores/builder" import ConfirmDialog from "@/components/common/ConfirmDialog.svelte" + import { helpers } from "@budibase/shared-core" import { SourceType } from "@budibase/types" import { goto, params } from "@roxi/routify" import { DB_TYPE_EXTERNAL } from "@/constants/backend" @@ -85,7 +86,7 @@ async function deleteView(view: ViewV2 | View) { try { - if ("version" in view && view.version === 2) { + if ("version" in view && helpers.views.isCalculationView(view)) { await viewsV2.delete(view as ViewV2) } else { await views.delete(view as View) @@ -99,10 +100,10 @@ async function deleteDatasource(datasource: Datasource) { try { - const isSelected = - get(datasources).selectedDatasourceId === datasource._id await datasources.delete(datasource) notifications.success("Datasource deleted") + const isSelected = + get(datasources).selectedDatasourceId === datasource._id if (isSelected) { $goto("./datasource") } diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index 90ec4a567f..b6d6ceda3b 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -33,7 +33,7 @@ describe("/screens", () => { describe("fetch", () => { it("should be able to create a layout", async () => { - const screens = await config.api.screen.list({ status: 200 }) + const screens = await config.api.screen.list() expect(screens.length).toEqual(1) expect(screens.some(s => s._id === screen._id)).toEqual(true) }) @@ -67,28 +67,22 @@ describe("/screens", () => { inherits: [role1._id!, role2._id!], permissionId: BuiltinPermissionID.WRITE, }) - screen1 = await config.api.screen.save( - { - ...basicScreen(), - routing: { - roleId: role1._id!, - route: "/foo", - homeScreen: false, - }, + screen1 = await config.api.screen.save({ + ...basicScreen(), + routing: { + roleId: role1._id!, + route: "/foo", + homeScreen: false, }, - { status: 200 } - ) - screen2 = await config.api.screen.save( - { - ...basicScreen(), - routing: { - roleId: role2._id!, - route: "/bar", - homeScreen: false, - }, + }) + screen2 = await config.api.screen.save({ + ...basicScreen(), + routing: { + roleId: role2._id!, + route: "/bar", + homeScreen: false, }, - { status: 200 } - ) + }) // get into prod app await config.publish() }) @@ -96,10 +90,7 @@ describe("/screens", () => { async function checkScreens(roleId: string, screenIds: string[]) { await config.loginAsRole(roleId, async () => { const res = await config.api.application.getDefinition( - config.prodAppId!, - { - status: 200, - } + config.prodAppId! ) expect(res.screens.length).toEqual(screenIds.length) expect(res.screens.map(s => s._id).sort()).toEqual(screenIds.sort()) @@ -129,10 +120,7 @@ describe("/screens", () => { }, async () => { const res = await config.api.application.getDefinition( - config.prodAppId!, - { - status: 200, - } + config.prodAppId! ) const screenIds = [screen._id!, screen1._id!] expect(res.screens.length).toEqual(screenIds.length) @@ -149,9 +137,7 @@ describe("/screens", () => { it("should be able to create a screen", async () => { const screen = basicScreen() - const responseScreen = await config.api.screen.save(screen, { - status: 200, - }) + const responseScreen = await config.api.screen.save(screen) expect(responseScreen._rev).toBeDefined() expect(responseScreen.name).toEqual(screen.name) @@ -160,13 +146,13 @@ describe("/screens", () => { it("should be able to update a screen", async () => { const screen = basicScreen() - let responseScreen = await config.api.screen.save(screen, { status: 200 }) + let responseScreen = await config.api.screen.save(screen) screen._id = responseScreen._id screen._rev = responseScreen._rev screen.name = "edit" jest.clearAllMocks() - responseScreen = await config.api.screen.save(screen, { status: 200 }) + responseScreen = await config.api.screen.save(screen) expect(responseScreen._rev).toBeDefined() expect(responseScreen.name).toEqual(screen.name) @@ -186,8 +172,7 @@ describe("/screens", () => { it("should be able to delete the screen", async () => { const response = await config.api.screen.destroy( screen._id!, - screen._rev!, - { status: 200 } + screen._rev! ) expect(response.message).toBeDefined() expect(events.screen.deleted).toHaveBeenCalledTimes(1) @@ -205,9 +190,7 @@ describe("/screens", () => { describe("usage", () => { beforeEach(async () => { await config.init() - await config.api.screen.save(basicScreen(), { - status: 200, - }) + await config.api.screen.save(basicScreen()) }) function confirmScreen(usage: UsageOfScreensResponse, screen: Screen) { @@ -217,57 +200,41 @@ describe("/screens", () => { } it("should find table usage", async () => { - const table = await config.api.table.save(basicTable(), { status: 200 }) + const table = await config.api.table.save(basicTable()) const screen = await config.api.screen.save( - tableScreen("BudibaseDB", table), - { status: 200 } + tableScreen("BudibaseDB", table) ) - const usage = await config.api.screen.usage(table._id!, { status: 200 }) + const usage = await config.api.screen.usage(table._id!) expect(usage.sourceType).toEqual(SourceType.TABLE) confirmScreen(usage, screen) }) it("should find view usage", async () => { - const table = await config.api.table.save(basicTable(), { status: 200 }) + const table = await config.api.table.save(basicTable()) const view = await config.api.viewV2.create( viewV2.createRequest(table._id!), { status: 201 } ) const screen = await config.api.screen.save( - viewScreen("BudibaseDB", view), - { - status: 200, - } + viewScreen("BudibaseDB", view) ) - const usage = await config.api.screen.usage(view.id, { status: 200 }) + const usage = await config.api.screen.usage(view.id) expect(usage.sourceType).toEqual(SourceType.VIEW) confirmScreen(usage, screen) }) it("should find datasource/query usage", async () => { const datasource = await config.api.datasource.create( - basicDatasource().datasource, - { - status: 200, - } + basicDatasource().datasource ) - const query = await config.api.query.save(basicQuery(datasource._id!), { - status: 200, - }) + const query = await config.api.query.save(basicQuery(datasource._id!)) const screen = await config.api.screen.save( - queryScreen(datasource._id!, query), - { - status: 200, - } + queryScreen(datasource._id!, query) ) - const dsUsage = await config.api.screen.usage(datasource._id!, { - status: 200, - }) + const dsUsage = await config.api.screen.usage(datasource._id!) expect(dsUsage.sourceType).toEqual(SourceType.DATASOURCE) confirmScreen(dsUsage, screen) - const queryUsage = await config.api.screen.usage(query._id!, { - status: 200, - }) + const queryUsage = await config.api.screen.usage(query._id!) expect(queryUsage.sourceType).toEqual(SourceType.QUERY) confirmScreen(queryUsage, screen) }) diff --git a/packages/server/src/constants/screens.ts b/packages/server/src/constants/screens.ts index 52f0b3d9ff..1cbc049e42 100644 --- a/packages/server/src/constants/screens.ts +++ b/packages/server/src/constants/screens.ts @@ -1,6 +1,6 @@ import { roles } from "@budibase/backend-core" import { BASE_LAYOUT_PROP_IDS } from "./layouts" -import { Screen, Table, Query, ViewV2 } from "@budibase/types" +import { Screen, Table, Query, ViewV2, Component } from "@budibase/types" export function createHomeScreen( config: { @@ -54,7 +54,7 @@ export function createHomeScreen( } } -function heading(text: string) { +function heading(text: string): Component { return { _id: "c1bff24cd821e41d18c894ac77a80ef99", _component: "@budibase/standard-components/heading", diff --git a/packages/server/src/sdk/app/common/utils.ts b/packages/server/src/sdk/app/common/utils.ts index ed4e4c9a4f..6dac729872 100644 --- a/packages/server/src/sdk/app/common/utils.ts +++ b/packages/server/src/sdk/app/common/utils.ts @@ -11,5 +11,5 @@ export function getSourceType(sourceId: string): SourceType { } else if (docIds.isQueryId(sourceId)) { return SourceType.QUERY } - throw new Error("Unknown source type - cannot find document type") + throw new Error(`Unknown source type for source "${sourceId}"`) } diff --git a/packages/shared-core/src/sdk/documents/screens.ts b/packages/shared-core/src/sdk/documents/screens.ts index 8b6ea276b2..3ceffd26a6 100644 --- a/packages/shared-core/src/sdk/documents/screens.ts +++ b/packages/shared-core/src/sdk/documents/screens.ts @@ -3,17 +3,17 @@ import { Screen } from "@budibase/types" export function findInSettings(screen: Screen, toFind: string) { const foundIn: { setting: string; value: string }[] = [] function recurse(props: Record, parentKey = "") { - for (let key of Object.keys(props)) { - if (!props[key]) { + for (const [key, value] of Object.entries(props)) { + if (!value) { continue } - if (typeof props[key] === "string" && props[key].includes(toFind)) { + if (typeof value === "string" && value.includes(toFind)) { foundIn.push({ setting: parentKey ? `${parentKey}.${key}` : key, - value: props[key], + value: value, }) - } else if (typeof props[key] === "object") { - recurse(props[key], key) + } else if (typeof value === "object") { + recurse(value, key) } } } From 83fdbccd6b1f4aaa8f84495e165ad56ab0015004 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 17:34:44 +0000 Subject: [PATCH 59/76] export directly. --- .../src/api/routes/tests/screen.spec.ts | 12 +++++----- .../server/src/tests/utilities/structures.ts | 24 +++++-------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index b6d6ceda3b..261c287087 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -11,9 +11,9 @@ import { const { basicScreen, - tableScreen, - viewScreen, - queryScreen, + createTableScreen, + createViewScreen, + createQueryScreen, basicTable, viewV2, basicQuery, @@ -202,7 +202,7 @@ describe("/screens", () => { it("should find table usage", async () => { const table = await config.api.table.save(basicTable()) const screen = await config.api.screen.save( - tableScreen("BudibaseDB", table) + createTableScreen("BudibaseDB", table) ) const usage = await config.api.screen.usage(table._id!) expect(usage.sourceType).toEqual(SourceType.TABLE) @@ -216,7 +216,7 @@ describe("/screens", () => { { status: 201 } ) const screen = await config.api.screen.save( - viewScreen("BudibaseDB", view) + createViewScreen("BudibaseDB", view) ) const usage = await config.api.screen.usage(view.id) expect(usage.sourceType).toEqual(SourceType.VIEW) @@ -229,7 +229,7 @@ describe("/screens", () => { ) const query = await config.api.query.save(basicQuery(datasource._id!)) const screen = await config.api.screen.save( - queryScreen(datasource._id!, query) + createQueryScreen(datasource._id!, query) ) const dsUsage = await config.api.screen.usage(datasource._id!) expect(dsUsage.sourceType).toEqual(SourceType.DATASOURCE) diff --git a/packages/server/src/tests/utilities/structures.ts b/packages/server/src/tests/utilities/structures.ts index 864b9f5399..7ca326e825 100644 --- a/packages/server/src/tests/utilities/structures.ts +++ b/packages/server/src/tests/utilities/structures.ts @@ -1,10 +1,5 @@ import { roles, utils } from "@budibase/backend-core" -import { - createHomeScreen, - createTableScreen, - createQueryScreen, - createViewScreen, -} from "../../constants/screens" +import { createHomeScreen } from "../../constants/screens" import { EMPTY_LAYOUT } from "../../constants/layouts" import { cloneDeep } from "lodash/fp" import { @@ -45,6 +40,11 @@ import { import { LoopInput } from "../../definitions/automations" import { merge } from "lodash" import { generator } from "@budibase/backend-core/tests" +export { + createTableScreen, + createQueryScreen, + createViewScreen, +} from "../../constants/screens" const { BUILTIN_ROLE_IDS } = roles @@ -523,18 +523,6 @@ export function basicScreen(route = "/") { }) } -export function tableScreen(datasourceName: string, table: Table) { - return createTableScreen(datasourceName, table) -} - -export function viewScreen(datasourceName: string, view: ViewV2) { - return createViewScreen(datasourceName, view) -} - -export function queryScreen(datasourceId: string, query: Query) { - return createQueryScreen(datasourceId, query) -} - export function powerScreen(route = "/") { return createHomeScreen({ roleId: BUILTIN_ROLE_IDS.POWER, From a5f2a050617495a847917ca1e14b7decdccdfb38 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 17:42:06 +0000 Subject: [PATCH 60/76] Linting. --- packages/server/src/tests/utilities/structures.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/server/src/tests/utilities/structures.ts b/packages/server/src/tests/utilities/structures.ts index 7ca326e825..3055b9c760 100644 --- a/packages/server/src/tests/utilities/structures.ts +++ b/packages/server/src/tests/utilities/structures.ts @@ -35,7 +35,6 @@ import { WebhookActionType, BuiltinPermissionID, DeepPartial, - ViewV2, } from "@budibase/types" import { LoopInput } from "../../definitions/automations" import { merge } from "lodash" From f9c75a213534a2ca7a8b5188328f871b462ade76 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 17:53:23 +0000 Subject: [PATCH 61/76] Final comments. --- .../backend/modals/DeleteDataConfirmationModal.svelte | 2 +- packages/server/src/api/routes/tests/screen.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index f55e0e7013..e3656328d7 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -86,7 +86,7 @@ async function deleteView(view: ViewV2 | View) { try { - if ("version" in view && helpers.views.isCalculationView(view)) { + if ("version" in view && helpers.views.isV2(view)) { await viewsV2.delete(view as ViewV2) } else { await views.delete(view as View) diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index 261c287087..a4c0b23232 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -90,7 +90,7 @@ describe("/screens", () => { async function checkScreens(roleId: string, screenIds: string[]) { await config.loginAsRole(roleId, async () => { const res = await config.api.application.getDefinition( - config.prodAppId! + config.getProdAppId() ) expect(res.screens.length).toEqual(screenIds.length) expect(res.screens.map(s => s._id).sort()).toEqual(screenIds.sort()) From c09809932d0cd91ef17c073273bd09adad82e11c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 6 Feb 2025 17:54:24 +0000 Subject: [PATCH 62/76] cleanup. --- .../backend/modals/DeleteDataConfirmationModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index e3656328d7..b52d3bce3c 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -86,7 +86,7 @@ async function deleteView(view: ViewV2 | View) { try { - if ("version" in view && helpers.views.isV2(view)) { + if (helpers.views.isV2(view)) { await viewsV2.delete(view as ViewV2) } else { await views.delete(view as View) From 85b2db1f023d49bc066315ee020c01db4ab4f8c9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 11:52:31 +0000 Subject: [PATCH 63/76] Majority of comments. --- .../backend/modals/DeleteDataConfirmationModal.svelte | 7 ++++--- packages/builder/src/stores/builder/screens.ts | 4 ++-- packages/frontend-core/src/api/screens.ts | 6 +++--- packages/server/src/api/controllers/screen.ts | 10 ++-------- packages/server/src/api/routes/tests/screen.spec.ts | 4 ++-- packages/server/src/tests/utilities/api/screen.ts | 6 +++--- packages/shared-core/src/sdk/documents/screens.ts | 4 ++-- packages/types/src/api/web/app/screen.ts | 3 +-- 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte index b52d3bce3c..82271bd066 100644 --- a/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte +++ b/packages/builder/src/components/backend/modals/DeleteDataConfirmationModal.svelte @@ -10,7 +10,7 @@ viewsV2, } from "@/stores/builder" import ConfirmDialog from "@/components/common/ConfirmDialog.svelte" - import { helpers } from "@budibase/shared-core" + import { helpers, utils } from "@budibase/shared-core" import { SourceType } from "@budibase/types" import { goto, params } from "@roxi/routify" import { DB_TYPE_EXTERNAL } from "@/constants/backend" @@ -45,7 +45,7 @@ } export const show = async () => { - const usage = await screenStore.usageOfScreens(getSourceID()) + const usage = await screenStore.usageInScreens(getSourceID()) affectedScreens = processScreens(usage.screens) sourceType = usage.sourceType confirmDeleteDialog.show() @@ -93,7 +93,6 @@ } notifications.success("View deleted") } catch (error) { - console.error(error) notifications.error("Error deleting view") } } @@ -140,6 +139,8 @@ return await deleteQuery(source as Query) case SourceType.DATASOURCE: return await deleteDatasource(source as Datasource) + default: + utils.unreachable(sourceType) } } diff --git a/packages/builder/src/stores/builder/screens.ts b/packages/builder/src/stores/builder/screens.ts index 1f23f9b1d1..b7d9a8be30 100644 --- a/packages/builder/src/stores/builder/screens.ts +++ b/packages/builder/src/stores/builder/screens.ts @@ -504,8 +504,8 @@ export class ScreenStore extends BudiStore { /** * Provides a list of screens that are used by a given source ID (table, view, datasource, query) */ - async usageOfScreens(sourceId: string) { - return API.usageOfScreens(sourceId) + async usageInScreens(sourceId: string) { + return API.usageInScreens(sourceId) } } diff --git a/packages/frontend-core/src/api/screens.ts b/packages/frontend-core/src/api/screens.ts index 8147db738d..0bcca9cfd3 100644 --- a/packages/frontend-core/src/api/screens.ts +++ b/packages/frontend-core/src/api/screens.ts @@ -2,14 +2,14 @@ import { DeleteScreenResponse, SaveScreenRequest, SaveScreenResponse, - UsageOfScreensResponse, + UsageInScreensResponse, } from "@budibase/types" import { BaseAPIClient } from "./types" export interface ScreenEndpoints { saveScreen: (screen: SaveScreenRequest) => Promise deleteScreen: (id: string, rev: string) => Promise - usageOfScreens: (sourceId: string) => Promise + usageInScreens: (sourceId: string) => Promise } export const buildScreenEndpoints = (API: BaseAPIClient): ScreenEndpoints => ({ @@ -35,7 +35,7 @@ export const buildScreenEndpoints = (API: BaseAPIClient): ScreenEndpoints => ({ }) }, - usageOfScreens: async sourceId => { + usageInScreens: async sourceId => { return await API.post({ url: `/api/screens/usage/${sourceId}`, }) diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index ea00e60e1a..456d5729db 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -17,7 +17,7 @@ import { ScreenProps, ScreenUsage, SourceType, - UsageOfScreensResponse, + UsageInScreensResponse, UserCtx, } from "@budibase/types" import { builderSocket } from "../../websockets" @@ -138,7 +138,7 @@ function findPlugins(component: ScreenProps, foundPlugins: string[]) { component._children.forEach(child => findPlugins(child, foundPlugins)) } -export async function usage(ctx: UserCtx) { +export async function usage(ctx: UserCtx) { const sourceId = ctx.params.sourceId const sourceType = sdk.common.getSourceType(sourceId) const allScreens = await sdk.screens.fetch() @@ -152,14 +152,8 @@ export async function usage(ctx: UserCtx) { }) } } - const isInternalTable = - sourceType === SourceType.TABLE && - sdk.tables.isInternal({ tableId: sourceId }) - const isInternalView = - sourceType === SourceType.VIEW && sdk.views.isInternal(sourceId) ctx.body = { sourceType, - internal: isInternalTable || isInternalView, screens: response, } } diff --git a/packages/server/src/api/routes/tests/screen.spec.ts b/packages/server/src/api/routes/tests/screen.spec.ts index a4c0b23232..32f4e4b361 100644 --- a/packages/server/src/api/routes/tests/screen.spec.ts +++ b/packages/server/src/api/routes/tests/screen.spec.ts @@ -6,7 +6,7 @@ import { Role, BuiltinPermissionID, SourceType, - UsageOfScreensResponse, + UsageInScreensResponse, } from "@budibase/types" const { @@ -193,7 +193,7 @@ describe("/screens", () => { await config.api.screen.save(basicScreen()) }) - function confirmScreen(usage: UsageOfScreensResponse, screen: Screen) { + function confirmScreen(usage: UsageInScreensResponse, screen: Screen) { expect(usage.screens.length).toEqual(1) expect(usage.screens[0].url).toEqual(screen.routing.route) expect(usage.screens[0]._id).toEqual(screen._id!) diff --git a/packages/server/src/tests/utilities/api/screen.ts b/packages/server/src/tests/utilities/api/screen.ts index bbbe704a29..8d4c0d9ac4 100644 --- a/packages/server/src/tests/utilities/api/screen.ts +++ b/packages/server/src/tests/utilities/api/screen.ts @@ -1,4 +1,4 @@ -import { Screen, UsageOfScreensResponse } from "@budibase/types" +import { Screen, UsageInScreensResponse } from "@budibase/types" import { Expectations, TestAPI } from "./base" export class ScreenAPI extends TestAPI { @@ -32,8 +32,8 @@ export class ScreenAPI extends TestAPI { usage = async ( sourceId: string, expectations?: Expectations - ): Promise => { - return this._post( + ): Promise => { + return this._post( `/api/screens/usage/${sourceId}`, { expectations, diff --git a/packages/shared-core/src/sdk/documents/screens.ts b/packages/shared-core/src/sdk/documents/screens.ts index 3ceffd26a6..218c6673aa 100644 --- a/packages/shared-core/src/sdk/documents/screens.ts +++ b/packages/shared-core/src/sdk/documents/screens.ts @@ -1,8 +1,8 @@ -import { Screen } from "@budibase/types" +import { Screen, Component } from "@budibase/types" export function findInSettings(screen: Screen, toFind: string) { const foundIn: { setting: string; value: string }[] = [] - function recurse(props: Record, parentKey = "") { + function recurse(props: Component, parentKey = "") { for (const [key, value] of Object.entries(props)) { if (!value) { continue diff --git a/packages/types/src/api/web/app/screen.ts b/packages/types/src/api/web/app/screen.ts index 9fc201d651..2ddac2f19a 100644 --- a/packages/types/src/api/web/app/screen.ts +++ b/packages/types/src/api/web/app/screen.ts @@ -21,8 +21,7 @@ export interface ScreenUsage { _id: string } -export interface UsageOfScreensResponse { +export interface UsageInScreensResponse { sourceType: SourceType - internal: boolean screens: ScreenUsage[] } From 126befde3ea1d40245eab697e0156211c31088ef Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 12:02:58 +0000 Subject: [PATCH 64/76] Updating UIEvent to an interface. --- packages/types/src/ui/common.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/types/src/ui/common.ts b/packages/types/src/ui/common.ts index 2f5d864ca0..0f5a2590b9 100644 --- a/packages/types/src/ui/common.ts +++ b/packages/types/src/ui/common.ts @@ -1,3 +1,5 @@ -export type UIEvent = Event & { +export interface UIEvent extends Omit { currentTarget: EventTarget & HTMLInputElement -} & { key?: string } & { target?: any } + key?: string + target?: any +} From 6435c9b529bb6411734a6338ddec8488e9db7a0b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 12:05:45 +0000 Subject: [PATCH 65/76] Linting. --- packages/server/src/api/controllers/screen.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index 456d5729db..038d87d548 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -16,7 +16,6 @@ import { Screen, ScreenProps, ScreenUsage, - SourceType, UsageInScreensResponse, UserCtx, } from "@budibase/types" From 5df197a36ea0c7bac123550e7b99d9e46f15535f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 13:49:34 +0000 Subject: [PATCH 66/76] Disabling cell formatting, it is currently incompatiable with cell/row conditions in grids and to avoid breaking those for now we are removing the capability until both can be a aligned to use the same mechanism of binding evaluation. --- packages/client/manifest.json | 9 +-------- packages/client/src/components/app/GridBlock.svelte | 2 +- .../src/components/grid/stores/conditions.ts | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 4b13713984..c236dd1ad9 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -3089,12 +3089,6 @@ "type": "tableConditions", "label": "Conditions", "key": "conditions" - }, - { - "type": "text", - "label": "Format", - "key": "format", - "info": "Changing format will display values as text" } ] }, @@ -7691,8 +7685,7 @@ { "type": "columns/grid", "key": "columns", - "resetOn": "table", - "nested": true + "resetOn": "table" } ] }, diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 1f4792ea8a..52040b8e58 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -105,7 +105,7 @@ order: idx, conditions: column.conditions, visible: !!column.active, - format: createFormatter(column), + // format: createFormatter(column), } if (column.width) { overrides[column.field].width = column.width diff --git a/packages/frontend-core/src/components/grid/stores/conditions.ts b/packages/frontend-core/src/components/grid/stores/conditions.ts index cf47456b44..37f8f3432a 100644 --- a/packages/frontend-core/src/components/grid/stores/conditions.ts +++ b/packages/frontend-core/src/components/grid/stores/conditions.ts @@ -173,5 +173,6 @@ const evaluateConditions = (row: UIRow, conditions: UICondition[]) => { // Swallow } } + console.log(metadata) return metadata } From 73345d8c05ed34cc1daf4958192f8e39f9c416d5 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 13:53:30 +0000 Subject: [PATCH 67/76] Linting. --- packages/client/src/components/app/GridBlock.svelte | 12 ++++++------ .../src/components/grid/stores/conditions.ts | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 52040b8e58..7f4990ace0 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -114,12 +114,12 @@ return overrides } - const createFormatter = column => { - if (typeof column.format !== "string" || !column.format.trim().length) { - return null - } - return row => processStringSync(column.format, { [id]: row }) - } + // const createFormatter = column => { + // if (typeof column.format !== "string" || !column.format.trim().length) { + // return null + // } + // return row => processStringSync(column.format, { [id]: row }) + // } const enrichButtons = buttons => { if (!buttons?.length) { diff --git a/packages/frontend-core/src/components/grid/stores/conditions.ts b/packages/frontend-core/src/components/grid/stores/conditions.ts index 37f8f3432a..cf47456b44 100644 --- a/packages/frontend-core/src/components/grid/stores/conditions.ts +++ b/packages/frontend-core/src/components/grid/stores/conditions.ts @@ -173,6 +173,5 @@ const evaluateConditions = (row: UIRow, conditions: UICondition[]) => { // Swallow } } - console.log(metadata) return metadata } From e9e1eb7a2db04c34b72cc88ca03f7b64447fe9ee Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Feb 2025 13:56:34 +0000 Subject: [PATCH 68/76] More linting. --- packages/client/src/components/app/GridBlock.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 7f4990ace0..b75ca46223 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -5,7 +5,7 @@ import { get, derived, readable } from "svelte/store" import { featuresStore } from "stores" import { Grid } from "@budibase/frontend-core" - import { processStringSync } from "@budibase/string-templates" + // import { processStringSync } from "@budibase/string-templates" // table is actually any datasource, but called table for legacy compatibility export let table From ad063b7de6c92664fd22af20cfbdb7d358358cf1 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Fri, 7 Feb 2025 14:10:38 +0000 Subject: [PATCH 69/76] Bump version to 3.4.4 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index bdb933c0c5..730d145ced 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.4.3", + "version": "3.4.4", "npmClient": "yarn", "concurrency": 20, "command": { From 2995961fd44c9085a7064fb6604a7e5938cd8757 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 7 Feb 2025 15:05:50 +0000 Subject: [PATCH 70/76] delete unneeded popover type --- packages/types/src/ui/components/popover.ts | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 packages/types/src/ui/components/popover.ts diff --git a/packages/types/src/ui/components/popover.ts b/packages/types/src/ui/components/popover.ts deleted file mode 100644 index 465e514647..0000000000 --- a/packages/types/src/ui/components/popover.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum PopoverAlign { - Left = "left", - Right = "right", - LeftOutside = "left-outside", - RightOutside = "right-outside", -} From feaaa173688693929ab6ffba34c76566cb2a99d7 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 7 Feb 2025 15:12:28 +0000 Subject: [PATCH 71/76] unused import --- .../src/components/common/ScreensPopover.svelte | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/common/ScreensPopover.svelte b/packages/builder/src/components/common/ScreensPopover.svelte index d6ae461590..0c4d9d47b7 100644 --- a/packages/builder/src/components/common/ScreensPopover.svelte +++ b/packages/builder/src/components/common/ScreensPopover.svelte @@ -1,15 +1,19 @@ From 2cd2c30c1dd093f3c213781640a970953b092ad0 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 7 Feb 2025 15:55:43 +0000 Subject: [PATCH 73/76] types --- packages/bbui/src/ActionButton/ActionButton.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte index d9c7a27fa1..633023a94a 100644 --- a/packages/bbui/src/ActionButton/ActionButton.svelte +++ b/packages/bbui/src/ActionButton/ActionButton.svelte @@ -19,7 +19,7 @@ $: accentStyle = getAccentStyle(accentColor) - const getAccentStyle = color => { + const getAccentStyle = (color: string | null) => { if (!color) { return "" } From b223c6355a565c5cbb1c0c0f9e77ae614a991d8c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 7 Feb 2025 17:01:36 +0100 Subject: [PATCH 74/76] Don't display key for missing settings --- .../design/[screenId]/_components/ScreenErrorsButton.svelte | 2 +- packages/builder/src/stores/builder/screenComponent.ts | 3 +++ packages/types/src/ui/components/errors.ts | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index d90fb2e91c..c5c0bda70c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -27,7 +27,7 @@ $screenComponentsList.find(c => c._id === error.componentId)! ._instanceName, ] - if (error.errorType === "setting") { + if (error.errorType === "setting" && error.cause === "invalid") { titleParts.push(error.label) } return titleParts.join(" - ") diff --git a/packages/builder/src/stores/builder/screenComponent.ts b/packages/builder/src/stores/builder/screenComponent.ts index 0c1e10f436..bb10bb2307 100644 --- a/packages/builder/src/stores/builder/screenComponent.ts +++ b/packages/builder/src/stores/builder/screenComponent.ts @@ -140,7 +140,9 @@ function getInvalidDatasources( key: setting.key, label: setting.label || setting.key, message: `The ${friendlyTypeName} named "${label}" could not be found`, + errorType: "setting", + cause: "invalid", }) } } @@ -217,6 +219,7 @@ function getMissingRequiredSettings( label: s.label || s.key, message: `Add the ${s.label} setting to start using your component`, errorType: "setting", + cause: "missing", })) ) } diff --git a/packages/types/src/ui/components/errors.ts b/packages/types/src/ui/components/errors.ts index 78a711fb13..78ca14c330 100644 --- a/packages/types/src/ui/components/errors.ts +++ b/packages/types/src/ui/components/errors.ts @@ -7,6 +7,7 @@ interface UISettingComponentError extends BaseUIComponentError { errorType: "setting" key: string label: string + cause: "missing" | "invalid" } interface UIAncestorComponentError extends BaseUIComponentError { From 7351adc6b66df7c0a777079037bf5bbe4a96ee3b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 7 Feb 2025 17:02:39 +0100 Subject: [PATCH 75/76] Changes on tooltip --- .../design/[screenId]/_components/ScreenErrorsButton.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index c5c0bda70c..949de1d882 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -43,8 +43,8 @@

Date: Fri, 7 Feb 2025 17:04:34 +0100 Subject: [PATCH 76/76] Smaller icon --- .../design/[screenId]/_components/ScreenErrorsButton.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte index 949de1d882..1ec86a3c22 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ScreenErrorsButton.svelte @@ -76,6 +76,7 @@
onErrorClick(error)}>