text formula

master^2
Pete Matsyburka 5 days ago
parent b8c29324b8
commit 5ec8e4ccc7

@ -69,8 +69,8 @@
:attachments-index="attachmentsIndex" :attachments-index="attachmentsIndex"
/> />
<FieldArea <FieldArea
v-else-if="item.type === 'formula_area' && isMathLoaded" v-else-if="item.type === 'formula_area' && (isMathLoaded || item.field.type === 'text')"
:model-value="calculateFormula(item.field)" :model-value="item.field.type === 'text' ? evalTextFormula(item.field) : calculateFormula(item.field)"
:is-inline-size="isInlineSize" :is-inline-size="isInlineSize"
:field="item.field" :field="item.field"
:area="item.area" :area="item.area"
@ -289,6 +289,7 @@ export default {
methods: { methods: {
normalizeFormula: FormulaAreas.methods.normalizeFormula, normalizeFormula: FormulaAreas.methods.normalizeFormula,
calculateFormula: FormulaAreas.methods.calculateFormula, calculateFormula: FormulaAreas.methods.calculateFormula,
evalTextFormula: FormulaAreas.methods.evalTextFormula,
scrollInContainer: FieldAreas.methods.scrollInContainer, scrollInContainer: FieldAreas.methods.scrollInContainer,
scrollIntoArea: FieldAreas.methods.scrollIntoArea, scrollIntoArea: FieldAreas.methods.scrollIntoArea,
scrollIntoField: FieldAreas.methods.scrollIntoField, scrollIntoField: FieldAreas.methods.scrollIntoField,

@ -12,8 +12,8 @@
:to="findPageElementForArea(area)" :to="findPageElementForArea(area)"
> >
<FieldArea <FieldArea
v-if="isMathLoaded" v-if="isMathLoaded || field.type === 'text'"
:model-value="calculateFormula(field)" :model-value="field.type === 'text' ? evalTextFormula(field) : calculateFormula(field)"
:is-inline-size="isInlineSize" :is-inline-size="isInlineSize"
:field="field" :field="field"
:area="area" :area="area"
@ -95,6 +95,25 @@ export default {
}) })
return this.math.evaluate(transformedFormula.toLowerCase()) return this.math.evaluate(transformedFormula.toLowerCase())
},
evalTextFormula (field, depth = 0) {
if (depth > 10) return ''
return field.preferences.formula.replace(/{{(.*?)}}/g, (match, uuid) => {
const formulaField = this.fieldsUuidIndex[uuid]
if (formulaField?.preferences?.formula) {
if (formulaField.type === 'text') {
return this.evalTextFormula(formulaField, depth + 1)
} else if (this.isMathLoaded) {
return this.calculateFormula(formulaField)
}
}
const value = this.readonlyValues[uuid] ?? this.values[uuid]
return Array.isArray(value) ? value.join(', ') : (value ?? '')
})
} }
} }
} }

@ -1259,7 +1259,7 @@ export default {
return formulaFields.reduce((acc, f) => { return formulaFields.reduce((acc, f) => {
if (this.conditionalFieldIndex[f.uuid] !== false) { if (this.conditionalFieldIndex[f.uuid] !== false) {
acc[f.uuid] = this.calculateFormula(f) acc[f.uuid] = f.type === 'text' ? this.evalTextFormula(f) : this.calculateFormula(f)
} }
return acc return acc
@ -1526,6 +1526,25 @@ export default {
return this.math.evaluate(transformedFormula.toLowerCase()) return this.math.evaluate(transformedFormula.toLowerCase())
}, },
evalTextFormula (field, depth = 0) {
if (depth > 10) return ''
return field.preferences.formula.replace(/{{(.*?)}}/g, (match, uuid) => {
const formulaField = this.fieldsUuidIndex[uuid]
if (formulaField?.preferences?.formula) {
if (formulaField.type === 'text') {
return this.evalTextFormula(formulaField, depth + 1)
} else if (this.isMathLoaded) {
return this.calculateFormula(formulaField)
}
}
const value = formulaField?.default_value
return Array.isArray(value) ? value.join(', ') : (value ?? '')
})
},
hasFormulaDependencyValue (field) { hasFormulaDependencyValue (field) {
const normalized = this.normalizeFormula(field.preferences.formula) const normalized = this.normalizeFormula(field.preferences.formula)

@ -611,7 +611,7 @@ export default {
return this.withCondition && !['stamp', 'heading'].includes(this.field.type) return this.withCondition && !['stamp', 'heading'].includes(this.field.type)
}, },
showFormula () { showFormula () {
return this.field.type === 'number' || this.field.type === 'payment' return this.field.type === 'number' || this.field.type === 'payment' || !!this.field.preferences?.formula
}, },
showRequired () { showRequired () {
return this.withRequired && !['phone', 'stamp', 'verification', 'strikethrough', 'heading'].includes(this.field.type) return this.withRequired && !['phone', 'stamp', 'verification', 'strikethrough', 'heading'].includes(this.field.type)

@ -500,7 +500,7 @@
</label> </label>
</li> </li>
<li <li
v-if="field.type == 'number'" v-if="field.type == 'number' || field.preferences?.formula"
class="field-settings-formula" class="field-settings-formula"
> >
<label <label

@ -61,7 +61,10 @@
@input="resizeTextarea" @input="resizeTextarea"
/> />
</div> </div>
<div class="mb-3 mt-1"> <div
v-if="field.type !== 'text'"
class="mb-3 mt-1"
>
<div <div
target="blank" target="blank"
class="text-sm mb-2 inline space-x-2 font-mono" class="text-sm mb-2 inline space-x-2 font-mono"
@ -161,7 +164,9 @@ export default {
computed: { computed: {
fields () { fields () {
return this.template.fields.reduce((acc, f) => { return this.template.fields.reduce((acc, f) => {
if (f !== this.field && this.isNumberField(f) && (!f.preferences?.formula || !f.preferences.formula.includes(this.field.uuid))) { const isAllowed = this.field.type === 'text' ? this.isTextField(f) : this.isNumberField(f)
if (f !== this.field && isAllowed && (!f.preferences?.formula || !f.preferences.formula.includes(this.field.uuid))) {
acc.push(f) acc.push(f)
} }
@ -179,6 +184,9 @@ export default {
isNumberField (field) { isNumberField (field) {
return field.type === 'number' || (['radio', 'select'].includes(field.type) && field.options?.every((o) => String(o.value).match(/^[\d.-]+$/))) return field.type === 'number' || (['radio', 'select'].includes(field.type) && field.options?.every((o) => String(o.value).match(/^[\d.-]+$/)))
}, },
isTextField (field) {
return ['text', 'number', 'select', 'radio', 'cells', 'phone'].includes(field.type)
},
humanizeFormula (text) { humanizeFormula (text) {
return text.replace(/{{(.*?)}}/g, (match, uuid) => { return text.replace(/{{(.*?)}}/g, (match, uuid) => {
const foundField = this.template.fields.find((f) => f.uuid === uuid) const foundField = this.template.fields.find((f) => f.uuid === uuid)

@ -220,9 +220,16 @@ module Submitters
submitter.values submitter.values
end end
formula = normalize_formula(formula, submitter.submission, submission_values:) values = submission_values.merge(acc.compact_blank)
acc[field['uuid']] = calculate_formula_value(formula, submission_values.merge(acc.compact_blank)) acc[field['uuid']] =
if field['type'] == 'text'
eval_text_formula_value(formula, values, submitter.submission)
else
normalized_formula = normalize_formula(formula, submitter.submission, submission_values:)
calculate_formula_value(normalized_formula, values)
end
end end
computed_values.compact_blank computed_values.compact_blank
@ -250,6 +257,10 @@ module Submitters
0 0
end end
def eval_text_formula_value(_formula, _values, _submission)
''
end
def replace_current_date_placeholders(submitter) def replace_current_date_placeholders(submitter)
submitter.values.each_with_object({}) do |(uuid, v), acc| submitter.values.each_with_object({}) do |(uuid, v), acc|
acc[uuid] = acc[uuid] =

Loading…
Cancel
Save