mirror of
https://github.com/docusealco/docuseal
synced 2026-11-05 06:42:32 -05:00
date formulas
This commit is contained in:
1 parent
ca7b9671f2
commit
439f95d87e
10 files changed
+150
-25
No files matched your search
@@ -125,6 +125,11 @@ export default {
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
fieldsUuidIndex: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
values: {
|
||||
type: Object,
|
||||
required: false,
|
||||
@@ -195,7 +200,7 @@ export default {
|
||||
},
|
||||
isMobileContainer: FieldAreas.computed.isMobileContainer,
|
||||
isInlineSize: FieldAreas.computed.isInlineSize,
|
||||
fieldsUuidIndex () {
|
||||
formulaFieldsUuidIndex () {
|
||||
return this.formulaFields.reduce((acc, field) => {
|
||||
acc[field.uuid] = field
|
||||
|
||||
@@ -289,6 +294,7 @@ export default {
|
||||
methods: {
|
||||
normalizeFormula: FormulaAreas.methods.normalizeFormula,
|
||||
calculateFormula: FormulaAreas.methods.calculateFormula,
|
||||
dateFormulaValue: FormulaAreas.methods.dateFormulaValue,
|
||||
evalTextFormula: FormulaAreas.methods.evalTextFormula,
|
||||
scrollInContainer: FieldAreas.methods.scrollInContainer,
|
||||
scrollIntoArea: FieldAreas.methods.scrollIntoArea,
|
||||
|
||||
@@ -633,6 +633,32 @@ defineFunction('contains', {
|
||||
return String(v[0]).indexOf(String(v[1])) !== -1
|
||||
}
|
||||
})
|
||||
defineFunction('today', {
|
||||
min: 0,
|
||||
max: 0,
|
||||
call: () => {
|
||||
const now = new Date()
|
||||
return Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) / 86400000
|
||||
}
|
||||
})
|
||||
defineFunction('datedif', {
|
||||
min: 3,
|
||||
max: 3,
|
||||
call: (v) => {
|
||||
if (v[0] == null || v[1] == null) return null
|
||||
const start = toNumber(v[0])
|
||||
const end = toNumber(v[1])
|
||||
const unit = String(v[2]).toLowerCase()
|
||||
if (unit === 'd') return end - start
|
||||
const from = new Date(Math.min(start, end) * 86400000)
|
||||
const to = new Date(Math.max(start, end) * 86400000)
|
||||
const months = (to.getUTCFullYear() - from.getUTCFullYear()) * 12 + to.getUTCMonth() - from.getUTCMonth() - (to.getUTCDate() < from.getUTCDate() ? 1 : 0)
|
||||
const sign = end < start ? -1 : 1
|
||||
if (unit === 'm') return sign * months
|
||||
if (unit === 'y') return sign * Math.floor(months / 12)
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
const OP_CLASSES = {
|
||||
add: Addition,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
:readonly-conditional-fields="readonlyConditionalFields"
|
||||
:readonly-conditional-field-values="readonlyConditionalFieldValues"
|
||||
:formula-fields="formulaFields"
|
||||
:fields-uuid-index="fieldsUuidIndex"
|
||||
:values="values"
|
||||
:readonly-values="readonlyFieldValues"
|
||||
:submitter="submitter"
|
||||
@@ -71,6 +72,7 @@
|
||||
<FormulaFieldAreas
|
||||
v-if="!withAccessibilityAreas && !isAccessibilityMode && formulaFields.length"
|
||||
:fields="formulaFields"
|
||||
:fields-uuid-index="fieldsUuidIndex"
|
||||
:readonly-values="readonlyFieldValues"
|
||||
:values="values"
|
||||
/>
|
||||
@@ -560,6 +562,7 @@
|
||||
:field="currentField"
|
||||
:submitter-slug="submitterSlug"
|
||||
:fields="formulaFields"
|
||||
:fields-uuid-index="fieldsUuidIndex"
|
||||
:values="values"
|
||||
:readonly-values="readonlyFieldValues"
|
||||
:fetch-options="fetchOptions"
|
||||
|
||||
@@ -48,6 +48,11 @@ export default {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
fieldsUuidIndex: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -59,7 +64,7 @@ export default {
|
||||
isInlineSize () {
|
||||
return CSS.supports('container-type: size')
|
||||
},
|
||||
fieldsUuidIndex () {
|
||||
formulaFieldsUuidIndex () {
|
||||
return this.fields.reduce((acc, field) => {
|
||||
acc[field.uuid] = field
|
||||
|
||||
@@ -82,8 +87,8 @@ export default {
|
||||
if (depth > 10) return formula
|
||||
|
||||
return formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
if (this.fieldsUuidIndex[uuid]) {
|
||||
return `(${this.normalizeFormula(this.fieldsUuidIndex[uuid].preferences.formula, depth + 1)})`
|
||||
if (this.formulaFieldsUuidIndex[uuid]) {
|
||||
return `(${this.normalizeFormula(this.formulaFieldsUuidIndex[uuid].preferences.formula, depth + 1)})`
|
||||
} else {
|
||||
return match
|
||||
}
|
||||
@@ -91,16 +96,36 @@ export default {
|
||||
},
|
||||
calculateFormula (field) {
|
||||
const transformedFormula = this.normalizeFormula(field.preferences.formula).replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
return this.readonlyValues[uuid] || this.values[uuid] || 0.0
|
||||
const value = this.readonlyValues[uuid] || this.values[uuid]
|
||||
|
||||
if (this.fieldsUuidIndex[uuid]?.type === 'date') {
|
||||
return this.dateFormulaValue(value)
|
||||
}
|
||||
|
||||
return value || 0.0
|
||||
})
|
||||
|
||||
return this.math.evaluate(transformedFormula.toLowerCase())
|
||||
const value = this.math.evaluate(transformedFormula.toLowerCase())
|
||||
|
||||
if (field.type === 'date') {
|
||||
return Number.isFinite(value) ? new Date(Math.floor(value) * 86400000).toISOString().slice(0, 10) : ''
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
dateFormulaValue (value) {
|
||||
if (!value) return 'null'
|
||||
if (value === '{{date}}') return 'today()'
|
||||
|
||||
const [year, month, day = 1] = value.slice(0, 10).split('-').map(Number)
|
||||
|
||||
return Date.UTC(year, month - 1, day) / 86400000
|
||||
},
|
||||
evalTextFormula (field, depth = 0) {
|
||||
if (depth > 10) return ''
|
||||
|
||||
return field.preferences.formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
const formulaField = this.fieldsUuidIndex[uuid]
|
||||
const formulaField = this.formulaFieldsUuidIndex[uuid]
|
||||
|
||||
if (formulaField?.preferences?.formula) {
|
||||
if (formulaField.type === 'text') {
|
||||
|
||||
@@ -104,6 +104,11 @@ export default {
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
fieldsUuidIndex: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
values: {
|
||||
type: Object,
|
||||
required: true
|
||||
@@ -137,7 +142,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fieldsUuidIndex () {
|
||||
formulaFieldsUuidIndex () {
|
||||
return this.fields.reduce((acc, field) => {
|
||||
acc[field.uuid] = field
|
||||
|
||||
@@ -216,17 +221,31 @@ export default {
|
||||
},
|
||||
calculateFormula () {
|
||||
const transformedFormula = this.normalizeFormula(this.field.preferences.formula).replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
return this.readonlyValues[uuid] || this.values[uuid] || 0.0
|
||||
const value = this.readonlyValues[uuid] || this.values[uuid]
|
||||
|
||||
if (this.fieldsUuidIndex[uuid]?.type === 'date') {
|
||||
return this.dateFormulaValue(value)
|
||||
}
|
||||
|
||||
return value || 0.0
|
||||
})
|
||||
|
||||
return this.math.evaluate(transformedFormula.toLowerCase())
|
||||
},
|
||||
dateFormulaValue (value) {
|
||||
if (!value) return 'null'
|
||||
if (value === '{{date}}') return 'today()'
|
||||
|
||||
const [year, month, day = 1] = value.slice(0, 10).split('-').map(Number)
|
||||
|
||||
return Date.UTC(year, month - 1, day) / 86400000
|
||||
},
|
||||
normalizeFormula (formula, depth = 0) {
|
||||
if (depth > 10) return formula
|
||||
|
||||
return formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
if (this.fieldsUuidIndex[uuid]) {
|
||||
return `(${this.normalizeFormula(this.fieldsUuidIndex[uuid].preferences.formula, depth + 1)})`
|
||||
if (this.formulaFieldsUuidIndex[uuid]) {
|
||||
return `(${this.normalizeFormula(this.formulaFieldsUuidIndex[uuid].preferences.formula, depth + 1)})`
|
||||
} else {
|
||||
return match
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user