diff --git a/lerna.json b/lerna.json index 38da724e2c..6718146315 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.27-alpha.22", + "version": "1.0.44-alpha.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 0813f2e468..caa922141a 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.27-alpha.22", + "version": "1.0.44-alpha.0", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 20ef5765b6..64404fd4a2 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": "1.0.27-alpha.22", + "version": "1.0.44-alpha.0", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index 96970efb56..5dbdb4bcd6 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.0.27-alpha.22", + "version": "1.0.44-alpha.0", "license": "GPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^1.0.27-alpha.22", - "@budibase/client": "^1.0.27-alpha.22", + "@budibase/bbui": "^1.0.44-alpha.0", + "@budibase/client": "^1.0.44-alpha.0", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^1.0.27-alpha.22", + "@budibase/string-templates": "^1.0.44-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/api.js b/packages/builder/src/builderStore/api.js index 4bcb9b74c6..897d3a74db 100644 --- a/packages/builder/src/builderStore/api.js +++ b/packages/builder/src/builderStore/api.js @@ -13,6 +13,9 @@ const apiCall = headers, }) if (resp.status === 403) { + if (url.includes("/api/templates")) { + return { json: () => [] } + } removeCookie(Cookies.Auth) // reload after removing cookie, go to login if (!url.includes("self") && !url.includes("login")) { diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte index d9425c961d..8d7f50a527 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte @@ -14,6 +14,7 @@ import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte" import { generate } from "shortid" import { getValidOperatorsForType, OperatorOptions } from "constants/lucene" + import { getFields } from "helpers/searchFields" export let schemaFields export let filters = [] @@ -21,11 +22,8 @@ export let panel = ClientBindingPanel export let allowBindings = true - const BannedTypes = ["link", "attachment", "formula", "json", "jsonarray"] - - $: fieldOptions = (schemaFields ?? []) - .filter(field => !BannedTypes.includes(field.type)) - .map(field => field.name) + $: enrichedSchemaFields = getFields(schemaFields || []) + $: fieldOptions = enrichedSchemaFields.map(field => field.name) || [] $: valueTypeOptions = allowBindings ? ["Value", "Binding"] : ["Value"] const addFilter = () => { @@ -53,7 +51,7 @@ const onFieldChange = (expression, field) => { // Update the field type - expression.type = schemaFields.find(x => x.name === field)?.type + expression.type = enrichedSchemaFields.find(x => x.name === field)?.type // Ensure a valid operator is set const validOperators = getValidOperatorsForType(expression.type).map( @@ -85,7 +83,7 @@ } const getFieldOptions = field => { - const schema = schemaFields.find(x => x.name === field) + const schema = enrichedSchemaFields.find(x => x.name === field) return schema?.constraints?.inclusion || [] } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/SearchFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/SearchFieldSelect.svelte new file mode 100644 index 0000000000..474fbc676c --- /dev/null +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/SearchFieldSelect.svelte @@ -0,0 +1,47 @@ + + + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js index e752240302..5e27cdce28 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js @@ -7,6 +7,7 @@ import ColorPicker from "./ColorPicker.svelte" import { IconSelect } from "./IconSelect" import FieldSelect from "./FieldSelect.svelte" import MultiFieldSelect from "./MultiFieldSelect.svelte" +import SearchFieldSelect from "./SearchFieldSelect.svelte" import SchemaSelect from "./SchemaSelect.svelte" import SectionSelect from "./SectionSelect.svelte" import NavigationEditor from "./NavigationEditor/NavigationEditor.svelte" @@ -30,6 +31,7 @@ const componentMap = { icon: IconSelect, field: FieldSelect, multifield: MultiFieldSelect, + searchfield: SearchFieldSelect, options: OptionsEditor, schema: SchemaSelect, section: SectionSelect, diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index c5fb294f80..c1eea5b0ef 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -229,3 +229,11 @@ export const PaginationLocations = [ { label: "Query parameters", value: "query" }, { label: "Request body", value: "body" }, ] + +export const BannedSearchTypes = [ + "link", + "attachment", + "formula", + "json", + "jsonarray", +] diff --git a/packages/builder/src/helpers/searchFields.js b/packages/builder/src/helpers/searchFields.js new file mode 100644 index 0000000000..650e04a680 --- /dev/null +++ b/packages/builder/src/helpers/searchFields.js @@ -0,0 +1,31 @@ +import { tables } from "../stores/backend" +import { BannedSearchTypes } from "../constants/backend" +import { get } from "svelte/store" + +export function getTableFields(linkField) { + const table = get(tables).list.find(table => table._id === linkField.tableId) + if (!table || !table.sql) { + return [] + } + const linkFields = getFields(Object.values(table.schema), { + allowLinks: false, + }) + return linkFields.map(field => ({ + ...field, + name: `${table.name}.${field.name}`, + })) +} + +export function getFields(fields, { allowLinks } = { allowLinks: true }) { + let filteredFields = fields.filter( + field => !BannedSearchTypes.includes(field.type) + ) + if (allowLinks) { + const linkFields = fields.filter(field => field.type === "link") + for (let linkField of linkFields) { + // only allow one depth of SQL relationship filtering + filteredFields = filteredFields.concat(getTableFields(linkField)) + } + } + return filteredFields +} diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index c85ad79d45..ac10b5317f 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -274,6 +274,9 @@ onMount(async () => { await apps.load() await templates.load() + if ($templates?.length === 0) { + notifications.error("There was a problem loading quick start templates.") + } // if the portal is loaded from an external URL with a template param const initInfo = await auth.getInitInfo() if (initInfo?.init_template) { diff --git a/packages/cli/package.json b/packages/cli/package.json index f4a0773c6d..6069253a06 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.27-alpha.22", + "version": "1.0.44-alpha.0", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/client/manifest.json b/packages/client/manifest.json index dfe9ae5a91..9431129fa0 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2811,7 +2811,7 @@ "key": "dataSource" }, { - "type": "multifield", + "type": "searchfield", "label": "Search Columns", "key": "searchColumns", "placeholder": "Choose search columns" @@ -2958,7 +2958,7 @@ "key": "dataSource" }, { - "type": "multifield", + "type": "searchfield", "label": "Search Columns", "key": "searchColumns", "placeholder": "Choose search columns" diff --git a/packages/client/package.json b/packages/client/package.json index 5a67c4dc29..cd77970413 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.27-alpha.22", + "version": "1.0.44-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": "^1.0.27-alpha.22", + "@budibase/bbui": "^1.0.44-alpha.0", "@budibase/standard-components": "^0.9.139", - "@budibase/string-templates": "^1.0.27-alpha.22", + "@budibase/string-templates": "^1.0.44-alpha.0", "regexparam": "^1.3.0", "shortid": "^2.2.15", "svelte-spa-router": "^3.0.5" diff --git a/packages/client/src/components/app/DataProvider.svelte b/packages/client/src/components/app/DataProvider.svelte index 71c54db4da..2341eef3b2 100644 --- a/packages/client/src/components/app/DataProvider.svelte +++ b/packages/client/src/components/app/DataProvider.svelte @@ -67,6 +67,7 @@ $: dataContext = { rows: $fetch.rows, info: $fetch.info, + datasource: dataSource || {}, schema: $fetch.schema, rowsLength: $fetch.rows.length, diff --git a/packages/client/src/components/app/blocks/CardsBlock.svelte b/packages/client/src/components/app/blocks/CardsBlock.svelte index 301b440ab3..f0892ca447 100644 --- a/packages/client/src/components/app/blocks/CardsBlock.svelte +++ b/packages/client/src/components/app/blocks/CardsBlock.svelte @@ -71,12 +71,13 @@ const enrichFilter = (filter, columns, formId) => { let enrichedFilter = [...(filter || [])] columns?.forEach(column => { + const safePath = column.name.split(".").map(safe).join(".") enrichedFilter.push({ field: column.name, operator: column.type === "string" ? "string" : "equal", type: column.type === "string" ? "string" : "number", valueType: "Binding", - value: `{{ [${formId}].[${column.name}] }}`, + value: `{{ ${safe(formId)}.${safePath} }}`, }) }) return enrichedFilter @@ -112,7 +113,9 @@ // Load the datasource schema so we can determine column types const fetchSchema = async dataSource => { if (dataSource) { - schema = await fetchDatasourceSchema(dataSource) + schema = await fetchDatasourceSchema(dataSource, { + enrichRelationships: true, + }) } schemaLoaded = true } diff --git a/packages/client/src/components/app/blocks/TableBlock.svelte b/packages/client/src/components/app/blocks/TableBlock.svelte index 936a8d1734..3de4497731 100644 --- a/packages/client/src/components/app/blocks/TableBlock.svelte +++ b/packages/client/src/components/app/blocks/TableBlock.svelte @@ -59,12 +59,13 @@ const enrichFilter = (filter, columns, formId) => { let enrichedFilter = [...(filter || [])] columns?.forEach(column => { + const safePath = column.name.split(".").map(safe).join(".") enrichedFilter.push({ field: column.name, operator: column.type === "string" ? "string" : "equal", type: column.type === "string" ? "string" : "number", valueType: "Binding", - value: `{{ ${safe(formId)}.${safe(column.name)} }}`, + value: `{{ ${safe(formId)}.${safePath} }}`, }) }) return enrichedFilter @@ -90,7 +91,9 @@ // Load the datasource schema so we can determine column types const fetchSchema = async dataSource => { if (dataSource) { - schema = await fetchDatasourceSchema(dataSource) + schema = await fetchDatasourceSchema(dataSource, { + enrichRelationships: true, + }) } schemaLoaded = true } diff --git a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte index 20909d011c..6a114afe3e 100644 --- a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte +++ b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte @@ -11,11 +11,14 @@ export let size = "M" const component = getContext("component") - const { builderStore, ActionTypes, getAction } = getContext("sdk") + const { builderStore, ActionTypes, getAction, fetchDatasourceSchema } = + getContext("sdk") let modal let tmpFilters = [] let filters = [] + let schemaLoaded = false, + schema $: dataProviderId = dataProvider?.id $: addExtension = getAction( @@ -26,7 +29,7 @@ dataProviderId, ActionTypes.RemoveDataProviderQueryExtension ) - $: schema = dataProvider?.schema + $: fetchSchema(dataProvider || {}) $: schemaFields = getSchemaFields(schema, allowedFields) // Add query extension to data provider @@ -39,7 +42,20 @@ } } - const getSchemaFields = (schema, allowedFields) => { + async function fetchSchema(dataProvider) { + const datasource = dataProvider?.datasource + if (datasource) { + schema = await fetchDatasourceSchema(datasource, { + enrichRelationships: true, + }) + } + schemaLoaded = true + } + + function getSchemaFields(schema, allowedFields) { + if (!schemaLoaded) { + return {} + } let clonedSchema = {} if (!allowedFields?.length) { clonedSchema = schema @@ -68,18 +84,20 @@ }) -