diff --git a/.github/workflows/close-featurebranch.yml b/.github/workflows/close-featurebranch.yml new file mode 100644 index 0000000000..0ec3b43598 --- /dev/null +++ b/.github/workflows/close-featurebranch.yml @@ -0,0 +1,21 @@ +name: close-featurebranch + +on: + pull_request: + types: [closed] + branches: + - develop + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: passeidireto/trigger-external-workflow-action@main + env: + PAYLOAD_BRANCH: ${{ github.head_ref }} + PAYLOAD_PR_NUMBER: ${{ github.ref }} + with: + repository: budibase/budibase-deploys + event: featurebranch-qa-close + github_pat: ${{ secrets.GH_ACCESS_TOKEN }} diff --git a/lerna.json b/lerna.json index b748b3fa36..c56776183c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.12-alpha.14", + "version": "2.10.12-alpha.19", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/bbui/src/Form/Core/TextField.svelte b/packages/bbui/src/Form/Core/TextField.svelte index b3b0865c64..7afd8f86c3 100644 --- a/packages/bbui/src/Form/Core/TextField.svelte +++ b/packages/bbui/src/Form/Core/TextField.svelte @@ -96,8 +96,8 @@ {disabled} {readonly} {id} - value={value || ""} - placeholder={placeholder || ""} + value={value ?? ""} + placeholder={placeholder ?? ""} on:click on:blur on:focus diff --git a/packages/builder/src/analytics/constants.js b/packages/builder/src/analytics/constants.js index 1bb8517a2b..5264e16abc 100644 --- a/packages/builder/src/analytics/constants.js +++ b/packages/builder/src/analytics/constants.js @@ -2,6 +2,7 @@ export const Events = { COMPONENT_CREATED: "component:created", COMPONENT_UPDATED: "component:updated", APP_VIEW_PUBLISHED: "app:view_published", + BLOCK_EJECTED: "block:ejected", } export const EventSource = { diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 13b28a3572..6c029ddff3 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -1287,6 +1287,11 @@ export const getFrontendStore = () => { return false } + // Log event + analytics.captureEvent(Events.BLOCK_EJECTED, { + block: block._component, + }) + // Attach block children back into ejected definition, using the // _containsSlot flag to know where to insert them const slotContainer = findAllMatchingComponents( diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 0384e7dbea..bea7fb1657 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -5,7 +5,6 @@ Label, Select, Toggle, - RadioGroup, Icon, DatePicker, Modal, @@ -26,16 +25,17 @@ ALLOWABLE_STRING_TYPES, ALLOWABLE_NUMBER_TYPES, SWITCHABLE_TYPES, + PrettyRelationshipDefinitions, } from "constants/backend" import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils" import ConfirmDialog from "components/common/ConfirmDialog.svelte" - import { truncate } from "lodash" import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" import { getBindings } from "components/backend/DataTable/formula" import JSONSchemaModal from "./JSONSchemaModal.svelte" import { ValidColumnNameRegex } from "@budibase/shared-core" import { admin } from "stores/portal" import { FieldSubtype, FieldType } from "@budibase/types" + import RelationshipSelector from "components/common/RelationshipSelector.svelte" const AUTO_TYPE = "auto" const FORMULA_TYPE = FIELDS.FORMULA.type @@ -64,6 +64,10 @@ let indexes = [...($tables.selected.indexes || [])] let isCreating = undefined + let relationshipPart1 = PrettyRelationshipDefinitions.Many + let relationshipPart2 = PrettyRelationshipDefinitions.One + + let relationshipTableIdSecondary = null let table = $tables.selected let confirmDeleteDialog let savingColumn @@ -111,6 +115,33 @@ editableColumn.constraints.presence = { allowEmpty: false } } + let relationshipMap = { + [RelationshipType.MANY_TO_ONE]: { + part1: PrettyRelationshipDefinitions.MANY, + part2: PrettyRelationshipDefinitions.ONE, + }, + [RelationshipType.MANY_TO_MANY]: { + part1: PrettyRelationshipDefinitions.MANY, + part2: PrettyRelationshipDefinitions.MANY, + }, + [RelationshipType.ONE_TO_MANY]: { + part1: PrettyRelationshipDefinitions.ONE, + part2: PrettyRelationshipDefinitions.MANY, + }, + } + + $: { + if (editableColumn.type === LINK_TYPE) { + // Determine the relationship type based on the selected values of both parts + editableColumn.relationshipType = Object.entries(relationshipMap).find( + ([_, parts]) => + parts.part1 === relationshipPart1 && parts.part2 === relationshipPart2 + )?.[0] + // Set the tableId based on the selected table + editableColumn.tableId = relationshipTableIdSecondary + } + } + const initialiseField = (field, savingColumn) => { isCreating = !field @@ -147,6 +178,16 @@ } allowedTypes = getAllowedTypes() + + if (editableColumn.type === LINK_TYPE && editableColumn.tableId) { + relationshipTableIdSecondary = editableColumn.tableId + if (editableColumn.relationshipType in relationshipMap) { + const { part1, part2 } = + relationshipMap[editableColumn.relationshipType] + relationshipPart1 = part1 + relationshipPart2 = part2 + } + } } $: initialiseField(field, savingColumn) @@ -206,7 +247,6 @@ !uneditable && editableColumn?.type !== AUTO_TYPE && !editableColumn.autocolumn - $: relationshipOptions = getRelationshipOptions(editableColumn) $: external = table.type === "external" // in the case of internal tables the sourceId will just be undefined $: tableOptions = $tables.list.filter( @@ -345,35 +385,6 @@ return match ? parseInt(match[1]) : 0 } - function getRelationshipOptions(field) { - if (!field || !field.tableId) { - return null - } - const linkTable = tableOptions?.find(table => table._id === field.tableId) - if (!linkTable) { - return null - } - const thisName = truncate(table.name, { length: 14 }), - linkName = truncate(linkTable.name, { length: 14 }) - return [ - { - name: `Many ${thisName} rows → many ${linkName} rows`, - alt: `Many ${table.name} rows → many ${linkTable.name} rows`, - value: RelationshipType.MANY_TO_MANY, - }, - { - name: `One ${linkName} row → many ${thisName} rows`, - alt: `One ${linkTable.name} rows → many ${table.name} rows`, - value: RelationshipType.ONE_TO_MANY, - }, - { - name: `One ${thisName} row → many ${linkName} rows`, - alt: `One ${table.name} rows → many ${linkTable.name} rows`, - value: RelationshipType.MANY_TO_ONE, - }, - ] - } - function getAllowedTypes() { if ( originalName && @@ -562,7 +573,7 @@ - {#if datasource?.source !== "ORACLE" && datasource?.source !== "SQL_SERVER"} + {#if datasource?.source !== "ORACLE" && datasource?.source !== "SQL_SERVER" && !editableColumn.dateOnly}
@@ -582,6 +593,7 @@ />
{/if} + {:else if editableColumn.type === "number" && !editableColumn.autocolumn}
@@ -608,30 +620,15 @@
{:else if editableColumn.type === "link"} - {:else if editableColumn.type === FORMULA_TYPE} {#if !table.sql} diff --git a/packages/builder/src/components/common/RelationshipSelector.svelte b/packages/builder/src/components/common/RelationshipSelector.svelte new file mode 100644 index 0000000000..c050323bb6 --- /dev/null +++ b/packages/builder/src/components/common/RelationshipSelector.svelte @@ -0,0 +1,69 @@ + + +
+
+ +
+
+
+
+ table.name} + getOptionValue={table => table._id} + /> +
+
+ + + diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index fbcab7fd8b..047152eeed 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -176,6 +176,11 @@ export const RelationshipType = { MANY_TO_ONE: "many-to-one", } +export const PrettyRelationshipDefinitions = { + MANY: "Many rows", + ONE: "One row", +} + export const ALLOWABLE_STRING_OPTIONS = [ FIELDS.STRING, FIELDS.OPTIONS, diff --git a/packages/frontend-core/src/components/grid/cells/TextCell.svelte b/packages/frontend-core/src/components/grid/cells/TextCell.svelte index 04485a6b50..d2ee0189fe 100644 --- a/packages/frontend-core/src/components/grid/cells/TextCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/TextCell.svelte @@ -45,7 +45,7 @@ on:focus={() => (active = true)} on:blur={() => (active = false)} {type} - value={value || ""} + value={value ?? ""} on:change={handleChange} spellcheck="false" /> diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index 2c4428599b..e5b2a82311 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -305,12 +305,7 @@ export class ExternalRequest { manyRelationships: ManyRelationship[] = [] for (let [key, field] of Object.entries(table.schema)) { // if set already, or not set just skip it - if (row[key] == null || newRow[key] || !isEditableColumn(field)) { - continue - } - // if its an empty string then it means return the column to null (if possible) - if (row[key] === "") { - newRow[key] = null + if (row[key] === undefined || newRow[key] || !isEditableColumn(field)) { continue } // parse floats/numbers