diff --git a/.github/workflows/close-featurebranch.yml b/.github/workflows/close-featurebranch.yml index 0ec3b43598..5f232b2f26 100644 --- a/.github/workflows/close-featurebranch.yml +++ b/.github/workflows/close-featurebranch.yml @@ -14,7 +14,7 @@ jobs: - uses: passeidireto/trigger-external-workflow-action@main env: PAYLOAD_BRANCH: ${{ github.head_ref }} - PAYLOAD_PR_NUMBER: ${{ github.ref }} + PAYLOAD_PR_NUMBER: ${{ github.event.pull_request.number }} with: repository: budibase/budibase-deploys event: featurebranch-qa-close diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 3a32075a33..77afd9453b 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -138,6 +138,8 @@ To develop the Budibase platform you'll need [Docker](https://www.docker.com/) a `yarn setup` will check that all necessary components are installed and setup the repo for usage. +If you have access to the `@budibase/pro` submodule then please follow the Pro section of this guide before running the above command. + ##### Manual method The following commands can be executed to manually get Budibase up and running (assuming Docker/Docker Compose has been installed). @@ -146,6 +148,8 @@ The following commands can be executed to manually get Budibase up and running ( `yarn build` will build all budibase packages. +If you have access to the `@budibase/pro` submodule then please follow the Pro section of this guide before running the above commands. + #### 4. Running To run the budibase server and builder in dev mode (i.e. with live reloading): diff --git a/lerna.json b/lerna.json index f56bd4e540..9298ac99ba 100644 --- a/lerna.json +++ b/lerna.json @@ -19,4 +19,4 @@ "loadEnvFiles": false } } -} \ No newline at end of file +} diff --git a/packages/backend-core/src/plugin/utils.ts b/packages/backend-core/src/plugin/utils.ts index f73ded0659..8974a9f5a2 100644 --- a/packages/backend-core/src/plugin/utils.ts +++ b/packages/backend-core/src/plugin/utils.ts @@ -6,6 +6,7 @@ import { AutomationStepIdArray, AutomationIOType, AutomationCustomIOType, + DatasourceFeature, } from "@budibase/types" import joi from "joi" @@ -67,9 +68,27 @@ function validateDatasource(schema: any) { version: joi.string().optional(), schema: joi.object({ docs: joi.string(), + plus: joi.boolean().optional(), + isSQL: joi.boolean().optional(), + auth: joi + .object({ + type: joi.string().required(), + }) + .optional(), + features: joi + .object( + Object.fromEntries( + Object.values(DatasourceFeature).map(key => [ + key, + joi.boolean().optional(), + ]) + ) + ) + .optional(), + relationships: joi.boolean().optional(), + description: joi.string().required(), friendlyName: joi.string().required(), type: joi.string().allow(...DATASOURCE_TYPES), - description: joi.string().required(), datasource: joi.object().pattern(joi.string(), fieldValidator).required(), query: joi .object() diff --git a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte index 9e42dfecd9..abec380b46 100644 --- a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte +++ b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte @@ -13,6 +13,8 @@ import { Helpers } from "@budibase/bbui" import { RelationshipErrorChecker } from "./relationshipErrors" import { onMount } from "svelte" + import RelationshipSelector from "components/common/RelationshipSelector.svelte" + import { PrettyRelationshipDefinitions } from "constants/backend" export let save export let datasource @@ -22,16 +24,21 @@ export let selectedFromTable export let close - const relationshipTypes = [ - { - label: "One to Many", - value: RelationshipType.MANY_TO_ONE, + let relationshipMap = { + [RelationshipType.MANY_TO_MANY]: { + part1: PrettyRelationshipDefinitions.MANY, + part2: PrettyRelationshipDefinitions.MANY, }, - { - label: "Many to Many", - value: RelationshipType.MANY_TO_MANY, + [RelationshipType.MANY_TO_ONE]: { + part1: PrettyRelationshipDefinitions.ONE, + part2: PrettyRelationshipDefinitions.MANY, }, - ] + } + let relationshipOpts1 = Object.values(PrettyRelationshipDefinitions) + let relationshipOpts2 = Object.values(PrettyRelationshipDefinitions) + + let relationshipPart1 = PrettyRelationshipDefinitions.MANY + let relationshipPart2 = PrettyRelationshipDefinitions.ONE let originalFromColumnName = toRelationship.name, originalToColumnName = fromRelationship.name @@ -49,14 +56,32 @@ ) let errors = {} let fromPrimary, fromForeign, fromColumn, toColumn - let fromId, toId, throughId, throughToKey, throughFromKey + + let throughId, throughToKey, throughFromKey let isManyToMany, isManyToOne, relationshipType let hasValidated = false + $: fromId = null + $: toId = null + $: tableOptions = plusTables.map(table => ({ label: table.name, value: table._id, + name: table.name, + _id: table._id, })) + + $: { + // Determine the relationship type based on the selected values of both parts + relationshipType = Object.entries(relationshipMap).find( + ([_, parts]) => + parts.part1 === relationshipPart1 && parts.part2 === relationshipPart2 + )?.[0] + + changed(() => { + hasValidated = false + }) + } $: valid = getErrorCount(errors) === 0 && allRequiredAttributesSet(relationshipType) $: isManyToMany = relationshipType === RelationshipType.MANY_TO_MANY @@ -338,33 +363,34 @@ onConfirm={saveRelationship} disabled={!valid} > - - changed(() => { - const table = plusTables.find(tbl => tbl._id === e.detail) - fromColumn = table?.name || "" - fromPrimary = table?.primary?.[0] - })} - /> - {/if} + + + changed(() => { + const table = plusTables.find(tbl => tbl._id === e.detail) + fromColumn = table?.name || "" + fromPrimary = table?.primary?.[0] + })} + secondaryTableChanged={e => + changed(() => { + const table = plusTables.find(tbl => tbl._id === e.detail) + toColumn = table.name || "" + fromForeign = null + })} + /> + {#if isManyToOne && fromId} - changed(() => { - const table = plusTables.find(tbl => tbl._id === e.detail) - toColumn = table.name || "" - fromForeign = null - })} - /> {#if isManyToMany} table.name} getOptionValue={table => table._id} bind:value={relationshipTableIdPrimary} + on:change={primaryTableChanged} + bind:error={errors.fromTable} /> @@ -46,20 +52,24 @@ +{#if editableColumn} + +{/if}