rough v1
This commit is contained in:
parent
b1462b4c19
commit
2d21afbe10
|
@ -1141,7 +1141,8 @@ class InternalBuilder {
|
|||
schema.constraints?.presence === true ||
|
||||
schema.type === FieldType.FORMULA ||
|
||||
schema.type === FieldType.AUTO ||
|
||||
schema.type === FieldType.LINK
|
||||
schema.type === FieldType.LINK ||
|
||||
schema.type === FieldType.AI
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import SchemaBuilder = Knex.SchemaBuilder
|
|||
import CreateTableBuilder = Knex.CreateTableBuilder
|
||||
|
||||
function isIgnoredType(type: FieldType) {
|
||||
const ignored = [FieldType.LINK, FieldType.FORMULA]
|
||||
const ignored = [FieldType.LINK, FieldType.FORMULA, FieldType.AI]
|
||||
return ignored.indexOf(type) !== -1
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,9 @@ function generateSchema(
|
|||
case FieldType.FORMULA:
|
||||
// This is allowed, but nothing to do on the external datasource
|
||||
break
|
||||
case FieldType.AI:
|
||||
// This is allowed, but nothing to do on the external datasource
|
||||
break
|
||||
case FieldType.ATTACHMENTS:
|
||||
case FieldType.ATTACHMENT_SINGLE:
|
||||
case FieldType.SIGNATURE_SINGLE:
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
} from "constants/backend"
|
||||
import { getAutoColumnInformation, buildAutoColumn } from "helpers/utils"
|
||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||
import AIFieldConfiguration from "components/common/AIFieldConfiguration.svelte"
|
||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
||||
import { getBindings } from "components/backend/DataTable/formula"
|
||||
import JSONSchemaModal from "./JSONSchemaModal.svelte"
|
||||
|
@ -54,6 +55,7 @@
|
|||
const NUMBER_TYPE = FieldType.NUMBER
|
||||
const JSON_TYPE = FieldType.JSON
|
||||
const DATE_TYPE = FieldType.DATETIME
|
||||
const AI_TYPE = FieldType.AI
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const { dispatch: gridDispatch, rows } = getContext("grid")
|
||||
|
@ -421,6 +423,7 @@
|
|||
FIELDS.ATTACHMENT_SINGLE,
|
||||
FIELDS.ATTACHMENTS,
|
||||
FIELDS.FORMULA,
|
||||
FIELDS.AI,
|
||||
FIELDS.JSON,
|
||||
FIELDS.BARCODEQR,
|
||||
FIELDS.SIGNATURE_SINGLE,
|
||||
|
@ -732,6 +735,13 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
{:else if editableColumn.type === AI_TYPE}
|
||||
<AIFieldConfiguration
|
||||
aiField={editableColumn}
|
||||
context={rowGoldenSample}
|
||||
bindings={getBindings({ table })}
|
||||
schema={table.schema}
|
||||
/>
|
||||
{:else if editableColumn.type === JSON_TYPE}
|
||||
<Button primary text on:click={openJsonSchemaEditor}
|
||||
>Open schema editor</Button
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
<script>
|
||||
import { Input, Multiselect, Select, TextArea } from "@budibase/bbui"
|
||||
import ServerBindingPanel from "components/common/bindings/ServerBindingPanel.svelte"
|
||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
||||
|
||||
const AIOperations = {
|
||||
SUMMARISE_TEXT: {
|
||||
label: "Summarise Text",
|
||||
value: "SUMMARISE_TEXT"
|
||||
},
|
||||
CLEAN_DATA: {
|
||||
label: "Clean Data",
|
||||
value: "CLEAN_DATA"
|
||||
},
|
||||
TRANSLATE: {
|
||||
label: "Translate",
|
||||
value: "TRANSLATE"
|
||||
},
|
||||
CATEGORISE_TEXT: {
|
||||
label: "Categorise Text",
|
||||
value: "CATEGORISE_TEXT"
|
||||
},
|
||||
SENTIMENT_ANALYSIS: {
|
||||
label: "Sentiment Analysis",
|
||||
value: "SENTIMENT_ANALYSIS"
|
||||
},
|
||||
PROMPT: {
|
||||
label: "Prompt",
|
||||
value: "PROMPT"
|
||||
},
|
||||
SEARCH_WEB: {
|
||||
label: "Search Web",
|
||||
value: "SEARCH_WEB"
|
||||
}
|
||||
}
|
||||
|
||||
const OperationFieldTypes = {
|
||||
MULTI_COLUMN: "columns",
|
||||
COLUMN: "column",
|
||||
BINDABLE_TEXT: "prompt",
|
||||
// LANGUAGE: "language",
|
||||
}
|
||||
|
||||
const OperationFields = {
|
||||
SUMMARISE_TEXT: {
|
||||
columns: OperationFieldTypes.MULTI_COLUMN,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
CLEAN_DATA: {
|
||||
columns: OperationFieldTypes.MULTI_COLUMN,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
TRANSLATE: {
|
||||
columns: OperationFieldTypes.MULTI_COLUMN,
|
||||
language: OperationFieldTypes.BINDABLE_TEXT,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
CATEGORISE_TEXT: {
|
||||
columns: OperationFieldTypes.MULTI_COLUMN,
|
||||
categories: OperationFieldTypes.BINDABLE_TEXT,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
SENTIMENT_ANALYSIS: {
|
||||
column: OperationFieldTypes.COLUMN,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
PROMPT: {
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
},
|
||||
SEARCH_WEB: {
|
||||
columns: OperationFieldTypes.MULTI_COLUMN,
|
||||
prompt: OperationFieldTypes.BINDABLE_TEXT,
|
||||
}
|
||||
}
|
||||
|
||||
const AIFieldConfigOptions = Object.keys(AIOperations).map(key => ({
|
||||
label: AIOperations[key].label,
|
||||
value: AIOperations[key].value
|
||||
}))
|
||||
|
||||
export let bindings
|
||||
export let context
|
||||
export let schema
|
||||
export let aiField = {}
|
||||
|
||||
$: OperationField = OperationFields[aiField.operation] || null
|
||||
$: console.log(aiField)
|
||||
$: console.log(schema)
|
||||
$: schemaWithoutRelations = Object.keys(schema).filter(key => schema[key].type !== "link")
|
||||
</script>
|
||||
|
||||
<Select
|
||||
options={AIFieldConfigOptions}
|
||||
bind:value={aiField.operation}
|
||||
/>
|
||||
{#if aiField.operation}
|
||||
{#each Object.keys(OperationField) as key}
|
||||
{#if OperationField[key] === OperationFieldTypes.BINDABLE_TEXT}
|
||||
<ModalBindableInput
|
||||
label={key}
|
||||
panel={ServerBindingPanel}
|
||||
title="Prompt"
|
||||
on:change={e => aiField[key] = e.detail}
|
||||
value={aiField[key]}
|
||||
{bindings}
|
||||
allowJS
|
||||
{context}
|
||||
/>
|
||||
{:else if OperationField[key] === OperationFieldTypes.MULTI_COLUMN}
|
||||
<Multiselect
|
||||
bind:value={aiField[key]}
|
||||
label={key}
|
||||
options={schemaWithoutRelations}
|
||||
/>
|
||||
{:else if OperationField[key] === OperationFieldTypes.COLUMN}
|
||||
<Select
|
||||
bind:value={aiField[key]}
|
||||
label={key}
|
||||
options={schemaWithoutRelations}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
|
@ -159,6 +159,12 @@ export const FIELDS = {
|
|||
icon: TypeIconMap[FieldType.FORMULA],
|
||||
constraints: {},
|
||||
},
|
||||
AI: {
|
||||
name: "AI",
|
||||
type: FieldType.AI,
|
||||
icon: TypeIconMap[FieldType.AI],
|
||||
constraints: {},
|
||||
},
|
||||
JSON: {
|
||||
name: "JSON",
|
||||
type: FieldType.JSON,
|
||||
|
|
|
@ -262,7 +262,7 @@
|
|||
{/if}
|
||||
{#if allowBindings && filter.field && filter.valueType === "Binding"}
|
||||
<slot name="binding" {filter} />
|
||||
{:else if [FieldType.STRING, FieldType.LONGFORM, FieldType.NUMBER, FieldType.BIGINT, FieldType.FORMULA].includes(filter.type)}
|
||||
{:else if [FieldType.STRING, FieldType.LONGFORM, FieldType.NUMBER, FieldType.BIGINT, FieldType.FORMULA, FieldType.AI].includes(filter.type)}
|
||||
<Input disabled={filter.noValue} bind:value={filter.value} />
|
||||
{:else if filter.type === FieldType.ARRAY || (filter.type === FieldType.OPTIONS && filter.operator === ArrayOperator.ONE_OF)}
|
||||
<Multiselect
|
||||
|
|
|
@ -95,7 +95,8 @@
|
|||
const { type, formulaType } = col.schema
|
||||
return (
|
||||
searchableTypes.includes(type) ||
|
||||
(type === FieldType.FORMULA && formulaType === FormulaType.STATIC)
|
||||
(type === FieldType.FORMULA && formulaType === FormulaType.STATIC) ||
|
||||
type === FieldType.AI
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ const TypeComponentMap = {
|
|||
[FieldType.ATTACHMENT_SINGLE]: AttachmentSingleCell,
|
||||
[FieldType.LINK]: RelationshipCell,
|
||||
[FieldType.FORMULA]: FormulaCell,
|
||||
// TODO: fix
|
||||
[FieldType.AI]: FormulaCell,
|
||||
[FieldType.JSON]: JSONCell,
|
||||
[FieldType.BB_REFERENCE]: BBReferenceCell,
|
||||
[FieldType.BB_REFERENCE_SINGLE]: BBReferenceSingleCell,
|
||||
|
|
|
@ -160,6 +160,7 @@ export const TypeIconMap = {
|
|||
[FieldType.ATTACHMENT_SINGLE]: "DocumentFragment",
|
||||
[FieldType.LINK]: "DataCorrelated",
|
||||
[FieldType.FORMULA]: "Calculator",
|
||||
[FieldType.AI]: "MagicWand",
|
||||
[FieldType.JSON]: "Brackets",
|
||||
[FieldType.BIGINT]: "TagBold",
|
||||
[FieldType.AUTO]: "MagicWand",
|
||||
|
|
|
@ -154,7 +154,8 @@ function isEditableColumn(column: FieldSchema) {
|
|||
column.autoReason !== AutoReason.FOREIGN_KEY &&
|
||||
column.subtype !== AutoFieldSubType.AUTO_ID
|
||||
const isFormula = column.type === FieldType.FORMULA
|
||||
return !(isExternalAutoColumn || isFormula)
|
||||
const isAIColumn = column.type === FieldType.AI
|
||||
return !(isExternalAutoColumn || isFormula || isAIColumn)
|
||||
}
|
||||
|
||||
export class ExternalRequest<T extends Operation> {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import { getRowParams } from "../../../db/utils"
|
||||
import {
|
||||
outputProcessing,
|
||||
processAIColumns,
|
||||
} from "../../../utilities/rowProcessor"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import { Table, Row } from "@budibase/types"
|
||||
import isEqual from "lodash/isEqual"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
||||
export async function updateAllAIColumnsInTable(table: Table) {
|
||||
const db = context.getAppDB()
|
||||
// start by getting the raw rows (which will be written back to DB after update)
|
||||
let rows = (
|
||||
await db.allDocs<Row>(
|
||||
getRowParams(table._id, null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
).rows.map(row => row.doc!)
|
||||
// now enrich the rows, note the clone so that we have the base state of the
|
||||
// rows so that we don't write any of the enriched information back
|
||||
let enrichedRows = await outputProcessing(table, cloneDeep(rows), {
|
||||
squash: false,
|
||||
})
|
||||
const updatedRows = []
|
||||
for (let row of rows) {
|
||||
// find the enriched row, if found process the formulas
|
||||
const enrichedRow = enrichedRows.find(
|
||||
(enriched: Row) => enriched._id === row._id
|
||||
)
|
||||
if (enrichedRow) {
|
||||
let processed = await processAIColumns(table, cloneDeep(row), {
|
||||
contextRows: [enrichedRow],
|
||||
})
|
||||
// values have changed, need to add to bulk docs to update
|
||||
if (!isEqual(processed, row)) {
|
||||
updatedRows.push(processed)
|
||||
}
|
||||
}
|
||||
}
|
||||
await db.bulkDocs(updatedRows)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { getRowParams } from "../../../db/utils"
|
||||
import {
|
||||
outputProcessing,
|
||||
outputProcessing, processAIColumns,
|
||||
processFormulas,
|
||||
} from "../../../utilities/rowProcessor"
|
||||
import { context } from "@budibase/backend-core"
|
||||
|
@ -101,7 +101,7 @@ export async function updateAllFormulasInTable(table: Table) {
|
|||
(enriched: Row) => enriched._id === row._id
|
||||
)
|
||||
if (enrichedRow) {
|
||||
const processed = await processFormulas(table, cloneDeep(row), {
|
||||
let processed = await processFormulas(table, cloneDeep(row), {
|
||||
dynamic: false,
|
||||
contextRows: [enrichedRow],
|
||||
})
|
||||
|
@ -142,6 +142,10 @@ export async function finaliseRow(
|
|||
dynamic: false,
|
||||
contextRows: [enrichedRow],
|
||||
})
|
||||
row = await processAIColumns(table, row, {
|
||||
contextRows: [enrichedRow],
|
||||
})
|
||||
|
||||
// don't worry about rev, tables handle rev/lastID updates
|
||||
// if another row has been written since processing this will
|
||||
// handle the auto ID clash
|
||||
|
@ -154,6 +158,10 @@ export async function finaliseRow(
|
|||
enrichedRow = await processFormulas(table, enrichedRow, {
|
||||
dynamic: false,
|
||||
})
|
||||
enrichedRow = await processAIColumns(table, row, {
|
||||
contextRows: [enrichedRow],
|
||||
})
|
||||
|
||||
// this updates the related formulas in other rows based on the relations to this row
|
||||
if (updateFormula) {
|
||||
await updateRelatedFormula(table, enrichedRow)
|
||||
|
|
|
@ -119,6 +119,7 @@ export function buildSqlFieldList(
|
|||
([columnName, column]) =>
|
||||
column.type !== FieldType.LINK &&
|
||||
column.type !== FieldType.FORMULA &&
|
||||
column.type !== FieldType.AI &&
|
||||
!existing.find((field: string) => field === columnName)
|
||||
)
|
||||
.map(column => `${table.name}.${column[0]}`)
|
||||
|
|
|
@ -5,15 +5,10 @@ import isEqual from "lodash/isEqual"
|
|||
import uniq from "lodash/uniq"
|
||||
import { updateAllFormulasInTable } from "../row/staticFormula"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import {
|
||||
FormulaType,
|
||||
FieldSchema,
|
||||
FieldType,
|
||||
FormulaFieldMetadata,
|
||||
Table,
|
||||
} from "@budibase/types"
|
||||
import { FieldSchema, FieldType, FormulaFieldMetadata, FormulaType, Table, } from "@budibase/types"
|
||||
import sdk from "../../../sdk"
|
||||
import { isRelationshipColumn } from "../../../db/utils"
|
||||
import { updateAllAIColumnsInTable } from "../row/aiColumn"
|
||||
|
||||
function isStaticFormula(
|
||||
column: FieldSchema
|
||||
|
@ -198,3 +193,21 @@ export async function runStaticFormulaChecks(
|
|||
await checkIfFormulaUpdated(table, { oldTable })
|
||||
}
|
||||
}
|
||||
|
||||
export async function runAIColumnChecks(
|
||||
table: Table,
|
||||
{ oldTable }: { oldTable?: Table }
|
||||
) {
|
||||
// look to see if any formula values have changed
|
||||
const shouldUpdate = Object.values(table.schema).find(
|
||||
column =>
|
||||
column.type === FieldType.AI &&
|
||||
(!oldTable ||
|
||||
!oldTable.schema[column.name] ||
|
||||
!isEqual(oldTable.schema[column.name], column))
|
||||
)
|
||||
// if a static formula column has updated, then need to run the update
|
||||
if (shouldUpdate != null) {
|
||||
await updateAllAIColumnsInTable(table)
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ import {
|
|||
} from "@budibase/types"
|
||||
import sdk from "../../../sdk"
|
||||
import env from "../../../environment"
|
||||
import { runStaticFormulaChecks } from "./bulkFormula"
|
||||
import { runAIColumnChecks, runStaticFormulaChecks } from "./bulkFormula"
|
||||
|
||||
export async function clearColumns(table: Table, columnNames: string[]) {
|
||||
const db = context.getAppDB()
|
||||
|
|
|
@ -296,7 +296,7 @@ export async function squashLinks<T = Row[] | Row>(
|
|||
return false
|
||||
}
|
||||
if (
|
||||
[FieldType.LINK, FieldType.FORMULA].includes(tableColumn.type)
|
||||
[FieldType.LINK, FieldType.FORMULA, FieldType.AI].includes(tableColumn.type)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ interface AuthTokenResponse {
|
|||
const isTypeAllowed: Record<FieldType, boolean> = {
|
||||
[FieldType.STRING]: true,
|
||||
[FieldType.FORMULA]: true,
|
||||
[FieldType.AI]: true,
|
||||
[FieldType.NUMBER]: true,
|
||||
[FieldType.LONGFORM]: true,
|
||||
[FieldType.DATETIME]: true,
|
||||
|
@ -490,7 +491,8 @@ export class GoogleSheetsIntegration implements DatasourcePlus {
|
|||
}
|
||||
if (
|
||||
!sheet.headerValues.includes(key) &&
|
||||
column.type !== FieldType.FORMULA
|
||||
column.type !== FieldType.FORMULA &&
|
||||
column.type !== FieldType.AI
|
||||
) {
|
||||
updatedHeaderValues.push(key)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { EventType, updateLinks } from "../../../../db/linkedRows"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import isEqual from "lodash/isEqual"
|
||||
import { runStaticFormulaChecks } from "../../../../api/controllers/table/bulkFormula"
|
||||
import { runAIColumnChecks, runStaticFormulaChecks } from "../../../../api/controllers/table/bulkFormula"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import { findDuplicateInternalColumns } from "@budibase/shared-core"
|
||||
import { getTable } from "../getters"
|
||||
|
@ -133,6 +133,7 @@ export async function save(
|
|||
}
|
||||
// has to run after, make sure it has _id
|
||||
await runStaticFormulaChecks(table, { oldTable, deletion: false })
|
||||
await runAIColumnChecks(table, { oldTable, deletion: false })
|
||||
return { table }
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const FieldTypeMap: Record<FieldType, SQLiteType> = {
|
|||
[FieldType.BOOLEAN]: SQLiteType.NUMERIC,
|
||||
[FieldType.DATETIME]: SQLiteType.TEXT,
|
||||
[FieldType.FORMULA]: SQLiteType.TEXT,
|
||||
[FieldType.AI]: SQLiteType.TEXT,
|
||||
[FieldType.LONGFORM]: SQLiteType.TEXT,
|
||||
[FieldType.NUMBER]: SQLiteType.REAL,
|
||||
[FieldType.STRING]: SQLiteType.TEXT,
|
||||
|
|
|
@ -172,7 +172,7 @@ export async function enrichSchema(
|
|||
|
||||
for (const relTableFieldName of Object.keys(relTable.schema)) {
|
||||
const relTableField = relTable.schema[relTableFieldName]
|
||||
if ([FieldType.LINK, FieldType.FORMULA].includes(relTableField.type)) {
|
||||
if ([FieldType.LINK, FieldType.FORMULA, FieldType.AI].includes(relTableField.type)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,10 @@ export async function inputProcessing(
|
|||
if (field.type === FieldType.FORMULA) {
|
||||
delete clonedRow[key]
|
||||
}
|
||||
// remove any AI values, they are to be generated
|
||||
if (field.type === FieldType.AI) {
|
||||
delete clonedRow[key]
|
||||
}
|
||||
// otherwise coerce what is there to correct types
|
||||
else {
|
||||
clonedRow[key] = coerce(value, field.type)
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "@budibase/types"
|
||||
import tracer from "dd-trace"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import * as pro from "@budibase/pro"
|
||||
|
||||
interface FormulaOpts {
|
||||
dynamic?: boolean
|
||||
|
@ -91,6 +92,56 @@ export async function processFormulas<T extends Row | Row[]>(
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks through the rows provided and finds AI columns - which it then processes.
|
||||
*/
|
||||
export async function processAIColumns<T extends Row | Row[]>(
|
||||
table: Table,
|
||||
inputRows: T,
|
||||
{ contextRows }: FormulaOpts
|
||||
): Promise<T> {
|
||||
return tracer.trace("processAIColumns", {}, async span => {
|
||||
const numRows = Array.isArray(inputRows) ? inputRows.length : 1
|
||||
span?.addTags({ table_id: table._id })
|
||||
const rows = Array.isArray(inputRows) ? inputRows : [inputRows]
|
||||
if (rows) {
|
||||
// Ensure we have snippet context
|
||||
await context.ensureSnippetContext()
|
||||
|
||||
for (let [column, schema] of Object.entries(table.schema)) {
|
||||
if (schema.type !== FieldType.AI) {
|
||||
continue
|
||||
}
|
||||
|
||||
// const llm = pro.ai.LargeLanguageModel()
|
||||
// if (
|
||||
// schema.formula == null ||
|
||||
// (dynamic && isStatic) ||
|
||||
// (!dynamic && !isStatic)
|
||||
// ) {
|
||||
// continue
|
||||
// }
|
||||
// iterate through rows and process formula
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i]
|
||||
// let context = contextRows ? contextRows[i] : row
|
||||
// let formula = schema.prompt
|
||||
rows[i] = {
|
||||
...row,
|
||||
[column]: tracer.trace("processAIColumn", {}, span => {
|
||||
span?.addTags({ table_id: table._id, column })
|
||||
// return processStringSync(formula, context)
|
||||
// TODO: Add the AI stuff in to this
|
||||
return "YEET AI"
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.isArray(inputRows) ? rows : rows[0]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes any date columns and ensures that those without the ignoreTimezones
|
||||
* flag set are parsed as UTC rather than local time.
|
||||
|
|
|
@ -87,6 +87,8 @@ export const getValidOperatorsForType = (
|
|||
ops = numOps
|
||||
} else if (type === FieldType.FORMULA && formulaType === FormulaType.STATIC) {
|
||||
ops = stringOps.concat([Op.MoreThan, Op.LessThan])
|
||||
} else if (type === FieldType.AI) {
|
||||
ops = stringOps.concat([Op.MoreThan, Op.LessThan])
|
||||
} else if (
|
||||
type === FieldType.BB_REFERENCE_SINGLE ||
|
||||
schema.isDeprecatedSingleUserColumn(fieldType)
|
||||
|
|
|
@ -8,6 +8,7 @@ const allowDisplayColumnByType: Record<FieldType, boolean> = {
|
|||
[FieldType.NUMBER]: true,
|
||||
[FieldType.DATETIME]: true,
|
||||
[FieldType.FORMULA]: true,
|
||||
[FieldType.AI]: true,
|
||||
[FieldType.AUTO]: true,
|
||||
[FieldType.INTERNAL]: true,
|
||||
[FieldType.BARCODEQR]: true,
|
||||
|
@ -38,6 +39,7 @@ const allowSortColumnByType: Record<FieldType, boolean> = {
|
|||
[FieldType.JSON]: true,
|
||||
|
||||
[FieldType.FORMULA]: false,
|
||||
[FieldType.AI]: false,
|
||||
[FieldType.ATTACHMENTS]: false,
|
||||
[FieldType.ATTACHMENT_SINGLE]: false,
|
||||
[FieldType.SIGNATURE_SINGLE]: false,
|
||||
|
@ -61,6 +63,7 @@ const allowDefaultColumnByType: Record<FieldType, boolean> = {
|
|||
[FieldType.BIGINT]: false,
|
||||
[FieldType.BOOLEAN]: false,
|
||||
[FieldType.FORMULA]: false,
|
||||
[FieldType.AI]: false,
|
||||
[FieldType.ATTACHMENTS]: false,
|
||||
[FieldType.ATTACHMENT_SINGLE]: false,
|
||||
[FieldType.SIGNATURE_SINGLE]: false,
|
||||
|
|
|
@ -76,6 +76,10 @@ export enum FieldType {
|
|||
* that is part of the initial formula definition, the formula will be live evaluated in the browser.
|
||||
*/
|
||||
AUTO = "auto",
|
||||
/**
|
||||
* A complex type, called an AI column within Budibase. This type has a... TODO: fill out
|
||||
*/
|
||||
AI = "ai",
|
||||
/**
|
||||
* a JSON type, called JSON within Budibase. This type allows any arbitrary JSON to be input to this column
|
||||
* type, which will be represented as a JSON object in the row. This type depends on a schema being
|
||||
|
|
|
@ -30,6 +30,7 @@ export enum JsonFieldSubType {
|
|||
export enum FormulaType {
|
||||
STATIC = "static",
|
||||
DYNAMIC = "dynamic",
|
||||
AI = "ai"
|
||||
}
|
||||
|
||||
export enum BBReferenceFieldSubType {
|
||||
|
|
|
@ -116,6 +116,17 @@ export interface FormulaFieldMetadata extends BaseFieldSchema {
|
|||
formulaType?: FormulaType
|
||||
}
|
||||
|
||||
export interface AIFieldMetadata extends BaseFieldSchema {
|
||||
type: FieldType.AI
|
||||
formula: string
|
||||
// TODO: needs better types
|
||||
operation: string
|
||||
columns?: string[]
|
||||
column?: string
|
||||
prompt?: string
|
||||
language?: string
|
||||
}
|
||||
|
||||
export interface BBReferenceFieldMetadata
|
||||
extends Omit<BaseFieldSchema, "subtype"> {
|
||||
type: FieldType.BB_REFERENCE
|
||||
|
@ -190,6 +201,7 @@ interface OtherFieldMetadata extends BaseFieldSchema {
|
|||
| FieldType.LINK
|
||||
| FieldType.AUTO
|
||||
| FieldType.FORMULA
|
||||
| FieldType.AI
|
||||
| FieldType.NUMBER
|
||||
| FieldType.LONGFORM
|
||||
| FieldType.BB_REFERENCE
|
||||
|
@ -207,6 +219,7 @@ export type FieldSchema =
|
|||
| RelationshipFieldMetadata
|
||||
| AutoColumnFieldMetadata
|
||||
| FormulaFieldMetadata
|
||||
| AIFieldMetadata
|
||||
| NumberFieldMetadata
|
||||
| LongFormFieldMetadata
|
||||
| StringFieldMetadata
|
||||
|
|
Loading…
Reference in New Issue