Merge branch 'master' of github.com:Budibase/budibase into cheeks-fixes

This commit is contained in:
Andrew Kingston 2024-03-21 13:34:37 +00:00
commit aee5cf8886
10 changed files with 85 additions and 55 deletions

View File

@ -1,5 +1,5 @@
{
"version": "2.22.8",
"version": "2.22.9",
"npmClient": "yarn",
"packages": [
"packages/*",

View File

@ -34,7 +34,12 @@
import { getBindings } from "components/backend/DataTable/formula"
import JSONSchemaModal from "./JSONSchemaModal.svelte"
import { ValidColumnNameRegex } from "@budibase/shared-core"
import { FieldType, FieldSubtype, SourceName } from "@budibase/types"
import {
FieldType,
FieldSubtype,
SourceName,
FieldTypeSubtypes,
} from "@budibase/types"
import RelationshipSelector from "components/common/RelationshipSelector.svelte"
import { RowUtils } from "@budibase/frontend-core"
import ServerBindingPanel from "components/common/bindings/ServerBindingPanel.svelte"
@ -191,8 +196,10 @@
// don't make field IDs for auto types
if (type === AUTO_TYPE || autocolumn) {
return type.toUpperCase()
} else {
} else if (type === FieldType.BB_REFERENCE) {
return `${type}${subtype || ""}`.toUpperCase()
} else {
return type.toUpperCase()
}
}
@ -705,17 +712,14 @@
/>
{:else if editableColumn.type === FieldType.ATTACHMENT}
<Toggle
value={editableColumn.constraints?.length?.maximum !== 1}
value={editableColumn.subtype !== FieldTypeSubtypes.ATTACHMENT.SINGLE &&
// Checking config before the subtype was added
editableColumn.constraints?.length?.maximum !== 1}
on:change={e => {
if (!e.detail) {
editableColumn.constraints ??= { length: {} }
editableColumn.constraints.length ??= {}
editableColumn.constraints.length.maximum = 1
editableColumn.constraints.length.message =
"cannot contain multiple files"
editableColumn.subtype = FieldTypeSubtypes.ATTACHMENT.SINGLE
} else {
delete editableColumn.constraints?.length?.maximum
delete editableColumn.constraints?.length?.message
delete editableColumn.subtype
}
}}
thin

View File

@ -30,6 +30,8 @@ import {
View,
RelationshipFieldMetadata,
FieldType,
FieldTypeSubtypes,
AttachmentFieldMetadata,
} from "@budibase/types"
export async function clearColumns(table: Table, columnNames: string[]) {
@ -88,6 +90,27 @@ export async function checkForColumnUpdates(
// Update views
await checkForViewUpdates(updatedTable, deletedColumns, columnRename)
}
const changedAttachmentSubtypeColumns = Object.values(
updatedTable.schema
).filter(
(column): column is AttachmentFieldMetadata =>
column.type === FieldType.ATTACHMENT &&
column.subtype !== oldTable?.schema[column.name]?.subtype
)
for (const attachmentColumn of changedAttachmentSubtypeColumns) {
if (attachmentColumn.subtype === FieldTypeSubtypes.ATTACHMENT.SINGLE) {
attachmentColumn.constraints ??= { length: {} }
attachmentColumn.constraints.length ??= {}
attachmentColumn.constraints.length.maximum = 1
attachmentColumn.constraints.length.message =
"cannot contain multiple files"
} else {
delete attachmentColumn.constraints?.length?.maximum
delete attachmentColumn.constraints?.length?.message
}
}
return { rows: updatedRows, table: updatedTable }
}

View File

@ -60,7 +60,7 @@ function generateSchema(
schema.text(key)
break
case FieldType.BB_REFERENCE: {
const subtype = column.subtype as FieldSubtype
const subtype = column.subtype
switch (subtype) {
case FieldSubtype.USER:
schema.text(key)

View File

@ -67,7 +67,7 @@ export function searchInputMapping(table: Table, options: SearchParams) {
for (let [key, column] of Object.entries(table.schema)) {
switch (column.type) {
case FieldType.BB_REFERENCE: {
const subtype = column.subtype as FieldSubtype
const subtype = column.subtype
switch (subtype) {
case FieldSubtype.USER:
case FieldSubtype.USERS:

View File

@ -7,7 +7,7 @@ const ROW_PREFIX = DocumentType.ROW + SEPARATOR
export async function processInputBBReferences(
value: string | string[] | { _id: string } | { _id: string }[],
subtype: FieldSubtype
subtype: FieldSubtype.USER | FieldSubtype.USERS
): Promise<string | string[] | null> {
let referenceIds: string[] = []
@ -61,7 +61,7 @@ export async function processInputBBReferences(
export async function processOutputBBReferences(
value: string | string[],
subtype: FieldSubtype
subtype: FieldSubtype.USER | FieldSubtype.USERS
) {
if (value === null || value === undefined) {
// Already processed or nothing to process

View File

@ -6,7 +6,6 @@ import { TYPE_TRANSFORM_MAP } from "./map"
import {
FieldType,
AutoFieldSubType,
FieldSubtype,
Row,
RowAttachment,
Table,
@ -159,10 +158,7 @@ export async function inputProcessing(
}
if (field.type === FieldType.BB_REFERENCE && value) {
clonedRow[key] = await processInputBBReferences(
value,
field.subtype as FieldSubtype
)
clonedRow[key] = await processInputBBReferences(value, field.subtype)
}
}
@ -238,7 +234,7 @@ export async function outputProcessing<T extends Row[] | Row>(
for (let row of enriched) {
row[property] = await processOutputBBReferences(
row[property],
column.subtype as FieldSubtype
column.subtype
)
}
}

View File

@ -1,26 +1,14 @@
import { FieldType, FieldSubtype } from "@budibase/types"
import {
FieldType,
FieldSubtype,
TableSchema,
FieldSchema,
Row,
} from "@budibase/types"
import { ValidColumnNameRegex, utils } from "@budibase/shared-core"
import { db } from "@budibase/backend-core"
import { parseCsvExport } from "../api/controllers/view/exporters"
interface SchemaColumn {
readonly name: string
readonly type: FieldType
readonly subtype: FieldSubtype
readonly autocolumn?: boolean
readonly constraints?: {
presence: boolean
}
}
interface Schema {
readonly [index: string]: SchemaColumn
}
interface Row {
[index: string]: any
}
type Rows = Array<Row>
interface SchemaValidation {
@ -34,12 +22,10 @@ interface ValidationResults {
errors: Record<string, string>
}
export function isSchema(schema: any): schema is Schema {
export function isSchema(schema: any): schema is TableSchema {
return (
typeof schema === "object" &&
Object.values(schema).every(rawColumn => {
const column = rawColumn as SchemaColumn
Object.values<FieldSchema>(schema).every(column => {
return (
column !== null &&
typeof column === "object" &&
@ -54,7 +40,7 @@ export function isRows(rows: any): rows is Rows {
return Array.isArray(rows) && rows.every(row => typeof row === "object")
}
export function validate(rows: Rows, schema: Schema): ValidationResults {
export function validate(rows: Rows, schema: TableSchema): ValidationResults {
const results: ValidationResults = {
schemaValidation: {},
allValid: false,
@ -64,9 +50,11 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
rows.forEach(row => {
Object.entries(row).forEach(([columnName, columnData]) => {
const columnType = schema[columnName]?.type
const columnSubtype = schema[columnName]?.subtype
const isAutoColumn = schema[columnName]?.autocolumn
const {
type: columnType,
subtype: columnSubtype,
autocolumn: isAutoColumn,
} = schema[columnName]
// If the column had an invalid value we don't want to override it
if (results.schemaValidation[columnName] === false) {
@ -123,7 +111,7 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
return results
}
export function parse(rows: Rows, schema: Schema): Rows {
export function parse(rows: Rows, schema: TableSchema): Rows {
return rows.map(row => {
const parsedRow: Row = {}
@ -133,9 +121,7 @@ export function parse(rows: Rows, schema: Schema): Rows {
return
}
const columnType = schema[columnName].type
const columnSubtype = schema[columnName].subtype
const { type: columnType, subtype: columnSubtype } = schema[columnName]
if (columnType === FieldType.NUMBER) {
// If provided must be a valid number
parsedRow[columnName] = columnData ? Number(columnData) : columnData
@ -172,7 +158,7 @@ export function parse(rows: Rows, schema: Schema): Rows {
function isValidBBReference(
columnData: any,
columnSubtype: FieldSubtype
columnSubtype: FieldSubtype.USER | FieldSubtype.USERS
): boolean {
switch (columnSubtype) {
case FieldSubtype.USER:

View File

@ -38,11 +38,16 @@ export interface Row extends Document {
export enum FieldSubtype {
USER = "user",
USERS = "users",
SINGLE = "single",
}
// The 'as' are required for typescript not to type the outputs as generic FieldSubtype
export const FieldTypeSubtypes = {
BB_REFERENCE: {
USER: FieldSubtype.USER,
USERS: FieldSubtype.USERS,
USER: FieldSubtype.USER as FieldSubtype.USER,
USERS: FieldSubtype.USERS as FieldSubtype.USERS,
},
ATTACHMENT: {
SINGLE: FieldSubtype.SINGLE as FieldSubtype.SINGLE,
},
}

View File

@ -112,6 +112,12 @@ export interface BBReferenceFieldMetadata
relationshipType?: RelationshipType
}
export interface AttachmentFieldMetadata
extends Omit<BaseFieldSchema, "subtype"> {
type: FieldType.ATTACHMENT
subtype?: FieldSubtype.SINGLE
}
export interface FieldConstraints {
type?: string
email?: boolean
@ -119,6 +125,7 @@ export interface FieldConstraints {
length?: {
minimum?: string | number | null
maximum?: string | number | null
message?: string
}
numericality?: {
greaterThanOrEqualTo: string | null
@ -156,6 +163,8 @@ interface OtherFieldMetadata extends BaseFieldSchema {
| FieldType.FORMULA
| FieldType.NUMBER
| FieldType.LONGFORM
| FieldType.BB_REFERENCE
| FieldType.ATTACHMENT
>
}
@ -169,6 +178,7 @@ export type FieldSchema =
| LongFormFieldMetadata
| BBReferenceFieldMetadata
| JsonFieldMetadata
| AttachmentFieldMetadata
export interface TableSchema {
[key: string]: FieldSchema
@ -203,3 +213,9 @@ export function isBBReferenceField(
): field is BBReferenceFieldMetadata {
return field.type === FieldType.BB_REFERENCE
}
export function isAttachmentField(
field: FieldSchema
): field is AttachmentFieldMetadata {
return field.type === FieldType.ATTACHMENT
}