diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index 9da52f8bc0..3e4b2221d2 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -18,6 +18,8 @@ env: BRANCH: ${{ github.event.pull_request.head.ref }} BASE_BRANCH: ${{ github.event.pull_request.base.ref}} PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + NX_BASE_BRANCH: origin/${{ github.base_ref }} + USE_NX_AFFECTED: ${{ github.event_name == 'pull_request' && github.base_ref != 'master'}} jobs: lint: @@ -25,20 +27,20 @@ jobs: steps: - name: Checkout repo and submodules uses: actions/checkout@v3 - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} - name: Checkout repo only uses: actions/checkout@v3 - if: github.repository != 'Budibase/budibase' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != 'Budibase/budibase' - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn + - run: yarn --frozen-lockfile - run: yarn lint build: @@ -46,45 +48,66 @@ jobs: steps: - name: Checkout repo and submodules uses: actions/checkout@v3 - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} + fetch-depth: 0 - name: Checkout repo only uses: actions/checkout@v3 - if: github.repository != 'Budibase/budibase' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != 'Budibase/budibase' + with: + fetch-depth: 0 - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn + - run: yarn --frozen-lockfile + # Run build all the projects - - run: yarn build + - name: Build + run: | + yarn build # Check the types of the projects built via esbuild - - run: yarn check:types + - name: Check types + run: | + if ${{ env.USE_NX_AFFECTED }}; then + yarn check:types --since=${{ env.NX_BASE_BRANCH }} + else + yarn check:types + fi test-libraries: runs-on: ubuntu-latest steps: - name: Checkout repo and submodules uses: actions/checkout@v3 - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} + fetch-depth: 0 - name: Checkout repo only uses: actions/checkout@v3 - if: github.repository != 'Budibase/budibase' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != 'Budibase/budibase' + with: + fetch-depth: 0 - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn - - run: yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/pro + - run: yarn --frozen-lockfile + - name: Test + run: | + if ${{ env.USE_NX_AFFECTED }}; then + yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/pro --since=${{ env.NX_BASE_BRANCH }} + else + yarn test --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/pro + fi - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos @@ -96,21 +119,31 @@ jobs: steps: - name: Checkout repo and submodules uses: actions/checkout@v3 - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} + fetch-depth: 0 - name: Checkout repo only uses: actions/checkout@v3 - if: github.repository != 'Budibase/budibase' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != 'Budibase/budibase' + with: + fetch-depth: 0 - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn - - run: yarn test --scope=@budibase/worker --scope=@budibase/server + - run: yarn --frozen-lockfile + - name: Test worker and server + run: | + if ${{ env.USE_NX_AFFECTED }}; then + yarn test --scope=@budibase/worker --scope=@budibase/server --since=${{ env.NX_BASE_BRANCH }} + else + yarn test --scope=@budibase/worker --scope=@budibase/server + fi + - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN || github.token }} # not required for public repos @@ -119,42 +152,50 @@ jobs: test-pro: runs-on: ubuntu-latest - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' steps: - name: Checkout repo and submodules uses: actions/checkout@v3 with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} + fetch-depth: 0 - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn - - run: yarn test --scope=@budibase/pro + - run: yarn --frozen-lockfile + - name: Test + run: | + if ${{ env.USE_NX_AFFECTED }}; then + yarn test --scope=@budibase/pro --since=${{ env.NX_BASE_BRANCH }} + else + yarn test --scope=@budibase/pro + fi integration-test: runs-on: ubuntu-latest steps: - name: Checkout repo and submodules uses: actions/checkout@v3 - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' with: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} - name: Checkout repo only uses: actions/checkout@v3 - if: github.repository != 'Budibase/budibase' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != 'Budibase/budibase' - - name: Use Node.js 14.x + - name: Use Node.js 18.x uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 18.x cache: "yarn" - - run: yarn - - run: yarn build --projects=@budibase/server,@budibase/worker,@budibase/client + - run: yarn --frozen-lockfile + - name: Build packages + run: yarn build --scope @budibase/server --scope @budibase/worker --scope @budibase/client --scope @budibase/backend-core - name: Run tests run: | cd qa-core @@ -166,13 +207,12 @@ jobs: check-pro-submodule: runs-on: ubuntu-latest - if: github.repository == 'Budibase/budibase' + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' steps: - name: Checkout repo and submodules uses: actions/checkout@v3 with: submodules: true - fetch-depth: 0 token: ${{ secrets.PERSONAL_ACCESS_TOKEN || github.token }} - name: Check pro commit diff --git a/.github/workflows/check_unreleased_changes.yml b/.github/workflows/check_unreleased_changes.yml new file mode 100644 index 0000000000..d558330545 --- /dev/null +++ b/.github/workflows/check_unreleased_changes.yml @@ -0,0 +1,29 @@ +name: check_unreleased_changes + +on: + pull_request: + branches: + - master + +jobs: + check_unreleased: + runs-on: ubuntu-latest + steps: + - name: Check for unreleased changes + env: + REPO: "Budibase/budibase" + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_TIMESTAMP=$(curl -s -H "Authorization: token $TOKEN" \ + "https://api.github.com/repos/$REPO/releases/latest" | \ + jq -r .published_at) + COMMIT_TIMESTAMP=$(curl -s -H "Authorization: token $TOKEN" \ + "https://api.github.com/repos/$REPO/commits/master" | \ + jq -r .commit.committer.date) + RELEASE_SECONDS=$(date --date="$RELEASE_TIMESTAMP" "+%s") + COMMIT_SECONDS=$(date --date="$COMMIT_TIMESTAMP" "+%s") + if (( COMMIT_SECONDS > RELEASE_SECONDS )); then + echo "There are unreleased changes. Please release these changes before merging." + exit 1 + fi + echo "No unreleased changes detected." diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml index 61cb283e28..bd727b7865 100644 --- a/.github/workflows/release-develop.yml +++ b/.github/workflows/release-develop.yml @@ -44,7 +44,7 @@ jobs: - uses: actions/setup-node@v1 with: - node-version: 14.x + node-version: 18.x - run: yarn install --frozen-lockfile - name: Update versions diff --git a/.nvmrc b/.nvmrc index 835d07c442..7950a44576 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14.20.1 +v18.17.0 diff --git a/.tool-versions b/.tool-versions index 9f2ea77b14..a909d60941 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -nodejs 14.21.3 +nodejs 18.17.0 python 3.10.0 -yarn 1.22.19 \ No newline at end of file +yarn 1.22.19 diff --git a/.vscode/launch.json b/.vscode/launch.json index 8cb49d5825..cfd8d7b155 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,42 +1,31 @@ + { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Budibase Server", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--nolazy", - "-r", - "ts-node/register/transpile-only" - ], - "args": [ - "${workspaceFolder}/packages/server/src/index.ts" - ], - "cwd": "${workspaceFolder}/packages/server" - }, - { - "name": "Budibase Worker", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--nolazy", - "-r", - "ts-node/register/transpile-only" - ], - "args": [ - "${workspaceFolder}/packages/worker/src/index.ts" - ], - "cwd": "${workspaceFolder}/packages/worker" - }, - ], - "compounds": [ - { - "name": "Start Budibase", - "configurations": ["Budibase Server", "Budibase Worker"] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Budibase Server", + "type": "node", + "request": "launch", + "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"], + "args": ["${workspaceFolder}/packages/server/src/index.ts"], + "cwd": "${workspaceFolder}/packages/server" + }, + { + "name": "Budibase Worker", + "type": "node", + "request": "launch", + "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"], + "args": ["${workspaceFolder}/packages/worker/src/index.ts"], + "cwd": "${workspaceFolder}/packages/worker" + } + ], + "compounds": [ + { + "name": "Start Budibase", + "configurations": ["Budibase Server", "Budibase Worker"] + } + ] +} diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 2fb4c36fa8..70f198a84c 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -90,7 +90,7 @@ Component libraries are collections of components as well as the definition of t #### 1. Prerequisites -- NodeJS version `14.x.x` +- NodeJS version `18.x.x` - Python version `3.x` ### Using asdf (recommended) diff --git a/hosting/docker-compose.test.yaml b/hosting/docker-compose.test.yaml deleted file mode 100644 index f059173d2d..0000000000 --- a/hosting/docker-compose.test.yaml +++ /dev/null @@ -1,47 +0,0 @@ -version: "3" - -# optional ports are specified throughout for more advanced use cases. - -services: - minio-service: - restart: on-failure - # Last version that supports the "fs" backend - image: minio/minio:RELEASE.2022-10-24T18-35-07Z - ports: - - "9000" - - "9001" - environment: - MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY} - MINIO_SECRET_KEY: ${MINIO_SECRET_KEY} - command: server /data --console-address ":9001" - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] - interval: 30s - timeout: 20s - retries: 3 - - couchdb-service: - # platform: linux/amd64 - restart: on-failure - image: budibase/couchdb - environment: - - COUCHDB_PASSWORD=${COUCH_DB_PASSWORD} - - COUCHDB_USER=${COUCH_DB_USER} - ports: - - "5984" - - "4369" - - "9100" - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:5984/_up"] - interval: 30s - timeout: 20s - retries: 3 - - redis-service: - restart: on-failure - image: redis - command: redis-server --requirepass ${REDIS_PASSWORD} - ports: - - "6379" - healthcheck: - test: ["CMD", "redis-cli", "ping"] \ No newline at end of file diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index e43e5ad10c..9fdf2449d1 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -1,7 +1,7 @@ -FROM node:14-slim as build +FROM node:18-slim as build # install node-gyp dependencies -RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends apt-utils cron g++ make python +RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends apt-utils cron g++ make python3 # add pin script WORKDIR / diff --git a/hosting/dependencies/Dockerfile b/hosting/tests/Dockerfile similarity index 100% rename from hosting/dependencies/Dockerfile rename to hosting/tests/Dockerfile diff --git a/hosting/dependencies/README.md b/hosting/tests/README.md similarity index 100% rename from hosting/dependencies/README.md rename to hosting/tests/README.md diff --git a/hosting/dependencies/runner.sh b/hosting/tests/runner.sh similarity index 100% rename from hosting/dependencies/runner.sh rename to hosting/tests/runner.sh diff --git a/jestTestcontainersConfigGenerator.js b/jestTestcontainersConfigGenerator.js index 4b94cf5016..1e39ed771f 100644 --- a/jestTestcontainersConfigGenerator.js +++ b/jestTestcontainersConfigGenerator.js @@ -1,9 +1,16 @@ module.exports = () => { return { - dockerCompose: { - composeFilePath: "../../hosting", - composeFile: "docker-compose.test.yaml", - startupTimeout: 10000, - }, + couchdb: { + image: "budibase/couchdb", + ports: [5984], + env: { + COUCHDB_PASSWORD: "budibase", + COUCHDB_USER: "budibase", + }, + wait: { + type: "ports", + timeout: 20000, + } + } } } diff --git a/lerna.json b/lerna.json index 27d07555d4..3d6bf559b8 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.9.31", + "version": "2.9.32", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index d27af2e27d..4e4befb5f2 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "preinstall": "node scripts/syncProPackage.js", "setup": "git config submodule.recurse true && git submodule update && node ./hosting/scripts/setup.js && yarn && yarn build && yarn dev", "bootstrap": "./scripts/link-dependencies.sh && echo '***BOOTSTRAP ONLY REQUIRED FOR USE WITH ACCOUNT PORTAL***'", - "build": "yarn nx run-many -t=build", + "build": "lerna run build --stream", "build:dev": "lerna run --stream prebuild && yarn nx run-many --target=build --output-style=dynamic --watch --preserveWatchOutput", "check:types": "lerna run check:types", "backend:bootstrap": "./scripts/scopeBackend.sh && yarn run bootstrap", @@ -109,7 +109,7 @@ "@budibase/types": "0.0.0" }, "engines": { - "node": ">=14.0.0 <15.0.0" + "node": ">=18.0.0 <19.0.0" }, "dependencies": {} } diff --git a/packages/backend-core/src/cache/user.ts b/packages/backend-core/src/cache/user.ts index 8281bfca62..e2af78adfd 100644 --- a/packages/backend-core/src/cache/user.ts +++ b/packages/backend-core/src/cache/user.ts @@ -4,6 +4,8 @@ import * as context from "../context" import * as platform from "../platform" import env from "../environment" import * as accounts from "../accounts" +import { UserDB } from "../users" +import { sdk } from "@budibase/shared-core" const EXPIRY_SECONDS = 3600 @@ -60,6 +62,18 @@ export async function getUser( // make sure the tenant ID is always correct/set user.tenantId = tenantId } + // if has groups, could have builder permissions granted by a group + if (user.userGroups && !sdk.users.isGlobalBuilder(user)) { + await context.doInTenant(tenantId, async () => { + const appIds = await UserDB.getGroupBuilderAppIds(user) + if (appIds.length) { + const existing = user.builder?.apps || [] + user.builder = { + apps: [...new Set(existing.concat(appIds))], + } + } + }) + } return user } diff --git a/packages/backend-core/src/db/lucene.ts b/packages/backend-core/src/db/lucene.ts index a491451a62..7451d581b5 100644 --- a/packages/backend-core/src/db/lucene.ts +++ b/packages/backend-core/src/db/lucene.ts @@ -1,7 +1,6 @@ import fetch from "node-fetch" import { getCouchInfo } from "./couch" -import { SearchFilters, Row } from "@budibase/types" -import { createUserIndex } from "./searchIndexes/searchIndexes" +import { SearchFilters, Row, EmptyFilterOption } from "@budibase/types" const QUERY_START_REGEX = /\d[0-9]*:/g @@ -65,6 +64,7 @@ export class QueryBuilder { this.#index = index this.#query = { allOr: false, + onEmptyFilter: EmptyFilterOption.RETURN_ALL, string: {}, fuzzy: {}, range: {}, @@ -218,6 +218,10 @@ export class QueryBuilder { this.#query.allOr = true } + setOnEmptyFilter(value: EmptyFilterOption) { + this.#query.onEmptyFilter = value + } + handleSpaces(input: string) { if (this.#noEscaping) { return input @@ -289,8 +293,9 @@ export class QueryBuilder { const builder = this let allOr = this.#query && this.#query.allOr let query = allOr ? "" : "*:*" + let allFiltersEmpty = true const allPreProcessingOpts = { escape: true, lowercase: true, wrap: true } - let tableId + let tableId: string = "" if (this.#query.equal!.tableId) { tableId = this.#query.equal!.tableId delete this.#query.equal!.tableId @@ -305,7 +310,7 @@ export class QueryBuilder { } const contains = (key: string, value: any, mode = "AND") => { - if (Array.isArray(value) && value.length === 0) { + if (!value || (Array.isArray(value) && value.length === 0)) { return null } if (!Array.isArray(value)) { @@ -384,6 +389,12 @@ export class QueryBuilder { built += ` ${mode} ` } built += expression + if ( + (typeof value !== "string" && value != null) || + (typeof value === "string" && value !== tableId && value !== "") + ) { + allFiltersEmpty = false + } } if (opts?.returnBuilt) { return built @@ -463,6 +474,13 @@ export class QueryBuilder { allOr = false build({ tableId }, equal) } + if (allFiltersEmpty) { + if (this.#query.onEmptyFilter === EmptyFilterOption.RETURN_NONE) { + return "" + } else if (this.#query?.allOr) { + return query.replace("()", "(*:*)") + } + } return query } diff --git a/packages/backend-core/src/db/tests/lucene.spec.ts b/packages/backend-core/src/db/tests/lucene.spec.ts index a82828d8f2..7716661d88 100644 --- a/packages/backend-core/src/db/tests/lucene.spec.ts +++ b/packages/backend-core/src/db/tests/lucene.spec.ts @@ -1,6 +1,6 @@ import { newid } from "../../docIds/newid" import { getDB } from "../db" -import { Database } from "@budibase/types" +import { Database, EmptyFilterOption } from "@budibase/types" import { QueryBuilder, paginatedSearch, fullSearch } from "../lucene" const INDEX_NAME = "main" @@ -156,6 +156,76 @@ describe("lucene", () => { expect(resp.rows.length).toBe(2) }) + describe("empty filters behaviour", () => { + it("should return all rows by default", async () => { + const builder = new QueryBuilder(dbName, INDEX_NAME) + builder.addEqual("property", "") + builder.addEqual("number", null) + builder.addString("property", "") + builder.addFuzzy("property", "") + builder.addNotEqual("number", undefined) + builder.addOneOf("number", null) + builder.addContains("array", undefined) + builder.addNotContains("array", null) + builder.addContainsAny("array", null) + + const resp = await builder.run() + expect(resp.rows.length).toBe(3) + }) + + it("should return all rows when onEmptyFilter is ALL", async () => { + const builder = new QueryBuilder(dbName, INDEX_NAME) + builder.setOnEmptyFilter(EmptyFilterOption.RETURN_ALL) + builder.setAllOr() + builder.addEqual("property", "") + builder.addEqual("number", null) + builder.addString("property", "") + builder.addFuzzy("property", "") + builder.addNotEqual("number", undefined) + builder.addOneOf("number", null) + builder.addContains("array", undefined) + builder.addNotContains("array", null) + builder.addContainsAny("array", null) + + const resp = await builder.run() + expect(resp.rows.length).toBe(3) + }) + + it("should return no rows when onEmptyFilter is NONE", async () => { + const builder = new QueryBuilder(dbName, INDEX_NAME) + builder.setOnEmptyFilter(EmptyFilterOption.RETURN_NONE) + builder.addEqual("property", "") + builder.addEqual("number", null) + builder.addString("property", "") + builder.addFuzzy("property", "") + builder.addNotEqual("number", undefined) + builder.addOneOf("number", null) + builder.addContains("array", undefined) + builder.addNotContains("array", null) + builder.addContainsAny("array", null) + + const resp = await builder.run() + expect(resp.rows.length).toBe(0) + }) + + it("should return all matching rows when onEmptyFilter is NONE, but a filter value is provided", async () => { + const builder = new QueryBuilder(dbName, INDEX_NAME) + builder.setOnEmptyFilter(EmptyFilterOption.RETURN_NONE) + builder.addEqual("property", "") + builder.addEqual("number", 1) + builder.addString("property", "") + builder.addFuzzy("property", "") + builder.addNotEqual("number", undefined) + builder.addOneOf("number", null) + builder.addContains("array", undefined) + builder.addNotContains("array", null) + builder.addContainsAny("array", null) + + const resp = await builder.run() + expect(resp.rows.length).toBe(1) + }) + }) + describe("skip", () => { const skipDbName = `db-${newid()}` let docs: { diff --git a/packages/backend-core/src/featureFlags/index.ts b/packages/backend-core/src/features/index.ts similarity index 98% rename from packages/backend-core/src/featureFlags/index.ts rename to packages/backend-core/src/features/index.ts index 877cd60e1a..8f5c903e05 100644 --- a/packages/backend-core/src/featureFlags/index.ts +++ b/packages/backend-core/src/features/index.ts @@ -1,5 +1,6 @@ import env from "../environment" import * as context from "../context" +export * from "./installation" /** * Read the TENANT_FEATURE_FLAGS env var and return an array of features flags for each tenant. diff --git a/packages/backend-core/src/features/installation.ts b/packages/backend-core/src/features/installation.ts new file mode 100644 index 0000000000..defc8bf987 --- /dev/null +++ b/packages/backend-core/src/features/installation.ts @@ -0,0 +1,17 @@ +export function processFeatureEnvVar( + fullList: string[], + featureList?: string +) { + let list + if (!featureList) { + list = fullList + } else { + list = featureList.split(",") + } + for (let feature of list) { + if (!fullList.includes(feature)) { + throw new Error(`Feature: ${feature} is not an allowed option`) + } + } + return list as unknown as T[] +} diff --git a/packages/backend-core/src/featureFlags/tests/featureFlags.spec.ts b/packages/backend-core/src/features/tests/featureFlags.spec.ts similarity index 100% rename from packages/backend-core/src/featureFlags/tests/featureFlags.spec.ts rename to packages/backend-core/src/features/tests/featureFlags.spec.ts diff --git a/packages/backend-core/src/index.ts b/packages/backend-core/src/index.ts index 7b98674788..ffffd8240a 100644 --- a/packages/backend-core/src/index.ts +++ b/packages/backend-core/src/index.ts @@ -6,7 +6,8 @@ export * as roles from "./security/roles" export * as permissions from "./security/permissions" export * as accounts from "./accounts" export * as installation from "./installation" -export * as featureFlags from "./featureFlags" +export * as featureFlags from "./features" +export * as features from "./features/installation" export * as sessions from "./security/sessions" export * as platform from "./platform" export * as auth from "./auth" diff --git a/packages/backend-core/src/middleware/builderOnly.ts b/packages/backend-core/src/middleware/builderOnly.ts index 8c1c54a44c..fafcc524cc 100644 --- a/packages/backend-core/src/middleware/builderOnly.ts +++ b/packages/backend-core/src/middleware/builderOnly.ts @@ -5,11 +5,12 @@ import env from "../environment" export default async (ctx: UserCtx, next: any) => { const appId = getAppId() - const builderFn = env.isWorker() - ? hasBuilderPermissions - : env.isApps() - ? isBuilder - : undefined + const builderFn = + env.isWorker() || !appId + ? hasBuilderPermissions + : env.isApps() + ? isBuilder + : undefined if (!builderFn) { throw new Error("Service name unknown - middleware inactive.") } diff --git a/packages/backend-core/src/middleware/builderOrAdmin.ts b/packages/backend-core/src/middleware/builderOrAdmin.ts index c03e856233..4b8badec15 100644 --- a/packages/backend-core/src/middleware/builderOrAdmin.ts +++ b/packages/backend-core/src/middleware/builderOrAdmin.ts @@ -5,11 +5,12 @@ import env from "../environment" export default async (ctx: UserCtx, next: any) => { const appId = getAppId() - const builderFn = env.isWorker() - ? hasBuilderPermissions - : env.isApps() - ? isBuilder - : undefined + const builderFn = + env.isWorker() || !appId + ? hasBuilderPermissions + : env.isApps() + ? isBuilder + : undefined if (!builderFn) { throw new Error("Service name unknown - middleware inactive.") } diff --git a/packages/backend-core/src/security/permissions.ts b/packages/backend-core/src/security/permissions.ts index 70dae57ae6..aa0b20a30c 100644 --- a/packages/backend-core/src/security/permissions.ts +++ b/packages/backend-core/src/security/permissions.ts @@ -78,7 +78,6 @@ export const BUILTIN_PERMISSIONS = { permissions: [ new Permission(PermissionType.QUERY, PermissionLevel.READ), new Permission(PermissionType.TABLE, PermissionLevel.READ), - new Permission(PermissionType.VIEW, PermissionLevel.READ), ], }, WRITE: { @@ -87,7 +86,6 @@ export const BUILTIN_PERMISSIONS = { permissions: [ new Permission(PermissionType.QUERY, PermissionLevel.WRITE), new Permission(PermissionType.TABLE, PermissionLevel.WRITE), - new Permission(PermissionType.VIEW, PermissionLevel.READ), new Permission(PermissionType.AUTOMATION, PermissionLevel.EXECUTE), ], }, @@ -98,7 +96,6 @@ export const BUILTIN_PERMISSIONS = { new Permission(PermissionType.TABLE, PermissionLevel.WRITE), new Permission(PermissionType.USER, PermissionLevel.READ), new Permission(PermissionType.AUTOMATION, PermissionLevel.EXECUTE), - new Permission(PermissionType.VIEW, PermissionLevel.READ), new Permission(PermissionType.WEBHOOK, PermissionLevel.READ), ], }, @@ -109,7 +106,6 @@ export const BUILTIN_PERMISSIONS = { new Permission(PermissionType.TABLE, PermissionLevel.ADMIN), new Permission(PermissionType.USER, PermissionLevel.ADMIN), new Permission(PermissionType.AUTOMATION, PermissionLevel.ADMIN), - new Permission(PermissionType.VIEW, PermissionLevel.ADMIN), new Permission(PermissionType.WEBHOOK, PermissionLevel.READ), new Permission(PermissionType.QUERY, PermissionLevel.ADMIN), ], diff --git a/packages/backend-core/src/users/db.ts b/packages/backend-core/src/users/db.ts index 55cc97bb1c..c288540f35 100644 --- a/packages/backend-core/src/users/db.ts +++ b/packages/backend-core/src/users/db.ts @@ -1,30 +1,32 @@ import env from "../environment" import * as eventHelpers from "./events" import * as accounts from "../accounts" +import * as accountSdk from "../accounts" import * as cache from "../cache" -import { getIdentity, getTenantId, getGlobalDB } from "../context" +import { getGlobalDB, getIdentity, getTenantId } from "../context" import * as dbUtils from "../db" import { EmailUnavailableError, HTTPError } from "../errors" import * as platform from "../platform" import * as sessions from "../security/sessions" import * as usersCore from "./users" import { + Account, AllDocsResponse, BulkUserCreated, BulkUserDeleted, + isSSOAccount, + isSSOUser, RowResponse, SaveUserOpts, User, - Account, - isSSOUser, - isSSOAccount, UserStatus, + UserGroup, + ContextUser, } from "@budibase/types" -import * as accountSdk from "../accounts" import { - validateUniqueUser, getAccountHolderFromUserIds, isAdmin, + validateUniqueUser, } from "./utils" import { searchExistingEmails } from "./lookup" import { hash } from "../utils" @@ -32,8 +34,14 @@ import { hash } from "../utils" type QuotaUpdateFn = (change: number, cb?: () => Promise) => Promise type GroupUpdateFn = (groupId: string, userIds: string[]) => Promise type FeatureFn = () => Promise +type GroupGetFn = (ids: string[]) => Promise +type GroupBuildersFn = (user: User) => Promise type QuotaFns = { addUsers: QuotaUpdateFn; removeUsers: QuotaUpdateFn } -type GroupFns = { addUsers: GroupUpdateFn } +type GroupFns = { + addUsers: GroupUpdateFn + getBulk: GroupGetFn + getGroupBuilderAppIds: GroupBuildersFn +} type FeatureFns = { isSSOEnforced: FeatureFn; isAppBuildersEnabled: FeatureFn } const bulkDeleteProcessing = async (dbUser: User) => { @@ -179,6 +187,14 @@ export class UserDB { return user } + static async bulkGet(userIds: string[]) { + return await usersCore.bulkGetGlobalUsersById(userIds) + } + + static async bulkUpdate(users: User[]) { + return await usersCore.bulkUpdateGlobalUsers(users) + } + static async save(user: User, opts: SaveUserOpts = {}): Promise { // default booleans to true if (opts.hashPassword == null) { @@ -457,4 +473,12 @@ export class UserDB { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "deletion" }) } + + static async getGroups(groupIds: string[]) { + return await this.groups.getBulk(groupIds) + } + + static async getGroupBuilderAppIds(user: User) { + return await this.groups.getGroupBuilderAppIds(user) + } } diff --git a/packages/backend-core/tests/core/utilities/mocks/licenses.ts b/packages/backend-core/tests/core/utilities/mocks/licenses.ts index 6747282040..309f0fd159 100644 --- a/packages/backend-core/tests/core/utilities/mocks/licenses.ts +++ b/packages/backend-core/tests/core/utilities/mocks/licenses.ts @@ -86,6 +86,10 @@ export const useAuditLogs = () => { return useFeature(Feature.AUDIT_LOGS) } +export const usePublicApiUserRoles = () => { + return useFeature(Feature.USER_ROLE_PUBLIC_API) +} + export const useScimIntegration = () => { return useFeature(Feature.SCIM) } @@ -98,6 +102,10 @@ export const useAppBuilders = () => { return useFeature(Feature.APP_BUILDERS) } +export const useViewPermissions = () => { + return useFeature(Feature.VIEW_PERMISSIONS) +} + // QUOTAS export const setAutomationLogsQuota = (value: number) => { diff --git a/packages/backend-core/tests/core/utilities/testContainerUtils.ts b/packages/backend-core/tests/core/utilities/testContainerUtils.ts index f6c702f7ef..7da6cbc777 100644 --- a/packages/backend-core/tests/core/utilities/testContainerUtils.ts +++ b/packages/backend-core/tests/core/utilities/testContainerUtils.ts @@ -32,8 +32,8 @@ function getTestContainerSettings( ): string | null { const entry = Object.entries(global).find( ([k]) => - k.includes(`_${serverName.toUpperCase()}`) && - k.includes(`_${key.toUpperCase()}__`) + k.includes(`${serverName.toUpperCase()}`) && + k.includes(`${key.toUpperCase()}`) ) if (!entry) { return null @@ -67,27 +67,14 @@ function getContainerInfo(containerName: string, port: number) { } function getCouchConfig() { - return getContainerInfo("couchdb-service", 5984) -} - -function getMinioConfig() { - return getContainerInfo("minio-service", 9000) -} - -function getRedisConfig() { - return getContainerInfo("redis-service", 6379) + return getContainerInfo("couchdb", 5984) } export function setupEnv(...envs: any[]) { - const couch = getCouchConfig(), - minio = getCouchConfig(), - redis = getRedisConfig() + const couch = getCouchConfig() const configs = [ { key: "COUCH_DB_PORT", value: couch.port }, { key: "COUCH_DB_URL", value: couch.url }, - { key: "MINIO_PORT", value: minio.port }, - { key: "MINIO_URL", value: minio.url }, - { key: "REDIS_URL", value: redis.url }, ] for (const config of configs.filter(x => !!x.value)) { diff --git a/packages/bbui/src/Actions/position_dropdown.js b/packages/bbui/src/Actions/position_dropdown.js index 8fa02bb8f3..4a5ef890bf 100644 --- a/packages/bbui/src/Actions/position_dropdown.js +++ b/packages/bbui/src/Actions/position_dropdown.js @@ -32,11 +32,10 @@ export default function positionDropdown(element, opts) { left: null, top: null, } - // Determine vertical styles if (align === "right-outside") { styles.top = anchorBounds.top - } else if (window.innerHeight - anchorBounds.bottom < 100) { + } else if (window.innerHeight - anchorBounds.bottom < (maxHeight || 100)) { styles.top = anchorBounds.top - elementBounds.height - offset styles.maxHeight = maxHeight || 240 } else { diff --git a/packages/bbui/src/ColorPicker/ColorPicker.svelte b/packages/bbui/src/ColorPicker/ColorPicker.svelte index 9a70134fb6..2ba5309860 100644 --- a/packages/bbui/src/ColorPicker/ColorPicker.svelte +++ b/packages/bbui/src/ColorPicker/ColorPicker.svelte @@ -1,8 +1,8 @@ -
-
(open = true)}> -
-
- {#if open} -
+
{ + dropdown.toggle() + }} +> +
+
+ + + +
{#each categories as category}
{category.label}
@@ -187,8 +184,8 @@
- {/if} -
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/AppThemeSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/AppThemeSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ButtonRoundnessSelect.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ButtonRoundnessSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ButtonRoundnessSelect.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ButtonRoundnessSelect.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte similarity index 72% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte index 8982cd20de..a08ded8eee 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte @@ -1,12 +1,8 @@ - - - {#if $selectedScreen.layoutId} - - This screen uses a custom layout, which is deprecated - - {/if} - {#each screenSettings as setting (setting.key)} - setScreenSetting(setting, val)} - props={{ ...setting.props, error: errors[setting.key] }} - {bindings} - /> - {/each} - - - +{#if $selectedScreen.layoutId} + + This screen uses a custom layout, which is deprecated + +{/if} +{#each screenSettings as setting (setting.key)} + setScreenSetting(setting, val)} + props={{ ...setting.props, error: errors[setting.key] }} + {bindings} + /> +{/each} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte new file mode 100644 index 0000000000..13a008fae0 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/ThemePanel.svelte @@ -0,0 +1,78 @@ + + +
+ + These settings apply to all screens +
+ + + + + + + update("buttonBorderRadius", e.detail)} + /> + + update("primaryColor", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + update("primaryColorHover", val)} + props={{ + spectrumTheme: $store.theme, + }} + /> + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte new file mode 100644 index 0000000000..778fa303cc --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte @@ -0,0 +1,51 @@ + + + +
+
+ {#each tabs as tab} + { + activeTab = tab + }} + > + {capitalise(tab)} + + {/each} +
+
+ + {#if activeTab === "theme"} + + {:else} + + {/if} + +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte new file mode 100644 index 0000000000..19cb1d8dff --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_layout.svelte @@ -0,0 +1,52 @@ + + +{#if routeComponentId === `${$store.selectedScreenId}-screen`} + +{:else if routeComponentId === `${$store.selectedScreenId}-navigation`} + +{:else} + +{/if} + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte new file mode 100644 index 0000000000..0ff63d1ead --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/index.svelte @@ -0,0 +1 @@ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte similarity index 98% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index 7dca5b792b..248bbc8141 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -31,6 +31,10 @@ $: orderMap = createComponentOrderMap(componentList) const getAllowedComponents = (allComponents, screen, component) => { + // Default to using the root screen container if no component specified + if (!component) { + component = screen.props + } const path = findComponentPath(screen?.props, component?._id) if (!path?.length) { return [] diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/index.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/index.svelte rename to packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/index.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 785b221239..09f97302fd 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,32 +1,16 @@
- +
+ Screens +
+
+ +
+
+ +
+
+
+ {#if filteredScreens?.length} + {#each filteredScreens as screen (screen._id)} + store.actions.screens.select(screen._id)} + rightAlignIcon + showTooltip + selectedBy={$userSelectedResourceMap[screen._id]} + > + +
+ +
+
+ {/each} + {:else} + +
+ There aren't any screens matching that route +
+
+ {/if} +
+ +
screensHeight.set("210px")} + /> +
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte deleted file mode 100644 index 00165e4ee9..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_fallback.svelte +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte index 8bc0dcc3e5..0e630b4f39 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_layout.svelte @@ -1,14 +1,10 @@ -
-
- - $goto("./screens")} - /> - $goto("./components")} - /> - $goto("./theme")} - /> - $goto("./navigation")} - /> - {#if $store.layouts?.length} - $goto("./layouts")} - /> - {/if} - -
- -
- {#if $selectedScreen} - +{#if $selectedScreen} +
+
+ - {/if} + +
-
+{/if} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte deleted file mode 100644 index 9513753d76..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentListPanel.svelte +++ /dev/null @@ -1,90 +0,0 @@ - - - -
- -
- -
    -
  • - { - $store.selectedComponentId = $selectedScreen?.props._id - }} - id={`component-${$selectedScreen?.props._id}`} - selectedBy={$userSelectedResourceMap[$selectedScreen?.props._id]} - > - - - - - - {#if $dndStore.dragging && $dndStore.valid} - - {#if $dndStore.dropPosition !== DropPosition.INSIDE} - - {/if} - {/if} -
  • -
-
-
- - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte deleted file mode 100644 index 860258c940..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_layout.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte deleted file mode 100644 index 9b5d05fe57..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/index.svelte +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte deleted file mode 100644 index f8c4cc0868..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/index.svelte +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte index f5e3806bd6..c4ed7d949c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/index.svelte @@ -1,5 +1,6 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte deleted file mode 100644 index cba68f899d..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutDropdownMenu.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - -
- -
- Delete -
- - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte deleted file mode 100644 index cc895317fd..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - -
- {#each $store.layouts as layout (layout._id)} - store.actions.layouts.select(layout._id)} - > - - - {/each} -
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte deleted file mode 100644 index bfc2f94f43..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Custom layouts are being deprecated. They will be removed in a future - release. - - - You can save the content of this layout by pressing the button below. - - - This will copy all components inside your layout, which you can then paste - into a screen. - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte deleted file mode 100644 index c82fefab3e..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_layout.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte deleted file mode 100644 index 4d39403bc3..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/index.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte deleted file mode 100644 index 1333c6afe3..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/_layout.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte deleted file mode 100644 index 09d45f8fde..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/index.svelte +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte deleted file mode 100644 index 614e1eed80..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {#if $selectedScreen.layoutId} - - You can't preview your navigation settings using this screen as it uses - a custom layout, which is deprecated - - {/if} - - Your navigation is configured for all the screens within your app. - - - You can hide and show your navigation for each screen in the screen - settings. - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte deleted file mode 100644 index c6d43984b2..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationSettingsPanel.svelte +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - update("navigation", "Top")} - /> - update("navigation", "Left")} - /> - - - {#if $store.navigation.navigation === "Top"} - update("sticky", e.detail)} - /> - update("logoUrl", e.detail)} - placeholder="Add logo URL" - updateOnChange={false} - /> - {/if} - - - update("hideTitle", !e.detail)} - /> - {#if !$store.navigation.hideTitle} - update("title", e.detail)} - placeholder="Add title" - updateOnChange={false} - /> - {/if} - - - - update("navBackground", e.detail)} - /> - - - - update("navTextColor", e.detail)} - /> - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte deleted file mode 100644 index fc2e03d8e8..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/index.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte deleted file mode 100644 index 6362af3073..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - (searchString = e.detail)} - /> -