diff --git a/docs/DEV-SETUP-DEBIAN.md b/docs/DEV-SETUP-DEBIAN.md index 88a124708c..9edd8286cb 100644 --- a/docs/DEV-SETUP-DEBIAN.md +++ b/docs/DEV-SETUP-DEBIAN.md @@ -1,12 +1,15 @@ ## Dev Environment on Debian 11 -### Install Node +### Install NVM & Node 14 +NVM documentation: https://github.com/nvm-sh/nvm#installing-and-updating -Budibase requires a recent version of node (14+): +Install NVM ``` -curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - -apt -y install nodejs -node -v +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +``` +Install Node 14 +``` +nvm install 14 ``` ### Install npm requirements @@ -31,7 +34,7 @@ This setup process was tested on Debian 11 (bullseye) with version numbers show - Docker: 20.10.5 - Docker-Compose: 1.29.2 -- Node: v16.15.1 +- Node: v14.20.1 - Yarn: 1.22.19 - Lerna: 5.1.4 diff --git a/docs/DEV-SETUP-MACOSX.md b/docs/DEV-SETUP-MACOSX.md index c5990e58da..d9e2dcad6a 100644 --- a/docs/DEV-SETUP-MACOSX.md +++ b/docs/DEV-SETUP-MACOSX.md @@ -11,7 +11,7 @@ through brew. ### Install Node -Budibase requires a recent version of node (14+): +Budibase requires a recent version of node 14: ``` brew install node npm node -v @@ -38,7 +38,7 @@ This setup process was tested on Mac OSX 12 (Monterey) with version numbers show - Docker: 20.10.14 - Docker-Compose: 2.6.0 -- Node: 18.3.0 +- Node: 14.20.1 - Yarn: 1.22.19 - Lerna: 5.1.4 @@ -59,4 +59,7 @@ The dev version will be available on port 10000 i.e. http://127.0.0.1:10000/builder/admin | **NOTE**: If you are working on a M1 Apple Silicon, you will need to uncomment `# platform: linux/amd64` line in -[hosting/docker-compose-dev.yaml](../hosting/docker-compose.dev.yaml) \ No newline at end of file +[hosting/docker-compose-dev.yaml](../hosting/docker-compose.dev.yaml) + +### Troubleshooting +If there are errors with the `yarn setup` command, you can try installing nvm and node 14. This is the same as the instructions for Debian 11. diff --git a/docs/DEV-SETUP-WINDOWS.md b/docs/DEV-SETUP-WINDOWS.md new file mode 100644 index 0000000000..c5608b7567 --- /dev/null +++ b/docs/DEV-SETUP-WINDOWS.md @@ -0,0 +1,81 @@ +## Dev Environment on Windows 10/11 (WSL2) + + +### Install WSL with Ubuntu LTS + +Enable WSL 2 on Windows 10/11 for docker support. +``` +wsl --set-default-version 2 +``` +Install Ubuntu LTS. +``` +wsl --install Ubuntu +``` + +Or follow the instruction here: +https://learn.microsoft.com/en-us/windows/wsl/install + +### Install Docker in windows +Download the installer from docker and install it. + +Check this url for more detailed instructions: +https://docs.docker.com/desktop/install/windows-install/ + +You should follow the next steps from within the Ubuntu terminal. + +### Install NVM & Node 14 +NVM documentation: https://github.com/nvm-sh/nvm#installing-and-updating + +Install NVM +``` +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +``` +Install Node 14 +``` +nvm install 14 +``` + + +### Install npm requirements + +``` +npm install -g yarn jest lerna +``` + +### Clone the repo +``` +git clone https://github.com/Budibase/budibase.git +``` + +### Check Versions + +This setup process was tested on Windows 11 with version numbers show below. Your mileage may vary using anything else. + +- Docker: 20.10.7 +- Docker-Compose: 2.10.2 +- Node: v14.20.1 +- Yarn: 1.22.19 +- Lerna: 5.5.4 + +### Build + +``` +cd budibase +yarn setup +``` +The yarn setup command runs several build steps i.e. +``` +node ./hosting/scripts/setup.js && yarn && yarn bootstrap && yarn build && yarn dev +``` +So this command will actually run the application in dev mode. It creates .env files under `./packages/server` and `./packages/worker` and runs docker containers for each service via docker-compose. + +The dev version will be available on port 10000 i.e. + +http://127.0.0.1:10000/builder/admin + +### Working with the code +Here are the instructions to work on the application from within Visual Studio Code (in Windows) through the WSL. All the commands and files are within the Ubuntu system and it should run as if you were working on a Linux machine. + +https://code.visualstudio.com/docs/remote/wsl + +Note you will be able to run the application from within the WSL terminal and you will be able to access the application from the a browser in Windows. \ No newline at end of file diff --git a/hosting/scripts/build-target-paths.sh b/hosting/scripts/build-target-paths.sh index c974d9a304..67e1765ca8 100644 --- a/hosting/scripts/build-target-paths.sh +++ b/hosting/scripts/build-target-paths.sh @@ -4,6 +4,7 @@ echo ${TARGETBUILD} > /buildtarget.txt if [[ "${TARGETBUILD}" = "aas" ]]; then # Azure AppService uses /home for persisent data & SSH on port 2222 DATA_DIR=/home + WEBSITES_ENABLE_APP_SERVICE_STORAGE=true mkdir -p $DATA_DIR/{search,minio,couch} mkdir -p $DATA_DIR/couch/{dbs,views} chown -R couchdb:couchdb $DATA_DIR/couch/ diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index f34290f627..58796f0362 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -19,8 +19,8 @@ ADD packages/worker . RUN node /pinVersions.js && yarn && yarn build && /cleanup.sh FROM couchdb:3.2.1 -# TARGETARCH can be amd64 or arm e.g. docker build --build-arg TARGETARCH=amd64 -ARG TARGETARCH=amd64 +ARG TARGETARCH +ENV TARGETARCH $TARGETARCH #TARGETBUILD can be set to single (for single docker image) or aas (for azure app service) # e.g. docker build --build-arg TARGETBUILD=aas .... ARG TARGETBUILD=single diff --git a/hosting/single/runner.sh b/hosting/single/runner.sh index e02b33d771..6770d27ee0 100644 --- a/hosting/single/runner.sh +++ b/hosting/single/runner.sh @@ -21,6 +21,7 @@ declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONME # Azure App Service customisations if [[ "${TARGETBUILD}" = "aas" ]]; then DATA_DIR=/home + WEBSITES_ENABLE_APP_SERVICE_STORAGE=true /etc/init.d/ssh start else DATA_DIR=${DATA_DIR:-/data} diff --git a/lerna.json b/lerna.json index 69a8cb66a4..a8276de8cc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 7ab82fcd60..90b645ff2c 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -20,7 +20,7 @@ "test:watch": "jest --watchAll" }, "dependencies": { - "@budibase/types": "2.0.14-alpha.1", + "@budibase/types": "2.0.24-alpha.0", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index d5557bc3c5..803396fb35 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.2.1", - "@budibase/string-templates": "2.0.14-alpha.1", + "@budibase/string-templates": "2.0.24-alpha.0", "@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/bbui/src/Form/Core/Picker.svelte b/packages/bbui/src/Form/Core/Picker.svelte index cdaf00aded..d80ca98153 100644 --- a/packages/bbui/src/Form/Core/Picker.svelte +++ b/packages/bbui/src/Form/Core/Picker.svelte @@ -19,6 +19,7 @@ export let placeholderOption = null export let options = [] export let isOptionSelected = () => false + export let isOptionEnabled = () => true export let onSelectOption = () => {} export let getOptionLabel = option => option export let getOptionValue = option => option @@ -164,6 +165,7 @@ aria-selected="true" tabindex="0" on:click={() => onSelectOption(getOptionValue(option, idx))} + class:is-disabled={!isOptionEnabled(option)} > {#if getOptionIcon(option, idx)} @@ -256,4 +258,7 @@ .spectrum-Popover :global(.spectrum-Search .spectrum-Textfield-icon) { top: 9px; } + .spectrum-Menu-item.is-disabled { + pointer-events: none; + } diff --git a/packages/bbui/src/Form/Core/Select.svelte b/packages/bbui/src/Form/Core/Select.svelte index f549f58d0c..3e15b7f6ef 100644 --- a/packages/bbui/src/Form/Core/Select.svelte +++ b/packages/bbui/src/Form/Core/Select.svelte @@ -12,6 +12,7 @@ export let getOptionValue = option => option export let getOptionIcon = () => null export let getOptionColour = () => null + export let isOptionEnabled export let readonly = false export let quiet = false export let autoWidth = false @@ -66,6 +67,7 @@ {getOptionValue} {getOptionIcon} {getOptionColour} + {isOptionEnabled} {autocomplete} {sort} isPlaceholder={value == null || value === ""} diff --git a/packages/bbui/src/Form/Select.svelte b/packages/bbui/src/Form/Select.svelte index 1b68746c5e..69126e648d 100644 --- a/packages/bbui/src/Form/Select.svelte +++ b/packages/bbui/src/Form/Select.svelte @@ -15,6 +15,7 @@ export let getOptionValue = option => extractProperty(option, "value") export let getOptionIcon = option => option?.icon export let getOptionColour = option => option?.colour + export let isOptionEnabled export let quiet = false export let autoWidth = false export let sort = false @@ -49,6 +50,7 @@ {getOptionValue} {getOptionIcon} {getOptionColour} + {isOptionEnabled} on:change={onChange} on:click /> diff --git a/packages/builder/package.json b/packages/builder/package.json index 631b1988ad..687b571b66 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", - "@budibase/client": "2.0.14-alpha.1", - "@budibase/frontend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", + "@budibase/bbui": "2.0.24-alpha.0", + "@budibase/client": "2.0.24-alpha.0", + "@budibase/frontend-core": "2.0.24-alpha.0", + "@budibase/string-templates": "2.0.24-alpha.0", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 7456ec5691..c83daa7807 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -396,19 +396,17 @@ export const getUserBindings = () => { bindings = keys.reduce((acc, key) => { const fieldSchema = schema[key] - if (fieldSchema.type !== "link") { - acc.push({ - type: "context", - runtimeBinding: `${safeUser}.${makePropSafe(key)}`, - readableBinding: `Current User.${key}`, - // Field schema and provider are required to construct relationship - // datasource options, based on bindable properties - fieldSchema, - providerId: "user", - category: "Current User", - icon: "User", - }) - } + acc.push({ + type: "context", + runtimeBinding: `${safeUser}.${makePropSafe(key)}`, + readableBinding: `Current User.${key}`, + // Field schema and provider are required to construct relationship + // datasource options, based on bindable properties + fieldSchema, + providerId: "user", + category: "Current User", + icon: "User", + }) return acc }, []) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 21059b32dd..3fd38bddeb 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -314,7 +314,7 @@ const relatedTable = $tables.list.find( tbl => tbl._id === fieldInfo.tableId ) - if (inUse(relatedTable, fieldInfo.fieldName)) { + if (inUse(relatedTable, fieldInfo.fieldName) && !originalName) { newError.relatedName = `Column name already in use in table ${relatedTable.name}` } } diff --git a/packages/builder/src/components/portal/overview/automation/HistoryTab.svelte b/packages/builder/src/components/portal/overview/automation/HistoryTab.svelte index c676e00d2d..bd32e423c9 100644 --- a/packages/builder/src/components/portal/overview/automation/HistoryTab.svelte +++ b/packages/builder/src/components/portal/overview/automation/HistoryTab.svelte @@ -1,5 +1,5 @@ +{"is adming" + $auth.isAdmin} {#if $auth.isAdmin} { - if (license?.plan.type === PlanType.FREE) { + if (license?.plan.type === Constants.PlanType.FREE) { window.location.href = upgradeUrl } else { window.location.href = manageUrl @@ -133,7 +133,7 @@ } const setPrimaryActionText = () => { - if (license?.plan.type === PlanType.FREE) { + if (license?.plan.type === Constants.PlanType.FREE) { primaryActionText = "Upgrade" return } diff --git a/packages/cli/package.json b/packages/cli/package.json index 6f094416f8..0d99b165f6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { @@ -26,9 +26,9 @@ "outputPath": "build" }, "dependencies": { - "@budibase/backend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", - "@budibase/types": "2.0.14-alpha.1", + "@budibase/backend-core": "2.0.24-alpha.0", + "@budibase/string-templates": "2.0.24-alpha.0", + "@budibase/types": "2.0.24-alpha.0", "axios": "0.21.2", "chalk": "4.1.0", "cli-progress": "3.11.2", diff --git a/packages/cli/src/exec.js b/packages/cli/src/exec.js index 72fd8e00eb..4df486aed6 100644 --- a/packages/cli/src/exec.js +++ b/packages/cli/src/exec.js @@ -22,6 +22,6 @@ exports.runPkgCommand = async (command, dir = "./") => { throw new Error("Must have yarn or npm installed to run build.") } const npmCmd = command === "install" ? `npm ${command}` : `npm run ${command}` - const cmd = yarn ? `yarn ${command}` : npmCmd + const cmd = yarn ? `yarn ${command} --ignore-engines` : npmCmd await exports.exec(cmd, dir) } diff --git a/packages/client/package.json b/packages/client/package.json index 86ba8c5088..7f662c557e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", - "@budibase/frontend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", + "@budibase/bbui": "2.0.24-alpha.0", + "@budibase/frontend-core": "2.0.24-alpha.0", + "@budibase/string-templates": "2.0.24-alpha.0", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index ab19e91038..537e963ff3 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -16,7 +16,6 @@ themeStore, appStore, devToolsStore, - environmentStore, } from "stores" import NotificationDisplay from "components/overlay/NotificationDisplay.svelte" import ConfirmationDisplay from "components/overlay/ConfirmationDisplay.svelte" @@ -48,8 +47,6 @@ !$builderStore.inBuilder && $devToolsStore.enabled && !$routeStore.queryParams?.peek - $: objectStoreUrl = $environmentStore.cloud ? "https://cdn.budi.live" : "" - $: pluginsUrl = `${objectStoreUrl}/plugins` // Handle no matching route $: { @@ -95,8 +92,7 @@ {#if $builderStore.usedPlugins?.length} {#each $builderStore.usedPlugins as plugin (plugin.hash)} - + {/each} {/if} diff --git a/packages/client/src/components/app/charts/ApexOptionsBuilder.js b/packages/client/src/components/app/charts/ApexOptionsBuilder.js index 31c5a820f7..6b3e3a4440 100644 --- a/packages/client/src/components/app/charts/ApexOptionsBuilder.js +++ b/packages/client/src/components/app/charts/ApexOptionsBuilder.js @@ -1,37 +1,39 @@ export class ApexOptionsBuilder { - formatters = { - ["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100), - ["Thousands"]: val => `${Math.round(val / 1000)}K`, - ["Millions"]: val => `${Math.round(val / 1000000)}M`, - } - options = { - series: [], - legend: { - show: false, - position: "top", - horizontalAlign: "right", - showForSingleSeries: true, - showForNullSeries: true, - showForZeroSeries: true, - }, - chart: { - toolbar: { + constructor() { + this.formatters = { + ["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100), + ["Thousands"]: val => `${Math.round(val / 1000)}K`, + ["Millions"]: val => `${Math.round(val / 1000000)}M`, + } + this.options = { + series: [], + legend: { show: false, + position: "top", + horizontalAlign: "right", + showForSingleSeries: true, + showForNullSeries: true, + showForZeroSeries: true, }, - zoom: { - enabled: false, + chart: { + toolbar: { + show: false, + }, + zoom: { + enabled: false, + }, }, - }, - xaxis: { - labels: { - formatter: this.formatters.Default, + xaxis: { + labels: { + formatter: this.formatters.Default, + }, }, - }, - yaxis: { - labels: { - formatter: this.formatters.Default, + yaxis: { + labels: { + formatter: this.formatters.Default, + }, }, - }, + } } setOption(path, value) { diff --git a/packages/client/src/licensing/constants.js b/packages/client/src/licensing/constants.js deleted file mode 100644 index 57454bc37a..0000000000 --- a/packages/client/src/licensing/constants.js +++ /dev/null @@ -1,7 +0,0 @@ -export const PlanType = { - FREE: "free", - PRO: "pro", - TEAM: "team", - BUSINESS: "business", - ENTERPRISE: "enterprise", -} diff --git a/packages/client/src/licensing/utils.js b/packages/client/src/licensing/utils.js index efe1839ecb..effed6867f 100644 --- a/packages/client/src/licensing/utils.js +++ b/packages/client/src/licensing/utils.js @@ -1,6 +1,6 @@ import { authStore } from "../stores/auth.js" import { get } from "svelte/store" -import { PlanType } from "./constants" +import { Constants } from "@budibase/frontend-core" const getLicense = () => { const user = get(authStore) @@ -12,7 +12,7 @@ const getLicense = () => { export const isFreePlan = () => { const license = getLicense() if (license) { - return license.plan.type === PlanType.FREE + return license.plan.type === Constants.PlanType.FREE } else { // safety net - no license means free plan return true diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index b98282b9bd..4f1d618840 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", + "@budibase/bbui": "2.0.24-alpha.0", "lodash": "^4.17.21", "svelte": "^3.46.2" } diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index eb7a8849a5..9a5acf8a9b 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -98,6 +98,7 @@ export const BuilderRoleDescriptions = [ export const PlanType = { FREE: "free", TEAM: "team", + PRO: "pro", BUSINESS: "business", ENTERPRISE: "enterprise", } diff --git a/packages/frontend-core/src/fetch/DataFetch.js b/packages/frontend-core/src/fetch/DataFetch.js index a3cc1c231c..31007121f1 100644 --- a/packages/frontend-core/src/fetch/DataFetch.js +++ b/packages/frontend-core/src/fetch/DataFetch.js @@ -14,52 +14,52 @@ import { convertJSONSchemaToTableSchema } from "../utils/json" * For other types of datasource, this class is overridden and extended. */ export default class DataFetch { - // API client - API = null - - // Feature flags - featureStore = writable({ - supportsSearch: false, - supportsSort: false, - supportsPagination: false, - }) - - // Config - options = { - datasource: null, - limit: 10, - - // Search config - filter: null, - query: null, - - // Sorting config - sortColumn: null, - sortOrder: "ascending", - sortType: null, - - // Pagination config - paginate: true, - } - - // State of the fetch - store = writable({ - rows: [], - info: null, - schema: null, - loading: false, - loaded: false, - query: null, - pageNumber: 0, - cursor: null, - cursors: [], - }) - /** * Constructs a new DataFetch instance. * @param opts the fetch options */ constructor(opts) { + // API client + this.API = null + + // Feature flags + this.featureStore = writable({ + supportsSearch: false, + supportsSort: false, + supportsPagination: false, + }) + + // Config + this.options = { + datasource: null, + limit: 10, + + // Search config + filter: null, + query: null, + + // Sorting config + sortColumn: null, + sortOrder: "ascending", + sortType: null, + + // Pagination config + paginate: true, + } + + // State of the fetch + this.store = writable({ + rows: [], + info: null, + schema: null, + loading: false, + loaded: false, + query: null, + pageNumber: 0, + cursor: null, + cursors: [], + }) + // Merge options with their default values this.API = opts?.API this.options = { diff --git a/packages/frontend-core/src/utils/lucene.js b/packages/frontend-core/src/utils/lucene.js index 1221e20664..774ddbd834 100644 --- a/packages/frontend-core/src/utils/lucene.js +++ b/packages/frontend-core/src/utils/lucene.js @@ -121,7 +121,12 @@ export const buildLuceneQuery = filter => { query.allOr = true return } - if (type === "datetime" && !isHbs) { + if ( + type === "datetime" && + !isHbs && + operator !== "empty" && + operator !== "notEmpty" + ) { // Ensure date value is a valid date and parse into correct format if (!value) { return diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 992b391dea..403fcf7cf5 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/sdk", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "description": "Budibase Public API SDK", "author": "Budibase", "license": "MPL-2.0", diff --git a/packages/server/package.json b/packages/server/package.json index 1997a3e1aa..8a5929aa55 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "2.0.14-alpha.1", + "version": "2.0.24-alpha.0", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -77,11 +77,11 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "2.0.14-alpha.1", - "@budibase/client": "2.0.14-alpha.1", - "@budibase/pro": "2.0.14-alpha.0", - "@budibase/string-templates": "2.0.14-alpha.1", - "@budibase/types": "2.0.14-alpha.1", + "@budibase/backend-core": "2.0.24-alpha.0", + "@budibase/client": "2.0.24-alpha.0", + "@budibase/pro": "2.0.23", + "@budibase/string-templates": "2.0.24-alpha.0", + "@budibase/types": "2.0.24-alpha.0", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index d7e2a8f0bd..9dde91b348 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -50,6 +50,7 @@ import { errors, events, migrations } from "@budibase/backend-core" import { App, Layout, Screen, MigrationType } from "@budibase/types" import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" import { groups } from "@budibase/pro" +import { enrichPluginURLs } from "../../utilities/plugins" const URL_REGEX_SLASH = /\/|\\/g @@ -208,10 +209,13 @@ export const fetchAppDefinition = async (ctx: any) => { export const fetchAppPackage = async (ctx: any) => { const db = context.getAppDB() - const application = await db.get(DocumentType.APP_METADATA) + let application = await db.get(DocumentType.APP_METADATA) const layouts = await getLayouts() let screens = await getScreens() + // Enrich plugin URLs + application.usedPlugins = enrichPluginURLs(application.usedPlugins) + // Only filter screens if the user is not a builder if (!(ctx.user.builder && ctx.user.builder.global)) { const userRoleId = getUserRoleId(ctx) diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 4fafaa546c..af52be8e26 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -68,6 +68,7 @@ exports.buildSchemaFromDb = async function (ctx) { datasource.entities = tables } + setDefaultDisplayColumns(datasource) const dbResp = await db.put(datasource) datasource._rev = dbResp.rev @@ -78,6 +79,24 @@ exports.buildSchemaFromDb = async function (ctx) { ctx.body = response } +/** + * Make sure all datasource entities have a display name selected + */ +const setDefaultDisplayColumns = datasource => { + // + for (let entity of Object.values(datasource.entities)) { + if (entity.primaryDisplay) { + continue + } + const notAutoColumn = Object.values(entity.schema).find( + schema => !schema.autocolumn + ) + if (notAutoColumn) { + entity.primaryDisplay = notAutoColumn.name + } + } +} + /** * Check for variables that have been updated or removed and invalidate them. */ @@ -155,6 +174,7 @@ exports.save = async function (ctx) { const { tables, error } = await buildSchemaHelper(datasource) schemaError = error datasource.entities = tables + setDefaultDisplayColumns(datasource) } const dbResp = await db.put(datasource) @@ -238,19 +258,6 @@ const buildSchemaHelper = async datasource => { const connector = new Connector(datasource.config) await connector.buildSchema(datasource._id, datasource.entities) - // make sure they all have a display name selected - for (let entity of Object.values(datasource.entities ?? {})) { - if (entity.primaryDisplay) { - continue - } - const notAutoColumn = Object.values(entity.schema).find( - schema => !schema.autocolumn - ) - if (notAutoColumn) { - entity.primaryDisplay = notAutoColumn.name - } - } - const errors = connector.schemaErrors let error = null if (errors && Object.keys(errors).length > 0) { diff --git a/packages/server/src/api/controllers/public/rows.ts b/packages/server/src/api/controllers/public/rows.ts index 4daccd9542..67059ec2f5 100644 --- a/packages/server/src/api/controllers/public/rows.ts +++ b/packages/server/src/api/controllers/public/rows.ts @@ -52,14 +52,19 @@ export async function read(ctx: any, next: any) { } export async function update(ctx: any, next: any) { - ctx.request.body = await addRev(fixRow(ctx.request.body, ctx.params)) + const { tableId } = ctx.params + ctx.request.body = await addRev(fixRow(ctx.request.body, ctx.params), tableId) await rowController.save(ctx) await next() } export async function destroy(ctx: any, next: any) { + const { tableId } = ctx.params // set the body as expected, with the _id and _rev fields - ctx.request.body = await addRev(fixRow({ _id: ctx.params.rowId }, ctx.params)) + ctx.request.body = await addRev( + fixRow({ _id: ctx.params.rowId }, ctx.params), + tableId + ) await rowController.destroy(ctx) // destroy controller doesn't currently return the row as the body, need to adjust this // in the public API to be correct diff --git a/packages/server/src/api/controllers/public/utils.ts b/packages/server/src/api/controllers/public/utils.ts index d86eced9ba..6909db9628 100644 --- a/packages/server/src/api/controllers/public/utils.ts +++ b/packages/server/src/api/controllers/public/utils.ts @@ -22,7 +22,7 @@ export async function addRev( } /** - * Performs a case insensitive search on the provided documents, using the + * Performs a case in-sensitive search on the provided documents, using the * provided key and value. This will be a string based search, using the * startsWith function. */ diff --git a/packages/server/src/api/controllers/query/index.ts b/packages/server/src/api/controllers/query/index.ts index f69653b720..5c09a2f3b6 100644 --- a/packages/server/src/api/controllers/query/index.ts +++ b/packages/server/src/api/controllers/query/index.ts @@ -240,6 +240,10 @@ async function execute( const { rows, pagination, extra } = await quotas.addQuery(runFn, { datasourceId: datasource._id, }) + // remove the raw from execution incase transformer being used to hide data + if (extra?.raw) { + delete extra.raw + } if (opts && opts.rowsOnly) { ctx.body = rows } else { diff --git a/packages/server/src/api/controllers/row/internalSearch.js b/packages/server/src/api/controllers/row/internalSearch.js index 3cf60fbcc0..051a55aa9f 100644 --- a/packages/server/src/api/controllers/row/internalSearch.js +++ b/packages/server/src/api/controllers/row/internalSearch.js @@ -145,7 +145,7 @@ class QueryBuilder { * @param options The preprocess options * @returns {string|*} */ - preprocess(value, { escape, lowercase, wrap } = {}) { + preprocess(value, { escape, lowercase, wrap, type } = {}) { const hasVersion = !!this.version // Determine if type needs wrapped const originalType = typeof value @@ -157,8 +157,11 @@ class QueryBuilder { if (escape && originalType === "string") { value = `${value}`.replace(/[ #+\-&|!(){}\]^"~*?:\\]/g, "\\$&") } + // Wrap in quotes - if (hasVersion && wrap) { + if (originalType === "string" && !isNaN(value) && !type) { + value = `"${value}"` + } else if (hasVersion && wrap) { value = originalType === "number" ? value : `"${value}"` } return value @@ -253,6 +256,7 @@ class QueryBuilder { value = builder.preprocess(value, { escape: true, lowercase: true, + type: "string", }) return `${key}:${value}*` }) @@ -281,6 +285,7 @@ class QueryBuilder { value = builder.preprocess(value, { escape: true, lowercase: true, + type: "fuzzy", }) return `${key}:${value}~` }) diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 80116a21f5..08213c2cf8 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -1,3 +1,5 @@ +import { enrichPluginURLs } from "../../../utilities/plugins" + require("svelte/register") const send = require("koa-send") @@ -107,12 +109,13 @@ export const serveApp = async function (ctx: any) { if (!env.isJest()) { const App = require("./templates/BudibaseApp.svelte").default + const plugins = enrichPluginURLs(appInfo.usedPlugins) const { head, html, css } = App.render({ title: appInfo.name, production: env.isProd(), appId, clientLibPath: clientLibraryPath(appId, appInfo.version, ctx), - usedPlugins: appInfo.usedPlugins, + usedPlugins: plugins, }) const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`) diff --git a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte index 4bf54f2c91..227f980896 100644 --- a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte +++ b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte @@ -88,9 +88,7 @@ {#if usedPlugins?.length} {#each usedPlugins as plugin} - + {/each} {/if}