Merge branch 'develop' into feature/user-column-type
This commit is contained in:
commit
f4542283f5
|
@ -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 }}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.10.12-alpha.14",
|
||||
"version": "2.10.12-alpha.19",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -96,8 +96,8 @@
|
|||
{disabled}
|
||||
{readonly}
|
||||
{id}
|
||||
value={value || ""}
|
||||
placeholder={placeholder || ""}
|
||||
value={value ?? ""}
|
||||
placeholder={placeholder ?? ""}
|
||||
on:click
|
||||
on:blur
|
||||
on:focus
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 @@
|
|||
<DatePicker bind:value={editableColumn.constraints.datetime.latest} />
|
||||
</div>
|
||||
</div>
|
||||
{#if datasource?.source !== "ORACLE" && datasource?.source !== "SQL_SERVER"}
|
||||
{#if datasource?.source !== "ORACLE" && datasource?.source !== "SQL_SERVER" && !editableColumn.dateOnly}
|
||||
<div>
|
||||
<div class="row">
|
||||
<Label>Time zones</Label>
|
||||
|
@ -582,6 +593,7 @@
|
|||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<Toggle bind:value={editableColumn.dateOnly} text="Date only" />
|
||||
{:else if editableColumn.type === "number" && !editableColumn.autocolumn}
|
||||
<div class="split-label">
|
||||
<div class="label-length">
|
||||
|
@ -608,30 +620,15 @@
|
|||
</div>
|
||||
</div>
|
||||
{:else if editableColumn.type === "link"}
|
||||
<Select
|
||||
label="Table"
|
||||
disabled={linkEditDisabled}
|
||||
bind:value={editableColumn.tableId}
|
||||
options={tableOptions}
|
||||
getOptionLabel={table => table.name}
|
||||
getOptionValue={table => table._id}
|
||||
/>
|
||||
{#if relationshipOptions && relationshipOptions.length > 0}
|
||||
<RadioGroup
|
||||
disabled={linkEditDisabled}
|
||||
label="Define the relationship"
|
||||
bind:value={editableColumn.relationshipType}
|
||||
options={relationshipOptions}
|
||||
getOptionLabel={option => option.name}
|
||||
getOptionValue={option => option.value}
|
||||
getOptionTitle={option => option.alt}
|
||||
/>
|
||||
{/if}
|
||||
<Input
|
||||
disabled={linkEditDisabled}
|
||||
label={`Column name in other table`}
|
||||
bind:value={editableColumn.fieldName}
|
||||
error={errors.relatedName}
|
||||
<RelationshipSelector
|
||||
bind:relationshipPart1
|
||||
bind:relationshipPart2
|
||||
bind:relationshipTableIdPrimary={table.name}
|
||||
bind:relationshipTableIdSecondary
|
||||
bind:editableColumn
|
||||
{linkEditDisabled}
|
||||
{tableOptions}
|
||||
{errors}
|
||||
/>
|
||||
{:else if editableColumn.type === FORMULA_TYPE}
|
||||
{#if !table.sql}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<script>
|
||||
import { Select, Input } from "@budibase/bbui"
|
||||
import { PrettyRelationshipDefinitions } from "constants/backend"
|
||||
|
||||
export let relationshipPart1
|
||||
export let relationshipPart2
|
||||
export let relationshipTableIdPrimary
|
||||
export let relationshipTableIdSecondary
|
||||
export let editableColumn
|
||||
export let linkEditDisabled
|
||||
export let tableOptions
|
||||
export let errors
|
||||
</script>
|
||||
|
||||
<div class="relationship-container">
|
||||
<div class="relationship-part">
|
||||
<Select
|
||||
disabled={linkEditDisabled}
|
||||
bind:value={relationshipPart1}
|
||||
options={Object.values(PrettyRelationshipDefinitions)}
|
||||
/>
|
||||
</div>
|
||||
<div class="relationship-label">in</div>
|
||||
<div class="relationship-part">
|
||||
<Select
|
||||
disabled
|
||||
options={[relationshipTableIdPrimary]}
|
||||
value={relationshipTableIdPrimary}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relationship-container">
|
||||
<div class="relationship-part">
|
||||
<Select
|
||||
disabled={linkEditDisabled}
|
||||
bind:value={relationshipPart2}
|
||||
options={Object.values(PrettyRelationshipDefinitions)}
|
||||
getOptionLabel={option => "To " + option.toLowerCase()}
|
||||
/>
|
||||
</div>
|
||||
<div class="relationship-label">in</div>
|
||||
<div class="relationship-part">
|
||||
<Select
|
||||
disabled={linkEditDisabled}
|
||||
bind:value={relationshipTableIdSecondary}
|
||||
options={tableOptions}
|
||||
getOptionLabel={table => table.name}
|
||||
getOptionValue={table => table._id}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Input
|
||||
disabled={linkEditDisabled}
|
||||
label={`Column name in other table`}
|
||||
bind:value={editableColumn.fieldName}
|
||||
error={errors.relatedName}
|
||||
/>
|
||||
|
||||
<style>
|
||||
.relationship-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.relationship-part {
|
||||
flex-basis: 60%;
|
||||
}
|
||||
</style>
|
|
@ -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,
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
on:focus={() => (active = true)}
|
||||
on:blur={() => (active = false)}
|
||||
{type}
|
||||
value={value || ""}
|
||||
value={value ?? ""}
|
||||
on:change={handleChange}
|
||||
spellcheck="false"
|
||||
/>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue