better typing - discriminated unions

This commit is contained in:
Martin McKeaveney 2024-10-01 16:36:37 +01:00
parent 0b9b9ab440
commit 2aaef12a1a
7 changed files with 118 additions and 16 deletions

View File

@ -417,13 +417,13 @@
FIELDS.BOOLEAN, FIELDS.BOOLEAN,
FIELDS.DATETIME, FIELDS.DATETIME,
FIELDS.LINK, FIELDS.LINK,
FIELDS.AI,
FIELDS.LONGFORM, FIELDS.LONGFORM,
FIELDS.USER, FIELDS.USER,
FIELDS.USERS, FIELDS.USERS,
FIELDS.ATTACHMENT_SINGLE, FIELDS.ATTACHMENT_SINGLE,
FIELDS.ATTACHMENTS, FIELDS.ATTACHMENTS,
FIELDS.FORMULA, FIELDS.FORMULA,
FIELDS.AI,
FIELDS.JSON, FIELDS.JSON,
FIELDS.BARCODEQR, FIELDS.BARCODEQR,
FIELDS.SIGNATURE_SINGLE, FIELDS.SIGNATURE_SINGLE,

View File

@ -1,5 +1,5 @@
<script> <script>
import { Input, Multiselect, Select, TextArea } from "@budibase/bbui" import { Input, Helpers, Multiselect, Select, TextArea } from "@budibase/bbui"
import ServerBindingPanel from "components/common/bindings/ServerBindingPanel.svelte" import ServerBindingPanel from "components/common/bindings/ServerBindingPanel.svelte"
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
@ -44,32 +44,26 @@
const OperationFields = { const OperationFields = {
SUMMARISE_TEXT: { SUMMARISE_TEXT: {
columns: OperationFieldTypes.MULTI_COLUMN, columns: OperationFieldTypes.MULTI_COLUMN,
prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
CLEAN_DATA: { CLEAN_DATA: {
column: OperationFieldTypes.COLUMN, column: OperationFieldTypes.COLUMN,
prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
TRANSLATE: { TRANSLATE: {
column: OperationFieldTypes.COLUMN, column: OperationFieldTypes.COLUMN,
language: OperationFieldTypes.BINDABLE_TEXT, language: OperationFieldTypes.BINDABLE_TEXT,
prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
CATEGORISE_TEXT: { CATEGORISE_TEXT: {
columns: OperationFieldTypes.MULTI_COLUMN, columns: OperationFieldTypes.MULTI_COLUMN,
categories: OperationFieldTypes.BINDABLE_TEXT, categories: OperationFieldTypes.BINDABLE_TEXT,
prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
SENTIMENT_ANALYSIS: { SENTIMENT_ANALYSIS: {
column: OperationFieldTypes.COLUMN, column: OperationFieldTypes.COLUMN,
prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
PROMPT: { PROMPT: {
prompt: OperationFieldTypes.BINDABLE_TEXT, prompt: OperationFieldTypes.BINDABLE_TEXT,
}, },
SEARCH_WEB: { SEARCH_WEB: {
columns: OperationFieldTypes.MULTI_COLUMN, columns: OperationFieldTypes.MULTI_COLUMN,
prompt: OperationFieldTypes.BINDABLE_TEXT,
} }
} }
@ -90,6 +84,7 @@
</script> </script>
<Select <Select
label={"Operation"}
options={AIFieldConfigOptions} options={AIFieldConfigOptions}
bind:value={aiField.operation} bind:value={aiField.operation}
/> />
@ -97,7 +92,7 @@
{#each Object.keys(OperationField) as key} {#each Object.keys(OperationField) as key}
{#if OperationField[key] === OperationFieldTypes.BINDABLE_TEXT} {#if OperationField[key] === OperationFieldTypes.BINDABLE_TEXT}
<ModalBindableInput <ModalBindableInput
label={key} label={Helpers.capitalise(key)}
panel={ServerBindingPanel} panel={ServerBindingPanel}
title="Prompt" title="Prompt"
on:change={e => aiField[key] = e.detail} on:change={e => aiField[key] = e.detail}
@ -109,13 +104,13 @@
{:else if OperationField[key] === OperationFieldTypes.MULTI_COLUMN} {:else if OperationField[key] === OperationFieldTypes.MULTI_COLUMN}
<Multiselect <Multiselect
bind:value={aiField[key]} bind:value={aiField[key]}
label={key} label={Helpers.capitalise(key)}
options={schemaWithoutRelations} options={schemaWithoutRelations}
/> />
{:else if OperationField[key] === OperationFieldTypes.COLUMN} {:else if OperationField[key] === OperationFieldTypes.COLUMN}
<Select <Select
bind:value={aiField[key]} bind:value={aiField[key]}
label={key} label={Helpers.capitalise(key)}
options={schemaWithoutRelations} options={schemaWithoutRelations}
/> />
{/if} {/if}

@ -1 +1 @@
Subproject commit dcc9e50b8064a2097d408771462ad80f48de7ff6 Subproject commit d194be2339a1ee2e5b2ed1fe59d103249f2d8d2c

View File

@ -198,7 +198,7 @@ export async function runAIColumnChecks(
table: Table, table: Table,
{ oldTable }: { oldTable?: Table } { oldTable }: { oldTable?: Table }
) { ) {
// look to see if any formula values have changed // look to see if any AI column values have changed
const shouldUpdate = Object.values(table.schema).find( const shouldUpdate = Object.values(table.schema).find(
column => column =>
column.type === FieldType.AI && column.type === FieldType.AI &&
@ -206,7 +206,7 @@ export async function runAIColumnChecks(
!oldTable.schema[column.name] || !oldTable.schema[column.name] ||
!isEqual(oldTable.schema[column.name], column)) !isEqual(oldTable.schema[column.name], column))
) )
// if a static formula column has updated, then need to run the update // if an AI column has updated, then need to run the update
if (shouldUpdate != null) { if (shouldUpdate != null) {
await updateAllAIColumnsInTable(table) await updateAllAIColumnsInTable(table)
} }

View File

@ -0,0 +1,105 @@
export enum AIOperationEnum {
SUMMARISE_TEXT = "SUMMARISE_TEXT",
CLEAN_DATA = "CLEAN_DATA",
TRANSLATE = "TRANSLATE",
CATEGORISE_TEXT = "CATEGORISE_TEXT",
SENTIMENT_ANALYSIS = "SENTIMENT_ANALYSIS",
PROMPT = "PROMPT",
SEARCH_WEB = "SEARCH_WEB",
}
enum OperationFieldTypeEnum {
MULTI_COLUMN = "columns",
COLUMN = "column",
BINDABLE_TEXT = "prompt",
}
type OperationFieldsType = {
[AIOperationEnum.SUMMARISE_TEXT]: {
columns: OperationFieldTypeEnum.MULTI_COLUMN
}
[AIOperationEnum.CLEAN_DATA]: {
column: OperationFieldTypeEnum.COLUMN
}
[AIOperationEnum.TRANSLATE]: {
column: OperationFieldTypeEnum.COLUMN
language: OperationFieldTypeEnum.BINDABLE_TEXT
}
[AIOperationEnum.CATEGORISE_TEXT]: {
columns: OperationFieldTypeEnum.MULTI_COLUMN
categories: OperationFieldTypeEnum.BINDABLE_TEXT
}
[AIOperationEnum.SENTIMENT_ANALYSIS]: {
column: OperationFieldTypeEnum.COLUMN
}
[AIOperationEnum.PROMPT]: {
prompt: OperationFieldTypeEnum.BINDABLE_TEXT
}
[AIOperationEnum.SEARCH_WEB]: {
columns: OperationFieldTypeEnum.MULTI_COLUMN
}
}
// Define the AI operations with just their labels (no need for separate 'value' property)
const AIOperations: { [key in AIOperationEnum]: string } = {
[AIOperationEnum.SUMMARISE_TEXT]: "Summarise Text",
[AIOperationEnum.CLEAN_DATA]: "Clean Data",
[AIOperationEnum.TRANSLATE]: "Translate",
[AIOperationEnum.CATEGORISE_TEXT]: "Categorise Text",
[AIOperationEnum.SENTIMENT_ANALYSIS]: "Sentiment Analysis",
[AIOperationEnum.PROMPT]: "Prompt",
[AIOperationEnum.SEARCH_WEB]: "Search Web",
}
type BaseSchema = {
operation: AIOperationEnum
}
type SummariseTextSchema = BaseSchema & {
operation: AIOperationEnum.SUMMARISE_TEXT
columns: string[]
}
type CleanDataSchema = BaseSchema & {
operation: AIOperationEnum.CLEAN_DATA
column: string
}
type TranslateSchema = BaseSchema & {
operation: AIOperationEnum.TRANSLATE
column: string
language: string
}
type CategoriseTextSchema = BaseSchema & {
operation: AIOperationEnum.CATEGORISE_TEXT
columns: string[]
categories: string
}
type SentimentAnalysisSchema = BaseSchema & {
operation: AIOperationEnum.SENTIMENT_ANALYSIS
column: string
}
type PromptSchema = BaseSchema & {
operation: AIOperationEnum.PROMPT
prompt: string
}
type SearchWebSchema = BaseSchema & {
operation: AIOperationEnum.SEARCH_WEB
columns: string[]
}
export type AIColumnSchema =
| SummariseTextSchema
| CleanDataSchema
| TranslateSchema
| CategoriseTextSchema
| SentimentAnalysisSchema
| PromptSchema
| SearchWebSchema

View File

@ -1,3 +1,4 @@
export * from "./ai"
export * from "./app" export * from "./app"
export * from "./automation" export * from "./automation"
export * from "./datasource" export * from "./datasource"

View File

@ -9,6 +9,7 @@ import {
JsonFieldSubType, JsonFieldSubType,
RelationshipType, RelationshipType,
} from "./constants" } from "./constants"
import { AIOperationEnum } from "../ai"
export interface UIFieldMetadata { export interface UIFieldMetadata {
order?: number order?: number
@ -119,10 +120,10 @@ export interface FormulaFieldMetadata extends BaseFieldSchema {
export interface AIFieldMetadata extends BaseFieldSchema { export interface AIFieldMetadata extends BaseFieldSchema {
type: FieldType.AI type: FieldType.AI
formula: string formula: string
// TODO: needs better types operation: AIOperationEnum
operation: string
columns?: string[] columns?: string[]
column?: string column?: string
categories?: string
prompt?: string prompt?: string
language?: string language?: string
} }