mirror of
https://github.com/PanJiaChen/vue-element-admin.git
synced 2025-08-10 20:39:48 +08:00
* fix: #401 Display logic's showed fields. * Update evaluator.js * minor changes.
This commit is contained in:
parent
7fe04ce531
commit
20dfa472b1
@ -15,11 +15,11 @@
|
||||
:class="classField"
|
||||
>
|
||||
<el-form-item
|
||||
:required="isMandatory()"
|
||||
:required="isMandatory"
|
||||
>
|
||||
<template slot="label">
|
||||
<operator-comparison
|
||||
v-if="isAdvancedQuery && isDisplayed"
|
||||
v-if="isAdvancedQuery"
|
||||
key="is-field-operator-comparison"
|
||||
:field-attributes="fieldAttributes"
|
||||
:field-value="field.value"
|
||||
@ -31,14 +31,13 @@
|
||||
:field-value="field.value"
|
||||
/>
|
||||
<span v-else key="is-field-name">
|
||||
{{ isFieldOnly() }}
|
||||
{{ isFieldOnly }}
|
||||
</span>
|
||||
|
||||
<document-status
|
||||
v-if="isDocuemntStatus"
|
||||
:field="fieldAttributes"
|
||||
/>
|
||||
|
||||
<translated
|
||||
v-if="field.isTranslated && !isAdvancedQuery"
|
||||
:field-attributes="fieldAttributes"
|
||||
@ -134,8 +133,8 @@ export default {
|
||||
inTable: this.inTable,
|
||||
isAdvancedQuery: this.isAdvancedQuery,
|
||||
// DOM properties
|
||||
required: this.isMandatory(),
|
||||
readonly: this.isReadOnly(),
|
||||
required: this.isMandatory,
|
||||
readonly: this.isReadOnly,
|
||||
displayed: this.isDisplayed,
|
||||
disabled: !this.field.isActive,
|
||||
isSelectCreated: this.isSelectCreated
|
||||
@ -145,7 +144,63 @@ export default {
|
||||
if (this.isAdvancedQuery) {
|
||||
return this.field.isShowedFromUser
|
||||
}
|
||||
return fieldIsDisplayed(this.field) && (this.isMandatory() || this.field.isShowedFromUser || this.inTable)
|
||||
return fieldIsDisplayed(this.field) && (this.isMandatory || this.field.isShowedFromUser || this.inTable)
|
||||
},
|
||||
isMandatory() {
|
||||
if (this.isAdvancedQuery) {
|
||||
return false
|
||||
}
|
||||
return this.field.isMandatory || this.field.isMandatoryFromLogic
|
||||
},
|
||||
isReadOnly() {
|
||||
if (this.isAdvancedQuery) {
|
||||
if (['NULL', 'NOT_NULL'].includes(this.field.operator)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (!this.field.isActive) {
|
||||
return true
|
||||
}
|
||||
|
||||
const isUpdateableAllFields = this.field.isReadOnly || this.field.isReadOnlyFromLogic
|
||||
|
||||
if (this.field.panelType === 'window') {
|
||||
if (this.field.isAlwaysUpdateable) {
|
||||
return false
|
||||
}
|
||||
if (this.getterContextProcessing) {
|
||||
return true
|
||||
}
|
||||
if (this.getterContextProcessed) {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: Evaluate record uuid without route.action
|
||||
// edit mode is diferent to create new
|
||||
let isWithRecord = this.field.recordUuid !== 'create-new'
|
||||
if (this.inTable) {
|
||||
isWithRecord = !this.isEmptyValue(this.field.recordUuid)
|
||||
}
|
||||
|
||||
return (!this.field.isUpdateable && isWithRecord) || (isUpdateableAllFields || this.field.isReadOnlyFromForm)
|
||||
} else if (this.field.panelType === 'browser') {
|
||||
if (this.inTable) {
|
||||
// browser result
|
||||
return this.field.isReadOnly
|
||||
}
|
||||
// query criteria
|
||||
return this.field.isReadOnlyFromLogic
|
||||
}
|
||||
// other type of panels (process/report)
|
||||
return isUpdateableAllFields
|
||||
},
|
||||
isFieldOnly() {
|
||||
if (this.inTable || this.field.isFieldOnly) {
|
||||
return undefined
|
||||
}
|
||||
return this.field.name
|
||||
},
|
||||
isSelectCreated() {
|
||||
return this.isAdvancedQuery &&
|
||||
@ -273,64 +328,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
showMessage,
|
||||
isReadOnly() {
|
||||
if (this.isAdvancedQuery) {
|
||||
if (['NULL', 'NOT_NULL'].includes(this.field.operator)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (!this.field.isActive) {
|
||||
return true
|
||||
}
|
||||
|
||||
const isUpdateableAllFields = this.field.isReadOnly || this.field.isReadOnlyFromLogic
|
||||
|
||||
if (this.field.panelType === 'window') {
|
||||
if (this.field.isAlwaysUpdateable) {
|
||||
return false
|
||||
}
|
||||
if (this.getterContextProcessing) {
|
||||
return true
|
||||
}
|
||||
if (this.getterContextProcessed) {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: Evaluate record uuid without route.action
|
||||
// edit mode is diferent to create new
|
||||
let isWithRecord = this.field.recordUuid !== 'create-new'
|
||||
if (this.inTable) {
|
||||
isWithRecord = !this.isEmptyValue(this.field.recordUuid)
|
||||
}
|
||||
|
||||
return (!this.field.isUpdateable && isWithRecord) || (isUpdateableAllFields || this.field.isReadOnlyFromForm)
|
||||
} else if (this.field.panelType === 'browser') {
|
||||
if (this.inTable) {
|
||||
// browser result
|
||||
return this.field.isReadOnly
|
||||
}
|
||||
// query criteria
|
||||
return this.field.isReadOnlyFromLogic
|
||||
}
|
||||
// other type of panels (process/report)
|
||||
return isUpdateableAllFields
|
||||
},
|
||||
isMandatory() {
|
||||
if (this.isAdvancedQuery) {
|
||||
return false
|
||||
}
|
||||
return this.field.isMandatory || this.field.isMandatoryFromLogic
|
||||
},
|
||||
isFieldOnly() {
|
||||
if (this.inTable || this.field.isFieldOnly) {
|
||||
return undefined
|
||||
}
|
||||
return this.field.name
|
||||
},
|
||||
focusField() {
|
||||
if (this.isDisplayed && this.isMandatory() && !this.isReadOnly()) {
|
||||
if (this.isDisplayed && this.isMandatory && !this.isReadOnly) {
|
||||
this.$refs[this.field.columnName].activeFocus()
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
// - Process & Report: Always save a panel and parameters
|
||||
// - Smart Browser: Can have a search panel, table panel and process panel
|
||||
import { isEmptyValue, parsedValueComponent } from '@/utils/ADempiere/valueUtils'
|
||||
import evaluator, { parseContext } from '@/utils/ADempiere/contextUtils'
|
||||
import evaluator, { getContext, parseContext } from '@/utils/ADempiere/contextUtils'
|
||||
import { showMessage } from '@/utils/ADempiere/notification'
|
||||
import { assignedGroup, fieldIsDisplayed } from '@/utils/ADempiere/dictionaryUtils'
|
||||
import router from '@/router'
|
||||
@ -775,28 +775,27 @@ const panel = {
|
||||
dependentsList.map(async fieldDependent => {
|
||||
// isDisplayed Logic
|
||||
let isDisplayedFromLogic, isMandatoryFromLogic, isReadOnlyFromLogic, defaultValue
|
||||
if (fieldDependent.displayLogic.trim() !== '') {
|
||||
if (!isEmptyValue(fieldDependent.displayLogic)) {
|
||||
isDisplayedFromLogic = evaluator.evaluateLogic({
|
||||
context: getters,
|
||||
context: getContext,
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
logic: fieldDependent.displayLogic,
|
||||
type: 'displayed'
|
||||
logic: fieldDependent.displayLogic
|
||||
})
|
||||
}
|
||||
// Mandatory Logic
|
||||
if (fieldDependent.mandatoryLogic.trim() !== '') {
|
||||
if (!isEmptyValue(fieldDependent.mandatoryLogic)) {
|
||||
isMandatoryFromLogic = evaluator.evaluateLogic({
|
||||
context: getters,
|
||||
context: getContext,
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
logic: fieldDependent.mandatoryLogic
|
||||
})
|
||||
}
|
||||
// Read Only Logic
|
||||
if (fieldDependent.readOnlyLogic.trim() !== '') {
|
||||
if (!isEmptyValue(fieldDependent.readOnlyLogic)) {
|
||||
isReadOnlyFromLogic = evaluator.evaluateLogic({
|
||||
context: getters,
|
||||
context: getContext,
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
logic: fieldDependent.readOnlyLogic
|
||||
|
@ -129,7 +129,7 @@ export function parseContext({
|
||||
}
|
||||
}
|
||||
if (contextInfo === undefined || contextInfo.length === 0) {
|
||||
console.info(`No Context for: ${token}`)
|
||||
// console.info(`No Context for: ${token}`)
|
||||
isError = true
|
||||
errorsList.push(token)
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import evaluator from '@/utils/ADempiere/evaluator'
|
||||
import { isEmptyValue, parsedValueComponent } from '@/utils/ADempiere/valueUtils'
|
||||
import { getParentFields, getPreference, parseContext } from '@/utils/ADempiere/contextUtils'
|
||||
import { getContext, getParentFields, getPreference, parseContext } from '@/utils/ADempiere/contextUtils'
|
||||
import REFERENCES, { FIELD_NOT_SHOWED } from '@/components/ADempiere/Field/references'
|
||||
import { FIELD_DISPLAY_SIZES, DEFAULT_SIZE } from '@/components/ADempiere/Field/fieldSize'
|
||||
import language from '@/lang'
|
||||
@ -26,7 +26,10 @@ export function generateField({
|
||||
|
||||
const componentReference = evalutateTypeField(fieldToGenerate.displayType, true)
|
||||
const referenceType = componentReference.alias[0]
|
||||
|
||||
let isDisplayedFromLogic = fieldToGenerate.isDisplayed
|
||||
let isMandatoryFromLogic = false
|
||||
let isReadOnlyFromLogic = false
|
||||
let parentFieldsList = []
|
||||
let parsedDefaultValue = fieldToGenerate.defaultValue
|
||||
let parsedDefaultValueTo = fieldToGenerate.defaultValueTo
|
||||
let operator = 'EQUAL'
|
||||
@ -116,6 +119,33 @@ export function generateField({
|
||||
referenceType,
|
||||
isMandatory: fieldToGenerate.isMandatory
|
||||
})
|
||||
|
||||
parentFieldsList = getParentFields(fieldToGenerate)
|
||||
|
||||
// evaluate logics
|
||||
const setEvaluateLogics = {
|
||||
parentUuid: moreAttributes.parentUuid,
|
||||
containerUuid: moreAttributes.containerUuid,
|
||||
context: getContext
|
||||
}
|
||||
if (!isEmptyValue(fieldToGenerate.displayLogic)) {
|
||||
isDisplayedFromLogic = evaluator.evaluateLogic({
|
||||
...setEvaluateLogics,
|
||||
logic: fieldToGenerate.displayLogic
|
||||
})
|
||||
}
|
||||
if (!isEmptyValue(fieldToGenerate.mandatoryLogic)) {
|
||||
isMandatoryFromLogic = evaluator.evaluateLogic({
|
||||
...setEvaluateLogics,
|
||||
logic: fieldToGenerate.mandatoryLogic
|
||||
})
|
||||
}
|
||||
if (!isEmptyValue(fieldToGenerate.readOnlyLogic)) {
|
||||
isReadOnlyFromLogic = evaluator.evaluateLogic({
|
||||
...setEvaluateLogics,
|
||||
logic: fieldToGenerate.readOnlyLogic
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const field = {
|
||||
@ -134,11 +164,11 @@ export function generateField({
|
||||
parsedDefaultValue,
|
||||
parsedDefaultValueTo,
|
||||
// logics to app
|
||||
isDisplayedFromLogic: fieldToGenerate.isDisplayed,
|
||||
isReadOnlyFromLogic: false,
|
||||
isMandatoryFromLogic: false,
|
||||
isDisplayedFromLogic,
|
||||
isReadOnlyFromLogic,
|
||||
isMandatoryFromLogic,
|
||||
//
|
||||
parentFieldsList: [],
|
||||
parentFieldsList,
|
||||
dependentFieldsList: [],
|
||||
// TODO: Add support on server
|
||||
// app attributes
|
||||
@ -152,31 +182,6 @@ export function generateField({
|
||||
defaultOperator: operator
|
||||
}
|
||||
|
||||
// evaluate simple logics without context
|
||||
if (!field.isAdvancedQuery) {
|
||||
field.parentFieldsList = getParentFields(fieldToGenerate)
|
||||
|
||||
if (field.displayLogic.trim() !== '' && !field.displayLogic.includes('@')) {
|
||||
field.isDisplayedFromLogic = evaluator.evaluateLogic({
|
||||
type: 'displayed',
|
||||
logic: field.displayLogic
|
||||
})
|
||||
field.isDisplayedFromLogic = Boolean(field.isDisplayedFromLogic)
|
||||
}
|
||||
if (field.mandatoryLogic.trim() !== '' && !field.mandatoryLogic.includes('@')) {
|
||||
field.isMandatoryFromLogic = evaluator.evaluateLogic({
|
||||
logic: field.mandatoryLogic
|
||||
})
|
||||
field.isMandatoryFromLogic = Boolean(field.isMandatoryFromLogic)
|
||||
}
|
||||
if (field.readOnlyLogic.trim() !== '' && !field.readOnlyLogic.includes('@')) {
|
||||
field.isReadOnlyFromLogic = evaluator.evaluateLogic({
|
||||
logic: field.readOnlyLogic
|
||||
})
|
||||
field.isReadOnlyFromLogic = Boolean(field.isReadOnlyFromLogic)
|
||||
}
|
||||
}
|
||||
|
||||
// Sizes from panel and groups
|
||||
field.sizeFieldFromType = FIELD_DISPLAY_SIZES.find(item => {
|
||||
return item.type === field.componentPath
|
||||
@ -201,9 +206,7 @@ export function generateField({
|
||||
|
||||
// hidden field type button
|
||||
const notShowedField = FIELD_NOT_SHOWED.find(itemField => {
|
||||
if (field.displayType === itemField.id) {
|
||||
return true
|
||||
}
|
||||
return field.displayType === itemField.id
|
||||
})
|
||||
if (notShowedField) {
|
||||
field.isDisplayedFromLogic = false
|
||||
|
@ -15,26 +15,29 @@ class evaluator {
|
||||
/**
|
||||
* Evaluate logic's
|
||||
* @param {string} parentUuid Parent (Window / Process / Smart Browser)
|
||||
* @param {function} context
|
||||
* @param {string} logic
|
||||
* @param {boolean} defaultReturned value to return if logic or context is undefined
|
||||
*/
|
||||
static evaluateLogic(objectToEvaluate) {
|
||||
let defaultUndefined = false
|
||||
if (objectToEvaluate.type === 'displayed') {
|
||||
defaultUndefined = true
|
||||
}
|
||||
static evaluateLogic({
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
context,
|
||||
logic,
|
||||
defaultReturned = false
|
||||
}) {
|
||||
// empty logic
|
||||
if (objectToEvaluate.logic === undefined ||
|
||||
objectToEvaluate.logic === null ||
|
||||
objectToEvaluate.logic.trim() === '') {
|
||||
return defaultUndefined
|
||||
if (logic === undefined || logic === null || logic.trim() === '') {
|
||||
return defaultReturned
|
||||
}
|
||||
const st = objectToEvaluate.logic.trim().replace('\n', '')
|
||||
const st = logic.trim().replace('\n', '')
|
||||
const expr = /(\||&)/
|
||||
const stList = st.split(expr)
|
||||
const it = stList.length
|
||||
|
||||
if (((it / 2) - ((it + 1) / 2)) === 0) {
|
||||
console.info(`Logic does not comply with format "<expression> [<logic> <expression>]" --> ${objectToEvaluate.logic}`)
|
||||
return defaultUndefined
|
||||
console.info(`Logic does not comply with format "<expression> [<logic> <expression>]" --> ${logic}`)
|
||||
return defaultReturned
|
||||
}
|
||||
|
||||
let retValue = null
|
||||
@ -44,23 +47,32 @@ class evaluator {
|
||||
logOp = element
|
||||
} else if (retValue === null) {
|
||||
retValue = evaluator.evaluateLogicTuples({
|
||||
...objectToEvaluate,
|
||||
conditional: element
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
context,
|
||||
logic: element,
|
||||
defaultReturned
|
||||
})
|
||||
} else {
|
||||
if (logOp.trim() === '&') {
|
||||
retValue = retValue & evaluator.evaluateLogicTuples({
|
||||
...objectToEvaluate,
|
||||
conditional: element
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
context,
|
||||
logic: element,
|
||||
defaultReturned
|
||||
})
|
||||
} else if (logOp.trim() === '|') {
|
||||
retValue = retValue | evaluator.evaluateLogicTuples({
|
||||
...objectToEvaluate,
|
||||
conditional: element
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
context,
|
||||
logic: element,
|
||||
defaultReturned
|
||||
})
|
||||
} else {
|
||||
console.info(`Logic operant '|' or '&' expected --> ${objectToEvaluate.logic}`)
|
||||
return defaultUndefined
|
||||
console.info(`Logic operant '|' or '&' expected --> ${logic}`)
|
||||
return defaultReturned
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -69,19 +81,23 @@ class evaluator {
|
||||
|
||||
/**
|
||||
* Evaluate Logic Tuples
|
||||
* @param {object} objectToEvaluate Complete object
|
||||
* @param {string} parentUuid Complete object
|
||||
* @param {string} containerUuid Complete object
|
||||
* @param {function} context
|
||||
* @param {string} logic If is displayed or not (mandatory and readonly)
|
||||
* @param {boolean} defaultReturned
|
||||
* @return {boolean}
|
||||
*/
|
||||
static evaluateLogicTuples(objectToEvaluate) {
|
||||
let _defaultUndefined = false
|
||||
if (objectToEvaluate.type === 'displayed') {
|
||||
_defaultUndefined = true
|
||||
}
|
||||
const logic = objectToEvaluate.conditional
|
||||
static evaluateLogicTuples({
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
context,
|
||||
defaultReturned = false,
|
||||
logic
|
||||
}) {
|
||||
// not context info, not logic
|
||||
if (logic === undefined) {
|
||||
return _defaultUndefined
|
||||
if (logic === undefined || logic === null || logic.trim() === '') {
|
||||
return defaultReturned
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +113,7 @@ class evaluator {
|
||||
|
||||
if (!st) {
|
||||
console.info(`.Logic tuple does not comply with format '@context@=value' where operand could be one of '=!^><' --> ${logic}`)
|
||||
return _defaultUndefined
|
||||
return defaultReturned
|
||||
}
|
||||
|
||||
expr = /(<>|<=|==|>=|!=|<|=|>|!|\^)/gm
|
||||
@ -113,21 +129,26 @@ class evaluator {
|
||||
first = first.replace(/@/g, '').trim()
|
||||
isGlobal = first.startsWith('#')
|
||||
isCountable = first.startsWith('$')
|
||||
const value = objectToEvaluate.context.getContext({
|
||||
parentUuid: (isGlobal || isCountable) ? '' : objectToEvaluate.parentUuid,
|
||||
containerUuid: (isGlobal || isCountable) ? '' : objectToEvaluate.containerUuid,
|
||||
if (isGlobal || isCountable) {
|
||||
parentUuid = null
|
||||
containerUuid = null
|
||||
}
|
||||
|
||||
const value = context({
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
columnName: first
|
||||
})
|
||||
// in context exists this column name
|
||||
if (value === null || value === undefined) {
|
||||
// console.info(`.The column ${first} not exists in context.`)
|
||||
return _defaultUndefined
|
||||
return defaultReturned
|
||||
}
|
||||
firstEval = value // replace with it's value
|
||||
}
|
||||
|
||||
if (firstEval === null || firstEval === undefined) {
|
||||
return _defaultUndefined
|
||||
return defaultReturned
|
||||
}
|
||||
if (typeof firstEval === 'string') {
|
||||
firstEval = firstEval.replace(/['"]/g, '').trim() // strip ' and "
|
||||
@ -140,9 +161,9 @@ class evaluator {
|
||||
let secondEval = second.trim()
|
||||
if (expr.test(second)) {
|
||||
second = second.replace(/@/g, ' ').trim() // strip tag
|
||||
secondEval = objectToEvaluate.context.getContext({
|
||||
parentUuid: (isGlobal || isCountable) ? null : objectToEvaluate.parentUuid,
|
||||
containerUuid: (isGlobal || isCountable) ? null : objectToEvaluate.containerUuid,
|
||||
secondEval = context({
|
||||
parentUuid,
|
||||
containerUuid,
|
||||
columnName: first
|
||||
}) // replace with it's value
|
||||
}
|
||||
@ -161,7 +182,7 @@ class evaluator {
|
||||
// Logical Comparison
|
||||
const result = this.evaluateLogicTuple(firstEval, operand, secondEval)
|
||||
|
||||
return result
|
||||
return Boolean(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,19 +193,21 @@ class evaluator {
|
||||
* @return {boolean}
|
||||
*/
|
||||
static evaluateLogicTuple(value1, operand, value2) {
|
||||
// Convert value 1 string value to boolean value
|
||||
if (value1 === 'Y') {
|
||||
value1 = true
|
||||
} else if (value1 === 'N') {
|
||||
value1 = false
|
||||
const convertStringToBoolean = (valueToParsed) => {
|
||||
const valueString = String(valueToParsed).trim()
|
||||
if (valueString === 'Y') {
|
||||
return true
|
||||
} else if (valueString === 'N') {
|
||||
return false
|
||||
}
|
||||
return valueToParsed
|
||||
}
|
||||
|
||||
// Convert value 1 string value to boolean value
|
||||
value1 = convertStringToBoolean(value1)
|
||||
|
||||
// Convert value 2 string value to boolean value
|
||||
if (value2 === 'Y') {
|
||||
value2 = true
|
||||
} else if (value2 === 'N') {
|
||||
value2 = false
|
||||
}
|
||||
value2 = convertStringToBoolean(value2)
|
||||
|
||||
let isValueLogic
|
||||
// TODO: Add '^' operand comparison
|
||||
|
Loading…
x
Reference in New Issue
Block a user