Skip to content

Commit 8d25a43

Browse files
authored
Add new formula editor
1 parent 15beb4f commit 8d25a43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+4800
-831
lines changed

premium/web-frontend/modules/baserow_premium/components/field/FieldAISubForm.vue

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@
6969
<div style="max-width: 366px">
7070
<FormulaInputField
7171
:value="formulaStr"
72-
:data-providers="dataProviders"
73-
:application-context="applicationContext"
72+
:mode="localMode"
73+
:nodes-hierarchy="nodesHierarchy"
7474
:placeholder="$t('fieldAISubForm.promptPlaceholder')"
7575
@input="updatedFormulaStr"
76-
></FormulaInputField>
76+
@update:mode="updateMode"
77+
/>
7778
</div>
7879
<template #error> {{ $t('error.requiredField') }}</template>
7980
</FormGroup>
@@ -99,6 +100,8 @@ import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm'
99100
import FormulaInputField from '@baserow/modules/core/components/formula/FormulaInputField'
100101
import SelectAIModelForm from '@baserow/modules/core/components/ai/SelectAIModelForm'
101102
import { TextAIFieldOutputType } from '@baserow_premium/aiFieldOutputTypes'
103+
import { buildFormulaFunctionNodes } from '@baserow/modules/core/formula'
104+
import { getDataNodesFromDataProvider } from '@baserow/modules/core/utils/dataProviders'
102105
103106
export default {
104107
name: 'FieldAISubForm',
@@ -111,11 +114,12 @@ export default {
111114
return {
112115
allowedValues: ['ai_prompt', 'ai_file_field_id', 'ai_output_type'],
113116
values: {
114-
ai_prompt: { formula: '' },
117+
ai_prompt: { formula: '', mode: 'simple' },
115118
ai_output_type: TextAIFieldOutputType.getType(),
116119
ai_file_field_id: null,
117120
},
118121
fileFieldSupported: false,
122+
localMode: 'simple',
119123
}
120124
},
121125
computed: {
@@ -146,6 +150,29 @@ export default {
146150
dataProviders() {
147151
return [this.$registry.get('databaseDataProvider', 'fields')]
148152
},
153+
nodesHierarchy() {
154+
const hierarchy = []
155+
156+
const filteredDataNodes = getDataNodesFromDataProvider(
157+
this.dataProviders,
158+
this.applicationContext
159+
)
160+
161+
if (filteredDataNodes.length > 0) {
162+
hierarchy.push({
163+
name: this.$t('runtimeFormulaTypes.formulaTypeData'),
164+
type: 'data',
165+
icon: 'iconoir-database',
166+
nodes: filteredDataNodes,
167+
})
168+
}
169+
170+
// Add functions and operators from the registry
171+
const formulaNodes = buildFormulaFunctionNodes(this)
172+
hierarchy.push(...formulaNodes)
173+
174+
return hierarchy
175+
},
149176
isDeactivated() {
150177
return this.$registry
151178
.get('field', this.fieldType)
@@ -171,6 +198,16 @@ export default {
171198
)
172199
},
173200
},
201+
watch: {
202+
'values.ai_prompt.mode': {
203+
handler(newMode) {
204+
if (newMode && newMode !== this.localMode) {
205+
this.localMode = newMode
206+
}
207+
},
208+
immediate: true,
209+
},
210+
},
174211
methods: {
175212
/**
176213
* When `FormulaInputField` emits a new formula string, we need to emit the
@@ -181,6 +218,17 @@ export default {
181218
this.v$.values.ai_prompt.formula.$model = newFormulaStr
182219
this.$emit('input', { formula: newFormulaStr })
183220
},
221+
/**
222+
* When the mode changes, update the local mode value
223+
* @param {String} newMode The new mode value
224+
*/
225+
updateMode(newMode) {
226+
this.localMode = newMode
227+
this.values.ai_prompt = {
228+
...this.values.ai_prompt,
229+
mode: newMode,
230+
}
231+
},
184232
setFileFieldSupported(generativeAIType) {
185233
if (generativeAIType) {
186234
const modelType = this.$registry.get(

web-frontend/locales/en.json

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,12 +675,25 @@
675675
"ifDescription": "If the first argument is true, returns the second argument, otherwise returns the third argument.",
676676
"andDescription": "Returns true if all arguments are true, otherwise returns false.",
677677
"orDescription": "Returns true if any argument is true, otherwise returns false.",
678-
"formulaTypeFormula": "Formula",
679-
"formulaTypeOperator": "Operator",
678+
"formulaTypeFormula": "Function | Functions",
679+
"formulaTypeOperator": "Operator | Operators",
680+
"formulaTypeData": "Data",
681+
"formulaTypeDataEmpty": "No data sources available",
680682
"categoryText": "Text",
681683
"categoryNumber": "Number",
682684
"categoryBoolean": "Boolean",
683685
"categoryDate": "Date",
684-
"caregoryCondition": "Condition"
686+
"categoryCondition": "Condition"
687+
},
688+
"formulaInputContext": {
689+
"useRegularInput": "Use regular input",
690+
"useRegularInputModalTitle": "Switch to regular input?",
691+
"useAdvancedInputModalTitle": "Switch to advanced input?",
692+
"useAdvancedInput": "Use advanced input",
693+
"modalMessage": "Switching to a different input mode will clear the current formula. Are you sure you want to continue?"
694+
},
695+
"nodeExplorer": {
696+
"noResults": "No results found",
697+
"resetSearch": "Reset search"
685698
}
686699
}

web-frontend/modules/automation/components/AutomationBuilderFormulaInput.vue

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,80 @@
33
v-bind="$attrs"
44
required
55
:value="formulaStr"
6-
:data-providers="dataProviders"
7-
:application-context="applicationContext"
8-
enable-advanced-mode
9-
:mode="currentMode"
6+
:nodes-hierarchy="nodesHierarchy"
7+
context-position="left"
8+
:mode="localMode"
9+
@update:mode="updateMode"
1010
@input="updatedFormulaStr"
11-
@mode-changed="updateMode"
1211
/>
1312
</template>
1413

1514
<script setup>
16-
import { ref, watch } from 'vue'
17-
import { inject, computed, useContext } from '@nuxtjs/composition-api'
15+
import {
16+
inject,
17+
computed,
18+
useContext,
19+
ref,
20+
watch,
21+
} from '@nuxtjs/composition-api'
1822
import FormulaInputField from '@baserow/modules/core/components/formula/FormulaInputField'
23+
import { buildFormulaFunctionNodes } from '@baserow/modules/core/formula'
24+
import { getDataNodesFromDataProvider } from '@baserow/modules/core/utils/dataProviders'
1925
2026
const props = defineProps({
2127
value: { type: [Object, String], required: false, default: () => ({}) },
2228
dataProvidersAllowed: { type: Array, required: false, default: () => [] },
2329
})
2430
2531
const applicationContext = inject('applicationContext')
26-
const currentMode = ref(props.value.mode)
2732
33+
const emit = defineEmits(['input'])
34+
35+
// Local mode state
36+
const localMode = ref(props.value.mode || 'simple')
37+
38+
// Watch for external changes to the mode
2839
watch(
2940
() => props.value.mode,
3041
(newMode) => {
31-
if (newMode) {
32-
currentMode.value = newMode
42+
if (newMode !== undefined && newMode !== localMode.value) {
43+
localMode.value = newMode
3344
}
3445
}
3546
)
3647
3748
const { app } = useContext()
49+
3850
const dataProviders = computed(() => {
3951
return props.dataProvidersAllowed.map((dataProviderName) =>
4052
app.$registry.get('automationDataProvider', dataProviderName)
4153
)
4254
})
4355
56+
const nodesHierarchy = computed(() => {
57+
const hierarchy = []
58+
59+
const filteredDataNodes = getDataNodesFromDataProvider(
60+
dataProviders.value,
61+
applicationContext
62+
)
63+
64+
hierarchy.push({
65+
name: app.i18n.t('runtimeFormulaTypes.formulaTypeData'),
66+
type: 'data',
67+
icon: 'iconoir-database',
68+
nodes: filteredDataNodes,
69+
empty: filteredDataNodes.length === 0,
70+
emptyText: app.i18n.t('runtimeFormulaTypes.formulaTypeDataEmpty'),
71+
})
72+
73+
// Add functions and operators from the registry
74+
const formulaNodes = buildFormulaFunctionNodes(app)
75+
hierarchy.push(...formulaNodes)
76+
77+
return hierarchy
78+
})
79+
4480
/**
4581
* Extract the formula string from the value object, the FormulaInputField
4682
* component only needs the formula string itself.
@@ -55,16 +91,19 @@ const formulaStr = computed(() => {
5591
* entire value object with the updated formula string.
5692
* @param {String} newFormulaStr The new formula string.
5793
*/
58-
const emit = defineEmits(['input'])
5994
const updatedFormulaStr = (newFormulaStr) => {
6095
emit('input', {
6196
...props.value,
6297
formula: newFormulaStr,
63-
mode: currentMode.value,
98+
mode: localMode.value,
6499
})
65100
}
66101
102+
/**
103+
* When the mode changes, update the local mode value only
104+
* @param {String} newMode The new mode value
105+
*/
67106
const updateMode = (newMode) => {
68-
currentMode.value = newMode
107+
localMode.value = newMode
69108
}
70109
</script>

0 commit comments

Comments
 (0)