1
0
mirror of https://github.com/PanJiaChen/vue-element-admin.git synced 2025-08-13 23:20:12 +08:00

Improves/reduce create form (#457)

* improves: Reduce and more easy create news Forms.

* fix: Overwrite template metadata component with metadata prop from mixin

* Add search from server for product price inquiry

* add isEvaluateValueChanges.

* Add support to latest version from POS client

* Add clean for all fields

* add style with prop cssClassName

* Add style for components

* fix subscribe mutation's and add set value and set values.

* Change error by info for form

Co-authored-by: Edwin Betancourt <EdwinBetanc0urt@hotmail.com>
This commit is contained in:
Yamel Senih 2020-04-23 20:26:18 -04:00 committed by GitHub
parent a52d2ee0de
commit 9d59700aa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 529 additions and 397 deletions

View File

@ -46,9 +46,9 @@
"dependencies": { "dependencies": {
"@adempiere/grpc-access-client": "^1.1.8", "@adempiere/grpc-access-client": "^1.1.8",
"@adempiere/grpc-data-client": "^2.2.3", "@adempiere/grpc-data-client": "^2.2.3",
"@adempiere/grpc-pos-client": "^1.0.4",
"@adempiere/grpc-dictionary-client": "^1.3.9", "@adempiere/grpc-dictionary-client": "^1.3.9",
"@adempiere/grpc-enrollment-client": "^1.0.7", "@adempiere/grpc-enrollment-client": "^1.0.7",
"@adempiere/grpc-pos-client": "^1.0.7",
"autoprefixer": "^9.5.1", "autoprefixer": "^9.5.1",
"axios": "0.18.0", "axios": "0.18.0",
"clipboard": "2.0.4", "clipboard": "2.0.4",

View File

@ -1,15 +1,17 @@
import { getLanguage } from '@/lang/index' import { getLanguage } from '@/lang/index'
import { getToken } from '@/utils/auth' import { getToken, getCurrentOrganization, getCurrentWarehouse } from '@/utils/auth'
import POS from '@adempiere/grpc-pos-client' import POS from '@adempiere/grpc-pos-client'
import { BUSINESS_DATA_ADDRESS } from '@/api/ADempiere/constants' import { BUSINESS_DATA_ADDRESS } from '@/api/ADempiere/constants'
// Get Instance for connection // Get Instance for connection
function Instance() { function Instance() {
return new POS( return new POS({
BUSINESS_DATA_ADDRESS, host: BUSINESS_DATA_ADDRESS,
getToken(), sessionUuid: getToken(),
getLanguage() || 'en_US' organizationUuid: getCurrentOrganization(),
) warehouseUuid: getCurrentWarehouse(),
language: getLanguage() || 'en_US'
})
} }
export function getProductPrice({ export function getProductPrice({

View File

@ -6,7 +6,7 @@
:on-remove="handleRemove" :on-remove="handleRemove"
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
class="image-uploader" :class="'image-uploader ' + metadata.cssClassName"
action="https://jsonplaceholder.typicode.com/posts/" action="https://jsonplaceholder.typicode.com/posts/"
:disabled="isDisabled" :disabled="isDisabled"
@change="preHandleChange" @change="preHandleChange"

View File

@ -4,6 +4,7 @@
v-model="value" v-model="value"
show-alpha show-alpha
:disabled="isDisabled" :disabled="isDisabled"
:class="metadata.cssClassName"
@change="preHandleChange" @change="preHandleChange"
/> />
</template> </template>

View File

@ -10,10 +10,10 @@
:start-placeholder="$t('components.dateStartPlaceholder')" :start-placeholder="$t('components.dateStartPlaceholder')"
:end-placeholder="$t('components.dateEndPlaceholder')" :end-placeholder="$t('components.dateEndPlaceholder')"
unlink-panels unlink-panels
class="date-base" :class="'date-base ' + metadata.cssClassName"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"
:disabled="isDisabled" :disabled="isDisabled"
:picker-options="typePicker === 'daterange' ? pickerOptionsDateRange : pickerOptionsDate" :picker-options="pickerOptions"
@change="preHandleChange" @change="preHandleChange"
/> />
</template> </template>
@ -137,6 +137,12 @@ export default {
.replace(/[aA]/gi, '') .replace(/[aA]/gi, '')
} }
return undefined return undefined
},
pickerOptions() {
if (this.typePicker === 'daterange') {
return this.pickerOptionsDateRange
}
return this.pickerOptionsDate
} }
}, },
watch: { watch: {

View File

@ -6,7 +6,7 @@
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload" :before-upload="beforeAvatarUpload"
:disabled="isDisabled" :disabled="isDisabled"
class="avatar-uploader" :class="'avatar-uploader ' + metadata.cssClassName"
> >
<img v-if="value" :src="value" class="avatar"> <img v-if="value" :src="value" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon" /> <i v-else class="el-icon-plus avatar-uploader-icon" />

View File

@ -10,7 +10,7 @@
:disabled="isDisabled" :disabled="isDisabled"
:precision="precision" :precision="precision"
controls-position="right" controls-position="right"
:class="'display-type-amount'" :class="'display-type-amount ' + metadata.cssClassName"
@change="preHandleChange" @change="preHandleChange"
@blur="changeValue" @blur="changeValue"
@keydown.native="calculateValue" @keydown.native="calculateValue"

View File

@ -6,7 +6,7 @@
:placeholder="metadata.help" :placeholder="metadata.help"
:loading="isLoading" :loading="isLoading"
value-key="key" value-key="key"
:class="classStyle" :class="classStyle + ' ' + metadata.cssClassName"
clearable clearable
:multiple="isSelectMultiple" :multiple="isSelectMultiple"
:allow-create="metadata.isSelectCreated" :allow-create="metadata.isSelectCreated"

View File

@ -5,7 +5,7 @@
filterable filterable
allow-create allow-create
:placeholder="metadata.help" :placeholder="metadata.help"
class="custom-field-select custom-field-select-multiple" :class="'custom-field-select custom-field-select-multiple ' + metadata.cssClassName"
@change="preHandleChange" @change="preHandleChange"
> >
<el-option <el-option

View File

@ -4,6 +4,7 @@
v-model="value" v-model="value"
:pattern="pattern" :pattern="pattern"
:rows="rows" :rows="rows"
:class="metadata.cssClassName"
:type="typeTextBox" :type="typeTextBox"
:placeholder="metadata.help" :placeholder="metadata.help"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"

View File

@ -1,5 +1,5 @@
<template> <template>
<div :id="id" :class="classDisable" /> <div :id="id" :class="classDisable + ' ' + metadata.cssClassName" />
</template> </template>
<script> <script>

View File

@ -9,7 +9,7 @@
:is-range="isPickerRange" :is-range="isPickerRange"
range-separator="-" range-separator="-"
:placeholder="$t('components.timePlaceholder')" :placeholder="$t('components.timePlaceholder')"
class="time-base" :class="'time-base ' + metadata.cssClassName"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"
:disabled="isDisabled" :disabled="isDisabled"
@change="preHandleChange" @change="preHandleChange"

View File

@ -4,7 +4,7 @@
v-model="value" v-model="value"
:inactive-text="$t('components.switchInactiveText')" :inactive-text="$t('components.switchInactiveText')"
:active-text="$t('components.switchActiveText')" :active-text="$t('components.switchActiveText')"
class="custom-field-yes-no" :class="'custom-field-yes-no ' + metadata.cssClassName"
:true-value="true" :true-value="true"
:false-value="false" :false-value="false"
:disabled="isDisabled" :disabled="isDisabled"
@ -86,7 +86,7 @@ export default {
</script> </script>
<style> <style>
.custom-field-yes-no { .custom-field-yes-no {
min-height: 34px; min-height: 34px;
} }
</style> </style>

View File

@ -8,13 +8,10 @@ import 'tui-editor/dist/tui-editor.css' // editor ui
import 'tui-editor/dist/tui-editor-contents.css' // editor content import 'tui-editor/dist/tui-editor-contents.css' // editor content
import 'codemirror/lib/codemirror.css' // codemirror import 'codemirror/lib/codemirror.css' // codemirror
import Editor from 'tui-editor' import Editor from 'tui-editor'
import { getLanguage } from '@/lang' import { getLanguage } from '@/lang'
// import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin'
export default { export default {
name: 'ChatTextLong', name: 'ChatTextLong',
// mixins: [fieldMixin],
props: { props: {
id: { id: {
type: String, type: String,
@ -137,15 +134,14 @@ export default {
}) })
}, },
preHandleChange(value) { preHandleChange(value) {
var comment = value
if (this.clean) { if (this.clean) {
this.$store.dispatch('setchatText', comment) this.$store.dispatch('setchatText', value)
.then((responseComment) => { .then(responseComment => {
this.$store.dispatch('setMarkDown', false) this.$store.dispatch('setMarkDown', false)
this.$store.dispatch('setchatText', '') this.$store.dispatch('setchatText', '')
}) })
} else { } else {
this.$store.dispatch('setchatText', comment) this.$store.dispatch('setchatText', value)
} }
}, },
addReanOnlyChanges() { addReanOnlyChanges() {
@ -176,6 +172,7 @@ export default {
} }
} }
</script> </script>
<style> <style>
.isdisable { .isdisable {
background: #F5F7FA; background: #F5F7FA;

View File

@ -0,0 +1,73 @@
import { TEXT } from '@/utils/ADempiere/references'
export default [
// Product Code
{
elementColumnName: 'ProductValue',
isFromDictionary: true,
overwriteDefinition: {
size: 24,
sequence: 10,
cssClassName: 'price-inquiry'
}
},
// Product Name
{
elementColumnName: 'ProductName',
isFromDictionary: true,
overwriteDefinition: {
size: 24,
sequence: 20,
isReadOnly: true,
cssClassName: 'price-inquiry'
}
},
// Product Description
{
elementColumnName: 'ProductDescription',
isFromDictionary: true,
overwriteDefinition: {
size: 24,
sequence: 30,
displayType: TEXT.id,
isReadOnly: true,
cssClassName: 'price-inquiry'
}
},
// Price List
{
elementColumnName: 'PriceList',
isFromDictionary: true,
overwriteDefinition: {
size: 16,
sequence: 40,
isReadOnly: true,
cssClassName: 'price-inquiry',
help: '0.00'
}
},
// Tax Amount
{
elementColumnName: 'TaxAmt',
isFromDictionary: true,
overwriteDefinition: {
size: 8,
sequence: 50,
isReadOnly: true,
cssClassName: 'price-inquiry',
help: '0.00'
}
},
// Total
{
elementColumnName: 'GrandTotal',
isFromDictionary: true,
overwriteDefinition: {
size: 24,
sequence: 60,
isReadOnly: true,
cssClassName: 'price-inquiry',
help: '0.00'
}
}
]

View File

@ -8,9 +8,10 @@
> >
<el-row> <el-row>
<field <field
v-for="(metadata) in metadataList" v-for="(field) in fieldsList"
:key="metadata.columnName" :key="field.columnName"
:metadata-field="metadata" :metadata-field="field"
:v-model="field.value"
/> />
</el-row> </el-row>
</el-form> </el-form>
@ -28,122 +29,75 @@
<script> <script>
import formMixin from '@/components/ADempiere/Form/formMixin' import formMixin from '@/components/ADempiere/Form/formMixin'
import { TEXT } from '@/utils/ADempiere/references' import fieldsList from './fieldsList.js'
import { getProductPrice } from '@/api/ADempiere/pos'
export default { export default {
name: 'TestView', name: 'PriceInquiry',
mixins: [formMixin], mixins: [formMixin],
data() { data() {
return { return {
metadataList: [], fieldsList
panelMetadata: {},
isLoaded: false,
panelType: 'custom'
}
},
computed: {
getterPanel() {
return this.$store.getters.getPanel(this.metadata.containerUuid)
} }
}, },
created() { created() {
this.getPanel() this.unsubscribe = this.subscribeChanges()
},
beforeDestroy() {
this.unsubscribe()
}, },
methods: { methods: {
setFieldsList() { subscribeChanges() {
const fieldsList = [] return this.$store.subscribe((mutation, state) => {
// Product Code if (mutation.type === 'changeFieldValue' && mutation.payload.field.columnName === 'ProductValue') {
this.createFieldFromDictionary({ // cleans all values except column name 'ProductValue'
containerUuid: this.metadata.containerUuid, this.setValues({ withOutColumnNames: ['ProductValue'] })
elementColumnName: 'ProductValue', getProductPrice({
overwriteDefinition: { searchValue: mutation.payload.newValue
size: 24, })
sequence: 10, .then(productPrice => {
isMandatory: true const { product, taxRate } = productPrice
const values = {
ProductName: product.name,
ProductDescription: product.description,
PriceList: productPrice.priceList,
TaxAmt: this.getTaxAmount(productPrice.priceList, taxRate.rate),
GrandTotal: this.getGrandTotal(productPrice.priceList, taxRate.rate)
}
// set new values except column name 'ProductValue'
this.setValues({ values, withOutColumnNames: ['ProductValue'] })
})
.catch(error => {
this.$message({
type: 'info',
message: error.message
})
})
} }
}) })
.then(metadata => { },
fieldsList.push(metadata) getTaxAmount(priceList, taxRate) {
}).catch(error => { if (this.isEmptyValue(priceList) || this.isEmptyValue(taxRate)) {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`) return 0
}) }
// Product Name return (priceList * taxRate) / 100
this.createFieldFromDictionary({ },
containerUuid: this.metadata.containerUuid, getGrandTotal(priceList, taxRate) {
elementColumnName: 'ProductName', if (this.isEmptyValue(priceList)) {
overwriteDefinition: { return 0
size: 24, }
sequence: 20, return priceList + this.getTaxAmount(priceList, taxRate)
isReadOnly: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// Product Description
this.createFieldFromDictionary({
containerUuid: this.metadata.containerUuid,
elementColumnName: 'ProductDescription',
overwriteDefinition: {
size: 24,
sequence: 30,
displayType: TEXT.id,
isReadOnly: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// Price List
this.createFieldFromDictionary({
containerUuid: this.metadata.containerUuid,
elementColumnName: 'PriceList',
overwriteDefinition: {
size: 16,
sequence: 40,
isReadOnly: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// Tax Amount
this.createFieldFromDictionary({
containerUuid: this.metadata.containerUuid,
elementColumnName: 'TaxAmt',
overwriteDefinition: {
size: 8,
sequence: 50,
isReadOnly: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// Total
this.createFieldFromDictionary({
containerUuid: this.metadata.containerUuid,
elementColumnName: 'GrandTotal',
overwriteDefinition: {
size: 24,
sequence: 60,
isReadOnly: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
this.metadataList = fieldsList
} }
} }
} }
</script> </script>
<style lang="scss">
.price-inquiry {
input {
color: #606266 !important;
font-size: 200% !important;
}
}
</style>

View File

@ -14,10 +14,10 @@ export default {
}, },
data() { data() {
return { return {
metadataList: [], fieldsList: [],
panelMetadata: {}, panelMetadata: {},
isLoaded: false, isLoaded: false,
panelType: 'custom' panelType: 'form'
} }
}, },
computed: { computed: {
@ -25,35 +25,137 @@ export default {
return this.$store.getters.getPanel(this.metadata.containerUuid) return this.$store.getters.getPanel(this.metadata.containerUuid)
} }
}, },
created() {
this.getPanel()
},
methods: { methods: {
createFieldFromDefinition, createFieldFromDefinition,
createFieldFromDictionary, createFieldFromDictionary,
getPanel() { async getPanel() {
const panel = this.getterPanel const panel = this.getterPanel
if (panel) { if (panel) {
this.metadataList = panel.fieldList this.fieldsList = panel.fieldList
this.isLoaded = true this.isLoaded = true
} else { } else {
this.setFieldsList() await this.generateFieldsList()
this.$store.dispatch('addPanel', { this.$store.dispatch('addPanel', {
...this.metadata, ...this.metadata,
uuid: this.metadata.containerUuid, uuid: this.metadata.containerUuid,
panelType: this.panelType, panelType: this.panelType,
fieldList: this.metadataList fieldList: this.fieldsList
}) })
.then(responsePanel => { .then(responsePanel => {
this.metadataList = responsePanel.fieldList this.fieldsList = responsePanel.fieldList
this.$store.dispatch('changeFormAttribute', { this.$store.dispatch('changeFormAttribute', {
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
attributeName: 'fieldList', attributeName: 'fieldList',
attributeValue: this.metadataList attributeValue: this.fieldsList
}) })
}) })
.finally(() => { .finally(() => {
this.isLoaded = true this.isLoaded = true
}) })
} }
},
generateFieldsList() {
let sequence = 0
const incrementSequence = (newValue) => {
if (newValue) {
sequence = newValue
}
sequence = sequence + 10
return sequence
}
return new Promise(resolve => {
const additionalAttributes = {
containerUuid: this.metadata.containerUuid,
isEvaluateValueChanges: false,
panelType: this.panelType
}
const fieldsListFromDictionary = []
const fieldsListFromMetadata = []
this.fieldsList.forEach(fieldElement => {
if (fieldElement.isFromDictionary) {
// set sequence
if (fieldElement.overwriteDefinition) {
if (this.isEmptyValue(fieldElement.overwriteDefinition.sequence)) {
fieldElement.overwriteDefinition.sequence = incrementSequence()
} else {
incrementSequence(fieldElement.overwriteDefinition.sequence)
}
} else {
fieldElement.overwriteDefinition = {}
fieldElement.overwriteDefinition.sequence = incrementSequence()
}
fieldsListFromDictionary.push(
this.createFieldFromDictionary({
...fieldElement,
...additionalAttributes
})
)
} else {
// set sequence
if (fieldElement.definition) {
if (this.isEmptyValue(fieldElement.definition.sequence)) {
fieldElement.definition.sequence = incrementSequence()
} else {
incrementSequence(fieldElement.definition.sequence)
}
} else {
fieldElement.definition = {}
fieldElement.definition.sequence = incrementSequence()
}
fieldsListFromMetadata.push(
this.createFieldFromDefinition({
...fieldElement,
...additionalAttributes
})
)
}
})
let fieldsList = fieldsListFromMetadata
if (this.isEmptyValue(fieldsListFromDictionary)) {
this.fieldsList = fieldsList
resolve(fieldsList)
this.isLoaded = true
} else {
Promise.all(fieldsListFromDictionary)
.then(responsefields => {
fieldsList = fieldsList.concat(responsefields)
resolve(fieldsList)
this.fieldsList = fieldsList
this.isLoaded = true
})
}
})
},
// Set value for one field from panel
// use example: setValue('ProductName', 'Patio Fun')
setValue(columnName, value) {
this.$store.dispatch('notifyFieldChange', {
containerUuid: this.metadata.containerUuid,
panelType: this.metadata.panelType,
columnName,
newValue: value
})
},
// Set values for all list of columns
// Use example: setValues(values)
setValues({ values = {}, withOutColumnNames = [] }) {
this.$store.dispatch('notifyPanelChange', {
containerUuid: this.metadata.containerUuid,
panelType: this.metadata.panelType,
newValues: values,
withOutColumnNames,
isChangedAllValues: true
})
} }
} }
} }

View File

@ -35,7 +35,8 @@ const browser = {
const panelType = 'browser' const panelType = 'browser'
const additionalAttributes = { const additionalAttributes = {
containerUuid, containerUuid,
panelType panelType,
isEvaluateValueChanges: true
} }
const { const {
query, query,

View File

@ -85,7 +85,7 @@ const panel = {
count++ count++
} }
} else { } else {
if (['browser', 'process', 'report', 'custom'].includes(panelType) || if (['browser', 'process', 'report', 'form'].includes(panelType) ||
panelType === 'window' && params.isParentTab) { panelType === 'window' && params.isParentTab) {
dispatch('setContext', { dispatch('setContext', {
parentUuid: params.parentUuid, parentUuid: params.parentUuid,
@ -393,6 +393,7 @@ const panel = {
* @param {object} fieldList, field list of panel * @param {object} fieldList, field list of panel
* @param {object} newValues, values to set in panel * @param {object} newValues, values to set in panel
* @param {boolean} isSendToServer, indicate if changes send to server * @param {boolean} isSendToServer, indicate if changes send to server
* @param {boolean} isChangedAllValues, check if it changes all the values of the fields, if it does not exist, set an empty value
*/ */
notifyPanelChange({ dispatch, getters, rootGetters }, { notifyPanelChange({ dispatch, getters, rootGetters }, {
parentUuid, parentUuid,
@ -407,7 +408,8 @@ const panel = {
isPrivateAccess = false, isPrivateAccess = false,
fieldList = [], fieldList = [],
isChangeFromCallout = false, isChangeFromCallout = false,
isChangeMultipleFields = true isChangeMultipleFields = true,
isChangedAllValues = false
}) { }) {
return new Promise(resolve => { return new Promise(resolve => {
if (!fieldList.length) { if (!fieldList.length) {
@ -422,7 +424,12 @@ const panel = {
// Evaluate with hasOwnProperty if exits this value // Evaluate with hasOwnProperty if exits this value
if (!newValues.hasOwnProperty(actionField.columnName)) { if (!newValues.hasOwnProperty(actionField.columnName)) {
return if (!isChangedAllValues || withOutColumnNames.includes(actionField.columnName)) {
// breaks if this value does not exist or ignore with out column names
return
}
// set empty value and continue
newValues[actionField.columnName] = undefined
} }
if (isChangeFromCallout && if (isChangeFromCallout &&
@ -630,7 +637,7 @@ const panel = {
} }
// the field has not changed, then the action is broken // the field has not changed, then the action is broken
if (newValue === field.value && isEmptyValue(displayColumn) && !isAdvancedQuery) { if (newValue === field.value && isEmptyValue(displayColumn) && field.isEvaluateValueChanges) {
resolve() resolve()
return return
} }

View File

@ -259,7 +259,8 @@ const window = {
tableName: tabResponse.tableName, tableName: tabResponse.tableName,
// //
isReadOnlyFromForm: false, isReadOnlyFromForm: false,
isAdvancedQuery isAdvancedQuery,
isEvaluateValueChanges: !isAdvancedQuery
} }
let isWithUuidField = false // indicates it contains the uuid field let isWithUuidField = false // indicates it contains the uuid field

View File

@ -244,6 +244,7 @@ export function generateProcess({ processToGenerate, containerUuidAssociated = u
processId: processToGenerate.id, processId: processToGenerate.id,
processName: processToGenerate.name, processName: processToGenerate.name,
containerUuid: processToGenerate.uuid, containerUuid: processToGenerate.uuid,
isEvaluateValueChanges: true,
panelType panelType
} }

View File

@ -108,7 +108,7 @@ export function createFieldFromDictionary({
function getFactoryFromField({ function getFactoryFromField({
containerUuid, containerUuid,
field, field,
overwriteDefinition overwriteDefinition = {}
}) { }) {
const fieldDefinition = { const fieldDefinition = {
displayType: field.displayType, displayType: field.displayType,
@ -152,62 +152,14 @@ function getFactoryFromField({
readOnlyLogic: field.readOnlyLogic, readOnlyLogic: field.readOnlyLogic,
parentFieldsList: field.parentFieldsList, parentFieldsList: field.parentFieldsList,
dependentFieldsList: field.dependentFieldsList, dependentFieldsList: field.dependentFieldsList,
contextInfo: field.contextInfo contextInfo: field.contextInfo,
} // Overwrite definition
// Overwrite definition ...overwriteDefinition
if (!isEmptyValue(overwriteDefinition)) {
if (!isEmptyValue(overwriteDefinition.isQueryCriteria)) {
fieldDefinition.isQueryCriteria = overwriteDefinition.isQueryCriteria
}
if (!isEmptyValue(overwriteDefinition.isMandatory)) {
fieldDefinition.isMandatory = overwriteDefinition.isMandatory
}
if (!isEmptyValue(overwriteDefinition.isReadOnly)) {
fieldDefinition.isReadOnly = overwriteDefinition.isReadOnly
}
if (!isEmptyValue(overwriteDefinition.isSelectionColumn)) {
fieldDefinition.isSelectionColumn = overwriteDefinition.isSelectionColumn
}
if (!isEmptyValue(overwriteDefinition.isUpdateable)) {
fieldDefinition.isUpdateable = overwriteDefinition.isUpdateable
}
if (!isEmptyValue(overwriteDefinition.isFieldOnly)) {
fieldDefinition.isFieldOnly = overwriteDefinition.isFieldOnly
}
if (!isEmptyValue(overwriteDefinition.isRange)) {
fieldDefinition.isRange = overwriteDefinition.isRange
}
if (!isEmptyValue(overwriteDefinition.displayLogic)) {
fieldDefinition.displayLogic = overwriteDefinition.displayLogic
}
if (!isEmptyValue(overwriteDefinition.mandatoryLogic)) {
fieldDefinition.mandatoryLogic = overwriteDefinition.mandatoryLogic
}
if (!isEmptyValue(overwriteDefinition.readOnlyLogic)) {
fieldDefinition.readOnlyLogic = overwriteDefinition.readOnlyLogic
}
if (!isEmptyValue(overwriteDefinition.formatPattern)) {
fieldDefinition.formatPattern = overwriteDefinition.formatPattern
}
if (!isEmptyValue(overwriteDefinition.vFormat)) {
fieldDefinition.vFormat = overwriteDefinition.vFormat
}
if (!isEmptyValue(overwriteDefinition.defaultValue)) {
fieldDefinition.defaultValue = overwriteDefinition.defaultValue
}
if (!isEmptyValue(overwriteDefinition.defaultValueTo)) {
fieldDefinition.defaultValueTo = overwriteDefinition.defaultValueTo
}
if (!isEmptyValue(overwriteDefinition.displayType)) {
fieldDefinition.displayType = overwriteDefinition.displayType
}
if (!isEmptyValue(overwriteDefinition.size)) {
fieldDefinition.size = overwriteDefinition.size
}
} }
// Convert it // Convert it
return createFieldFromDefinition({ return createFieldFromDefinition({
containerUuid: containerUuid, containerUuid,
columnName: field.columnName, columnName: field.columnName,
definition: fieldDefinition definition: fieldDefinition
}) })
@ -218,6 +170,7 @@ export function createFieldFromDefinition({
parentUuid, parentUuid,
containerUuid, containerUuid,
columnName, columnName,
panelType = 'form',
definition = {} definition = {}
}) { }) {
if (!isEmptyValue(definition)) { if (!isEmptyValue(definition)) {
@ -270,6 +223,7 @@ export function createFieldFromDefinition({
definition.reference = reference definition.reference = reference
} }
return getFieldTemplate({ return getFieldTemplate({
panelType,
...definition, ...definition,
isShowedFromUser: true, isShowedFromUser: true,
isCustomField: true, isCustomField: true,

View File

@ -41,7 +41,6 @@
<form-panel <form-panel
:metadata="{ :metadata="{
...formMetadata, ...formMetadata,
containerUuid: formUuid,
title: formTitle title: formTitle
}" }"
/> />

View File

@ -0,0 +1,83 @@
import { URL, TEXT, NUMBER, INTEGER, TEXT_LONG, TABLE_DIRECT } from '@/utils/ADempiere/references'
export default [
// URL
{
columnName: 'URL',
definition: {
name: 'Web',
displayType: URL.id
}
},
// From Field UUID
{
isFromDictionary: true,
fieldUuid: '8ceabe8a-fb40-11e8-a479-7a0060f0aa01'
},
// From Column UUID
{
isFromDictionary: true,
columnUuid: '8b4bbb7e-fb40-11e8-a479-7a0060f0aa01'
},
// From Element Column Name
{
isFromDictionary: true,
elementColumnName: 'M_RMA_ID'
},
// From Table and Column Name
{
tableName: 'C_BPartner',
columnName: 'PaymentRule',
isFromDictionary: true,
overwriteDefinition: {
isMandatory: true
}
},
// Table direct
// To be define
{
columnName: 'C_Currency_ID',
definition: {
name: 'Currency',
displayType: TABLE_DIRECT.id,
keyColumn: 'C_Currency.C_Currency_ID',
directQuery: 'SELECT C_Currency.C_Currency_ID,NULL,C_Currency.ISO_Code,C_Currency.IsActive FROM C_Currency WHERE C_Currency.C_Currency_ID=?',
query: 'SELECT C_Currency.C_Currency_ID,NULL,C_Currency.ISO_Code,C_Currency.IsActive FROM C_Currency ORDER BY 3'
}
},
// Text
{
columnName: 'Name',
definition: {
name: 'Only Name',
displayType: TEXT.id,
displayLogic: '@URL@!""'
}
},
// Amount
{
columnName: 'Amount',
definition: {
name: 'Amount for it',
displayType: NUMBER.id,
readOnlyLogic: '@C_Currency_ID@<>""'
}
},
// Integer
{
columnName: 'SeqNo',
definition: {
name: 'Sequence for record',
displayType: INTEGER.id,
mandatoryLogic: '@URL@!""'
}
},
// Text Long
{
columnName: 'Description',
definition: {
name: 'Only Description',
displayType: TEXT_LONG.id
}
}
]

View File

@ -1,213 +1,163 @@
<template> <template>
<div class="wrapper"> <el-container
<el-form v-if="isLoaded"
v-if="isLoaded" key="form-loaded"
key="form-loaded" class="view-base"
label-position="top" style="height: 84vh;"
label-width="200px" >
> <el-header style="height: 39px;">
<el-row> <context-menu
<field :menu-parent-uuid="$route.meta.parentUuid"
v-for="(metadata) in metadataList" :container-uuid="metadata.containerUuid"
:key="metadata.columnName" :panel-type="panelType"
:metadata-field="metadata" />
/> </el-header>
<el-main>
<el-row :gutter="20">
<el-col :span="24">
<el-card
class="content-collapse"
:style="isEmptyValue(metadata.fieldList) ? 'height: 75vh !important;' : ''"
>
<h3 class="warn-content text-center">
<el-popover
v-if="!isEmptyValue(metadata.help)"
ref="helpTitle"
placement="top-start"
:title="formTitle"
width="400"
trigger="hover"
>
<div v-html="metadata.help" />
</el-popover>
<el-button
v-popover:helpTitle
type="text"
class="title text-center"
>
{{ formTitle }}
</el-button>
</h3>
<!-- emulated component form -->
<div class="wrapper">
<el-form
label-position="top"
label-width="200px"
>
<el-row>
<field
v-for="(fieldMetadata) in fieldsList"
:key="fieldMetadata.columnName"
:metadata-field="fieldMetadata"
/>
</el-row>
</el-form>
</div>
<!-- emulated component form -->
</el-card>
</el-col>
</el-row> </el-row>
</el-form> </el-main>
<div </el-container>
v-else <div
key="form-loading" v-else
v-loading="!isLoaded" key="form-loading"
:element-loading-text="$t('notifications.loading')" v-loading="!isLoaded"
element-loading-spinner="el-icon-loading" :element-loading-text="$t('notifications.loading')"
element-loading-background="rgba(255, 255, 255, 0.8)" element-loading-spinner="el-icon-loading"
class="loading-panel" element-loading-background="rgba(255, 255, 255, 0.8)"
/> class="view-loading"
</div> />
</template> </template>
<script> <script>
import Field from '@/components/ADempiere/Field' import formMixin from '@/components/ADempiere/Form/formMixin'
import { createFieldFromDefinition, createFieldFromDictionary } from '@/utils/ADempiere/lookupFactory' import fieldsList from './fieldsList.js'
import { URL, TEXT, NUMBER, INTEGER, TEXT_LONG, TABLE_DIRECT } from '@/utils/ADempiere/references' import ContextMenu from '@/components/ADempiere/ContextMenu'
export default { export default {
name: 'TestView', name: 'TestView',
components: { components: {
Field ContextMenu
},
mixins: [formMixin],
props: {
metadata: {
type: Object,
default: () => {
return {
containerUuid: 'Test-View',
name: 'Test View'
}
}
}
}, },
data() { data() {
return { return {
metadataList: [], fieldsList
panelMetadata: {},
isLoaded: false,
panelUuid: 'Test-View',
panelType: 'custom'
} }
}, },
computed: { computed: {
getterPanel() { formTitle() {
return this.$store.getters.getPanel(this.panelUuid) return this.metadata.name || this.$route.meta.title
}
},
created() {
this.getPanel()
},
methods: {
getPanel() {
const panel = this.getterPanel
if (panel) {
this.metadataList = panel.fieldList
this.isLoaded = true
} else {
this.setFieldsList()
this.$store.dispatch('addPanel', {
name: 'Test View',
uuid: this.panelUuid,
panelType: this.panelType,
fieldList: this.metadataList
})
.then(responsePanel => {
this.metadataList = responsePanel.fieldList
})
.finally(() => {
this.isLoaded = true
})
}
},
setFieldsList() {
const fieldsList = []
let sequence = 10
// URL
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'URL',
definition: {
name: 'Web',
displayType: URL.id,
panelType: this.panelType,
sequence
}
}))
// From Field UUID
createFieldFromDictionary({
containerUuid: this.panelUuid,
fieldUuid: '8ceabe8a-fb40-11e8-a479-7a0060f0aa01'
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// From Column UUID
createFieldFromDictionary({
containerUuid: this.panelUuid,
columnUuid: '8b4bbb7e-fb40-11e8-a479-7a0060f0aa01'
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// From Element Column Name
createFieldFromDictionary({
containerUuid: this.panelUuid,
elementColumnName: 'M_RMA_ID'
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// From Table and Column Name
createFieldFromDictionary({
containerUuid: this.panelUuid,
tableName: 'C_BPartner',
columnName: 'PaymentRule',
overwriteDefinition: {
isMandatory: true
}
})
.then(metadata => {
fieldsList.push(metadata)
}).catch(error => {
console.warn(`LookupFactory: Get Field From Server (State) - Error ${error.code}: ${error.message}.`)
})
// Table direct
// To be define
sequence = sequence + 10
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'C_Currency_ID',
definition: {
name: 'Currency',
displayType: TABLE_DIRECT.id,
panelType: this.panelType,
keyColumn: 'C_Currency.C_Currency_ID',
directQuery: 'SELECT C_Currency.C_Currency_ID,NULL,C_Currency.ISO_Code,C_Currency.IsActive FROM C_Currency WHERE C_Currency.C_Currency_ID=?',
query: 'SELECT C_Currency.C_Currency_ID,NULL,C_Currency.ISO_Code,C_Currency.IsActive FROM C_Currency ORDER BY 3',
sequence
}
}))
sequence = sequence + 10
// Text
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'Name',
definition: {
name: 'Only Name',
displayType: TEXT.id,
panelType: this.panelType,
displayLogic: '@URL@!""',
sequence
}
}))
sequence = sequence + 10
// Amount
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'Amount',
definition: {
name: 'Amount for it',
displayType: NUMBER.id,
panelType: this.panelType,
readOnlyLogic: '@C_Currency_ID@<>""',
sequence
}
}))
sequence = sequence + 10
// Integer
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'SeqNo',
definition: {
name: 'Sequence for record',
displayType: INTEGER.id,
panelType: this.panelType,
mandatoryLogic: '@URL@!""',
sequence
}
}))
sequence = sequence + 10
// Text Long
fieldsList.push(createFieldFromDefinition({
containerUuid: this.panelUuid,
columnName: 'Description',
definition: {
name: 'Only Description',
displayType: TEXT_LONG.id,
panelType: this.panelType,
sequence
}
}))
this.metadataList = fieldsList
} }
} }
} }
</script> </script>
<style>
.el-card__body {
padding-top: 0px !important;
padding-right: 20px;
padding-bottom: 20px;
padding-left: 20px;
}
</style>
<style scoped >
.view-base {
height: 100%;
min-height: calc(100vh - 84px);
}
.view-loading {
padding: 100px 100px;
height: 100%;
}
.title, .custom-title {
color: #000;
text-size-adjust: 20px;
font-size: 100%;
font-weight: 605 !important;
/* left: 50%; */
}
.w-33 {
width: 100%;
background-color: transparent;
}
.warn-content {
margin: 0px 0px !important;
padding-top: 0px !important;
}
.content-help {
width: 100%;
height: 200%;
padding-left: 39px !important;
}
.el-card {
width: 100% !important;
height: 200% !important;
}
.content-collapse {
padding-left: 20 px !important;
padding-top: 50 px !important;
}
.center{
text-align: center;
}
</style>