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

feat: Remove context (#508)

* Change definition for v-model of fields using reactive store

* change custom validateValue to custom and overwrite parsedValue.

* Delete unused parameters.

* Add queue for persistence

* fix: Create entity.

* Add return value as array for persistence

* Add multiple commit for panel

* remove commnets

* Change context session to preference.

* fix: Load window.

* Add support to seekrecord for panel

* Set default value to isActive columnName.

* set default values.

* Separate template mobile and panel desktop with mixin.

* set values into panel with first load of records.

* fix lookups value and display value.

* change `DisplayColumn_${columnName}` to `displayColumnName` property.

* fix create entity with default values.

* Set default values and fix browser search.

* fix context values from SmartBrowser.

* fix: Associated process.

* set context values to process associated.

* fix set values.

* fix style field components.

* fix send values to server.

Co-authored-by: Yamel Senih <ysenih@erpya.com>
This commit is contained in:
Edwin Betancourt 2020-06-12 12:07:24 -04:00 committed by GitHub
parent d21b7f3f89
commit 0800511177
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 5489 additions and 4945 deletions

View File

@ -6,10 +6,10 @@ import { BusinessDataInstance as Instance } from '@/api/ADempiere/instances.js'
* @param {string} tableName * @param {string} tableName
* @param {array} attributesList * @param {array} attributesList
*/ */
export function createEntity({ tableName, attributesList }) { export function createEntity({ tableName, attributes }) {
return Instance.call(this).requestCreateEntity({ return Instance.call(this).requestCreateEntity({
tableName, tableName,
attributesList attributesList: attributes
}) })
} }
@ -20,12 +20,12 @@ export function createEntity({ tableName, attributesList }) {
* @param {string} recordUuid * @param {string} recordUuid
* @param {array} attributesList * @param {array} attributesList
*/ */
export function updateEntity({ tableName, recordId, recordUuid, attributesList }) { export function updateEntity({ tableName, recordId, recordUuid, attributes }) {
return Instance.call(this).requestUpdateEntity({ return Instance.call(this).requestUpdateEntity({
tableName, tableName,
recordId, recordId,
recordUuid, recordUuid,
attributesList attributesList: attributes
}) })
} }

View File

@ -8,7 +8,7 @@ import { BusinessDataInstance as Instance } from '@/api/ADempiere/instances.js'
* @param {string} directQuery * @param {string} directQuery
* @param {string|number} value * @param {string|number} value
*/ */
export function getLookup({ export function requestLookup({
tableName, tableName,
directQuery, directQuery,
value value
@ -25,16 +25,21 @@ export function getLookup({
* The main attributes that function hope are: * The main attributes that function hope are:
* @param {string} tableName * @param {string} tableName
* @param {string} query * @param {string} query
* @param {Array<String>|<Number>} valuesList
* @param {string} pageToken
* @param {number} pageSize
*/ */
export function getLookupList({ export function requestLookupList({
tableName, tableName,
query, query,
valuesList = [],
pageToken, pageToken,
pageSize pageSize
}) { }) {
return Instance.call(this).requestListLookupFromReference({ return Instance.call(this).requestListLookupFromReference({
tableName, tableName,
query, query,
valuesList,
pageToken, pageToken,
pageSize pageSize
}) })

View File

@ -139,7 +139,7 @@ export const contextMixin = {
}) })
return value.map(fieldItem => { return value.map(fieldItem => {
if (fieldItem.componentPath === 'FieldSelect') { if (fieldItem.componentPath === 'FieldSelect') {
return 'DisplayColumn_' + fieldItem.columnName return fieldItem.displayColumnName
} }
return fieldItem.columnName return fieldItem.columnName
}) })
@ -174,7 +174,7 @@ export const contextMixin = {
}, },
getOldRouteOfWindow() { getOldRouteOfWindow() {
if (this.panelType === 'window') { if (this.panelType === 'window') {
const oldRoute = this.$store.state.windowControl.windowOldRoute const oldRoute = this.$store.state.window.windowOldRoute
if (!this.isEmptyValue(oldRoute.query.action) && oldRoute.query.action !== 'create-new' && this.$route.query.action === 'create-new') { if (!this.isEmptyValue(oldRoute.query.action) && oldRoute.query.action !== 'create-new' && this.$route.query.action === 'create-new') {
return oldRoute return oldRoute
} }
@ -234,7 +234,7 @@ export const contextMixin = {
actionContextMenu(event) { actionContextMenu(event) {
switch (event.srcKey) { switch (event.srcKey) {
case 'f2': case 'f2':
this.$store.dispatch('resetPanelToNew', { this.$store.dispatch('setDefaultValues', {
parentUuid: this.parentUuid, parentUuid: this.parentUuid,
containerUuid: this.containerUuid, containerUuid: this.containerUuid,
recordUuid: this.recordUuid, recordUuid: this.recordUuid,
@ -395,14 +395,15 @@ export const contextMixin = {
if (action.type === 'process') { if (action.type === 'process') {
// Add context from view open in process to opening // Add context from view open in process to opening
if (action.parentUuidAssociated || action.containerUuidAssociated) { if (action.parentUuidAssociated || action.containerUuidAssociated) {
const contextValues = this.$store.getters.getContextView({ const attributes = this.$store.getters.getValuesView({
parentUuid: action.parentUuidAssociated, parentUuid: action.parentUuidAssociated,
containerUuid: action.containerUuidAssociated containerUuid: action.containerUuidAssociated
}) })
if (!this.isEmptyValue(contextValues)) {
this.$store.dispatch('setMultipleContextView', { if (!this.isEmptyValue(attributes)) {
this.$store.dispatch('updateValuesOfContainer', {
containerUuid: action.uuid, containerUuid: action.uuid,
values: contextValues attributes
}) })
} }
} }
@ -437,7 +438,7 @@ export const contextMixin = {
containerUuid: this.containerUuid, containerUuid: this.containerUuid,
recordUuid: this.recordUuid, recordUuid: this.recordUuid,
panelType: this.panelType, panelType: this.panelType,
isNewRecord: action.action === 'resetPanelToNew', isNewRecord: action.action === 'setDefaultValues',
tableName: action.tableName, tableName: action.tableName,
recordId: action.recordId recordId: action.recordId
}) })

View File

@ -186,7 +186,7 @@
:in-table="true" :in-table="true"
:metadata-field="{ :metadata-field="{
...fieldAttributes, ...fieldAttributes,
displayColumn: scope.row['DisplayColumn_' + fieldAttributes.columnName], displayColumn: scope.row[fieldAttributes.displayColumnName],
tableIndex: scope.$index, tableIndex: scope.$index,
rowKey: scope.row[getterPanel.keyColumn], rowKey: scope.row[getterPanel.keyColumn],
keyColumn: getterPanel.keyColumn, keyColumn: getterPanel.keyColumn,
@ -470,22 +470,21 @@ export default {
isPanelWindow() { isPanelWindow() {
return Boolean(this.panelType === 'window') return Boolean(this.panelType === 'window')
}, },
getterContextClientId() { preferenceClientId() {
if (this.isPanelWindow) { if (this.isPanelWindow) {
return this.$store.getters.getContextClientId return this.$store.getters.getPreferenceClientId
} }
return undefined return undefined
}, },
isReadOnlyParent() { isReadOnlyParent() {
if (this.isPanelWindow) { if (this.isPanelWindow) {
if (this.$store.getters.getContextIsActive(this.parentUuid) === false) { if (!this.$store.getters.getContainerIsActive(this.parentUuid)) {
return true return true
} }
if (this.$store.getters.getContextProcessing(this.parentUuid) === true || if (this.$store.getters.getContainerProcessing(this.parentUuid)) {
this.$store.getters.getContextProcessing(this.parentUuid) === 'Y') {
return true return true
} }
if (this.$store.getters.getContextProcessed(this.parentUuid)) { if (this.$store.getters.getContainerProcessed(this.parentUuid)) {
return true return true
} }
} }
@ -617,7 +616,7 @@ export default {
*/ */
displayedValue(row, field) { displayedValue(row, field) {
if (typeof row[field.columnName] === 'boolean') { if (typeof row[field.columnName] === 'boolean') {
// replace boolean true-false value for 'Yes' or 'Not' // replace boolean true-false value for 'Yes' or 'Not' ('Si' or 'No' for spanish)
return row[field.columnName] ? this.$t('components.switchActiveText') : this.$t('components.switchInactiveText') return row[field.columnName] ? this.$t('components.switchActiveText') : this.$t('components.switchInactiveText')
} else if (field.componentPath === 'FieldDate' || field.componentPath === 'FieldTime') { } else if (field.componentPath === 'FieldDate' || field.componentPath === 'FieldTime') {
let cell = row[field.columnName] let cell = row[field.columnName]
@ -634,10 +633,12 @@ export default {
displayType: field.displayType, displayType: field.displayType,
number: row[field.columnName] number: row[field.columnName]
}) })
} else if (field.componentPath === 'FieldSelect' && this.isEmptyValue(row['DisplayColumn_' + field.columnName]) && row[field.columnName] === 0) { } else if (field.componentPath === 'FieldSelect' &&
this.isEmptyValue(row[field.displayColumnName]) &&
row[field.columnName] === 0) {
return field.defaultValue return field.defaultValue
} }
return row['DisplayColumn_' + field.columnName] || row[field.columnName] return row[field.displayColumnName] || row[field.columnName]
}, },
rowCanBeEdited(record, fieldAttributes) { rowCanBeEdited(record, fieldAttributes) {
if (!this.isParent) { if (!this.isParent) {
@ -663,28 +664,19 @@ export default {
}, },
isReadOnlyRow(row, field) { isReadOnlyRow(row, field) {
// evaluate context // evaluate context
if (this.getterContextClientId !== parseInt(row.AD_Client_ID, 10)) { if (this.preferenceClientId !== parseInt(row.AD_Client_ID, 10)) {
return true return true
} }
if (fieldIsDisplayed(field)) { if (fieldIsDisplayed(field)) {
// const fieldReadOnlyAllForm = FIELDS_READ_ONLY_FORM.filter(item => {
// return item.isChangedAllForm &&
// Object.prototype.hasOwnProperty.call(row, item.columnName)
// })
// // columnName: Processed, Processing
// if (fieldReadOnlyAllForm.length) {
// const isReadOnlyAllRow = Boolean(fieldReadOnlyAllForm.find(item => row[item.columnName] === item.valueIsReadOnlyForm))
// return isReadOnlyAllRow
// }
// columnName: IsActive // columnName: IsActive
const fieldReadOnlyForm = FIELDS_READ_ONLY_FORM.find(item => { const fieldReadOnlyForm = FIELDS_READ_ONLY_FORM.find(item => {
return !item.isChangedAllForm && return !item.isChangedAllForm &&
// columnName: IsActive, Processed, Processing
Object.prototype.hasOwnProperty.call(row, item.columnName) Object.prototype.hasOwnProperty.call(row, item.columnName)
}) })
if (fieldReadOnlyForm) { if (fieldReadOnlyForm) {
const isReadOnlyRow = row[fieldReadOnlyForm.columnName] === fieldReadOnlyForm.valueIsReadOnlyForm && field.columnName !== fieldReadOnlyForm.columnName return field.columnName !== fieldReadOnlyForm.columnName &&
return isReadOnlyRow row[fieldReadOnlyForm.columnName] === fieldReadOnlyForm.valueIsReadOnlyForm
} }
} }
return false return false
@ -1078,8 +1070,7 @@ export default {
} }
} }
} }
</style>
<style>
.el-table .warning-row { .el-table .warning-row {
background: rgba(161, 250, 223, 0.945); background: rgba(161, 250, 223, 0.945);
} }

View File

@ -86,14 +86,13 @@ export const menuTableMixin = {
}, },
isReadOnlyParent() { isReadOnlyParent() {
if (this.isPanelWindow) { if (this.isPanelWindow) {
if (this.$store.getters.getContextIsActive(this.parentUuid) === false) { if (!this.$store.getters.getContainerIsActive(this.parentUuid)) {
return true return true
} }
if (this.$store.getters.getContextProcessing(this.parentUuid) === true || if (this.$store.getters.getContainerProcessing(this.parentUuid)) {
this.$store.getters.getContextProcessing(this.parentUuid) === 'Y') {
return true return true
} }
if (this.$store.getters.getContextProcessed(this.parentUuid)) { if (this.$store.getters.getContainerProcessed(this.parentUuid)) {
return true return true
} }
} }
@ -146,7 +145,7 @@ export const menuTableMixin = {
}) })
return value.map(fieldItem => { return value.map(fieldItem => {
if (fieldItem.componentPath === 'FieldSelect') { if (fieldItem.componentPath === 'FieldSelect') {
return 'DisplayColumn_' + fieldItem.columnName return fieldItem.displayColumnName
} }
return fieldItem.columnName return fieldItem.columnName
}) })

View File

@ -86,10 +86,10 @@ export default {
return 50 return 50
}, },
isVisibleDialog() { isVisibleDialog() {
return this.$store.state.processControl.isVisibleDialog return this.$store.state.process.isVisibleDialog
}, },
modalMetadata() { modalMetadata() {
return this.$store.state.processControl.metadata return this.$store.state.process.metadata
}, },
windowRecordSelected() { windowRecordSelected() {
return this.$store.state.window.recordSelected return this.$store.state.window.recordSelected

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 ' + metadata.cssClassName" :class="cssClassStyle"
action="https://jsonplaceholder.typicode.com/posts/" action="https://jsonplaceholder.typicode.com/posts/"
:disabled="isDisabled" :disabled="isDisabled"
@change="preHandleChange" @change="preHandleChange"
@ -21,21 +21,14 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
export default { export default {
name: 'FieldBinary', name: 'FieldBinary',
mixins: [fieldMixin], mixins: [fieldMixin],
watch: { computed: {
valueModel(value) { cssClassStyle() {
if (this.metadata.inTable) { return this.metadata.cssClassName + ' image-uploader'
this.value = value
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = value
}
} }
}, },
methods: { methods: {

View File

@ -8,22 +8,14 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import fieldMixinText from '@/components/ADempiere/Field/mixin/mixinFieldText.js'
export default { export default {
name: 'FieldButton', name: 'FieldButton',
mixins: [fieldMixin], mixins: [
watch: { fieldMixin,
valueModel(value) { fieldMixinText
if (this.metadata.inTable) { ]
this.value = String(value)
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = String(value)
}
}
}
} }
</script> </script>

View File

@ -4,34 +4,20 @@
v-model="value" v-model="value"
show-alpha show-alpha
:disabled="isDisabled" :disabled="isDisabled"
:class="metadata.cssClassName" :class="cssClassStyle"
@change="preHandleChange" @change="preHandleChange"
/> />
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import fieldMixinText from '@/components/ADempiere/Field/mixin/mixinFieldText.js'
export default { export default {
name: 'FieldColor', name: 'FieldColor',
mixins: [fieldMixin], mixins: [
watch: { fieldMixin,
valueModel(value) { fieldMixinText
if (this.metadata.inTable) { ]
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
}
}
} }
</script> </script>

View File

@ -10,7 +10,7 @@
: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 ' + metadata.cssClassName" :class="cssClassStyle"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"
:disabled="isDisabled" :disabled="isDisabled"
:picker-options="pickerOptions" :picker-options="pickerOptions"
@ -23,20 +23,14 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import { DATE_PLUS_TIME } from '@/utils/ADempiere/references' import { DATE_PLUS_TIME } from '@/utils/ADempiere/references'
export default { export default {
name: 'FieldDate', name: 'FieldDate',
mixins: [fieldMixin], mixins: [fieldMixin],
data() { data() {
// value render
let value = this.metadata.value
if (this.metadata.inTable) {
value = this.valueModel
}
return { return {
value: this.parsedDateValue(value),
pickerOptionsDate: { pickerOptionsDate: {
shortcuts: [{ shortcuts: [{
text: this.$t('components.date.Today'), text: this.$t('components.date.Today'),
@ -117,6 +111,9 @@ export default {
} }
return picker return picker
}, },
cssClassStyle() {
return this.metadata.cssClassName + ' custom-field-date'
},
/** /**
* Parse the date format to be compatible with element-ui * Parse the date format to be compatible with element-ui
*/ */
@ -149,22 +146,53 @@ export default {
return this.pickerOptionsDateRange return this.pickerOptionsDateRange
} }
return this.pickerOptionsDate return this.pickerOptionsDate
}
}, },
watch: { value: {
valueModel(value) { get() {
if (this.metadata.inTable) { let value = this.$store.getters.getValueOfField({
this.value = this.parsedDateValue(value) containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName
})
if (!this.metadata.isRange) {
return this.parseValue(value)
} }
const valueTo = this.$store.getters.getValueOfField({
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnNameTo
})
value = this.parseValue([value, valueTo])
return value
}, },
'metadata.value'(value) { set(value) {
if (!this.metadata.inTable) { let startValue = value
this.value = this.parsedDateValue(value) if (Array.isArray(value)) {
startValue = value[0]
}
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName,
value: startValue
})
if (!this.metadata.isRange) {
return
}
const endValue = value[1]
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnNameTo,
value: endValue
})
} }
} }
}, },
methods: { methods: {
parsedDateValue(value) { parseValue(value) {
// not return undefined to v-model // not return undefined to v-model
if (this.isEmptyValue(value)) { if (this.isEmptyValue(value)) {
if (['IN', 'NOT_IN'].includes(this.metadata.operator) && this.metadata.isAdvancedQuery) { if (['IN', 'NOT_IN'].includes(this.metadata.operator) && this.metadata.isAdvancedQuery) {
@ -198,7 +226,11 @@ export default {
// generate range value // generate range value
if (this.metadata.isRange && !this.metadata.inTable) { if (this.metadata.isRange && !this.metadata.inTable) {
let valueTo = this.metadata.valueTo let valueTo // = this.metadata.valueTo
if (Array.isArray(value)) {
valueTo = value[1]
value = value[0]
}
if (typeof valueTo === 'number') { if (typeof valueTo === 'number') {
valueTo = new Date(valueTo).toUTCString() valueTo = new Date(valueTo).toUTCString()
} }
@ -206,6 +238,9 @@ export default {
valueTo = undefined valueTo = undefined
} }
value = [value, valueTo] value = [value, valueTo]
if (this.isEmptyValue(value[0]) || this.isEmptyValue(value[1])) {
value = []
}
} }
return value return value
@ -219,7 +254,7 @@ export default {
if (Array.isArray(value)) { if (Array.isArray(value)) {
value = value.map(itemValue => new Date(itemValue)) value = value.map(itemValue => new Date(itemValue))
} }
this.handleChange(value) this.handleFieldChange({ value })
return return
} }
@ -238,14 +273,17 @@ export default {
endValue = new Date(endValue) endValue = new Date(endValue)
} }
this.handleChange(startValue, endValue) this.handleFieldChange({
value: startValue,
valueTo: endValue
})
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.date-base { .custom-field-date {
width: 100% !important; width: 100% !important;
} }
</style> </style>

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 ' + metadata.cssClassName" :class="cssClassStyle"
> >
<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" />
@ -14,33 +14,21 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
export default { export default {
name: 'FieldImage', name: 'FieldImage',
mixins: [fieldMixin], mixins: [fieldMixin],
data() { computed: {
return { cssClassStyle() {
value: '' return this.metadata.cssClassName + ' custom-field-image'
}
},
watch: {
valueModel(value) {
if (this.metadata.inTable) {
this.value = value
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = value
}
} }
}, },
methods: { methods: {
handleAvatarSuccess(res, file) { handleAvatarSuccess(res, file) {
this.value = URL.createObjectURL(file.raw) this.value = URL.createObjectURL(file.raw)
// TODO: define one method to control change value // TODO: define one method to control change value
this.handleChange(this.value) this.handleFieldChange({ value: this.value })
}, },
beforeAvatarUpload(file) { beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg' const isJPG = file.type === 'image/jpeg'
@ -58,8 +46,8 @@ export default {
} }
</script> </script>
<style> <style scoped>
.avatar-uploader .el-upload { .custom-field-image .el-upload {
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
@ -67,7 +55,7 @@ export default {
overflow: hidden; overflow: hidden;
} }
.avatar-uploader .el-upload:hover { .custom-field-image .el-upload:hover {
border-color: #409EFF; border-color: #409EFF;
} }

View File

@ -17,7 +17,7 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import { getLocatorList } from '@/api/ADempiere/field/locator' import { getLocatorList } from '@/api/ADempiere/field/locator'
export default { export default {
@ -25,7 +25,6 @@ export default {
mixins: [fieldMixin], mixins: [fieldMixin],
data() { data() {
return { return {
value: [],
options: [], options: [],
props: { props: {
// checkStrictly: true, // checkStrictly: true,
@ -59,7 +58,7 @@ export default {
if (Array.isArray(value)) { if (Array.isArray(value)) {
selected = value[value.length - 1] selected = value[value.length - 1]
} }
this.handleChange(selected) this.handleFieldChange({ value: selected })
this.value = value this.value = value
}, },
searchLocatorByWarehouse(node, resolve) { searchLocatorByWarehouse(node, resolve) {

View File

@ -11,7 +11,7 @@
:precision="precision" :precision="precision"
:controls="isShowControls" :controls="isShowControls"
:controls-position="controlsPosition" :controls-position="controlsPosition"
:class="'display-type-amount ' + metadata.cssClassName" :class="cssClassStyle"
@change="preHandleChange" @change="preHandleChange"
@blur="focusLost" @blur="focusLost"
@focus="focusGained" @focus="focusGained"
@ -22,21 +22,14 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import { FIELDS_DECIMALS } from '@/utils/ADempiere/references' import { FIELDS_DECIMALS } from '@/utils/ADempiere/references'
export default { export default {
name: 'FieldNumber', name: 'FieldNumber',
mixins: [fieldMixin], mixins: [fieldMixin],
data() { data() {
// value render
let value = this.metadata.value
if (this.metadata.inTable) {
value = this.valueModel
}
value = this.validateValue(value)
return { return {
value: value,
showControls: true, showControls: true,
operation: '', operation: '',
expression: /[\d\/.()%\*\+\-]/gim, expression: /[\d\/.()%\*\+\-]/gim,
@ -45,6 +38,9 @@ export default {
} }
}, },
computed: { computed: {
cssClassStyle() {
return this.metadata.cssClassName + ' custom-field-number'
},
maxValue() { maxValue() {
if (this.isEmptyValue(this.metadata.valueMax)) { if (this.isEmptyValue(this.metadata.valueMax)) {
return Infinity return Infinity
@ -83,22 +79,9 @@ export default {
return 'right' return 'right'
} }
}, },
watch: {
// enable to dataTable records
valueModel(value) {
if (this.metadata.inTable) {
this.value = this.validateValue(value)
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = this.validateValue(value)
}
}
},
methods: { methods: {
validateValue(value) { parseValue(value) {
if (this.isEmptyValue(value) || isNaN(value)) { if (this.isEmptyValue(value)) {
return undefined return undefined
} }
return Number(value) return Number(value)
@ -120,7 +103,7 @@ export default {
const newValue = String(this.value).slice(0, -1) const newValue = String(this.value).slice(0, -1)
const result = this.calculationValue(newValue, event) const result = this.calculationValue(newValue, event)
if (!this.isEmptyValue(result)) { if (!this.isEmptyValue(result)) {
this.value = this.validateValue(result) this.value = this.parseValue(result)
this.valueToDisplay = result this.valueToDisplay = result
this.isShowed = true this.isShowed = true
} else { } else {
@ -134,7 +117,7 @@ export default {
const newValue = String(this.value).slice(-1) const newValue = String(this.value).slice(-1)
const result = this.calculationValue(newValue, event) const result = this.calculationValue(newValue, event)
if (!this.isEmptyValue(result)) { if (!this.isEmptyValue(result)) {
this.value = this.validateValue(result) this.value = this.parseValue(result)
this.valueToDisplay = result this.valueToDisplay = result
this.isShowed = true this.isShowed = true
} else { } else {
@ -148,7 +131,7 @@ export default {
}, },
changeValue() { changeValue() {
if (!this.isEmptyValue(this.valueToDisplay) && this.valueToDisplay !== '...') { if (!this.isEmptyValue(this.valueToDisplay) && this.valueToDisplay !== '...') {
const result = this.validateValue(this.valueToDisplay) const result = this.parseValue(this.valueToDisplay)
this.preHandleChange(result) this.preHandleChange(result)
} }
this.clearVariables() this.clearVariables()
@ -158,14 +141,14 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
/* if is controls width 100% in container */ /* Show input width 100% in container */
.el-input-number, .el-input { .el-input-number, .el-input {
width: 100% !important; /* ADempiere Custom */ width: 100% !important; /* ADempiere Custom */
} }
/** Amount reference **/ /** Align text in right input **/
.display-type-amount { .custom-field-number {
text-align: right !important; text-align: right !important;
input, .el-input__inner { input, .el-input__inner {
text-align: right !important; text-align: right !important;

View File

@ -6,7 +6,7 @@
:placeholder="metadata.help" :placeholder="metadata.help"
:loading="isLoading" :loading="isLoading"
value-key="key" value-key="key"
:class="classStyle + ' ' + metadata.cssClassName" :class="cssClassStyle"
clearable clearable
:multiple="isSelectMultiple" :multiple="isSelectMultiple"
:allow-create="metadata.isSelectCreated" :allow-create="metadata.isSelectCreated"
@ -17,7 +17,7 @@
@clear="clearLookup" @clear="clearLookup"
> >
<el-option <el-option
v-for="(option, key) in options" v-for="(option, key) in optionsList"
:key="key" :key="key"
:value="option.key" :value="option.key"
:label="option.label" :label="option.label"
@ -26,7 +26,8 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import { convertBooleanToString } from '@/utils/ADempiere/valueUtils.js'
/** /**
* This component is a lookup type field, use as a replacement for fields: * This component is a lookup type field, use as a replacement for fields:
@ -36,23 +37,24 @@ import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin'
* *
* TODO: ALL: Although in the future these will have different components, and * TODO: ALL: Although in the future these will have different components, and
* are currently not supported is also displayed as a substitute for fields: * are currently not supported is also displayed as a substitute for fields:
* - Locator (WH)
* - Search Field * - Search Field
*/ */
export default { export default {
name: 'FieldSelect', name: 'FieldSelect',
mixins: [fieldMixin], mixins: [fieldMixin],
data() { data() {
// label with '' value is assumed to be undefined non-existent
const label = ' '
return { return {
isLoading: false, isLoading: false,
options: [{ optionsList: [{
label: ' ', label,
key: undefined key: undefined
}], }],
blankValues: [null, undefined, -1], blankValues: [null, undefined, -1],
blankOption: { blankOption: {
// label with '' value is assumed to be undefined non-existent label,
label: ' ',
key: undefined key: undefined
} }
} }
@ -67,8 +69,8 @@ export default {
isSelectMultiple() { isSelectMultiple() {
return ['IN', 'NOT_IN'].includes(this.metadata.operator) && this.metadata.isAdvancedQuery return ['IN', 'NOT_IN'].includes(this.metadata.operator) && this.metadata.isAdvancedQuery
}, },
classStyle() { cssClassStyle() {
let styleClass = 'custom-field-select' let styleClass = this.metadata.cssClassName + ' custom-field-select'
if (this.isSelectMultiple) { if (this.isSelectMultiple) {
styleClass += ' custom-field-select-multiple' styleClass += ' custom-field-select-multiple'
} }
@ -96,11 +98,60 @@ export default {
value: this.value value: this.value
}) })
// sets the value to blank when the lookupList or lookupItem have no
// values, or if only lookupItem does have a value
if (this.isEmptyValue(allOptions) || (allOptions.length && if (this.isEmptyValue(allOptions) || (allOptions.length &&
(!this.blankValues.includes(allOptions[0].key)))) { (!this.blankValues.includes(allOptions[0].key)))) {
allOptions.unshift(this.blankOption) allOptions.unshift(this.blankOption)
} }
return allOptions return allOptions
},
value: {
get() {
const value = this.$store.getters.getValueOfField({
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName
})
let label = this.findLabel(value)
if (!label) {
label = this.displayColumn
/* eslint-disable */
this.optionsList.push({
key: value,
label
})
/* eslint-disable */
}
return value
},
set(value) {
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName,
value
})
}
},
displayColumn: {
get() {
return this.$store.getters.getValueOfField({
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
// DisplayColumn_'ColumnName'
columnName: this.metadata.displayColumnName
})
},
set(value) {
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
// DisplayColumn_'ColumnName'
columnName: this.metadata.displayColumnName,
value
})
}
} }
}, },
watch: { watch: {
@ -114,27 +165,23 @@ export default {
} else { } else {
if (Array.isArray(this.value)) { if (Array.isArray(this.value)) {
if (this.value.length) { if (this.value.length) {
// set first value
this.value = this.value[0] this.value = this.value[0]
} else { } else {
this.value = undefined this.value = this.blankOption.key
} }
} }
} }
}, },
valueModel(value) { /*
if (this.metadata.inTable) {
this.value = value
}
},
'metadata.value'(value) { 'metadata.value'(value) {
if (!this.metadata.inTable) { if (!this.metadata.inTable) {
if (typeof value === 'boolean') { value = this.parseValue(value)
value = value ? 'Y' : 'N'
}
if (this.metadata.displayed) { if (this.metadata.displayed) {
if (!this.options.some(option => option.key === value) && if (!this.optionsList.some(option => option.key === value) &&
!this.isEmptyValue(this.metadata.displayColumn)) { !this.isEmptyValue(this.metadata.displayColumn)) {
this.options.push({ this.optionsList.push({
key: value, key: value,
label: this.metadata.displayColumn label: this.metadata.displayColumn
}) })
@ -154,7 +201,7 @@ export default {
if (!this.isEmptyValue(value)) { if (!this.isEmptyValue(value)) {
// verify if exists to add // verify if exists to add
if (!this.findLabel(this.value)) { if (!this.findLabel(this.value)) {
this.options.push({ this.optionsList.push({
key: this.value, key: this.value,
label: value label: value
}) })
@ -162,24 +209,31 @@ export default {
} }
} }
} }
}, }
*/
'metadata.displayed'(value) { 'metadata.displayed'(value) {
if (value) { if (value) {
// if is field showed, search into store all options to list
this.optionsList = this.getterLookupAll
}
}
},
created() {
this.changeBlankOption() this.changeBlankOption()
this.options = this.getterLookupAll
}
}
}, },
beforeMount() { beforeMount() {
if (this.metadata.displayed) { if (this.metadata.displayed) {
this.changeBlankOption() this.optionsList = this.getterLookupAll
this.options = this.getterLookupAll const value = this.value
if (!this.isEmptyValue(this.value) && !this.metadata.isAdvancedQuery) { if (!this.isEmptyValue(value) && !this.metadata.isAdvancedQuery) {
if (!this.findLabel(this.value)) { const label = this.findLabel(value)
if (label) {
this.displayColumn = label
} else {
if (!this.isEmptyValue(this.metadata.displayColumn)) { if (!this.isEmptyValue(this.metadata.displayColumn)) {
// verify if exists to add // verify if exists to add
this.options.push({ this.optionsList.push({
key: this.value, key: value,
label: this.metadata.displayColumn label: this.metadata.displayColumn
}) })
} else { } else {
@ -194,26 +248,28 @@ export default {
} }
}, },
methods: { methods: {
parseValue(value) {
if (typeof value === 'boolean') {
// value ? 'Y' : 'N'
value = convertBooleanToString(value)
}
return value
},
changeBlankOption() { changeBlankOption() {
if (Number(this.metadata.defaultValue) === -1) { if (Number(this.metadata.defaultValue) === -1) {
this.blankOption = { this.blankOption.key = -1
label: ' ',
key: -1
}
}
if (this.value === undefined || this.value === null) {
this.blankOption = {
label: ' ',
key: undefined
}
} }
}, },
preHandleChange(value) { preHandleChange(value) {
const label = this.findLabel(this.value) const label = this.findLabel(this.value)
this.handleChange(value, undefined, label) this.displayColumn = label
this.handleFieldChange({
value,
label
})
}, },
findLabel(value) { findLabel(value) {
const selected = this.options.find(item => item.key === value) const selected = this.optionsList.find(item => item.key === value)
if (selected) { if (selected) {
return selected.label return selected.label
} }
@ -230,20 +286,11 @@ export default {
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
tableName: this.metadata.reference.tableName, tableName: this.metadata.reference.tableName,
directQuery: this.metadata.reference.directQuery, directQuery: this.metadata.reference.directQuery,
value: this.metadata.value value: this.value
}) })
.then(responseLookupItem => { .then(responseLookupItem => {
if (this.isPanelWindow) { this.displayColumn = responseLookupItem.label
this.$store.dispatch('changeFieldAttribure', { this.optionsList = this.getterLookupAll
containerUuid: this.metadata.containerUuid,
isAdvancedQuery: this.metadata.isAdvancedQuery,
columnName: this.metadata.columnName,
attributeName: 'displayColumn',
attributeValue: responseLookupItem.label
})
}
this.changeBlankOption()
this.options = this.getterLookupAll
}) })
.finally(() => { .finally(() => {
this.isLoading = false this.isLoading = false
@ -261,26 +308,33 @@ export default {
} }
} }
}, },
async remoteMethod() { remoteMethod() {
if (this.isEmptyValue(this.metadata.reference.query)) {
return
}
this.isLoading = true this.isLoading = true
this.$store.dispatch('getLookupListFromServer', { this.$store.dispatch('getLookupListFromServer', {
parentUuid: this.metadata.parentUuid, parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
tableName: this.metadata.reference.tableName, tableName: this.metadata.reference.tableName,
query: this.metadata.reference.query query: this.metadata.reference.query,
isAddBlankValue: true,
blankValue: this.blankOption.key
}) })
.then(responseLookupList => { .then(responseLookupList => {
this.changeBlankOption() if (!this.isEmptyValue(responseLookupList)) {
this.options = this.getterLookupAll this.optionsList = responseLookupList
} else {
this.optionsList = this.getterLookupAll
}
}) })
.finally(() => { .finally(() => {
this.isLoading = false this.isLoading = false
}) })
}, },
clearLookup() { clearLookup() {
// set empty list and empty option
this.optionsList = [
this.blankOption
]
this.$store.dispatch('deleteLookupList', { this.$store.dispatch('deleteLookupList', {
parentUuid: this.metadata.parentUuid, parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
@ -290,12 +344,6 @@ export default {
value: this.value value: this.value
}) })
// set empty list and empty option
this.changeBlankOption()
const list = []
list.push(this.blankOption)
this.options = list
// set empty value // set empty value
this.value = this.blankOption.key this.value = this.blankOption.key
} }
@ -303,7 +351,7 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.custom-field-select { .custom-field-select {
width: 100%; width: 100%;
} }

View File

@ -17,18 +17,13 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
/** /**
* This component is a list type field, for IN and NOT IN search with advanced query * This component is a list type field, for IN and NOT IN search with advanced query
*/ */
export default { export default {
name: 'FieldSelectMultiple', name: 'FieldSelectMultiple',
mixins: [fieldMixin], mixins: [fieldMixin]
methods: {
preHandleChange(value) {
this.handleChange(value)
}
}
} }
</script> </script>

View File

@ -4,7 +4,7 @@
v-model="value" v-model="value"
:pattern="pattern" :pattern="pattern"
:rows="rows" :rows="rows"
:class="metadata.cssClassName" :class="cssClassStyle"
:type="typeTextBox" :type="typeTextBox"
:placeholder="metadata.help" :placeholder="metadata.help"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"
@ -22,12 +22,16 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import fieldMixinText from '@/components/ADempiere/Field/mixin/mixinFieldText.js'
import { TEXT } from '@/utils/ADempiere/references' import { TEXT } from '@/utils/ADempiere/references'
export default { export default {
name: 'FieldText', name: 'FieldText',
mixins: [fieldMixin], mixins: [
fieldMixin,
fieldMixinText
],
props: { props: {
inTable: { inTable: {
type: Boolean, type: Boolean,
@ -70,40 +74,6 @@ export default {
} }
return undefined return undefined
} }
},
watch: {
valueModel(value) {
if (this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
}
},
methods: {
validateUrl(e) {
// Entry pattern, in this case only accepts numbers and letters
const _Pattern = /^(http[s]?:\/\/(www\.)?|ftp:\/\/(www\.)?|www\.){1}([0-9A-Za-z-\.@:%_\+~#=]+)+((\.[a-zA-Z]{1,5})+)(\/(.)*)?(\?(.)*)?/g
var rex = RegExp(_Pattern)
var value = e.target.value
if (rex.test(value) && value.trim() !== '') {
console.log('url good format')
} else if (value.trim() === '') {
console.log('url empty')
} else {
// e.target.focus()
console.log('url wrong')
}
}
} }
} }
</script> </script>

View File

@ -1,5 +1,8 @@
<template> <template>
<div :id="id" :class="classDisable + ' ' + metadata.cssClassName" /> <div
:id="id"
:class="cssClassStyle"
/>
</template> </template>
<script> <script>
@ -10,11 +13,15 @@ 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' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import fieldMixinText from '@/components/ADempiere/Field/mixin/mixinFieldText.js'
export default { export default {
name: 'FieldTextLong', name: 'FieldTextLong',
mixins: [fieldMixin], mixins: [
fieldMixin,
fieldMixinText
],
props: { props: {
id: { id: {
type: String, type: String,
@ -32,11 +39,12 @@ export default {
} }
}, },
computed: { computed: {
classDisable() { cssClassStyle() {
let styleClass = this.metadata.cssClassName
if (this.isDisabled) { if (this.isDisabled) {
return 'isdisable' styleClass += ' custom-field-text-long-disable'
} }
return '' return styleClass
}, },
language() { language() {
// https://github.com/nhnent/tui.editor/tree/master/src/js/langs // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
@ -59,22 +67,6 @@ export default {
} }
}, },
watch: { watch: {
valueModel(value, oldValue) {
if (this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
'metadata.value'(value, oldValue) {
if (!this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
value(newValue, oldValue) { value(newValue, oldValue) {
if (this.isDisabled) { if (this.isDisabled) {
// not changed value // not changed value
@ -159,8 +151,9 @@ export default {
} }
} }
</script> </script>
<style>
.isdisable { <style scoped>
.custom-field-text-long-disable {
background: #F5F7FA; background: #F5F7FA;
} }
</style> </style>

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 ' + metadata.cssClassName" :class="cssClassStyle"
:readonly="Boolean(metadata.readonly)" :readonly="Boolean(metadata.readonly)"
:disabled="isDisabled" :disabled="isDisabled"
@change="preHandleChange" @change="preHandleChange"
@ -21,7 +21,7 @@
</template> </template>
<script> <script>
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
export default { export default {
name: 'FieldTime', name: 'FieldTime',
@ -44,22 +44,13 @@ export default {
return Number(this.metadata.valueMin) return Number(this.metadata.valueMin)
} }
return -Infinity return -Infinity
}
}, },
watch: { cssClassStyle() {
valueModel(value) { return this.metadata.cssClassName + ' custom-field-time'
if (this.metadata.inTable) {
this.value = this.parsedDateValue(value)
}
},
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = this.parsedDateValue(value)
}
} }
}, },
methods: { methods: {
parsedDateValue(value) { parseValue(value) {
if (typeof value === 'number') { if (typeof value === 'number') {
value = new Date(value).toUTCString() value = new Date(value).toUTCString()
} }
@ -73,7 +64,7 @@ export default {
</script> </script>
<style scoped> <style scoped>
.time-base { .custom-field-time {
width: 100% !important; width: 100% !important;
} }
</style> </style>

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 ' + metadata.cssClassName" :class="cssClassStyle"
:true-value="true" :true-value="true"
:false-value="false" :false-value="false"
:disabled="isDisabled" :disabled="isDisabled"
@ -17,7 +17,8 @@
<script> <script>
import { fieldIsDisplayed } from '@/utils/ADempiere' import { fieldIsDisplayed } from '@/utils/ADempiere'
import { FIELDS_READ_ONLY_FORM } from '@/utils/ADempiere/references' import { FIELDS_READ_ONLY_FORM } from '@/utils/ADempiere/references'
import { fieldMixin } from '@/components/ADempiere/Field/FieldMixin' import fieldMixin from '@/components/ADempiere/Field/mixin/mixinField.js'
import { convertStringToBoolean } from '@/utils/ADempiere/valueFormat.js'
export default { export default {
name: 'FieldYesNo', name: 'FieldYesNo',
@ -32,33 +33,17 @@ export default {
] ]
} }
}, },
watch: { computed: {
valueModel(value) { cssClassStyle() {
if (this.metadata.inTable) { return this.metadata.cssClassName + ' custom-field-yes-no'
this.value = Boolean(value)
} }
}, },
'metadata.value'(value) {
if (!this.metadata.inTable) {
this.value = Boolean(value)
}
},
value(value, oldValue) {
if (typeof value !== 'boolean') {
if (value === 'N' || value === 'n') {
value = false
}
this.value = Boolean(value)
}
this.preHandleChange('NotSend')
}
},
mounted() {
this.preHandleChange('NotSend') // activate logics
},
methods: { methods: {
parseValue(value) {
return convertStringToBoolean(value)
},
preHandleChange(value) { preHandleChange(value) {
this.handleChange(value) this.handleFieldChange({ value })
if (!this.metadata.inTable && !this.metadata.isAdvancedQuery) { if (!this.metadata.inTable && !this.metadata.isAdvancedQuery) {
this.isReadOnlyForm(this.value) this.isReadOnlyForm(this.value)
} }
@ -87,7 +72,7 @@ export default {
} }
</script> </script>
<style> <style scoped>
.custom-field-yes-no { .custom-field-yes-no {
max-height: 34px; max-height: 34px;
} }

View File

@ -59,27 +59,11 @@ export default {
} }
}, },
watch: { watch: {
valueModel(value, oldValue) {
if (this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
clean(value) { clean(value) {
if (value) { if (value) {
this.editor.setValue('') this.editor.setValue('')
} }
}, },
'metadata.value'(value, oldValue) {
if (!this.metadata.inTable) {
if (this.isEmptyValue(value)) {
value = ''
}
this.value = String(value)
}
},
value(newValue, oldValue) { value(newValue, oldValue) {
if (this.isDisabled) { if (this.isDisabled) {
// not changed value // not changed value

View File

@ -213,10 +213,7 @@ export default {
if (this.field.isAlwaysUpdateable) { if (this.field.isAlwaysUpdateable) {
return false return false
} }
if (this.field.isProcessingContext) { if (this.field.isProcessingContext || this.field.isProcessedContext) {
return true
}
if (this.field.isProcessedContext) {
return true return true
} }
@ -227,7 +224,8 @@ export default {
isWithRecord = !this.isEmptyValue(this.field.recordUuid) isWithRecord = !this.isEmptyValue(this.field.recordUuid)
} }
return (!this.field.isUpdateable && isWithRecord) || (isUpdateableAllFields || this.field.isReadOnlyFromForm) return (!this.field.isUpdateable && isWithRecord) ||
(isUpdateableAllFields || this.field.isReadOnlyFromForm)
} else if (this.field.panelType === 'browser') { } else if (this.field.panelType === 'browser') {
if (this.inTable) { if (this.inTable) {
// browser result // browser result
@ -247,8 +245,8 @@ export default {
}, },
isSelectCreated() { isSelectCreated() {
return this.isAdvancedQuery && return this.isAdvancedQuery &&
!['FieldBinary', 'FieldDate', 'FieldSelect', 'FieldYesNo'].includes(this.field.componentPath) && ['IN', 'NOT_IN'].includes(this.field.operator) &&
['IN', 'NOT_IN'].includes(this.field.operator) !['FieldBinary', 'FieldDate', 'FieldSelect', 'FieldYesNo'].includes(this.field.componentPath)
}, },
getWidth() { getWidth() {
return this.$store.getters.getWidthLayout return this.$store.getters.getWidthLayout
@ -343,7 +341,8 @@ export default {
if (!this.isAdvancedQuery) { if (!this.isAdvancedQuery) {
return false return false
} }
return (this.field.contextInfo && this.field.contextInfo.isActive) || (this.field.reference && this.field.reference.windowsList.length) return (this.field.contextInfo && this.field.contextInfo.isActive) ||
(this.field.reference && this.field.reference.windowsList.length)
} }
}, },
watch: { watch: {
@ -388,6 +387,7 @@ export default {
font-weight: bold; font-weight: bold;
float: left; float: left;
} }
/** /**
* Separation between elements (item) of the form * Separation between elements (item) of the form
*/ */
@ -396,6 +396,7 @@ export default {
margin-left: 10px; margin-left: 10px;
margin-right: 10px; margin-right: 10px;
} }
/** /**
* Reduce the spacing between the form element and its label * Reduce the spacing between the form element and its label
*/ */

View File

@ -1,5 +1,5 @@
export const fieldMixin = { export default {
props: { props: {
metadata: { metadata: {
type: Object, type: Object,
@ -13,26 +13,48 @@ export const fieldMixin = {
}, },
data() { data() {
// value render // value render
let value = this.metadata.value let value1 = this.metadata.value
if (this.metadata.inTable) { if (this.metadata.inTable) {
value = this.valueModel value1 = this.valueModel
} }
value1 = this.parseValue(value1)
return { return {
value value1
} }
}, },
computed: { computed: {
isDisabled() { isDisabled() {
return Boolean(this.metadata.readonly || this.metadata.disabled) return Boolean(this.metadata.readonly || this.metadata.disabled)
},
cssClassStyle() {
return this.metadata.cssClassName
},
value: {
get() {
return this.$store.getters.getValueOfField({
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName
})
},
set(value) {
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName,
value
})
}
} }
}, },
async created() { async created() {
if (this.metadata.isSQLValue && (this.isEmptyValue(this.metadata.value) || this.metadata.value.isSQL || isNaN(this.metadata.value))) { if (this.metadata.isSQLValue && (this.isEmptyValue(this.metadata.value) || this.metadata.value.isSQL)) {
const value = await this.$store.dispatch('getValueBySQL', { const value = await this.$store.dispatch('getValueBySQL', {
parentUuid: this.metadata.parentUuid, parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
query: this.metadata.defaultValue query: this.metadata.defaultValue
}) })
// set value and change into store
this.preHandleChange(value) this.preHandleChange(value)
} }
}, },
@ -41,7 +63,27 @@ export const fieldMixin = {
this.requestFocus() this.requestFocus()
} }
}, },
watch: {
// valueModel(value) {
// if (this.metadata.inTable) {
// this.value = this.parseValue(value)
// }
// },
// 'metadata.value'(value) {
// if (!this.metadata.inTable) {
// this.value = this.parseValue(value)
// }
// }
},
methods: { methods: {
/**
* Parse the value to a new value if required for element-ui component
* compatibility where this method is overwritten
* @param {mixed} value
*/
parseValue(value) {
return value
},
/** /**
* Set focus if handle focus attribute is true * Set focus if handle focus attribute is true
*/ */
@ -56,7 +98,7 @@ export const fieldMixin = {
* @param {mixed} value * @param {mixed} value
*/ */
preHandleChange(value) { preHandleChange(value) {
this.handleChange(value) this.handleFieldChange({ value })
}, },
focusGained(value) { focusGained(value) {
if (this.metadata.handleContentSelection) { if (this.metadata.handleContentSelection) {
@ -119,43 +161,17 @@ export const fieldMixin = {
* @param {mixed} valueTo, used in end value in range * @param {mixed} valueTo, used in end value in range
* @param {string} label, or displayColumn to show in select * @param {string} label, or displayColumn to show in select
*/ */
handleChange(value, valueTo = undefined, label = undefined) { handleFieldChange({
let newValue = value value,
let isSendCallout = true
let isSendToServer = true
let isChangedOldValue = false
if (value === 'NotSend') {
newValue = this.value
if (this.componentPath === 'FieldYesNo') {
isChangedOldValue = true
newValue = Boolean(newValue)
}
isSendToServer = false
isSendCallout = false
}
if (this.metadata.isAdvancedQuery) {
isSendCallout = false
}
const sendParameters = {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
field: this.metadata,
panelType: this.metadata.panelType,
columnName: this.metadata.columnName,
newValue,
valueTo, valueTo,
isAdvancedQuery: this.metadata.isAdvancedQuery, label
isSendToServer, }) {
isSendCallout,
isChangedOldValue
}
// Global Action performed // Global Action performed
if (this.metadata.handleActionPerformed) { if (this.metadata.handleActionPerformed) {
this.$store.dispatch('notifyActionPerformed', { this.$store.dispatch('notifyActionPerformed', {
containerUuid: this.metadata.containerUuid, containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName, columnName: this.metadata.columnName,
value: newValue value
}) })
} }
@ -163,20 +179,10 @@ export const fieldMixin = {
if (this.metadata.isCustomField) { if (this.metadata.isCustomField) {
return return
} }
if (this.metadata.inTable) {
this.$store.dispatch('notifyCellTableChange', {
...sendParameters,
keyColumn: this.metadata.keyColumn,
tableIndex: this.metadata.tableIndex,
rowKey: this.metadata.rowKey
})
} else {
this.$store.dispatch('notifyFieldChange', { this.$store.dispatch('notifyFieldChange', {
...sendParameters, containerUuid: this.metadata.containerUuid,
displayColumn: label field: this.metadata
}) })
} }
} }
}
} }

View File

@ -0,0 +1,29 @@
export default {
computed: {
value: {
get() {
const value = this.$store.getters.getValueOfField({
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName
})
const valueTo = this.$store.getters.getValueOfField({
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName
})
return [
value,
valueTo
]
},
set(value) {
this.$store.commit('updateValueOfField', {
parentUuid: this.metadata.parentUuid,
containerUuid: this.metadata.containerUuid,
columnName: this.metadata.columnName,
value
})
}
}
}
}

View File

@ -0,0 +1,10 @@
export default {
methods: {
parseValue(value) {
if (this.isEmptyValue(value)) {
value = ''
}
return String(value)
}
}
}

View File

@ -235,33 +235,33 @@ export default {
} }
}, },
changeValue() { changeValue() {
const newValue = Number(this.valueToDisplay) // const newValue = Number(this.valueToDisplay)
let isSendCallout = true // let isSendCallout = true
const isSendToServer = true // const isSendToServer = true
const isChangedOldValue = false // const isChangedOldValue = false
if (this.fieldAttributes.isAdvancedQuery) { // if (this.fieldAttributes.isAdvancedQuery) {
isSendCallout = false // isSendCallout = false
} // }
//
const sendParameters = { // const sendParameters = {
parentUuid: this.fieldAttributes.parentUuid, // parentUuid: this.fieldAttributes.parentUuid,
containerUuid: this.fieldAttributes.containerUuid, // containerUuid: this.fieldAttributes.containerUuid,
field: this.fieldAttributes, // field: this.fieldAttributes,
panelType: this.fieldAttributes.panelType, // panelType: this.fieldAttributes.panelType,
columnName: this.fieldAttributes.columnName, // columnName: this.fieldAttributes.columnName,
newValue, // newValue,
isAdvancedQuery: this.fieldAttributes.isAdvancedQuery, // isAdvancedQuery: this.fieldAttributes.isAdvancedQuery,
isSendToServer, // isSendToServer,
isSendCallout, // isSendCallout,
isChangedOldValue // isChangedOldValue
} // }
this.$store.dispatch('notifyFieldChange', { // this.$store.dispatch('notifyFieldChange', {
...sendParameters // ...sendParameters
}) // })
.finally(() => { // .finally(() => {
this.clearVariables() // this.clearVariables()
this.$children[0].visible = false // this.$children[0].visible = false
}) // })
}, },
spanMethod({ row, column, rowIndex, columnIndex }) { spanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 1) { if (rowIndex === 1) {

View File

@ -108,13 +108,13 @@ export default {
} }
}, },
documentActionChange(value) { documentActionChange(value) {
this.$store.dispatch('notifyFieldChange', { // this.$store.dispatch('notifyFieldChange', {
parentUuid: this.field.parentUuid, // parentUuid: this.field.parentUuid,
containerUuid: this.field.containerUuid, // containerUuid: this.field.containerUuid,
columnName: 'DocAction', // columnName: 'DocAction',
isSendToServer: true, // isSendToServer: true,
newValue: value // newValue: value
}) // })
const actionProcess = this.$store.getters.getOrders const actionProcess = this.$store.getters.getOrders
this.$store.dispatch('startProcess', { this.$store.dispatch('startProcess', {

View File

@ -66,22 +66,21 @@ export default {
* @param {string} label, or displayColumn to show in select * @param {string} label, or displayColumn to show in select
*/ */
handleChange(value) { handleChange(value) {
const sendParameters = { // const sendParameters = {
parentUuid: this.fieldAttributes.parentUuid, // parentUuid: this.fieldAttributes.parentUuid,
containerUuid: this.fieldAttributes.containerUuid, // containerUuid: this.fieldAttributes.containerUuid,
field: this.fieldAttributes, // field: this.fieldAttributes,
panelType: this.fieldAttributes.panelType, // panelType: this.fieldAttributes.panelType,
columnName: this.fieldAttributes.columnName, // columnName: this.fieldAttributes.columnName,
newValue: value === 'NotSend' ? this.value : value, // newValue: value === 'NotSend' ? this.value : value,
isAdvancedQuery: true, // isAdvancedQuery: true,
isSendToServer: !(value === 'NotSend'), // isSendToServer: !(value === 'NotSend'),
isSendCallout: false // isSendCallout: false
} // }
// this.$store.dispatch('notifyFieldChange', {
this.$store.dispatch('notifyFieldChange', { // ...sendParameters,
...sendParameters, // isChangedOldValue: this.fieldAttributes.componentPath === 'FieldYesNo' && Boolean(value === 'NotSend')
isChangedOldValue: this.fieldAttributes.componentPath === 'FieldYesNo' && Boolean(value === 'NotSend') // })
})
} }
} }
} }

View File

@ -139,12 +139,12 @@ export default {
// Set value for one field from panel // Set value for one field from panel
// use example: setValue('ProductName', 'Patio Fun') // use example: setValue('ProductName', 'Patio Fun')
setValue(columnName, value) { setValue(columnName, value) {
this.$store.dispatch('notifyFieldChange', { // this.$store.dispatch('notifyFieldChange', {
containerUuid: this.metadata.containerUuid, // containerUuid: this.metadata.containerUuid,
panelType: this.metadata.panelType, // panelType: this.metadata.panelType,
columnName, // columnName,
newValue: value // newValue: value
}) // })
}, },
// Set values for all list of columns // Set values for all list of columns
// Use example: setValues(values) // Use example: setValues(values)

View File

@ -1,199 +1,19 @@
<template> <template>
<div class="wrapper"> <component
<el-form :is="templateDevice"
v-if="isLoadPanel" :parent-uuid="parentUuid"
key="panel-loaded"
v-model="dataRecords"
label-position="top"
label-width="200px"
>
<template
v-if="firstGroup && firstGroup.groupFinal === ''"
>
<div v-show="firstGroup.activeFields" class="cards-not-group">
<div
v-if="(groupTab.groupType == 'T' && groupTab.groupName == firstGroup.groupFinal)
|| (groupTab.groupType !== 'T' && firstGroup.typeGroup !== 'T')"
class="card"
>
<div class="select-filter">
<span>
{{ firstGroup.groupFinal }}
</span>
<filter-fields
:container-uuid="containerUuid" :container-uuid="containerUuid"
:metadata="metadata"
:group-tab="groupTab"
:panel-type="panelType" :panel-type="panelType"
:group-field="firstGroup.groupFinal"
:is-advanced-query="isAdvancedQuery" :is-advanced-query="isAdvancedQuery"
:is-showed-record-navigation="isShowedRecordNavigation"
/> />
</div>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<el-row>
<template v-for="(fieldAttributes, subKey) in firstGroup.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
isShowedRecordNavigation,
isProcessingContext: getterContextProcessing,
isProcessedContext: getterContextProcessed,
optionCRUD,
recordUuid: uuidRecord
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="!isShowedRecordNavigation"
:is-advanced-query="isAdvancedQuery"
/>
</template>
</el-row>
</el-card>
</div>
</div>
</template>
<div :class="classCards">
<draggable
v-if="!isMobile"
key="draggable-loaded"
:list="fieldGroups"
v-bind="$attrs"
:set-data="setData"
>
<template v-for="(item, key) in fieldGroups">
<el-row :key="key">
<el-col :key="key" :span="24">
<div
v-if="item.groupFinal !== ''
&& (groupTab.groupType == 'T' && groupTab.groupName == item.groupFinal)
|| (groupTab.groupType !== 'T' && item.typeGroup !== 'T')"
:key="key"
class="card"
>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<div slot="header" class="clearfix">
<span>
{{ item.groupFinal }}
</span>
<div class="select-filter-header">
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="item.groupFinal"
:is-first-group="false"
:is-advanced-query="isAdvancedQuery"
/>
</div>
</div>
<el-row>
<template v-for="(fieldAttributes, subKey) in item.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
isShowedRecordNavigation,
isProcessingContext: getterContextProcessing,
isProcessedContext: getterContextProcessed,
optionCRUD,
recordUuid: uuidRecord
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="isPanelWindow && fieldGroups.length > 1"
:is-advanced-query="isAdvancedQuery"
/>
</template>
</el-row>
</el-card>
</div>
</el-col>
</el-row>
</template>
</draggable>
<template v-else>
<template v-for="(item, key) in fieldGroups">
<el-row :key="key">
<el-col :key="key" :span="24">
<div
v-if="item.groupFinal !== ''
&& (groupTab.groupType == 'T' && groupTab.groupName == item.groupFinal)
|| (groupTab.groupType !== 'T' && item.typeGroup !== 'T')"
:key="key"
class="card"
>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<div slot="header" class="clearfix">
<span>
{{ item.groupFinal }}
</span>
<div v-if="!isAdvancedQuery" class="select-filter-header">
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="item.groupFinal"
:is-first-group="false"
/>
</div>
</div>
<el-row>
<template v-for="(fieldAttributes, subKey) in item.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
isShowedRecordNavigation,
isProcessingContext: getterContextProcessing,
isProcessedContext: getterContextProcessed,
optionCRUD,
recordUuid: uuidRecord
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="isPanelWindow && fieldGroups.length > 1"
/>
</template>
</el-row>
</el-card>
</div>
</el-col>
</el-row>
</template>
</template>
</div>
</el-form>
<div
v-else
key="panel-loading"
v-loading="!isLoadPanel"
:element-loading-text="$t('notifications.loading')"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255, 255, 255, 0.8)"
class="loading-panel"
/>
</div>
</template> </template>
<script> <script>
import FieldDefinition from '@/components/ADempiere/Field'
import FilterFields from '@/components/ADempiere/Panel/filterFields'
import draggable from 'vuedraggable'
import { fieldIsDisplayed, parsedValueComponent } from '@/utils/ADempiere'
export default { export default {
name: 'MainPanel', name: 'MainPanel',
components: {
FieldDefinition,
FilterFields,
draggable
},
props: { props: {
parentUuid: { parentUuid: {
type: String, type: String,
@ -228,563 +48,20 @@ export default {
default: false default: false
} }
}, },
data() {
return {
fieldList: [],
dataRecords: {},
isLoadPanel: false,
isLoadRecord: false,
uuidRecord: this.$route.query.action,
fieldGroups: [],
firstGroup: {},
groupsView: 0,
tagTitle: {
base: this.$route.meta.title,
action: ''
}
}
},
computed: { computed: {
shadowGroup() {
if (this.isMobile) {
return 'never'
}
return 'hover'
},
optionCRUD() {
return this.isEmptyValue(this.uuidRecord) ? 'create-new' : this.uuidRecord
},
isPanelWindow() {
return this.panelType === 'window'
},
getterContextProcessing() {
if (this.panelType === 'window' && !this.isAdvancedQuery) {
const processing = this.$store.getters.getContextProcessing(this.parentUuid)
if (processing === true || processing === 'Y') {
return true
}
}
return false
},
getterContextProcessed() {
if (this.panelType === 'window' && !this.isAdvancedQuery) {
const processed = this.$store.getters.getContextProcessed(this.parentUuid)
if (processed === true || processed === 'Y') {
return true
}
}
return false
},
getterPanel() {
return this.$store.getters.getPanel(this.containerUuid, this.isAdvancedQuery)
},
getterFieldList() {
if (this.getterPanel) {
return this.getterPanel.fieldList
}
return undefined
},
isMobile() { isMobile() {
return this.$store.state.app.device === 'mobile' return this.$store.state.app.device === 'mobile'
}, },
getterDataStore() { templateDevice() {
if (this.isPanelWindow) { if (this.isMobile) {
return this.$store.getters.getDataRecordAndSelection(this.containerUuid) return () => import('@/components/ADempiere/Panel/mainPanelMobile')
} }
return { return () => import('@/components/ADempiere/Panel/mainPanelDesktop')
recordCount: 0,
isLoaded: false,
record: []
}
},
getterIsLoadedRecord() {
return this.getterDataStore.isLoaded
},
classCards() {
if (this.isMobile || this.fieldGroups.length < 2 || this.isShowedRecordNavigation) {
return 'cards-not-group'
}
return 'cards-in-group'
}
},
watch: {
// used only panel modal (process associated in browser or window)
containerUuid() {
if (['report', 'process'].includes(this.panelType)) {
this.generatePanel(this.metadata.fieldList)
}
},
'$route.query.action'(newValue, oldValue) {
// used in field, if uuid record or different create-new, field is read only
this.uuidRecord = newValue
if (newValue !== oldValue && this.isPanelWindow) {
this.changePanelRecord(newValue)
}
},
isLoadPanel(value) {
if (value) {
this.readParameters()
}
}
},
created() {
// get fields with uuid
this.getPanel()
},
methods: {
/**
* Get the tab object with all its attributes as well as the fields it contains
*/
getPanel() {
const fieldsList = this.getterFieldList
if (fieldsList && Array.isArray(fieldsList)) {
this.generatePanel(fieldsList)
} else {
this.$store.dispatch('getPanelAndFields', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
panelType: this.panelType,
panelMetadata: this.metadata,
isAdvancedQuery: this.isAdvancedQuery
}).then(() => {
this.generatePanel(this.getterFieldList)
}).catch(error => {
console.warn(`Field Load Error: ${error.message}. Code: ${error.code}.`)
})
}
},
generatePanel(fieldsList) {
// order and assign groups
this.fieldList = fieldsList
if (fieldsList.length) {
this.fieldGroups = this.sortAndGroup(fieldsList)
}
let firstGroup
if (this.fieldGroups[0] && this.fieldGroups[0].groupFinal === '') {
firstGroup = this.fieldGroups[0]
this.fieldGroups.shift()
}
this.firstGroup = firstGroup
this.isLoadPanel = true
},
/**
* TODO: Delete route parameters after reading them
*/
readParameters() {
const parameters = {
isLoadAllRecords: true,
isReference: false,
isNewRecord: false,
isWindow: true,
criteria: {}
}
const route = this.$route
if (this.isPanelWindow) {
// TODO: use action notifyPanelChange with isShowedField in true
this.getterFieldList.forEach(fieldItem => {
if (Object.prototype.hasOwnProperty.call(route.query, fieldItem.columnName) && !fieldItem.isAdvancedQuery) {
fieldItem.isShowedFromUser = true
fieldItem.value = parsedValueComponent({
fieldType: fieldItem.componentPath,
value: route.query[fieldItem.columnName],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (String(route.query.isAdvancedQuery) === String(fieldItem.isAdvancedQuery)) {
fieldItem.value = parsedValueComponent({
fieldType: fieldItem.componentPath,
value: route.query[fieldItem.columnName],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (fieldItem.isRange && this.$route.query[`${fieldItem.columnName}_To`]) {
fieldItem.valueTo = parsedValueComponent({
fieldType: fieldItem.componentPath,
value: route.query[`${fieldItem.columnName}_To`],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
}
}
}
})
if (route.query.action && route.query.action === 'reference') {
const referenceInfo = this.$store.getters.getReferencesInfo({
windowUuid: this.parentUuid,
recordUuid: route.query.recordUuid,
referenceUuid: route.query.referenceUuid
})
route.params.isReadParameters = true
parameters.isLoadAllRecords = false
parameters.isReference = true
parameters.referenceUuid = referenceInfo.uuid
parameters.referenceWhereClause = referenceInfo.whereClause
} else if (route.query.action && route.query.action === 'create-new') {
parameters.isNewRecord = true
} else if (route.query.action && route.query.action === 'criteria') {
route.params.isReadParameters = true
Object.keys(route.params).forEach(param => {
if (!this.isEmptyValue(route.params[param])) {
parameters.criteria[param] = route.params[param]
}
})
} else if (route.query.action && route.query.action === 'listRecords') {
parameters.isLoadAllRecords = true
route.params.isReadParameters = true
} else if (!this.isEmptyValue(route.query.action) &&
!['create-new', 'reference', 'advancedQuery', 'criteria', 'listRecords'].includes(route.query.action)) {
parameters.isLoadAllRecords = false
parameters.value = route.query.action
parameters.tableName = this.metadata.tableName
parameters.columnName = 'UUID'
route.params.isReadParameters = true
}
// Only call get data if panel type is window
if (!Object.prototype.hasOwnProperty.call(route.params, 'isReadParameters') || route.params.isReadParameters) {
this.getData(parameters)
}
let viewTitle = ''
if (route.query && !this.isEmptyValue(route.query.action)) {
viewTitle = route.query.action
}
this.setTagsViewTitle(viewTitle)
} else {
if (this.panelType === 'table' && route.query.action === 'advancedQuery') {
// TODO: use action notifyPanelChange with isShowedField in true
this.fieldList.forEach(fieldItem => {
if (Object.prototype.hasOwnProperty.call(route.query, fieldItem.columnName) && fieldItem.isAdvancedQuery) {
fieldItem.isShowedFromUser = true
if (route.query.action === 'advancedQuery' && fieldItem.isAdvancedQuery) {
this.dataRecords[fieldItem.columnName] = parsedValueComponent({
fieldType: fieldItem.componentPath,
value: route.query[fieldItem.columnName],
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (fieldItem.isRange && route.query[`${fieldItem.columnName}_To`]) {
this.dataRecords[fieldItem.columnName] = parsedValueComponent({
fieldType: fieldItem.componentPath,
value: route.query[`${fieldItem.columnName}_To`],
isIdentifier: fieldItem.columnName.includes('_ID')
})
}
}
}
})
parameters.isWindow = false
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
isAdvancedQuery: route.query.action === 'advancedQuery',
newValues: this.dataRecords,
isSendToServer: true,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
})
} else if (['process', 'browser'].includes(this.panelType)) {
if (!this.isEmptyValue(route.query)) {
this.$store.dispatch('notifyPanelChange', {
containerUuid: this.containerUuid,
newValues: route.query,
isShowedField: true,
isSendCallout: false,
panelType: this.panelType
})
parameters.isWindow = false
}
}
}
},
/**
* @param {object} parameters parameters to condition the data query
*/
getData(parameters) {
if (parameters.isWindow && this.isPanelWindow && !this.getterIsLoadedRecord) {
this.$store.dispatch('getDataListTab', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
isLoadAllRecords: parameters.isLoadAllRecords,
isReference: parameters.isReference,
referenceWhereClause: parameters.referenceWhereClause,
columnName: parameters.columnName,
value: parameters.value,
criteria: parameters.criteria
})
.then(response => {
if (response.length && !parameters.isNewRecord) {
this.dataRecords = response[0]
const recordId = this.dataRecords[`${this.metadata.tableName}_ID`]
if (this.$route.query.action === 'criteria') {
this.$router.push({
name: this.$route.name,
query: {
...this.$route.query,
action: this.dataRecords.UUID
},
params: {
...this.$route.params,
tableName: this.metadata.tableName,
recordId
}
}).catch(error => {
console.info(`Panel Component: ${error.name}, ${error.message}`)
})
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
newValues: this.dataRecords,
isSendToServer: false,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
})
} else if (this.$route.query.action === 'reference') {
this.$router.push({
name: this.$route.name,
query: {
...this.$route.query
},
params: {
...this.$route.params,
tableName: this.metadata.tableName,
recordId
}
}).catch(error => {
console.info(`Panel Component: ${error.name}, ${error.message}`)
})
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
newValues: this.dataRecords,
isSendToServer: false,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
})
} else {
this.$router.push({
query: {
...this.$route.query,
action: this.dataRecords.UUID
},
params: {
...this.$route.params,
tableName: this.metadata.tableName,
recordId
}
}).catch(error => {
console.info(`Panel Component: ${error.name}, ${error.message}`)
})
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
newValues: this.dataRecords,
isSendToServer: false,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
})
}
let viewTitle = ''
if (this.$route.query && !this.isEmptyValue(this.$route.query.action)) {
viewTitle = this.$route.query.action
}
this.setTagsViewTitle(viewTitle)
this.isLoadRecord = true
} else {
this.$router.push({
query: {
...this.$route.query,
action: 'create-new'
}
}).catch(error => {
console.info(`Panel Component: ${error.name}, ${error.message}`)
})
}
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
}
},
/**
* Group the arrangement into groups of columns that they contain, it must
* be grouped after having the order
* @param {array} fieldsList
* @return {array} groupsList
*/
sortAndGroup(fieldsList) {
if (this.isEmptyValue(fieldsList)) {
return
}
let groupsList = [{
groupFinal: '',
metadataFields: fieldsList
}]
// reduce, create array with number groupAssigned element comun
if (this.isPanelWindow) {
groupsList = fieldsList
.reduce((groupsList, currentValue) => {
if (!groupsList.includes(currentValue.groupAssigned)) {
groupsList.push(currentValue.groupAssigned)
}
return groupsList
}, [])
.map(itemGroup => {
return {
groupFinal: itemGroup,
metadataFields: fieldsList.filter(itemField => {
return itemField.groupAssigned === itemGroup
})
}
})
}
// count and add the field numbers according to your group
groupsList.forEach(groupFields => {
const typeG = groupFields.metadataFields[0].typeGroupAssigned
groupFields.typeGroup = typeG
const fieldsDisplayed = groupFields.metadataFields.filter(field => {
return fieldIsDisplayed(field)
})
if ((this.groupTab.groupType === 'T' && this.groupTab.groupName === groupFields.groupFinal) ||
(this.groupTab.groupType !== 'T' && groupFields.typeGroup !== 'T')) {
this.groupsView = this.groupsView + 1
}
groupFields.activeFields = fieldsDisplayed.length
})
return groupsList
},
setTagsViewTitle(actionValue) {
if (actionValue !== 'create-new' && !this.isEmptyValue(actionValue) && this.getterPanel.isDocument && this.getterDataStore.isLoaded) {
this.$store.dispatch('listWorkflows', this.metadata.tableName)
this.$store.dispatch('listDocumentStatus', {
recordUuid: this.$route.query.action,
tableName: this.metadata.tableName
})
}
if (actionValue === 'create-new' || this.isEmptyValue(actionValue)) {
this.tagTitle.action = this.$t('tagsView.newRecord')
} else if (actionValue === 'advancedQuery') {
this.tagTitle.action = this.$t('tagsView.advancedQuery')
} else {
const { identifierColumns } = this.getterPanel
if (!this.isEmptyValue(identifierColumns)) {
if (this.dataRecords[identifierColumns[0]]) {
this.tagTitle.action = this.dataRecords[identifierColumns[0]]
} else {
const field = this.fieldList.find(fieldItem => fieldItem.isIdentifier)
this.tagTitle.action = field.value
}
} else {
this.tagTitle.action = this.$t('tagsView.seeRecord')
}
}
if (this.isPanelWindow) {
this.$store.dispatch('tagsView/updateVisitedView', {
...this.$route,
title: `${this.tagTitle.base} - ${this.tagTitle.action}`
})
}
},
setData(dataTransfer) {
// to avoid Firefox bug
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
dataTransfer.setData('Text', '')
},
changePanelRecord(uuidRecord) {
if (!['create-new', 'reference', 'advancedQuery', 'criteria', 'listRecords'].includes(uuidRecord)) {
const recordSelected = this.getterDataStore.record.find(record => record.UUID === uuidRecord)
if (recordSelected) {
this.dataRecords = recordSelected
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
newValues: this.dataRecords,
isSendToServer: false,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
}).then(() => {
if (this.getterPanel.isTabsChildren) {
// delete records tabs children when change record uuid
this.$store.dispatch('deleteRecordContainer', {
viewUuid: this.parentUuid,
withOut: [this.containerUuid]
})
}
})
}
}
this.setTagsViewTitle(uuidRecord)
if (this.$route.query && this.$route.query.action === 'create-new') {
this.setFocus()
}
const currentRecord = this.getterDataStore.record.find(record => record.UUID === uuidRecord)
this.$store.dispatch('currentRecord', currentRecord)
},
async setFocus() {
return new Promise(resolve => {
const fieldFocus = this.getterFieldList.find(itemField => {
if (itemField.handleRequestFocus) {
return true
}
if (Object.prototype.hasOwnProperty.call(this.$refs, itemField.columnName)) {
if (fieldIsDisplayed(itemField) && !itemField.isReadOnly && itemField.isUpdateable && itemField.componentPath !== 'FieldSelect') {
return true
}
}
})
if (fieldFocus) {
this.$refs[fieldFocus.columnName][0].focusField()
}
resolve()
return
})
} }
} }
} }
</script> </script>
<style scoped>
.loading-panel {
padding: 100px;
height: 100%;
}
.cards-in-group {
column-count: 2; /*numbers of columns */
column-gap: 1em;
}
.cards-not-group {
column-count: 1; /* numbers of columns */
column-gap: 1em;
margin-bottom: 5px;
}
.card {
/* padding: 10px; */
width: 100% !important;
transition: all 100ms ease-in-out;
display: inline-block;
perspective: 1000;
backface-visibility: hidden;
}
.el-card {
width: 100% !important;
}
</style>
<style> <style>
.select-filter { .select-filter {
width: 280px !important; width: 280px !important;

View File

@ -0,0 +1,170 @@
<template>
<div class="wrapper">
<el-form
v-if="isLoadPanel"
key="panel-loaded"
v-model="dataRecords"
label-position="top"
label-width="200px"
>
<template
v-if="firstGroup && firstGroup.groupFinal === ''"
>
<div v-show="firstGroup.activeFields" class="cards-not-group">
<div
v-if="(groupTab.groupType == 'T' && groupTab.groupName == firstGroup.groupFinal)
|| (groupTab.groupType !== 'T' && firstGroup.typeGroup !== 'T')"
class="card"
>
<div class="select-filter">
<span>
{{ firstGroup.groupFinal }}
</span>
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="firstGroup.groupFinal"
:is-advanced-query="isAdvancedQuery"
/>
</div>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<el-row>
<template v-for="(fieldAttributes, subKey) in firstGroup.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
...panelAttributes
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="!isShowedRecordNavigation"
:is-advanced-query="isAdvancedQuery"
/>
</template>
</el-row>
</el-card>
</div>
</div>
</template>
<div :class="classCards">
<draggable
key="draggable-loaded"
:list="fieldGroups"
v-bind="$attrs"
:set-data="setData"
>
<template v-for="(item, key) in fieldGroups">
<el-row :key="key">
<el-col :key="key" :span="24">
<div
v-if="item.groupFinal !== ''
&& (groupTab.groupType == 'T' && groupTab.groupName == item.groupFinal)
|| (groupTab.groupType !== 'T' && item.typeGroup !== 'T')"
:key="key"
class="card"
>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<div slot="header" class="clearfix">
<span>
{{ item.groupFinal }}
</span>
<div class="select-filter-header">
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="item.groupFinal"
:is-first-group="false"
:is-advanced-query="isAdvancedQuery"
/>
</div>
</div>
<el-row>
<template v-for="(fieldAttributes, subKey) in item.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
...panelAttributes
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="isPanelWindow && fieldGroups.length > 1"
:is-advanced-query="isAdvancedQuery"
/>
</template>
</el-row>
</el-card>
</div>
</el-col>
</el-row>
</template>
</draggable>
</div>
</el-form>
<div
v-else
key="panel-loading"
v-loading="!isLoadPanel"
:element-loading-text="$t('notifications.loading')"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255, 255, 255, 0.8)"
class="loading-panel"
/>
</div>
</template>
<script>
import { mainPanelMixin } from '@/components/ADempiere/Panel/mainPanelMixin.js'
import draggable from 'vuedraggable'
export default {
name: 'MainPanelDesktop',
components: {
draggable
},
mixins: [mainPanelMixin],
methods: {
setData(dataTransfer) {
// to avoid Firefox bug
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
dataTransfer.setData('Text', '')
}
}
}
</script>
<style scoped>
.loading-panel {
padding: 100px;
height: 100%;
}
.cards-in-group {
column-count: 2; /*numbers of columns */
column-gap: 1em;
}
.cards-not-group {
column-count: 1; /* numbers of columns */
column-gap: 1em;
margin-bottom: 5px;
}
.card {
/* padding: 10px; */
width: 100% !important;
transition: all 100ms ease-in-out;
display: inline-block;
perspective: 1000;
backface-visibility: hidden;
}
.el-card {
width: 100% !important;
}
</style>

View File

@ -0,0 +1,542 @@
import FieldDefinition from '@/components/ADempiere/Field'
import FilterFields from '@/components/ADempiere/Panel/filterFields'
import { fieldIsDisplayed } from '@/utils/ADempiere/dictionaryUtils.js'
import { parsedValueComponent } from '@/utils/ADempiere/valueUtils.js'
import { convertObjectToKeyValue } from '@/utils/ADempiere/valueFormat.js'
export const mainPanelMixin = {
name: 'MainPanelMixin',
components: {
FieldDefinition,
FilterFields
},
props: {
parentUuid: {
type: String,
default: undefined
},
containerUuid: {
type: String,
required: true
},
metadata: {
type: Object,
default: () => {}
},
// tab type group
groupTab: {
type: Object,
default: () => ({
groupType: '',
groupName: ''
})
},
panelType: {
type: String,
default: 'window'
},
isAdvancedQuery: {
type: Boolean,
default: false
},
isShowedRecordNavigation: {
type: Boolean,
default: false
}
},
data() {
return {
panelMetadata: {},
fieldList: [], // groups list of fields
dataRecords: {},
isLoadPanel: false,
isLoadRecord: false,
uuidRecord: this.$route.query.action,
fieldGroups: [],
firstGroup: {},
groupsView: 0,
tagTitle: {
base: this.$route.meta.title,
action: ''
}
}
},
computed: {
shadowGroup() {
if (this.isMobile) {
return 'never'
}
return 'hover'
},
optionCRUD() {
return this.isEmptyValue(this.uuidRecord) ? 'create-new' : this.uuidRecord
},
isPanelWindow() {
return this.panelType === 'window'
},
panelAttributes() {
return {
recordUuid: this.uuidRecord,
optionCRUD: this.optionCRUD,
isShowedRecordNavigation: this.isShowedRecordNavigation,
isProcessingContext: this.getContainerProcessing,
isProcessedContext: this.getContainerProcessed
}
},
getContainerProcessing() {
if (this.panelType === 'window' && !this.isAdvancedQuery) {
return this.$store.getters.getContainerProcessing(this.parentUuid)
}
return false
},
getContainerProcessed() {
if (this.panelType === 'window' && !this.isAdvancedQuery) {
return this.$store.getters.getContainerProcessed(this.parentUuid)
}
return false
},
getterPanel() {
return this.$store.getters.getPanel(this.containerUuid, this.isAdvancedQuery)
},
fieldsList() {
let panel = this.panelMetadata
if (!this.isEmptyValue(panel) && panel.fieldList) {
return panel.fieldList
}
panel = this.getterPanel
if (panel) {
return panel.fieldList
}
return undefined
},
isMobile() {
return this.$store.state.app.device === 'mobile'
},
getterDataStore() {
if (this.isPanelWindow) {
return this.$store.getters.getDataRecordAndSelection(this.containerUuid)
}
return {
recordCount: 0,
isLoaded: false,
record: []
}
},
getterIsLoadedRecord() {
return this.getterDataStore.isLoaded
},
classCards() {
if (this.isMobile || this.fieldGroups.length < 2 || this.isShowedRecordNavigation) {
return 'cards-not-group'
}
return 'cards-in-group'
}
},
watch: {
// used only panel modal (process associated in browser or window)
containerUuid() {
if (['report', 'process'].includes(this.panelType)) {
this.generatePanel(this.metadata.fieldList)
}
},
'$route.query.action'(newValue, oldValue) {
// used in field, if uuid record or different create-new, field is read only
this.uuidRecord = newValue
if (newValue !== oldValue && this.isPanelWindow) {
this.changePanelRecord(newValue)
}
},
isLoadPanel(value) {
if (value) {
this.readParameters()
}
}
},
created() {
// get fields with uuid
this.getPanel()
},
methods: {
/**
* Get the tab object with all its attributes as well as the fields it contains
*/
getPanel() {
const panel = this.getterPanel
if (!this.isEmptyValue(panel) && panel.fieldList) {
this.panelMetadata = panel
const fieldsList = panel.fieldList
if (fieldsList && Array.isArray(fieldsList)) {
this.generatePanel(fieldsList)
}
} else {
this.$store.dispatch('getPanelAndFields', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
panelType: this.panelType,
panelMetadata: this.metadata,
isAdvancedQuery: this.isAdvancedQuery
}).then(panelResponse => {
this.panelMetadata = panelResponse
this.generatePanel(panelResponse.fieldList)
}).catch(error => {
console.warn(`Field Load Error: ${error.message}. Code: ${error.code}.`)
})
}
},
generatePanel(fieldsList) {
// order and assign groups
this.fieldList = fieldsList
if (fieldsList.length) {
this.fieldGroups = this.sortAndGroup(fieldsList)
}
let firstGroup
if (this.fieldGroups[0] && this.fieldGroups[0].groupFinal === '') {
firstGroup = this.fieldGroups[0]
this.fieldGroups.shift()
}
this.firstGroup = firstGroup
this.isLoadPanel = true
},
/**
* TODO: Delete route parameters after reading them
*/
readParameters() {
const parameters = {
isLoadAllRecords: true,
isReference: false,
isNewRecord: false,
isWindow: true,
criteria: {}
}
const route = this.$route
if (this.isPanelWindow) {
// TODO: use action notifyPanelChange with isShowedField in true
this.fieldsList.forEach(fieldItem => {
if (Object.prototype.hasOwnProperty.call(route.query, fieldItem.columnName) && !fieldItem.isAdvancedQuery) {
fieldItem.isShowedFromUser = true
fieldItem.value = parsedValueComponent({
componentPath: fieldItem.componentPath,
columnName: fieldItem.columnName,
value: route.query[fieldItem.columnName],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (String(route.query.isAdvancedQuery) === String(fieldItem.isAdvancedQuery)) {
fieldItem.value = parsedValueComponent({
componentPath: fieldItem.componentPath,
columnName: fieldItem.columnName,
value: route.query[fieldItem.columnName],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (fieldItem.isRange && this.$route.query[`${fieldItem.columnName}_To`]) {
fieldItem.valueTo = parsedValueComponent({
componentPath: fieldItem.componentPath,
columnName: fieldItem.componentPath,
value: route.query[`${fieldItem.columnName}_To`],
displayType: fieldItem.displayType,
isIdentifier: fieldItem.columnName.includes('_ID')
})
}
}
}
})
if (route.query.action && route.query.action === 'reference') {
const referenceInfo = this.$store.getters.getReferencesInfo({
windowUuid: this.parentUuid,
recordUuid: route.query.recordUuid,
referenceUuid: route.query.referenceUuid
})
route.params.isReadParameters = true
parameters.isLoadAllRecords = false
parameters.isReference = true
parameters.referenceUuid = referenceInfo.uuid
parameters.referenceWhereClause = referenceInfo.whereClause
} else if (route.query.action && route.query.action === 'create-new') {
parameters.isNewRecord = true
} else if (route.query.action && route.query.action === 'criteria') {
route.params.isReadParameters = true
Object.keys(route.params).forEach(param => {
if (!this.isEmptyValue(route.params[param])) {
parameters.criteria[param] = route.params[param]
}
})
} else if (route.query.action && route.query.action === 'listRecords') {
parameters.isLoadAllRecords = true
route.params.isReadParameters = true
} else if (!this.isEmptyValue(route.query.action) &&
!['create-new', 'reference', 'advancedQuery', 'criteria', 'listRecords'].includes(route.query.action)) {
parameters.isLoadAllRecords = false
parameters.value = route.query.action
parameters.tableName = this.metadata.tableName
parameters.columnName = 'UUID'
route.params.isReadParameters = true
}
// Only call get data if panel type is window
if (!Object.prototype.hasOwnProperty.call(route.params, 'isReadParameters') || route.params.isReadParameters) {
this.getData(parameters)
}
let viewTitle = ''
if (route.query && !this.isEmptyValue(route.query.action)) {
viewTitle = route.query.action
}
this.setTagsViewTitle(viewTitle)
} else {
if (this.panelType === 'table' && route.query.action === 'advancedQuery') {
// TODO: use action notifyPanelChange with isShowedField in true
this.fieldList.forEach(fieldItem => {
if (Object.prototype.hasOwnProperty.call(route.query, fieldItem.columnName) && fieldItem.isAdvancedQuery) {
fieldItem.isShowedFromUser = true
if (route.query.action === 'advancedQuery' && fieldItem.isAdvancedQuery) {
this.dataRecords[fieldItem.columnName] = parsedValueComponent({
componentPath: fieldItem.componentPath,
columnName: fieldItem.columnName,
value: route.query[fieldItem.columnName],
isIdentifier: fieldItem.columnName.includes('_ID')
})
if (fieldItem.isRange && route.query[`${fieldItem.columnName}_To`]) {
this.dataRecords[fieldItem.columnName] = parsedValueComponent({
componentPath: fieldItem.componentPath,
columnName: fieldItem.columnName,
value: route.query[`${fieldItem.columnName}_To`],
isIdentifier: fieldItem.columnName.includes('_ID')
})
}
}
}
})
parameters.isWindow = false
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
isAdvancedQuery: route.query.action === 'advancedQuery',
newValues: this.dataRecords,
isSendToServer: true,
isSendCallout: false,
fieldList: this.fieldList,
panelType: this.panelType
})
} else if (['process', 'browser'].includes(this.panelType)) {
if (!this.isEmptyValue(route.query)) {
this.$store.dispatch('notifyPanelChange', {
containerUuid: this.containerUuid,
newValues: route.query,
isShowedField: true,
isSendCallout: false,
panelType: this.panelType
})
parameters.isWindow = false
}
}
}
},
/**
* @param {object} parameters parameters to condition the data query
*/
getData(parameters) {
if (parameters.isWindow && this.isPanelWindow && !this.getterIsLoadedRecord) {
this.$store.dispatch('getDataListTab', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
isLoadAllRecords: parameters.isLoadAllRecords,
isReference: parameters.isReference,
referenceWhereClause: parameters.referenceWhereClause,
columnName: parameters.columnName,
value: parameters.value,
criteria: parameters.criteria
})
.then(response => {
let action = 'create-new'
let params = this.$route.params
if (response.length && !parameters.isNewRecord) {
this.dataRecords = response[0]
const recordId = this.dataRecords[`${this.metadata.tableName}_ID`]
params = {
...params,
tableName: this.metadata.tableName,
recordId
}
if (this.$route.query.action === 'reference') {
action = 'reference'
} else {
// 'criteria'
action = this.dataRecords.UUID
}
let viewTitle = ''
if (this.$route.query && !this.isEmptyValue(this.$route.query.action)) {
viewTitle = this.$route.query.action
}
this.setTagsViewTitle(viewTitle)
this.isLoadRecord = true
}
this.$router.push({
name: this.$route.name,
params,
query: {
...this.$route.query,
action
}
}).catch(error => {
console.info(`Panel Component: ${error.name}, ${error.message}`)
})
if (action === 'create-new') {
this.$store.dispatch('setDefaultValues', {
panelType: this.panelType,
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
isNewRecord: true
})
} else {
const attributes = convertObjectToKeyValue({
object: this.dataRecords
})
this.$store.dispatch('notifyPanelChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
attributes
})
}
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
}
},
/**
* Group the arrangement into groups of columns that they contain, it must
* be grouped after having the order
* @param {array} fieldsList
* @return {array} groupsList
* TODO: Save into store to dont regenerate
*/
sortAndGroup(fieldsList) {
if (this.isEmptyValue(fieldsList)) {
return
}
let groupsList = [{
groupFinal: '',
metadataFields: fieldsList
}]
// reduce, create array with number groupAssigned element comun
if (this.isPanelWindow) {
groupsList = fieldsList
.reduce((groupsList, currentValue) => {
if (!groupsList.includes(currentValue.groupAssigned)) {
groupsList.push(currentValue.groupAssigned)
}
return groupsList
}, [])
.map(itemGroup => {
return {
groupFinal: itemGroup,
metadataFields: fieldsList.filter(itemField => {
return itemField.groupAssigned === itemGroup
})
}
})
}
// count and add the field numbers according to your group
groupsList.forEach(groupFields => {
const typeG = groupFields.metadataFields[0].typeGroupAssigned
groupFields.typeGroup = typeG
const fieldsDisplayed = groupFields.metadataFields.filter(field => {
return fieldIsDisplayed(field)
})
if ((this.groupTab.groupType === 'T' && this.groupTab.groupName === groupFields.groupFinal) ||
(this.groupTab.groupType !== 'T' && groupFields.typeGroup !== 'T')) {
this.groupsView = this.groupsView + 1
}
groupFields.activeFields = fieldsDisplayed.length
})
return groupsList
},
setTagsViewTitle(actionValue) {
if (actionValue !== 'create-new' && !this.isEmptyValue(actionValue) && this.panelMetadata.isDocument && this.getterDataStore.isLoaded) {
this.$store.dispatch('listWorkflows', this.metadata.tableName)
this.$store.dispatch('listDocumentStatus', {
recordUuid: this.$route.query.action,
tableName: this.metadata.tableName
})
}
if (actionValue === 'create-new' || this.isEmptyValue(actionValue)) {
this.tagTitle.action = this.$t('tagsView.newRecord')
} else if (actionValue === 'advancedQuery') {
this.tagTitle.action = this.$t('tagsView.advancedQuery')
} else {
const { identifierColumns } = this.panelMetadata
if (!this.isEmptyValue(identifierColumns)) {
if (this.dataRecords[identifierColumns[0]]) {
this.tagTitle.action = this.dataRecords[identifierColumns[0]]
} else {
const field = this.fieldList.find(fieldItem => fieldItem.isIdentifier)
this.tagTitle.action = field.value
}
} else {
this.tagTitle.action = this.$t('tagsView.seeRecord')
}
}
if (this.isPanelWindow) {
this.$store.dispatch('tagsView/updateVisitedView', {
...this.$route,
title: `${this.tagTitle.base} - ${this.tagTitle.action}`
})
}
},
changePanelRecord(uuidRecord) {
if (!['create-new', 'reference', 'advancedQuery', 'criteria', 'listRecords'].includes(uuidRecord)) {
this.$store.dispatch('seekRecord', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
recordUuid: uuidRecord
}).then(() => {
if (this.panelMetadata.isTabsChildren) {
// delete records tabs children when change record uuid
this.$store.dispatch('deleteRecordContainer', {
viewUuid: this.parentUuid,
withOut: [this.containerUuid]
})
}
})
}
this.setTagsViewTitle(uuidRecord)
if (this.$route.query && this.$route.query.action === 'create-new') {
this.setFocus()
}
const currentRecord = this.getterDataStore.record.find(record => record.UUID === uuidRecord)
this.$store.dispatch('currentRecord', currentRecord)
},
async setFocus() {
return new Promise(resolve => {
const fieldFocus = this.fieldsList.find(itemField => {
if (itemField.handleRequestFocus) {
return true
}
if (Object.prototype.hasOwnProperty.call(this.$refs, itemField.columnName)) {
if (fieldIsDisplayed(itemField) &&
!itemField.isReadOnly &&
itemField.isUpdateable &&
itemField.componentPath !== 'FieldSelect') {
return true
}
}
})
if (fieldFocus) {
this.$refs[fieldFocus.columnName][0].focusField()
}
resolve()
return
})
}
}
}

View File

@ -0,0 +1,150 @@
<template>
<div class="wrapper">
<el-form
v-if="isLoadPanel"
key="panel-loaded"
v-model="dataRecords"
label-position="top"
label-width="200px"
>
<template
v-if="firstGroup && firstGroup.groupFinal === ''"
>
<div v-show="firstGroup.activeFields" class="cards-not-group">
<div
v-if="(groupTab.groupType == 'T' && groupTab.groupName == firstGroup.groupFinal)
|| (groupTab.groupType !== 'T' && firstGroup.typeGroup !== 'T')"
class="card"
>
<div class="select-filter">
<span>
{{ firstGroup.groupFinal }}
</span>
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="firstGroup.groupFinal"
:is-advanced-query="isAdvancedQuery"
/>
</div>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<el-row>
<template v-for="(fieldAttributes, subKey) in firstGroup.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
...panelAttributes
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="!isShowedRecordNavigation"
:is-advanced-query="isAdvancedQuery"
/>
</template>
</el-row>
</el-card>
</div>
</div>
</template>
<div :class="classCards">
<template v-for="(item, key) in fieldGroups">
<el-row :key="key">
<el-col :key="key" :span="24">
<div
v-if="item.groupFinal !== ''
&& (groupTab.groupType == 'T' && groupTab.groupName == item.groupFinal)
|| (groupTab.groupType !== 'T' && item.typeGroup !== 'T')"
:key="key"
class="card"
>
<el-card
:shadow="shadowGroup"
:body-style="{ padding: '10px' }"
>
<div slot="header" class="clearfix">
<span>
{{ item.groupFinal }}
</span>
<div v-if="!isAdvancedQuery" class="select-filter-header">
<filter-fields
:container-uuid="containerUuid"
:panel-type="panelType"
:group-field="item.groupFinal"
:is-first-group="false"
/>
</div>
</div>
<el-row>
<template v-for="(fieldAttributes, subKey) in item.metadataFields">
<field-definition
:ref="fieldAttributes.columnName"
:key="subKey"
:metadata-field="{
...fieldAttributes,
...panelAttributes
}"
:record-data-fields="isAdvancedQuery ? undefined : dataRecords[fieldAttributes.columnName]"
:in-group="isPanelWindow && fieldGroups.length > 1"
/>
</template>
</el-row>
</el-card>
</div>
</el-col>
</el-row>
</template>
</div>
</el-form>
<div
v-else
key="panel-loading"
v-loading="!isLoadPanel"
:element-loading-text="$t('notifications.loading')"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255, 255, 255, 0.8)"
class="loading-panel"
/>
</div>
</template>
<script>
import { mainPanelMixin } from '@/components/ADempiere/Panel/mainPanelMixin'
export default {
name: 'MainPanelMobile',
mixins: [mainPanelMixin]
}
</script>
<style scoped>
.loading-panel {
padding: 100px;
height: 100%;
}
.cards-in-group {
column-count: 2; /*numbers of columns */
column-gap: 1em;
}
.cards-not-group {
column-count: 1; /* numbers of columns */
column-gap: 1em;
margin-bottom: 5px;
}
.card {
/* padding: 10px; */
width: 100% !important;
transition: all 100ms ease-in-out;
display: inline-block;
perspective: 1000;
backface-visibility: hidden;
}
.el-card {
width: 100% !important;
}
</style>

View File

@ -177,35 +177,35 @@ export default {
} }
}, },
documentActionChange(value) { documentActionChange(value) {
this.$store.dispatch('notifyFieldChange', { // this.$store.dispatch('notifyFieldChange', {
parentUuid: this.parentUuid, // parentUuid: this.parentUuid,
containerUuid: this.containerUuid, // containerUuid: this.containerUuid,
columnName: 'DocAction', // columnName: 'DocAction',
isSendToServer: true, // isSendToServer: true,
newValue: value // newValue: value
}) // })
.then(response => { // .then(response => {
const actionProcess = this.$store.getters.getOrders // const actionProcess = this.$store.getters.getOrders
this.$store.dispatch('startProcess', { // this.$store.dispatch('startProcess', {
action: { // action: {
uuid: actionProcess.uuid, // uuid: actionProcess.uuid,
id: actionProcess.id, // id: actionProcess.id,
name: actionProcess.name // name: actionProcess.name
}, // process metadata // }, // process metadata
tableName: this.$route.params.tableName, // tableName: this.$route.params.tableName,
recordId: this.$route.params.recordId, // recordId: this.$route.params.recordId,
recordUuid: this.$route.query.action, // recordUuid: this.$route.query.action,
parametersList: [{ // parametersList: [{
columnName: 'DocAction', // columnName: 'DocAction',
value: this.valueActionDocument // value: this.valueActionDocument
}], // }],
isActionDocument: true, // isActionDocument: true,
parentUuid: this.parentUuid, // parentUuid: this.parentUuid,
panelType: this.panelType, // panelType: this.panelType,
containerUuid: this.containerUuid// determinate if get table name and record id (window) or selection (browser) // containerUuid: this.containerUuid// determinate if get table name and record id (window) or selection (browser)
}) // })
this.valueActionDocument = '' // this.valueActionDocument = ''
}) // })
} }
} }
} }

View File

@ -203,7 +203,7 @@ export default {
this.$store.dispatch('setWindowOldRoute') this.$store.dispatch('setWindowOldRoute')
} }
this.$store.dispatch('resetPanelToNew', { this.$store.dispatch('setDefaultValues', {
parentUuid, parentUuid,
containerUuid, containerUuid,
panelType: view.meta.type, panelType: view.meta.type,

View File

@ -1,192 +1,171 @@
import { getBrowser as getBrowserMetadata } from '@/api/ADempiere/dictionary' import { getBrowserSearch } from '@/api/ADempiere/browser'
import { showMessage } from '@/utils/ADempiere/notification'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils' import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { generateField } from '@/utils/ADempiere/dictionaryUtils' import { parseContext } from '@/utils/ADempiere/contextUtils'
import router from '@/router' import { showMessage } from '@/utils/ADempiere/notification'
import { fieldIsDisplayed } from '@/utils/ADempiere/dictionaryUtils'
import language from '@/lang' import language from '@/lang'
const browser = { const browserControl = {
state: {
browser: []
},
mutations: {
addBrowser(state, payload) {
state.browser.push(payload)
},
dictionaryResetCacheBrowser(state) {
state.browser = []
},
changeBrowserAttribute(state, payload) {
let value = payload.attributeValue
if (payload.attributeNameControl) {
value = payload.browser[payload.attributeNameControl]
}
payload.browser[payload.attributeName] = value
}
},
actions: { actions: {
getBrowserFromServer({ commit, dispatch }, { browserActionPerformed({ dispatch, getters }, {
containerUuid, containerUuid,
browserId, field,
routeToDelete value
}) { }) {
return new Promise(resolve => { const fieldsEmpty = getters.getFieldListEmptyMandatory({
getBrowserMetadata({
uuid: containerUuid,
id: browserId
})
.then(browserResponse => {
const panelType = 'browser'
const additionalAttributes = {
containerUuid, containerUuid,
panelType, fieldsList: getters.getFieldsListFromPanel(containerUuid)
isEvaluateValueChanges: true
}
const {
query,
whereClause,
process
} = browserResponse
// Convert from gRPC
const fieldsRangeList = []
let isShowedCriteria = false
let awaitForValues = 0
let fieldsList = browserResponse.fieldsList.map((fieldItem, index) => {
const someAttributes = {
...additionalAttributes,
fieldListIndex: index
}
const field = generateField({
fieldToGenerate: fieldItem,
moreAttributes: someAttributes,
isSOTrxMenu: routeToDelete.meta.isSOTrx
}) })
// Add new field if is range number if (!isEmptyValue(fieldsEmpty)) {
if (field.isRange && field.componentPath === 'FieldNumber') { showMessage({
const fieldRange = generateField({ message: language.t('notifications.mandatoryFieldMissing') + fieldsEmpty,
fieldToGenerate: fieldItem, type: 'info'
moreAttributes: someAttributes,
typeRange: true
}) })
if (!isEmptyValue(fieldRange.value)) { return
fieldRange.isShowedFromUser = true
}
fieldsRangeList.push(fieldRange)
} }
// Only isQueryCriteria fields with values, displayed in main panel // Validate if a field is called and visible
if (field.isQueryCriteria) { if (fieldIsDisplayed(field)) {
let isReadyForQuery = true
if (field.isSQLValue) { if (field.isSQLValue) {
isShowedCriteria = true const panel = getters.getPanel(containerUuid)
field.isShowedFromUser = true let awaitForValuesToQuery = panel.awaitForValuesToQuery
awaitForValues++ awaitForValuesToQuery--
} dispatch('changeBrowserAttribute', {
if (query.includes(`@${field.columnName}@`) ||
query.includes(`@${field.columnName}_To@`) ||
whereClause.includes(`@${field.columnName}@`) ||
whereClause.includes(`@${field.columnName}_To@`)) {
field.isMandatory = true
field.isMandatoryFromLogic = true
field.isShowedFromUser = true
}
if (isEmptyValue(field.value)) {
// isMandatory params to showed search criteria
if (field.isMandatory || field.isMandatoryFromLogic) {
isShowedCriteria = true
}
} else {
// with value
field.isShowedFromUser = true
}
}
return field
})
fieldsList = fieldsList.concat(fieldsRangeList)
// Panel for save on store
const newBrowser = {
...browserResponse,
containerUuid, containerUuid,
fieldList: fieldsList, attributeName: 'awaitForValuesToQuery',
panelType, attributeValue: awaitForValuesToQuery
// app attributes
awaitForValues, // control to values
awaitForValuesToQuery: awaitForValues, // get values from request search
isShowedCriteria,
isShowedTotals: true
}
commit('addBrowser', newBrowser)
dispatch('addPanel', newBrowser)
resolve(newBrowser)
// Convert from gRPC process list
const actions = []
if (process) {
actions.push({
type: 'process',
panelType: 'process',
uuid: process.uuid,
name: process.name,
description: process.description,
isReport: process.isReport,
isDirectPrint: process.isDirectPrint,
containerUuidAssociated: containerUuid,
panelTypeAssociated: panelType
}) })
// TODO: No list of parameters if (awaitForValuesToQuery === 0) {
// // add process associated in vuex store if (panel.isShowedCriteria) {
// dispatch('addProcessAssociated', { dispatch('changeBrowserAttribute', {
// processToGenerate: process,
// containerUuidAssociated: containerUuid
// })
}
// Add process menu
dispatch('setContextMenu', {
containerUuid, containerUuid,
actions attributeName: 'isShowedCriteria',
attributeValue: false
}) })
}
} else if (awaitForValuesToQuery > 0) {
isReadyForQuery = false
}
}
if (isReadyForQuery && !field.dependentFieldsList.length) {
dispatch('getBrowserSearch', {
containerUuid,
isClearSelection: true
})
}
}
},
// Search with query criteria
getBrowserSearch({ dispatch, rootGetters }, {
containerUuid,
isClearSelection = false
}) {
showMessage({
title: language.t('notifications.loading'),
message: language.t('notifications.searching'),
type: 'info'
})
const allData = rootGetters.getDataRecordAndSelection(containerUuid)
// deletes the data from the container to replace it and to report the searches in the table
dispatch('deleteRecordContainer', {
viewUuid: containerUuid
})
const browser = rootGetters.getBrowser(containerUuid)
// parameters isQueryCriteria
const parametersList = rootGetters.getParametersToServer({
containerUuid,
fieldList: browser.fieldList
})
let parsedQuery = browser.query
if (!isEmptyValue(parsedQuery) && parsedQuery.includes('@')) {
parsedQuery = parseContext({
containerUuid,
value: parsedQuery,
isBooleanToString: true
}).value
}
let parsedWhereClause = browser.whereClause
if (!isEmptyValue(parsedWhereClause) && parsedWhereClause.includes('@')) {
parsedWhereClause = parseContext({
containerUuid,
value: parsedWhereClause,
isBooleanToString: true
}).value
}
let nextPageToken
if (!isEmptyValue(allData.nextPageToken)) {
nextPageToken = allData.nextPageToken + '-' + allData.pageNumber
}
// Add validation compare browserSearchQueryParameters
return getBrowserSearch({
uuid: containerUuid,
query: parsedQuery,
whereClause: parsedWhereClause,
orderByClause: browser.orderByClause,
parametersList,
nextPageToken: nextPageToken
})
.then(browserSearchResponse => {
const recordsList = browserSearchResponse.recordsList.map(itemRecord => {
return {
...itemRecord.values,
// datatables attributes
isNew: false,
isEdit: false,
isSelected: false,
isReadOnlyFromRow: false
}
})
let selection = allData.selection
if (isClearSelection) {
selection = []
}
let token = browserSearchResponse.nextPageToken
if (token !== undefined) {
token = token.slice(0, -2)
}
dispatch('setRecordSelection', {
containerUuid,
record: recordsList,
pageNumber: rootGetters.getPageNumber(containerUuid),
selection: selection,
recordCount: browserSearchResponse.recordCount,
nextPageToken: token
})
showMessage({
title: language.t('notifications.succesful'),
message: language.t('notifications.succcessSearch'),
type: 'success'
})
return recordsList
}) })
.catch(error => { .catch(error => {
router.push({ path: '/dashboard' }) // Set default registry values so that the table does not say loading,
dispatch('tagsView/delView', routeToDelete) // there was already a response from the server
dispatch('setRecordSelection', {
containerUuid,
panelType: 'browser'
})
showMessage({ showMessage({
message: language.t('login.unexpectedError'), title: language.t('notifications.error'),
message: language.t('notifications.errorSearch'),
summary: error.message,
type: 'error' type: 'error'
}) })
console.warn(`Dictionary Browser - Error ${error.code}: ${error.message}.`) console.warn(`Error getting browser search: ${error.message}. Code: ${error.code}.`)
}) })
})
},
changeBrowserAttribute({ commit, getters }, {
containerUuid,
browser,
attributeName,
attributeNameControl,
attributeValue
}) {
if (isEmptyValue(browser)) {
browser = getters.getBrowser(containerUuid)
}
commit('changeBrowserAttribute', {
browser,
attributeName,
attributeValue,
attributeNameControl
})
}
},
getters: {
getBrowser: (state) => (browserUuid) => {
return state.browser.find(
item => item.uuid === browserUuid
)
} }
} }
} }
export default browser export default browserControl

View File

@ -1,125 +0,0 @@
import { getBrowserSearch } from '@/api/ADempiere/browser'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { parseContext } from '@/utils/ADempiere/contextUtils'
import { showMessage } from '@/utils/ADempiere/notification'
import language from '@/lang'
const browserControl = {
actions: {
/**
* Search with query criteria
* @param {string} containerUuid, browser to search record data
* @param {boolean} isClearSelection, clear selection after search
*/
getBrowserSearch({ dispatch, rootGetters }, {
containerUuid,
isClearSelection = false
}) {
showMessage({
title: language.t('notifications.loading'),
message: language.t('notifications.searching'),
type: 'info'
})
const allData = rootGetters.getDataRecordAndSelection(containerUuid)
// deletes the data from the container to replace it and to report the searches in the table
dispatch('deleteRecordContainer', {
viewUuid: containerUuid
})
const browser = rootGetters.getBrowser(containerUuid)
// parameters isQueryCriteria
const parametersList = rootGetters.getParametersToServer({
containerUuid,
fieldList: browser.fieldList
})
let parsedQuery = browser.query
if (!isEmptyValue(parsedQuery) && parsedQuery.includes('@')) {
parsedQuery = parseContext({
containerUuid,
value: parsedQuery,
isBooleanToString: true
}).value
}
let parsedWhereClause = browser.whereClause
if (!isEmptyValue(parsedWhereClause) && parsedWhereClause.includes('@')) {
parsedWhereClause = parseContext({
containerUuid,
value: parsedWhereClause,
isBooleanToString: true
}).value
}
let nextPageToken
if (!isEmptyValue(allData.nextPageToken)) {
nextPageToken = allData.nextPageToken + '-' + allData.pageNumber
}
// Add validation compare browserSearchQueryParameters
return getBrowserSearch({
uuid: containerUuid,
query: parsedQuery,
whereClause: parsedWhereClause,
orderByClause: browser.orderByClause,
parametersList,
nextPageToken: nextPageToken
})
.then(browserSearchResponse => {
const recordsList = browserSearchResponse.recordsList.map(itemRecord => {
return {
...itemRecord.values,
// datatables attributes
isNew: false,
isEdit: false,
isSelected: false,
isReadOnlyFromRow: false
}
})
let selection = allData.selection
if (isClearSelection) {
selection = []
}
let token = browserSearchResponse.nextPageToken
if (token !== undefined) {
token = token.slice(0, -2)
}
dispatch('setRecordSelection', {
containerUuid,
record: recordsList,
pageNumber: rootGetters.getPageNumber(containerUuid),
selection: selection,
recordCount: browserSearchResponse.recordCount,
nextPageToken: token
})
showMessage({
title: language.t('notifications.succesful'),
message: language.t('notifications.succcessSearch'),
type: 'success'
})
return recordsList
})
.catch(error => {
// Set default registry values so that the table does not say loading,
// there was already a response from the server
dispatch('setRecordSelection', {
containerUuid,
panelType: 'browser'
})
showMessage({
title: language.t('notifications.error'),
message: language.t('notifications.errorSearch'),
summary: error.message,
type: 'error'
})
console.warn(`Error getting browser search: ${error.message}. Code: ${error.code}.`)
})
}
}
}
export default browserControl

View File

@ -0,0 +1,198 @@
import { getBrowser as getBrowserMetadata } from '@/api/ADempiere/dictionary'
import { showMessage } from '@/utils/ADempiere/notification'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { generateField } from '@/utils/ADempiere/dictionaryUtils'
import router from '@/router'
import language from '@/lang'
const browser = {
state: {
browser: []
},
mutations: {
addBrowser(state, payload) {
state.browser.push(payload)
},
dictionaryResetCacheBrowser(state) {
state.browser = []
},
changeBrowserAttribute(state, payload) {
let value = payload.attributeValue
if (payload.attributeNameControl) {
value = payload.browser[payload.attributeNameControl]
}
payload.browser[payload.attributeName] = value
}
},
actions: {
/**
* Get Smart Browser metadata from server
* @param {string} containerUuid
* @param {number} browserId
* @param {object} routeToDelete, route to close in tagView when fail
*/
getBrowserFromServer({ commit, dispatch }, {
containerUuid,
browserId,
routeToDelete
}) {
return new Promise(resolve => {
getBrowserMetadata({
uuid: containerUuid,
id: browserId
})
.then(browserResponse => {
const panelType = 'browser'
const additionalAttributes = {
containerUuid,
panelType,
isEvaluateValueChanges: true
}
const {
query,
whereClause,
process
} = browserResponse
// Convert from gRPC
const fieldsRangeList = []
let isShowedCriteria = false
let awaitForValues = 0
let fieldsList = browserResponse.fieldsList.map((fieldItem, index) => {
const someAttributes = {
...additionalAttributes,
fieldListIndex: index
}
const field = generateField({
fieldToGenerate: fieldItem,
moreAttributes: someAttributes,
isSOTrxMenu: routeToDelete.meta.isSOTrx
})
// Add new field if is range number
if (field.isRange && field.componentPath === 'FieldNumber') {
const fieldRange = generateField({
fieldToGenerate: fieldItem,
moreAttributes: someAttributes,
typeRange: true
})
if (!isEmptyValue(fieldRange.value)) {
fieldRange.isShowedFromUser = true
}
fieldsRangeList.push(fieldRange)
}
// Only isQueryCriteria fields with values, displayed in main panel
if (field.isQueryCriteria) {
if (field.isSQLValue) {
isShowedCriteria = true
field.isShowedFromUser = true
awaitForValues++
}
if (query.includes(`@${field.columnName}@`) ||
query.includes(`@${field.columnName}_To@`) ||
whereClause.includes(`@${field.columnName}@`) ||
whereClause.includes(`@${field.columnName}_To@`)) {
field.isMandatory = true
field.isMandatoryFromLogic = true
field.isShowedFromUser = true
}
if (isEmptyValue(field.value)) {
// isMandatory params to showed search criteria
if (field.isMandatory || field.isMandatoryFromLogic) {
isShowedCriteria = true
}
} else {
// with value
field.isShowedFromUser = true
}
}
return field
})
fieldsList = fieldsList.concat(fieldsRangeList)
// Panel for save on store
const newBrowser = {
...browserResponse,
containerUuid,
fieldList: fieldsList,
panelType,
// app attributes
awaitForValues, // control to values
awaitForValuesToQuery: awaitForValues, // get values from request search
isShowedCriteria,
isShowedTotals: true
}
commit('addBrowser', newBrowser)
dispatch('addPanel', newBrowser)
resolve(newBrowser)
// Convert from gRPC process list
const actions = []
if (process) {
actions.push({
type: 'process',
panelType: 'process',
uuid: process.uuid,
name: process.name,
description: process.description,
isReport: process.isReport,
isDirectPrint: process.isDirectPrint,
containerUuidAssociated: containerUuid,
panelTypeAssociated: panelType
})
// TODO: No list of parameters
// // add process associated in vuex store
// dispatch('addProcessAssociated', {
// processToGenerate: process,
// containerUuidAssociated: containerUuid
// })
}
// Add process menu
dispatch('setContextMenu', {
containerUuid,
actions
})
})
.catch(error => {
router.push({ path: '/dashboard' })
dispatch('tagsView/delView', routeToDelete)
showMessage({
message: language.t('login.unexpectedError'),
type: 'error'
})
console.warn(`Dictionary Browser - Error ${error.code}: ${error.message}.`)
})
})
},
changeBrowserAttribute({ commit, getters }, {
containerUuid,
browser,
attributeName,
attributeNameControl,
attributeValue
}) {
if (isEmptyValue(browser)) {
browser = getters.getBrowser(containerUuid)
}
commit('changeBrowserAttribute', {
browser,
attributeName,
attributeValue,
attributeNameControl
})
}
},
getters: {
getBrowser: (state) => (browserUuid) => {
return state.browser.find(
item => item.uuid === browserUuid
)
}
}
}
export default browser

View File

@ -1,5 +1,6 @@
import { runCallOutRequest } from '@/api/ADempiere/rule' import { runCallOutRequest } from '@/api/ADempiere/rule'
import { showMessage } from '@/utils/ADempiere/notification' import { showMessage } from '@/utils/ADempiere/notification'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import language from '@/lang' import language from '@/lang'
const callOutControl = { const callOutControl = {
@ -19,7 +20,7 @@ const callOutControl = {
* @param {String} valueType * @param {String} valueType
* @return {Promise} values * @return {Promise} values
*/ */
getCallout({ rootGetters, dispatch }, { runCallout({ rootGetters, dispatch }, {
parentUuid, parentUuid,
containerUuid, containerUuid,
callout, callout,
@ -32,6 +33,10 @@ const callOutControl = {
oldValue, oldValue,
valueType valueType
}) { }) {
if (isEmptyValue(value) || isEmptyValue(callout)) {
return undefined
}
// Else
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const window = rootGetters.getWindow(parentUuid) const window = rootGetters.getWindow(parentUuid)
const attributesList = rootGetters.getParametersToServer({ const attributesList = rootGetters.getParametersToServer({

View File

@ -1,178 +0,0 @@
import Vue from 'vue'
// Delete when get global context and account context
import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
const context = {
state: {
context: {}
},
mutations: {
/**
* Set context in state
* @param {string} payload.parentUuid
* @param {string} payload.containerUuid
* @param {string} payload.columnName
* @param {mixed} payload.value
*/
setContext(state, payload) {
let key = ''
if (payload.parentUuid) {
key += payload.parentUuid + '|'
// set context for window
const keyParent = key + payload.columnName
Vue.set(state.context, keyParent, payload.value)
}
if (payload.containerUuid) {
key += payload.containerUuid + '|'
}
key += payload.columnName
// set property to object
Vue.set(state.context, key, payload.value)
},
setInitialContext(state, objectContext) {
Object.keys(objectContext).forEach(key => {
Vue.set(state.context, key, objectContext[key])
})
},
dictionaryResetCacheContext(state) {
state.context = {}
}
},
actions: {
setContext({ commit }, objectValue) {
commit('setContext', objectValue)
},
setMultipleContext({ commit }, valuesToSetter) {
valuesToSetter.forEach(itemToSetter => {
commit('setContext', itemToSetter)
})
},
setMultipleContextView({ commit }, {
parentUuid,
containerUuid,
values
}) {
Object.keys(values).forEach(key => {
commit('setContext', {
parentUuid,
containerUuid,
columnName: key,
value: values[key]
})
})
},
setMultipleContextObject({ commit }, valuesToSetter) {
Object.keys(valuesToSetter).forEach(key => {
commit('setContext', {
columnName: key,
value: valuesToSetter[key]
})
})
},
setMultipleContextMap({ commit }, valuesToSetter) {
return new Promise(resolve => {
valuesToSetter.forEach((value, key) => {
commit('setContext', {
columnName: key,
value: value
})
})
resolve()
})
},
setInitialContext({ commit }, otherContext = {}) {
commit('setInitialContext', otherContext)
}
},
getters: {
/**
* @param {string} parentUuid
* @param {string} containerUuid
* @param {string} columnName
*/
getContext: (state) => ({ parentUuid, containerUuid, columnName }) => {
let key = ''
if (parentUuid) {
key += parentUuid + '|'
// context for window
const keyParent = key + columnName
const valueParent = state.context[keyParent]
if (!isEmptyValue(valueParent)) {
return valueParent
}
}
if (containerUuid) {
key += containerUuid + '|'
}
key += columnName
return state.context[key]
},
/**
* @param {string} parentUuid
* @param {string} containerUuid
* @returns {object}
*/
getContextView: (state) => ({
parentUuid,
containerUuid
}) => {
// generate context with parent uuid or container uuid associated
const contextAllContainers = {}
Object.keys(state.context).forEach(key => {
if (key.includes(parentUuid) || key.includes(containerUuid)) {
contextAllContainers[key] = state.context[key]
}
})
// generate context only columnName
const contextContainer = {}
Object.keys(contextAllContainers).forEach(key => {
if (isEmptyValue(contextAllContainers[key])) {
return
}
let newKey
if (parentUuid) {
if (!key.includes(containerUuid)) {
newKey = key
.replace(`${parentUuid}|`, '')
.replace(`${containerUuid}|`, '')
// set window parent context
contextContainer[newKey] = contextAllContainers[key]
}
// next if is tab context
return
}
// set container context (smart browser, process/report)
newKey = key.replace(`${containerUuid}|`, '')
contextContainer[newKey] = contextAllContainers[key]
})
return contextContainer
},
getContextAll: (state) => {
return state.context
},
getContextClientId: (state) => {
return parseInt(state.context['#AD_Client_ID'], 10)
},
getContextOrgId: (state) => {
return parseInt(state.context['#AD_Org_ID'], 10)
},
// Using to read only in data tables
getContextIsActive: (state) => (parentUuid) => {
return state.context[`${parentUuid}|IsActive`]
},
getContextProcessing: (state) => (parentUuid) => {
return state.context[`${parentUuid}|Processing`]
},
getContextProcessed: (state) => (parentUuid) => {
return state.context[`${parentUuid}|Processed`]
}
}
}
export default context

View File

@ -1,4 +1,3 @@
import Vue from 'vue'
import { getEntity, getEntitiesList } from '@/api/ADempiere/persistence' import { getEntity, getEntitiesList } from '@/api/ADempiere/persistence'
import { getDefaultValueFromServer, getContextInfoValueFromServer } from '@/api/ADempiere/values' import { getDefaultValueFromServer, getContextInfoValueFromServer } from '@/api/ADempiere/values'
import { getPrivateAccessFromServer, lockPrivateAccessFromServer, unlockPrivateAccessFromServer } from '@/api/ADempiere/private-access' import { getPrivateAccessFromServer, lockPrivateAccessFromServer, unlockPrivateAccessFromServer } from '@/api/ADempiere/private-access'
@ -70,9 +69,6 @@ const data = {
addNewRow(state, payload) { addNewRow(state, payload) {
payload.data = payload.data.unshift(payload.values) payload.data = payload.data.unshift(payload.values)
}, },
addDisplayColumn(state, payload) {
Vue.set(payload.row, payload.columnName, payload.displayColumn)
},
setContextInfoField(state, payload) { setContextInfoField(state, payload) {
state.contextInfoField.push(payload) state.contextInfoField.push(payload)
}, },
@ -202,7 +198,11 @@ const data = {
if (fieldList.length) { if (fieldList.length) {
fieldList fieldList
// TODO: Evaluate if is field is read only and FieldSelect // TODO: Evaluate if is field is read only and FieldSelect
.filter(itemField => itemField.componentPath === 'FieldSelect' || String(values[itemField.columnName]) === '[object Object]' || itemField.isSQLValue) .filter(itemField => {
return itemField.componentPath === 'FieldSelect' ||
String(values[itemField.columnName]) === '[object Object]' ||
itemField.isSQLValue
})
.map(async itemField => { .map(async itemField => {
const { columnName, componentPath } = itemField const { columnName, componentPath } = itemField
let valueGetDisplayColumn = values[columnName] let valueGetDisplayColumn = values[columnName]
@ -210,7 +210,7 @@ const data = {
if (String(values[columnName]) === '[object Object]') { if (String(values[columnName]) === '[object Object]') {
if (componentPath === 'FieldSelect') { if (componentPath === 'FieldSelect') {
values[columnName] = ' ' values[columnName] = ' '
values[`DisplayColumn_${columnName}`] = ' ' values[itemField.displayColumnName] = ' '
} else if (componentPath === 'FieldNumber') { } else if (componentPath === 'FieldNumber') {
values[columnName] = 0 values[columnName] = 0
} }
@ -237,7 +237,9 @@ const data = {
} }
} }
if (!isEmptyValue(valueGetDisplayColumn) && String(valueGetDisplayColumn) === '[object Object]' && valueGetDisplayColumn.isSQL) { if (!isEmptyValue(valueGetDisplayColumn) &&
String(valueGetDisplayColumn) === '[object Object]' &&
valueGetDisplayColumn.isSQL) {
// get value from Query // get value from Query
valueGetDisplayColumn = await dispatch('getValueBySQL', { valueGetDisplayColumn = await dispatch('getValueBySQL', {
parentUuid, parentUuid,
@ -265,7 +267,7 @@ const data = {
const option = options.find(itemOption => itemOption.key === valueGetDisplayColumn) const option = options.find(itemOption => itemOption.key === valueGetDisplayColumn)
// if there is a lookup option, assign the display column with the label // if there is a lookup option, assign the display column with the label
if (option) { if (option) {
values[`DisplayColumn_${columnName}`] = option.label values[itemField.displayColumnName] = option.label
// if (isEmptyValue(option.label) && !itemField.isMandatory) { // if (isEmptyValue(option.label) && !itemField.isMandatory) {
// values[columnName] = undefined // values[columnName] = undefined
// } // }
@ -279,7 +281,7 @@ const data = {
columnName: 'Name' columnName: 'Name'
}) })
if (!isEmptyValue(nameParent)) { if (!isEmptyValue(nameParent)) {
values[`DisplayColumn_${columnName}`] = nameParent values[itemField.displayColumnName] = nameParent
return return
} }
} }
@ -291,7 +293,7 @@ const data = {
directQuery: itemField.reference.directQuery, directQuery: itemField.reference.directQuery,
value: valueGetDisplayColumn value: valueGetDisplayColumn
}) })
values[`DisplayColumn_${columnName}`] = label values[itemField.displayColumnName] = label
}) })
} }
@ -308,26 +310,6 @@ const data = {
data: dataStore data: dataStore
}) })
}, },
/**
* Add or change display column in table of records
* @param {string} containerUuid
* @param {string} columnName
* @param {string} displayColumn
*/
addDisplayColumn({ commit, getters }, {
containerUuid,
columnName,
displayColumn
}) {
const dataStore = getters.getDataRecordsList(containerUuid)
const rowRecord = dataStore.find(itemData => itemData.isNew)
commit('addDisplayColumn', {
row: rowRecord,
displayColumn,
columnName: `DisplayColumn_${columnName}`
})
},
/** /**
* Is load context in true when panel is set context * Is load context in true when panel is set context
* @param {string} containerUuid * @param {string} containerUuid
@ -524,6 +506,7 @@ const data = {
defaultValues = rootGetters.getParsedDefaultValues({ defaultValues = rootGetters.getParsedDefaultValues({
parentUuid, parentUuid,
containerUuid, containerUuid,
formatToReturn: 'object',
isGetServer: false isGetServer: false
}) })
} }
@ -744,7 +727,7 @@ const data = {
if (isSendCallout && !withOutColumnNames.includes(field.columnName) && if (isSendCallout && !withOutColumnNames.includes(field.columnName) &&
!isEmptyValue(newValue) && !isEmptyValue(field.callout)) { !isEmptyValue(newValue) && !isEmptyValue(field.callout)) {
withOutColumnNames.push(field.columnName) withOutColumnNames.push(field.columnName)
dispatch('getCallout', { dispatch('runCallout', {
parentUuid, parentUuid,
containerUuid, containerUuid,
tableName: field.tableName, tableName: field.tableName,

View File

@ -23,9 +23,11 @@
export const ACTION_PERFORMED = 1 export const ACTION_PERFORMED = 1
export const FOCUS_GAINED = 2 export const FOCUS_GAINED = 2
export const FOCUS_LOST = 3 export const FOCUS_LOST = 3
// Input actions // Input actions
export const KEY_PRESSED = 4 export const KEY_PRESSED = 4
export const KEY_RELEASED = 5 export const KEY_RELEASED = 5
const event = { const event = {
state: { state: {
fieldEvents: [], fieldEvents: [],

View File

@ -0,0 +1,159 @@
import Vue from 'vue'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
import { convertStringToBoolean } from '@/utils/ADempiere/valueFormat.js'
const UUID_KEY = 'UUID'
const value = {
state: {
field: {}
},
mutations: {
resetStatevalue(state) {
state = {
field: {}
}
},
updateValueOfField(state, payload) {
// Only Parent
if (payload.parentUuid) {
const keyParent = payload.parentUuid + '_' + payload.columnName
if (payload.value !== state.field[keyParent]) {
Vue.set(state.field, keyParent, payload.value)
}
}
// Only Container
if (payload.containerUuid) {
const keyContainer = payload.containerUuid + '_' + payload.columnName
if (payload.value !== state.field[keyContainer]) {
Vue.set(state.field, keyContainer, payload.value)
}
}
},
updateValuesOfContainer(state, payload) {
payload.attributes.forEach(attribute => {
const { value, columnName } = attribute
// Only Parent
if (payload.parentUuid) {
const keyParent = payload.parentUuid + '_' + columnName
if (value !== state.field[keyParent]) {
Vue.set(state.field, keyParent, value)
}
}
// Only Container
if (payload.containerUuid) {
const keyContainer = payload.containerUuid + '_' + columnName
if (value !== state.field[keyContainer]) {
Vue.set(state.field, keyContainer, value)
}
}
})
}
},
actions: {
updateValuesOfContainer({ commit }, {
parentUuid,
containerUuid,
attributes = []
}) {
commit('updateValuesOfContainer', {
parentUuid,
containerUuid,
attributes
})
}
},
getters: {
getValueOfField: (state) => ({ containerUuid, columnName }) => {
return state.field[containerUuid + '_' + columnName]
},
getValueOfContainer: (state) => ({ parentUuid, containerUuid, columnName }) => {
// get in tab level
let value = state.field[containerUuid + '_' + columnName]
if (isEmptyValue(value) && parentUuid) {
// get in window level
value = state.field[parentUuid + '_' + columnName]
}
return value
},
/**
* Get values and column's name as key (without parent uuid or container
* uuid), from a view (container)
* @param {string} parentUuid
* @param {string} containerUuid
* @returns {object|array}
*/
getValuesView: (state) => ({
parentUuid,
containerUuid,
format = 'array'
}) => {
console.log(parentUuid, containerUuid)
// generate context with parent uuid or container uuid associated
const contextAllContainers = {}
Object.keys(state.field).forEach(key => {
if (key.includes(parentUuid) || key.includes(containerUuid)) {
contextAllContainers[key] = state.field[key]
}
})
// generate context only columnName
const objectValues = {}
const pairsValues = Object.keys(contextAllContainers).map(key => {
const value = contextAllContainers[key]
if (isEmptyValue(value)) {
return
}
let columnName
if (parentUuid) {
if (!key.includes(containerUuid)) {
columnName = key
.replace(`${parentUuid}_`, '')
.replace(`${containerUuid}_`, '')
// set window parent context
objectValues[columnName] = value
}
// next if is tab context
return {
columnName,
value
}
}
// set container context (smart browser, process/report, form)
columnName = key.replace(`${containerUuid}_`, '')
objectValues[columnName] = value
return {
columnName,
value
}
})
if (format === 'array') {
return pairsValues
}
return objectValues
},
getUuidOfContainer: (state) => (containerUuid) => {
return state.field[containerUuid + '_' + UUID_KEY]
},
// Using to read only in data tables in Window
getContainerIsActive: (state) => (parentUuid) => {
const valueIsActive = state.field[`${parentUuid}_IsActive`]
return convertStringToBoolean(valueIsActive)
},
getContainerProcessing: (state) => (parentUuid) => {
const valueProcessing = state.field[`${parentUuid}_Processing`]
return convertStringToBoolean(valueProcessing)
},
getContainerProcessed: (state) => (parentUuid) => {
const valueProcessed = state.field[`${parentUuid}_Processed`]
return convertStringToBoolean(valueProcessed)
}
}
}
export default value

View File

@ -1,4 +1,4 @@
import { getLookup, getLookupList } from '@/api/ADempiere/values' import { requestLookup, requestLookupList } from '@/api/ADempiere/values.js'
import { getToken as getSession } from '@/utils/auth' import { getToken as getSession } from '@/utils/auth'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils' import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { parseContext } from '@/utils/ADempiere/contextUtils' import { parseContext } from '@/utils/ADempiere/contextUtils'
@ -55,7 +55,7 @@ const lookup = {
}).value }).value
} }
return getLookup({ return requestLookup({
tableName, tableName,
directQuery: parsedDirectQuery, directQuery: parsedDirectQuery,
value value
@ -73,7 +73,7 @@ const lookup = {
parsedDirectQuery: directQuery, parsedDirectQuery: directQuery,
tableName, tableName,
sessionUuid: getSession(), sessionUuid: getSession(),
clientId: rootGetters.getContextClientId clientId: rootGetters.getPreferenceClientId
}) })
return option return option
}) })
@ -87,12 +87,18 @@ const lookup = {
* @param {string} containerUuid * @param {string} containerUuid
* @param {string} tableName * @param {string} tableName
* @param {string} query * @param {string} query
* @param {boolean} isAddBlankValue
* @param {mixed} blankValue
* @param {Array<String>|<Number>} valuesList
*/ */
getLookupListFromServer({ commit, rootGetters }, { getLookupListFromServer({ commit, rootGetters }, {
parentUuid, parentUuid,
containerUuid, containerUuid,
tableName, tableName,
query query,
isAddBlankValue = false,
blankValue,
valuesList = []
}) { }) {
if (isEmptyValue(query)) { if (isEmptyValue(query)) {
return return
@ -106,28 +112,38 @@ const lookup = {
isBooleanToString: true isBooleanToString: true
}).value }).value
} }
return getLookupList({ return requestLookupList({
tableName, tableName,
query: parsedQuery query: parsedQuery,
valuesList
}) })
.then(lookupListResponse => { .then(lookupListResponse => {
const list = [] const list = []
lookupListResponse.recordsList.forEach(itemLookup => { lookupListResponse.recordsList.forEach(itemLookup => {
const key = itemLookup.values.KeyColumn const {
if (![null, -1, undefined].includes(key)) { KeyColumn: key,
DisplayColumn: label
} = itemLookup.values
if (!isEmptyValue(key)) {
list.push({ list.push({
label: itemLookup.values.DisplayColumn, label,
key key
}) })
} }
}) })
if (isAddBlankValue) {
list.unshift({
label: ' ',
key: blankValue
})
}
commit('addLoockupList', { commit('addLoockupList', {
list, list,
tableName, tableName,
parsedQuery, parsedQuery,
sessionUuid: getSession(), sessionUuid: getSession(),
clientId: rootGetters.getContextClientId clientId: rootGetters.getPreferenceClientId
}) })
return list return list
}) })
@ -200,7 +216,7 @@ const lookup = {
return itemLookup.parsedDirectQuery === parsedDirectQuery && return itemLookup.parsedDirectQuery === parsedDirectQuery &&
itemLookup.tableName === tableName && itemLookup.tableName === tableName &&
itemLookup.sessionUuid === getSession() && itemLookup.sessionUuid === getSession() &&
itemLookup.clientId === rootGetters.getContextClientId && itemLookup.clientId === rootGetters.getPreferenceClientId &&
itemLookup.value === value itemLookup.value === value
}) })
if (lookupItem) { if (lookupItem) {
@ -227,7 +243,7 @@ const lookup = {
return itemLookup.parsedQuery === parsedQuery && return itemLookup.parsedQuery === parsedQuery &&
itemLookup.tableName === tableName && itemLookup.tableName === tableName &&
itemLookup.sessionUuid === getSession() && itemLookup.sessionUuid === getSession() &&
itemLookup.clientId === rootGetters.getContextClientId itemLookup.clientId === rootGetters.getPreferenceClientId
}) })
if (lookupList) { if (lookupList) {
return lookupList.list return lookupList.list

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
import { createEntity, updateEntity } from '@/api/ADempiere/persistence.js'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
const persistence = {
state: {
persistence: {}
},
mutations: {
resetStatepersistence(state) {
state = {
persistence: {}
}
},
addChangeToPersistenceQueue(state, {
containerUuid,
columnName,
valueType,
value
}) {
if (isEmptyValue(state.persistence[containerUuid])) {
state.persistence[containerUuid] = new Map()
}
// Set value
state.persistence[containerUuid].set(columnName, {
columnName,
valueType,
value
})
}
},
actions: {
flushPersistenceQueue({ getters }, {
containerUuid,
tableName,
recordUuid
}) {
return new Promise((resolve, reject) => {
let attributes = getters.getPersistenceAttributes(containerUuid)
if (attributes) {
if (recordUuid) {
// Update existing entity
updateEntity({
tableName,
recordUuid,
attributes
})
.then(response => resolve(response))
.catch(error => reject(error))
} else {
attributes = attributes.filter(itemAttribute => !isEmptyValue(itemAttribute.value))
// Create new entity
createEntity({
tableName,
attributes
})
.then(response => resolve(response))
.catch(error => reject(error))
}
}
})
}
},
getters: {
getPersistenceMap: (state) => (tableName) => {
return state.persistence[tableName]
},
getPersistenceAttributes: (state) => (containerUuid) => {
const attributesMap = state.persistence[containerUuid]
if (!isEmptyValue(attributesMap)) {
return [
...attributesMap.values()
]
}
return undefined
}
}
}
export default persistence

View File

@ -0,0 +1,158 @@
import Vue from 'vue'
// Delete when get global context and account context
import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
const preference = {
state: {
preference: {}
},
mutations: {
/**
* Set context in state
* @param {string} payload.parentUuid
* @param {string} payload.containerUuid
* @param {string} payload.columnName
* @param {mixed} payload.value
*/
setContext(state, payload) {
let key = ''
if (payload.parentUuid) {
key += payload.parentUuid + '|'
// set context for window
const keyParent = key + payload.columnName
Vue.set(state.preference, keyParent, payload.value)
}
if (payload.containerUuid) {
key += payload.containerUuid + '|'
}
key += payload.columnName
// set property to object
Vue.set(state.preference, key, payload.value)
},
setInitialContext(state, objectContext) {
Object.keys(objectContext).forEach(key => {
Vue.set(state.preference, key, objectContext[key])
})
},
setMultiplePreference(state, preferenceToSet) {
if (!isEmptyValue(state.preference)) {
// join and overwrite old values
preferenceToSet = {
...state.preference,
...preferenceToSet
}
}
state.preference = preferenceToSet
},
dictionaryResetCacheContext(state) {
state.preference = {}
}
},
actions: {
setContext({ commit }, objectValue) {
commit('setContext', objectValue)
},
setMultiplePreference({ dispatch }, {
parentUuid,
containerUuid,
values
}) {
let actionToDispatch = 'setMultiplePreferenceObject'
if (Object.prototype.toString.call(values) === '[object Map]') {
actionToDispatch = 'setMultiplePreferenceMap'
}
return dispatch(actionToDispatch, {
parentUuid,
containerUuid,
values
})
},
setMultiplePreferenceObject({ commit }, {
parentUuid,
containerUuid,
values
}) {
return new Promise(resolve => {
if (!isEmptyValue(containerUuid) || !isEmptyValue(parentUuid)) {
Object.keys(values).forEach(key => {
commit('setContext', {
parentUuid,
containerUuid,
columnName: key,
value: values[key]
})
})
} else {
commit('setMultiplePreference', values)
}
resolve()
})
},
setMultiplePreferenceMap({ commit }, {
parentUuid,
containerUuid,
values
}) {
return new Promise(resolve => {
if (!isEmptyValue(containerUuid) || !isEmptyValue(parentUuid)) {
values.forEach((value, key) => {
commit('setContext', {
parentUuid,
containerUuid,
columnName: key,
value
})
})
} else {
commit('setMultiplePreference', Object.fromEntries(values))
}
resolve()
})
}
},
getters: {
/**
* @param {string} parentUuid
* @param {string} containerUuid
* @param {string} columnName
*/
getPreference: (state) => ({
parentUuid,
containerUuid,
columnName
}) => {
let key = ''
if (parentUuid) {
key += parentUuid + '|'
// context for window
const keyParent = key + columnName
const valueParent = state.preference[keyParent]
if (!isEmptyValue(valueParent)) {
return valueParent
}
}
if (containerUuid) {
key += containerUuid + '|'
}
key += columnName
return state.preference[key]
},
getAllPreference: (state) => {
return state.preference
},
getPreferenceClientId: (state) => {
return parseInt(state.preference['#AD_Client_ID'], 10)
},
getPreferenceOrgId: (state) => {
return parseInt(state.preference['#AD_Org_ID'], 10)
}
}
}
export default preference

File diff suppressed because it is too large Load Diff

View File

@ -1,994 +0,0 @@
import {
runProcess,
requestListProcessesLogs
} from '@/api/ADempiere/process'
import { showNotification } from '@/utils/ADempiere/notification'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import language from '@/lang'
import router from '@/router'
import { getToken } from '@/utils/auth'
const initStateProcessControl = {
inExecution: [], // process not response from server
isVisibleDialog: false,
reportObject: {},
reportList: [],
metadata: {},
process: [], // process to run finish
sessionProcess: [],
notificationProcess: [],
inRequestMetadata: [],
reportViewList: [],
totalResponse: 0,
totalRequest: 0,
totalSelection: 0,
errorSelection: 0,
successSelection: 0
}
const processControl = {
state: initStateProcessControl,
mutations: {
// Add process in execution
addInExecution(state, payload) {
state.inExecution.push(payload)
},
// Add process in notifation
addNotificationProcess(state, payload) {
state.notificationProcess.push(payload)
},
// Delete process in execution afther some response from server
deleteInExecution(state, payload) {
state.inExecution = state.inExecution.filter(item => item.containerUuid !== payload.containerUuid)
},
// Add process in request metadata from server
addInRequestMetadata(state, payload) {
state.inRequestMetadata.push(payload)
},
// Delete process in request metadata
deleteInRequestMetadata(state, payload) {
state.inRequestMetadata = state.inRequestMetadata.filter(item => item !== payload)
},
addStartedProcess(state, payload) {
state.process.push(payload)
},
resetStateProcessControl(state) {
state = initStateProcessControl
},
/**
*
* @param {object} state
* @param {boolean} payload, true or false value to change displayed dialog
*/
setShowDialog(state, payload) {
state.isVisibleDialog = payload
},
setMetadata(state, payload) {
state.metadata = payload
},
setReportValues(state, payload) {
state.reportObject = payload
if (state.reportList.some(report => report.instanceUuid === payload.instanceUuid)) {
const reportIndex = state.reportList.findIndex(report => report.instanceUuid === payload.instanceUuid)
state.reportList.splice(reportIndex, 1, payload)
} else {
state.reportList.push(payload)
}
},
setSessionProcess(state, payload) {
state.sessionProcess = payload.processList
},
changeFormatReport(state, payload) {
state.reportFormat = payload
},
setReportViewsList(state, payload) {
state.reportViewList.push(payload)
},
setTotalResponse(state, payload) {
state.totalResponse = payload
},
setTotalSelection(state, payload) {
state.totalSelection = payload
},
setSuccessSelection(state, payload) {
state.successSelection = payload
},
setErrorSelection(state, payload) {
state.errorSelection = payload
},
setTotalRequest(state, payload) {
state.totalRequest = payload
}
},
actions: {
// Supported Actions for it
startProcess({ commit, state, dispatch, getters, rootGetters }, {
parentUuid,
containerUuid,
panelType,
action,
parametersList,
reportFormat,
isProcessTableSelection,
isActionDocument,
tableNameUuidSelection,
recordUuidSelection,
menuParentUuid,
routeToDelete
}) {
return new Promise((resolve, reject) => {
// TODO: Add support to evaluate parameters list to send
// const samePocessInExecution = getters.getInExecution(containerUuid)
// exists some call to executed process with container uuid
// if (samePocessInExecution && !isProcessTableSelection) {
// return reject({
// error: 0,
// message: `In this process (${samePocessInExecution.name}) there is already an execution in progress.`
// })
// }
// additional attributes to send server, selection to browser, or table name and record id to window
let selection = []
let allData = {}
let tab, tableName, recordId
if (panelType) {
if (panelType === 'browser') {
allData = getters.getDataRecordAndSelection(containerUuid)
selection = rootGetters.getSelectionToServer({
containerUuid,
selection: allData.selection
})
if (selection.length < 1) {
showNotification({
title: language.t('data.selectionRequired'),
type: 'warning'
})
return reject({
error: 0,
message: `Required selection data record to run this process (${action.name})`
})
}
} else if (panelType === 'window') {
const contextMenu = getters.getRecordUuidMenu
tab = rootGetters.getTab(parentUuid, containerUuid)
if (isProcessTableSelection) {
tableName = tableNameUuidSelection
recordId = recordUuidSelection
} else {
if (contextMenu.processTable) {
tableName = contextMenu.tableName
recordId = contextMenu.valueRecord
} else {
tableName = tab.tableName
const field = rootGetters.getFieldFromColumnName({
containerUuid,
columnName: `${tableName}_ID`
})
recordId = field.value
}
}
}
}
// get info metadata process
const processDefinition = !isEmptyValue(isActionDocument) ? action : rootGetters.getProcess(action.uuid)
let reportType = reportFormat
const finalParameters = rootGetters.getParametersToServer({ containerUuid: processDefinition.uuid })
const isSession = !isEmptyValue(getToken())
let procesingMessage = {
close: () => false
}
if (isSession) {
procesingMessage = showNotification({
title: language.t('notifications.processing'),
message: processDefinition.name,
summary: processDefinition.description,
type: 'info'
})
}
const timeInitialized = (new Date()).getTime()
let processResult = {
// panel attributes from where it was executed
parentUuid,
containerUuid,
panelType,
lastRun: timeInitialized,
parametersList,
logs: [],
isError: false,
isProcessing: true,
summary: '',
resultTableName: '',
output: {
uuid: '',
name: '',
description: '',
fileName: '',
output: '',
outputStream: '',
reportType: ''
}
}
if (!isEmptyValue(isActionDocument)) {
processResult = {
...processResult,
processUuid: action.uuid,
processId: action.id,
processName: 'Procesar Orden',
parameters: parametersList
}
} else {
// Run process on server and wait for it for notify
// uuid of process
processResult = {
...processResult,
menuParentUuid,
processIdPath: routeToDelete.path,
printFormatUuid: action.printFormatUuid,
// process attributes
action: processDefinition.name,
name: processDefinition.name,
description: processDefinition.description,
instanceUuid: '',
processUuid: processDefinition.uuid,
processId: processDefinition.id,
processName: processDefinition.processName,
parameters: finalParameters,
isReport: processDefinition.isReport
}
}
commit('addInExecution', processResult)
if (panelType === 'window') {
reportType = 'pdf'
} else if (panelType === 'browser') {
if (allData.record.length <= 100) {
// close view if is browser.
router.push({ path: '/dashboard' })
dispatch('tagsView/delView', routeToDelete)
// delete data associate to browser
dispatch('deleteRecordContainer', {
viewUuid: containerUuid
})
}
} else {
// close view if is process, report.
router.push({ path: '/dashboard' })
dispatch('tagsView/delView', routeToDelete)
// reset panel and set defalt isShowedFromUser
if (!processDefinition.isReport) {
dispatch('resetPanelToNew', {
containerUuid,
panelType
})
}
}
if (isProcessTableSelection) {
const windowSelectionProcess = getters.getProcessSelect
windowSelectionProcess.selection.forEach(selection => {
Object.assign(processResult, {
selection: selection.UUID,
record: selection[windowSelectionProcess.tableName]
})
const countRequest = state.totalRequest + 1
commit('setTotalRequest', countRequest)
if (!windowSelectionProcess.finish) {
runProcess({
uuid: processDefinition.uuid,
id: processDefinition.id,
reportType,
parametersList: isEmptyValue(finalParameters) ? parametersList : finalParameters,
selectionsList: selection,
tableName: windowSelectionProcess.tableName,
recordId: selection[windowSelectionProcess.tableName]
})
.then(runProcessResponse => {
const { instanceUuid, output } = runProcessResponse
let logList = []
if (runProcessResponse.logsList) {
logList = runProcessResponse.logsList
}
let link = {
href: undefined,
download: undefined
}
if (processDefinition.isReport) {
const blob = new Blob(
[output.outputStream],
{ type: output.mimeType }
)
link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = output.fileName
if (reportType !== 'pdf' && reportType !== 'html') {
link.click()
}
// Report views List to context menu
const reportViewList = {
name: language.t('views.reportView'),
type: 'summary',
action: '',
childs: [],
option: 'reportView'
}
reportViewList.childs = getters.getReportViewList(processResult.processUuid)
if (reportViewList && isEmptyValue(reportViewList.childs)) {
dispatch('requestReportViews', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid // TODO: Change to uuid
})
.then(responseReportView => {
reportViewList.childs = responseReportView
if (reportViewList.childs.length) {
// Get contextMenu metadata and concat print report views with contextMenu actions
const contextMenuMetadata = rootGetters.getContextMenu(processResult.processUuid)
contextMenuMetadata.actions.push(reportViewList)
}
})
}
// Print formats to context menu
const printFormatList = {
name: language.t('views.printFormat'),
type: 'summary',
action: '',
childs: [],
option: 'printFormat'
}
printFormatList.childs = rootGetters.getPrintFormatList(processResult.processUuid)
if (printFormatList && isEmptyValue(printFormatList.childs.length)) {
dispatch('requestPrintFormats', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid
})
.then(printFormarResponse => {
printFormatList.childs = printFormarResponse
if (printFormatList.childs.length) {
// Get contextMenu metadata and concat print Format List with contextMenu actions
const contextMenuMetadata = rootGetters.getContextMenu(processResult.processUuid)
contextMenuMetadata.actions.push(printFormatList)
}
})
}
// Drill Tables to context menu
const drillTablesList = {
name: language.t('views.drillTable'),
type: 'summary',
action: '',
childs: [],
option: 'drillTable'
}
if (!isEmptyValue(output.tableName)) {
drillTablesList.childs = rootGetters.getDrillTablesList(processResult.processUuid)
if (drillTablesList && isEmptyValue(drillTablesList.childs)) {
dispatch('requestDrillTables', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid
})
.then(drillTablesResponse => {
drillTablesList.childs = drillTablesResponse
if (drillTablesList.childs.length) {
// Get contextMenu metadata and concat drill tables list with contextMenu actions
const contextMenuMetadata = rootGetters.getContextMenu(processResult.processUuid)
contextMenuMetadata.actions.push(drillTablesList)
}
})
}
}
}
// assign new attributes
Object.assign(processResult, {
...runProcessResponse,
url: link.href,
download: link.download,
logs: logList,
output
})
if (!isEmptyValue(processResult.output)) {
dispatch('setReportTypeToShareLink', processResult.output.reportType)
}
commit('addNotificationProcess', processResult)
resolve(processResult)
})
.catch(error => {
Object.assign(processResult, {
isError: true,
message: error.message,
isProcessing: false
})
console.warn(`Error running the process ${error}`)
reject(error)
})
.finally(() => {
if (processResult.isError) {
const countError = state.errorSelection + 1
commit('setErrorSelection', countError)
} else {
const countSuccess = state.successSelection + 1
commit('setSuccessSelection', countSuccess)
}
const countResponse = state.totalResponse + 1
commit('setTotalResponse', countResponse)
if (state.totalResponse === state.totalRequest) {
if (isSession) {
showNotification({
title: language.t('notifications.succesful'),
message: language.t('notifications.totalProcess') + countResponse + language.t('notifications.error') + state.errorSelection + language.t('notifications.succesful') + state.successSelection + language.t('notifications.processExecuted'),
type: 'success'
})
}
commit('setTotalRequest', 0)
commit('setTotalResponse', 0)
commit('setSuccessSelection', 0)
commit('setErrorSelection', 0)
}
dispatch('setProcessSelect', {
selection: 0,
finish: true,
tableName: ''
})
commit('addNotificationProcess', processResult)
commit('addStartedProcess', processResult)
commit('deleteInExecution', {
containerUuid
})
})
}
})
} else {
runProcess({
uuid: processDefinition.uuid,
id: processDefinition.id,
reportType,
parametersList: isEmptyValue(finalParameters) ? parametersList : finalParameters,
selectionsList: selection,
tableName,
recordId
})
.then(runProcessResponse => {
const { instanceUuid, output } = runProcessResponse
let logList = []
if (!isEmptyValue(runProcessResponse.logsList)) {
logList = runProcessResponse.logsList
}
let link = {
href: undefined,
download: undefined
}
if (runProcessResponse.isReport || processDefinition.isReport) {
const blob = new Blob(
[output.outputStream],
{ type: output.mimeType }
)
link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = output.fileName
if (reportType !== 'pdf' && reportType !== 'html') {
link.click()
}
const contextMenuMetadata = rootGetters.getContextMenu(processResult.processUuid)
// Report views List to context menu
const reportViewList = {
name: language.t('views.reportView'),
type: 'summary',
action: '',
childs: [],
option: 'reportView'
}
reportViewList.childs = getters.getReportViewList(processResult.processUuid)
if (reportViewList && !reportViewList.childs.length) {
dispatch('requestReportViews', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid
})
.then(responseReportView => {
reportViewList.childs = responseReportView
if (reportViewList.childs.length) {
// Get contextMenu metadata and concat print report views with contextMenu actions
contextMenuMetadata.actions.push(reportViewList)
}
})
}
// Print formats to context menu
const printFormatList = {
name: language.t('views.printFormat'),
type: 'summary',
action: '',
childs: [],
option: 'printFormat'
}
printFormatList.childs = rootGetters.getPrintFormatList(processResult.processUuid)
if (printFormatList && !printFormatList.childs.length) {
dispatch('requestPrintFormats', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid
})
.then(printFormarResponse => {
printFormatList.childs = printFormarResponse
if (printFormatList.childs.length) {
// Get contextMenu metadata and concat print Format List with contextMenu actions
contextMenuMetadata.actions.push(printFormatList)
}
})
} else {
const index = contextMenuMetadata.actions.findIndex(action => action.option === 'printFormat')
if (index !== -1) {
contextMenuMetadata.actions[index] = printFormatList
}
}
// Drill Tables to context menu
const drillTablesList = {
name: language.t('views.drillTable'),
type: 'summary',
action: '',
childs: [],
option: 'drillTable'
}
if (!isEmptyValue(output.tableName)) {
drillTablesList.childs = rootGetters.getDrillTablesList(processResult.processUuid)
if (drillTablesList && isEmptyValue(drillTablesList.childs)) {
dispatch('requestDrillTables', {
processUuid: processResult.processUuid,
instanceUuid,
processId: processDefinition.id,
tableName: output.tableName,
printFormatUuid: output.printFormatUuid,
reportViewUuid: output.reportViewUuid
})
.then(drillTablesResponse => {
drillTablesList.childs = drillTablesResponse
if (drillTablesList.childs.length) {
// Get contextMenu metadata and concat print Format List with contextMenu actions
contextMenuMetadata.actions.push(drillTablesList)
}
})
}
}
}
// assign new attributes
Object.assign(processResult, {
...runProcessResponse,
url: link.href,
download: link.download,
logs: logList,
output
})
resolve(processResult)
if (!isEmptyValue(processResult.output)) {
dispatch('setReportTypeToShareLink', processResult.output.reportType)
}
})
.catch(error => {
Object.assign(processResult, {
isError: true,
message: error.message,
isProcessing: false
})
console.warn(`Error running the process ${error.message}. Code: ${error.code}.`)
reject(error)
})
.finally(() => {
if (!processResult.isError) {
if (panelType === 'window') {
// TODO: Add conditional to indicate when update record
dispatch('updateRecordAfterRunProcess', {
parentUuid,
containerUuid,
tab
})
} else if (panelType === 'browser') {
if (allData.record.length >= 100) {
dispatch('getBrowserSearch', {
containerUuid
})
}
}
}
commit('addNotificationProcess', processResult)
dispatch('finishProcess', {
processOutput: processResult,
procesingMessage,
routeToDelete
})
commit('deleteInExecution', {
containerUuid
})
dispatch('setProcessTable', {
valueRecord: 0,
tableName: '',
processTable: false
})
dispatch('setProcessSelect', {
finish: true
})
})
}
})
},
// Supported to process selection
selectionProcess({ commit, state, dispatch, getters, rootGetters }, {
parentUuid,
containerUuid,
panelType,
action,
isProcessTableSelection,
menuParentUuid,
routeToDelete
}) {
// get info metadata process
const processDefinition = rootGetters.getProcess(action.uuid)
const reportType = 'pdf'
const finalParameters = rootGetters.getParametersToServer({ containerUuid: processDefinition.uuid })
const isSession = !isEmptyValue(getToken())
if (isSession) {
showNotification({
title: language.t('notifications.processing'),
message: processDefinition.name,
summary: processDefinition.description,
type: 'info'
})
}
const timeInitialized = (new Date()).getTime()
// Run process on server and wait for it for notify
if (isProcessTableSelection) {
const windowSelectionProcess = getters.getProcessSelect
windowSelectionProcess.selection.forEach(selection => {
const processResult = {
// panel attributes from where it was executed
parentUuid,
containerUuid,
panelType,
menuParentUuid,
processIdPath: routeToDelete.path,
// process attributes
lastRun: timeInitialized,
action: processDefinition.name,
name: processDefinition.name,
description: processDefinition.description,
instanceUuid: '',
processUuid: processDefinition.uuid,
processId: processDefinition.id,
processName: processDefinition.processName,
parameters: finalParameters,
isError: false,
isProcessing: true,
isReport: processDefinition.isReport,
summary: '',
resultTableName: '',
logs: [],
selection: selection.UUID,
record: selection[windowSelectionProcess.tableName],
output: {
uuid: '',
name: '',
description: '',
fileName: '',
output: '',
outputStream: '',
reportType: ''
}
}
const countRequest = state.totalRequest + 1
commit('addInExecution', processResult)
commit('setTotalRequest', countRequest)
if (!windowSelectionProcess.finish) {
return runProcess({
uuid: processDefinition.uuid,
id: processDefinition.id,
reportType,
parametersList: finalParameters,
selectionsList: selection,
tableName: windowSelectionProcess.tableName,
recordId: selection[windowSelectionProcess.tableName]
})
.then(response => {
let output = {
uuid: '',
name: '',
description: '',
fileName: '',
mimeType: '',
output: '',
outputStream: '',
reportType: ''
}
if (isEmptyValue(response.output)) {
const responseOutput = response.output
output = {
uuid: responseOutput.uuid,
name: responseOutput.name,
description: responseOutput.description,
fileName: responseOutput.filename,
mimeType: responseOutput.mimeType,
output: responseOutput.output,
outputStream: responseOutput.outputstream,
reportType: responseOutput.reporttype
}
}
let logList = []
if (response.getLogsList) {
logList = response.getLogsList.map(itemLog => {
return {
log: itemLog.log,
recordId: itemLog.recordid
}
})
}
// assign new attributes
Object.assign(processResult, {
instanceUuid: response.instanceUuid,
isError: response.isError,
isProcessing: response.isProcessing,
summary: response.summary,
ResultTableName: response.resulttablename,
lastRun: response.lastRun,
logs: logList,
output
})
dispatch('setReportTypeToShareLink', processResult.output.reportType)
if (processResult.isError) {
const countError = state.errorSelection + 1
commit('setErrorSelection', countError)
} else {
const countSuccess = state.successSelection + 1
commit('setSuccessSelection', countSuccess)
}
const countResponse = state.totalResponse + 1
commit('setTotalResponse', countResponse)
if (state.totalResponse === state.totalRequest) {
if (isSession) {
showNotification({
title: language.t('notifications.succesful'),
message: language.t('notifications.totalProcess') + countResponse + language.t('notifications.error') + state.errorSelection + language.t('notifications.succesful') + state.successSelection + language.t('notifications.processExecuted'),
type: 'success'
})
}
commit('setTotalRequest', 0)
commit('setTotalResponse', 0)
commit('setSuccessSelection', 0)
commit('setErrorSelection', 0)
}
dispatch('setProcessSelect', {
selection: 0,
finish: true,
tableName: ''
})
commit('addNotificationProcess', processResult)
commit('addStartedProcess', processResult)
commit('deleteInExecution', {
containerUuid
})
})
.catch(error => {
Object.assign(processResult, {
isError: true,
message: error.message,
isProcessing: false
})
console.warn(`Error running the process. Code ${error.code}: ${error.message}.`)
})
}
})
}
},
/**
* TODO: Add date time in which the process/report was executed
*/
getSessionProcessFromServer({ commit, dispatch, getters, rootGetters }, parameters) {
// process Activity
const { pageToken, pageSize } = parameters
return requestListProcessesLogs({ pageToken, pageSize })
.then(processActivityResponse => {
const responseList = processActivityResponse.processLogsList.map(processLogItem => {
const processMetadata = rootGetters.getProcess(processLogItem.uuid)
// if no exists metadata process in store and no request progess
if (processMetadata === undefined && getters.getInRequestMetadata(processLogItem.uuid) === undefined) {
commit('addInRequestMetadata', processLogItem.uuid)
dispatch('getProcessFromServer', {
containerUuid: processLogItem.uuid
})
.finally(() => {
commit('deleteInRequestMetadata', processLogItem.uuid)
})
}
const process = {
...processLogItem,
processUuid: processLogItem.uuid
}
return process
})
const processResponseList = {
recordCount: processActivityResponse.recordCount,
processList: responseList,
nextPageToken: processActivityResponse.nextPageToken
}
commit('setSessionProcess', processResponseList)
return processResponseList
})
.catch(error => {
showNotification({
title: language.t('notifications.error'),
message: error.message,
type: 'error'
})
console.warn(`Error getting process activity: ${error.message}. Code: ${error.code}.`)
})
},
/**
* Show modal dialog with process/report, tab (sequence) metadata
* @param {String} type of panel or panelType ('process', 'report', 'window')
* @param {Object} action
*/
setShowDialog({ state, commit, dispatch, rootGetters }, {
type,
action
}) {
const panels = ['process', 'report', 'window']
if (action && (panels.includes(type) || panels.includes(action.panelType))) {
// show some process loaded in store
if (state.metadata && !isEmptyValue(state.metadata.containerUuid) &&
state.metadata.containerUuid === action.containerUuid) {
commit('setShowDialog', true)
return
}
const panel = rootGetters.getPanel(action.containerUuid)
if (panel === undefined) {
dispatch('getPanelAndFields', {
parentUuid: action.parentUuid,
containerUuid: isEmptyValue(action.uuid) ? action.containerUuid : action.uuid,
panelType: action.panelType
})
.then(response => {
commit('setMetadata', response)
commit('setShowDialog', true)
})
} else {
commit('setMetadata', panel)
commit('setShowDialog', true)
}
return
}
commit('setShowDialog', false)
},
finishProcess({ commit }, {
processOutput,
routeToDelete,
procesingMessage
}) {
const processMessage = {
name: processOutput.processName,
title: language.t('notifications.succesful'),
message: language.t('notifications.processExecuted'),
type: 'success',
logs: processOutput.logs,
summary: processOutput.summary
}
const errorMessage = !isEmptyValue(processOutput.message) ? processOutput.message : language.t('notifications.error')
// TODO: Add isReport to type always 'success'
if (processOutput.isError || isEmptyValue(processOutput.processId) || isEmptyValue(processOutput.instanceUuid)) {
processMessage.title = language.t('notifications.error')
processMessage.message = errorMessage
processMessage.type = 'error'
processOutput.isError = true
}
if (processOutput.isReport && !processOutput.isError) {
// open report viewer with report response
let menuParentUuid = routeToDelete.params.menuParentUuid
if (isEmptyValue(menuParentUuid)) {
menuParentUuid = processOutput.menuParentUuid
}
let tableName
if (processOutput.option && !isEmptyValue(processOutput.option)) {
if (processOutput.option === 'drillTable') {
tableName = processOutput.tableName
}
}
router.push({
name: 'Report Viewer',
params: {
processId: processOutput.processId,
instanceUuid: processOutput.instanceUuid,
fileName: isEmptyValue(processOutput.output.fileName) ? processOutput.fileName : processOutput.output.fileName,
menuParentUuid,
tableName
}
})
}
const isSession = !isEmptyValue(getToken())
if (isSession) {
showNotification(processMessage)
}
if (!isEmptyValue(procesingMessage)) {
procesingMessage.close()
}
commit('addStartedProcess', processOutput)
commit('setReportValues', processOutput)
},
changeFormatReport({ commit }, reportFormat) {
if (!isEmptyValue(reportFormat)) {
commit('changeFormatReport', reportFormat)
}
}
},
getters: {
/**
* Running processes that have not received a response from the server
* @param {string} containerUuid
*/
getInExecution: (state) => (containerUuid) => {
return state.inExecution.find(item => item.containerUuid === containerUuid)
},
/**
* Process for send to server, or send without response
*/
getAllInExecution: (state) => {
return state.inExecution
},
/**
* Process send to server, with response from server
*/
getAllFinishProcess: (state) => {
return state.process
},
getNotificationProcess: (state) => {
return state.notificationProcess
},
/**
* Process receibed from server associated whith this session
*/
getAllSessionProcess: (state) => {
return state.sessionProcess
},
/**
* Process request metadata from server filter form uuid process
*/
getInRequestMetadata: (state) => (containerUuid) => {
return state.inRequestMetadata.find(item => item === containerUuid)
},
getProcessResult: (state) => {
return state.reportObject
},
getCachedReport: (state) => (instanceUuid) => {
return state.reportList.find(
item => item.instanceUuid === instanceUuid
)
}
}
}
export default processControl

View File

@ -0,0 +1,112 @@
import { getProcess as getProcessMetadata } from '@/api/ADempiere'
import { showMessage } from '@/utils/ADempiere'
import { generateProcess } from '@/utils/ADempiere/dictionaryUtils'
import language from '@/lang'
import router from '@/router'
const process = {
state: {
process: []
},
mutations: {
addProcess(state, payload) {
state.process.push(payload)
},
dictionaryResetCacheProcess(state) {
state.process = []
}
},
actions: {
/**
* Get Process/Report metadata from server
* @param {string} containerUuid
* @param {number} processId
* @param {object} routeToDelete, route to close in tagView when fail
*/
getProcessFromServer({ commit, dispatch }, {
containerUuid,
processId,
routeToDelete
}) {
return new Promise(resolve => {
getProcessMetadata({
uuid: containerUuid,
id: processId
})
.then(async responseProcess => {
let printFormatsAvailable = []
if (responseProcess.isReport) {
printFormatsAvailable = await dispatch('requestPrintFormats', {
processUuid: containerUuid
})
}
const { processDefinition, actions } = generateProcess({
processToGenerate: {
...responseProcess,
printFormatsAvailable
}
})
dispatch('addPanel', processDefinition)
commit('addProcess', processDefinition)
resolve(processDefinition)
// Add process menu
dispatch('setContextMenu', {
containerUuid,
actions
})
})
.catch(error => {
router.push({
path: '/dashboard'
})
dispatch('tagsView/delView', routeToDelete)
showMessage({
message: language.t('login.unexpectedError'),
type: 'error'
})
console.warn(`Dictionary Process - Error ${error.message}.`)
})
})
},
/**
* Add process associated in window or smart browser
* @param {object} processToGenerate
*/
addProcessAssociated({ commit, dispatch }, {
processToGenerate
}) {
return new Promise(resolve => {
const { processDefinition, actions } = generateProcess({
processToGenerate
})
dispatch('addPanel', processDefinition)
commit('addProcess', processDefinition)
resolve(processDefinition)
// Add process menu
dispatch('setContextMenu', {
containerUuid: processDefinition.uuid,
actions
})
})
}
},
getters: {
getProcess: (state) => (processUuid) => {
return state.process.find(
item => item.uuid === processUuid
)
},
getProcessById: (state) => (processId) => {
return state.process.find(
item => item.id === parseInt(processId)
)
}
}
}
export default process

View File

@ -33,6 +33,13 @@ const reportControl = {
} }
}, },
actions: { actions: {
reportActionPerformed({ commit }, {
containerUuid,
field,
value
}) {
},
requestPrintFormats({ commit }, { requestPrintFormats({ commit }, {
processId, processId,
processUuid, processUuid,
@ -147,7 +154,9 @@ const reportControl = {
if (isEmptyValue(printFormatUuid)) { if (isEmptyValue(printFormatUuid)) {
printFormatUuid = getters.getDefaultPrintFormat(processUuid).printFormatUuid printFormatUuid = getters.getDefaultPrintFormat(processUuid).printFormatUuid
} }
const parametersList = rootGetters.getParametersToServer({ containerUuid: processUuid }) const parametersList = rootGetters.getParametersToServer({
containerUuid: processUuid
})
getReportOutput({ getReportOutput({
parametersList, parametersList,
printFormatUuid, printFormatUuid,

File diff suppressed because it is too large Load Diff

View File

@ -1,935 +0,0 @@
import { createEntity, updateEntity, deleteEntity, rollbackEntity } from '@/api/ADempiere/persistence'
import { getReferencesList } from '@/api/ADempiere/values'
import { convertObjectToArrayPairs, isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { parseContext } from '@/utils/ADempiere/contextUtils'
import { showMessage } from '@/utils/ADempiere/notification'
import language from '@/lang'
import router from '@/router'
const initStateWindowControl = {
inCreate: [],
references: [],
windowOldRoute: {
path: '',
fullPath: '',
query: {}
},
dataLog: {}, // { containerUuid, recordId, tableName, eventType }
tabSequenceRecord: [],
totalResponse: 0,
totalRequest: 0
}
const windowControl = {
state: initStateWindowControl,
mutations: {
addInCreate(state, payload) {
state.inCreate.push(payload)
},
deleteInCreate(state, payload) {
state.inCreate = state.inCreate.filter(item => item.containerUuid !== payload.containerUuid)
},
addReferencesList(state, payload) {
state.references.push(payload)
},
setDataLog(state, payload) {
state.dataLog = payload
},
setWindowOldRoute(state, payload) {
state.windowOldRoute = payload
},
setTabSequenceRecord(state, payload) {
state.tabSequenceRecord = payload
},
setTotalResponse(state, payload) {
state.totalResponse = payload
},
setTotalRequest(state, payload) {
state.totalRequest = payload
},
resetStateWindowControl(state) {
state = initStateWindowControl
}
},
actions: {
undoPanelToNew({ dispatch, rootGetters }, { containerUuid }) {
const oldAttributes = rootGetters.getColumnNamesAndValues({
containerUuid,
propertyName: 'oldValue',
isObjectReturn: true,
isAddDisplayColumn: true
})
dispatch('notifyPanelChange', {
containerUuid,
newValues: oldAttributes
})
},
createNewEntity({ commit, dispatch, getters, rootGetters }, {
parentUuid,
containerUuid
}) {
return new Promise((resolve, reject) => {
// exists some call to create new record with container uuid
if (getters.getInCreate(containerUuid)) {
return reject({
error: 0,
message: `In this panel (${containerUuid}) is a create new record in progress`
})
}
const { tableName, fieldList } = rootGetters.getPanel(containerUuid)
// delete key from attributes
const attributesList = rootGetters.getColumnNamesAndValues({
containerUuid,
propertyName: 'value',
isEvaluateValues: true,
isAddDisplayColumn: false
})
commit('addInCreate', {
containerUuid,
tableName,
attributesList
})
createEntity({
tableName,
attributesList
})
.then(createEntityResponse => {
const newValues = createEntityResponse.values
attributesList.forEach(element => {
if (element.columnName.includes('DisplayColumn')) {
newValues[element.columnName] = element.value
}
})
showMessage({
message: language.t('data.createRecordSuccessful'),
type: 'success'
})
// update fields with new values
dispatch('notifyPanelChange', {
parentUuid,
containerUuid,
newValues,
isSendToServer: false
})
dispatch('addNewRow', {
parentUuid,
containerUuid,
isPanelValues: true,
isEdit: false
})
// set data log to undo action
const fieldId = fieldList.find(itemField => itemField.isKey)
dispatch('setDataLog', {
containerUuid,
tableName,
recordId: fieldId.value, // TODO: Verify performance with tableName_ID
recordUuid: newValues.UUID,
eventType: 'INSERT'
})
const oldRoute = router.app._route
router.push({
name: oldRoute.name,
params: {
...oldRoute.params
},
query: {
...oldRoute.query,
action: createEntityResponse.uuid
}
})
dispatch('tagsView/delView', oldRoute, true)
resolve({
data: newValues,
recordUuid: createEntityResponse.uuid,
recordId: createEntityResponse.id,
tableName: createEntityResponse.tableName
})
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Create Entity error: ${error.message}.`)
reject(error)
})
.finally(() => {
commit('deleteInCreate', {
containerUuid,
tableName,
attributesList
})
})
})
},
createEntityFromTable({ commit, dispatch, getters, rootGetters }, {
parentUuid,
containerUuid,
row
}) {
// exists some call to create new record with container uuid
if (getters.getInCreate(containerUuid)) {
return {
error: 0,
message: `In this panel (${containerUuid}) is a create new record in progress.`
}
}
const { tableName, isParentTab } = rootGetters.getPanel(containerUuid)
// TODO: Add support to Binary columns (BinaryData)
const columnsToDontSend = ['BinaryData', 'isEdit', 'isNew', 'isSendServer']
// TODO: Evaluate peformance without filter using delete(prop) before convert object to array
// attributes or fields
const fieldsList = getters.getFieldsListFromPanel(containerUuid)
const attributesList = []
fieldsList.forEach(itemAttribute => {
if (columnsToDontSend.includes(itemAttribute.columnName) || itemAttribute.columnName.includes('DisplayColumn')) {
return false
}
if (isEmptyValue(row[itemAttribute.columnName])) {
return false
}
attributesList.push({
value: row[itemAttribute.columnName],
columnName: itemAttribute.columnName,
valueType: itemAttribute.valueType
})
})
commit('addInCreate', {
containerUuid,
tableName,
attributesList
})
let isError = false
return createEntity({
tableName,
attributesList
})
.then(createEntityResponse => {
showMessage({
message: language.t('data.createRecordSuccessful'),
type: 'success'
})
if (isParentTab) {
// redirect to create new record
const oldRoute = router.app._route
router.push({
name: oldRoute.name,
params: {
...oldRoute.params
},
query: {
...oldRoute.query,
action: createEntityResponse.recordUuid
}
})
}
return {
data: createEntityResponse.values,
...createEntityResponse
}
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Create Entity Table Error ${error.code}: ${error.message}.`)
isError = true
})
.finally(() => {
if (isError) {
dispatch('addNewRow', {
containerUuid,
row
})
} else {
// refresh record list
dispatch('getDataListTab', {
parentUuid,
containerUuid
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
}
commit('deleteInCreate', {
containerUuid,
tableName,
attributesList
})
})
},
updateCurrentEntity({ dispatch, rootGetters }, {
containerUuid,
recordUuid = null
}) {
const panel = rootGetters.getPanel(containerUuid)
if (!recordUuid) {
recordUuid = rootGetters.getUuid(containerUuid)
}
// TODO: Add support to Binary columns (BinaryData)
const columnsToDontSend = ['Account_Acct']
// attributes or fields
let finalAttributes = rootGetters.getColumnNamesAndValues({
containerUuid: containerUuid,
isEvaluatedChangedValue: true
})
finalAttributes = finalAttributes.filter(itemAttribute => {
if (columnsToDontSend.includes(itemAttribute.columnName) || itemAttribute.columnName.includes('DisplayColumn')) {
return false
}
const field = panel.fieldList.find(itemField => itemField.columnName === itemAttribute.columnName)
if (!field || !field.isUpdateable || !field.isDisplayed) {
return false
}
return true
})
return updateEntity({
tableName: panel.tableName,
recordUuid,
attributesList: finalAttributes
})
.then(updateEntityResponse => {
const newValues = updateEntityResponse.values
// set data log to undo action
// TODO: Verify performance with tableName_ID
let recordId = updateEntityResponse.id
if (isEmptyValue(recordId)) {
recordId = newValues[`${panel.tableName}_ID`]
}
if (isEmptyValue(recordId)) {
const fieldId = panel.fieldList.find(itemField => itemField.isKey)
recordId = fieldId.value
}
if (isEmptyValue(recordUuid)) {
recordUuid = updateEntityResponse.uuid
}
if (isEmptyValue(recordUuid)) {
recordUuid = newValues.UUID
}
dispatch('setDataLog', {
containerUuid,
tableName: panel.tableName,
recordId,
recordUuid,
eventType: 'UPDATE'
})
if (rootGetters.getShowContainerInfo) {
dispatch('listRecordLogs', {
tableName: panel.tableName,
recordId
})
}
return newValues
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Update Entity Error ${error.code}: ${error.message}`)
})
},
updateCurrentEntityFromTable({ rootGetters }, {
containerUuid,
row
}) {
const { tableName, fieldList } = rootGetters.getPanel(containerUuid)
// TODO: Add support to Binary columns (BinaryData)
const columnsToDontSend = ['BinaryData', 'isEdit', 'isNew', 'isSendServer']
// TODO: Evaluate peformance without filter using delete(prop) before convert object to array
// attributes or fields
let finalAttributes = convertObjectToArrayPairs(row)
finalAttributes = finalAttributes.filter(itemAttribute => {
if (columnsToDontSend.includes(itemAttribute.columnName) || itemAttribute.columnName.includes('DisplayColumn')) {
return false
}
const field = fieldList.find(itemField => itemField.columnName === itemAttribute.columnName)
if (!field || !field.isUpdateable || !field.isDisplayed) {
return false
}
return true
})
return updateEntity({
tableName,
recordUuid: row.UUID,
attributesList: finalAttributes
})
.then(response => {
return response
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Update Entity Table Error ${error.code}: ${error.message}.`)
})
},
/**
* Update record after run process associated with window
* @param {string} parentUuid
* @param {string} containerUuid
* @param {object} tab
*/
updateRecordAfterRunProcess({ dispatch, rootGetters }, {
parentUuid,
containerUuid,
tab
}) {
const recordUuid = rootGetters.getUuid(containerUuid)
// get new values
dispatch('getEntity', {
parentUuid,
containerUuid,
tableName: tab.tableName,
recordUuid
})
.then(response => {
// update panel
if (tab.isParentTab) {
dispatch('notifyPanelChange', {
parentUuid,
containerUuid,
newValues: response,
isSendCallout: false,
isSendToServer: false
})
}
// update row in table
dispatch('notifyRowTableChange', {
parentUuid,
containerUuid,
row: response,
isEdit: false
})
})
},
deleteEntity({ dispatch, rootGetters }, {
parentUuid,
containerUuid,
recordUuid,
recordId,
row
}) {
return new Promise(resolve => {
const panel = rootGetters.getPanel(containerUuid)
if (!isEmptyValue(row)) {
recordUuid = row.UUID
recordId = row[`${panel.tableName}_ID`]
}
deleteEntity({
tableName: panel.tableName,
recordUuid,
recordId
})
.then(responseDeleteEntity => {
// refresh record list
dispatch('getDataListTab', {
parentUuid,
containerUuid
})
.then(responseDataList => {
if (panel.isParentTab) {
// if response is void, go to new record
if (responseDataList.length <= 0) {
dispatch('resetPanelToNew', {
parentUuid,
containerUuid,
panelType: 'window',
isNewRecord: true
})
} else {
const oldRoute = router.app._route
// else display first record of table in panel
router.push({
name: oldRoute.name,
params: {
...oldRoute.params
},
query: {
...oldRoute.query,
action: responseDataList[0].UUID
}
})
}
}
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
showMessage({
message: language.t('data.deleteRecordSuccessful'),
type: 'success'
})
if (isEmptyValue(recordId)) {
// TODO: Verify performance with tableName_ID
const fieldId = panel.fieldList.find(itemField => itemField.isKey)
recordId = fieldId.value
}
// set data log to undo action
dispatch('setDataLog', {
containerUuid,
tableName: panel.tableName,
recordId,
recordUuid,
eventType: 'DELETE'
})
resolve(responseDeleteEntity)
})
.catch(error => {
showMessage({
message: language.t('data.deleteRecordError'),
type: 'error'
})
console.warn(`Delete Entity - Error ${error.message}, Code: ${error.code}.`)
})
})
},
/**
* Delete selection records in table
* @param {string} parentUuid
* @param {string} containerUuid
* @param {string} tableName
* @param {boolean} isParentTab
*/
deleteSelectionDataList({ dispatch, rootGetters }, {
parentUuid,
containerUuid,
tableName,
isParentTab
}) {
if (isEmptyValue(tableName) || isEmptyValue(isParentTab)) {
const tab = rootGetters.getTab(parentUuid, containerUuid)
tableName = tab.tableName
isParentTab = tab.isParentTab
}
const allData = rootGetters.getDataRecordAndSelection(containerUuid)
let selectionLength = allData.selection.length
allData.selection.forEach((record, index) => {
// validate if the registry row has no uuid before sending to the server
if (isEmptyValue(record.UUID)) {
selectionLength = selectionLength - 1
console.warn(`This row does not contain a record with UUID`, record)
// refresh record list
dispatch('getDataListTab', {
parentUuid,
containerUuid
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
return
}
deleteEntity({
tableName,
recordUuid: record.UUID
})
.then(() => {
if (isParentTab) {
// redirect to create new record
const oldRoute = router.app._route
if (record.UUID === oldRoute.query.action) {
router.push({
name: oldRoute.name,
params: {
...oldRoute.params
},
query: {
...oldRoute.query,
action: 'create-new'
}
})
// clear fields with default values
dispatch('resetPanelToNew', {
parentUuid,
containerUuid
})
// delete view with uuid record delete
dispatch('tagsView/delView', oldRoute, true)
}
}
if ((index + 1) >= selectionLength) {
// refresh record list
dispatch('getDataListTab', {
parentUuid,
containerUuid
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
showMessage({
message: language.t('data.deleteRecordSuccessful'),
type: 'success'
})
}
})
})
},
undoModifyData({ getters }, {
containerUuid,
recordUuid
}) {
return rollbackEntity(getters.getDataLog(containerUuid, recordUuid))
.then(response => {
return response
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Rollback Entity error: ${error.message}. Code: ${error.code}.`)
})
},
setDataLog({ commit }, {
containerUuid,
tableName,
recordId,
recordUuid,
eventType
}) {
commit('setDataLog', {
containerUuid,
tableName,
recordId,
recordUuid,
eventType
})
},
/**
* Get data to table in tab
* @param {string} parentUuid, window to search record data
* @param {string} containerUuid, tab to search record data
* @param {string} recordUuid, uuid to search
* @param {boolean} isRefreshPanel, if main panel is updated with new response data
* @param {boolean} isLoadAllRecords, if main panel is updated with new response data
*/
getDataListTab({ dispatch, rootGetters }, {
parentUuid,
containerUuid,
recordUuid,
referenceWhereClause = '',
columnName,
value,
criteria,
isAddRecord = false,
isLoadAllRecords = false,
isRefreshPanel = false,
isReference = false,
isShowNotification = true
}) {
const tab = rootGetters.getTab(parentUuid, containerUuid)
let parsedQuery = tab.query
if (!isEmptyValue(parsedQuery) && parsedQuery.includes('@')) {
parsedQuery = parseContext({
parentUuid,
containerUuid,
value: tab.query,
isBooleanToString: true
}).value
}
let parsedWhereClause = tab.whereClause
if (!isEmptyValue(parsedWhereClause) && parsedWhereClause.includes('@')) {
parsedWhereClause = parseContext({
parentUuid,
containerUuid,
value: tab.whereClause,
isBooleanToString: true
}).value
}
if (isReference) {
if (!isEmptyValue(parsedWhereClause)) {
parsedWhereClause += ` AND ${referenceWhereClause}`
} else {
parsedWhereClause += referenceWhereClause
}
}
if (!isEmptyValue(criteria)) {
if (!isEmptyValue(parsedWhereClause)) {
parsedWhereClause += ` AND ${criteria.whereClause}`
} else {
parsedWhereClause += criteria.whereClause
}
}
const conditionsList = []
// TODO: evaluate if overwrite values to conditions
if (!isLoadAllRecords && tab.isParentTab && !isEmptyValue(tab.tableName) && !isEmptyValue(value)) {
conditionsList.push({
columnName,
value
})
}
return dispatch('getObjectListFromCriteria', {
parentUuid,
containerUuid,
tableName: tab.tableName,
query: parsedQuery,
whereClause: parsedWhereClause,
orderByClause: tab.orderByClause,
conditionsList,
isParentTab: tab.isParentTab,
isAddRecord,
isShowNotification
})
.then(response => {
if (isRefreshPanel && !isEmptyValue(recordUuid) && recordUuid !== 'create-new') {
const newValues = response.find(itemData => itemData.UUID === recordUuid)
if (newValues) {
// update fields with values obtained from the server
dispatch('notifyPanelChange', {
parentUuid,
containerUuid,
newValues,
isSendCallout: false,
isSendToServer: false
})
} else {
// this record is missing (Deleted or the query does not include it)
dispatch('resetPanelToNew', {
parentUuid,
containerUuid
})
}
}
return response
})
.catch(error => {
return error
})
.finally(() => {
const currentData = rootGetters.getDataRecordAndSelection(containerUuid)
const { originalNextPageToken, pageNumber, recordCount } = currentData
let nextPage = pageNumber
const isAdd = isAddRecord
if (originalNextPageToken && isAddRecord) {
const pageInToken = originalNextPageToken.substring(originalNextPageToken.length - 2)
if (pageInToken === '-1') {
isAddRecord = false
}
if (pageNumber === 1 && recordCount > 50) {
nextPage = nextPage + 1
isAddRecord = true
}
} else {
isAddRecord = false
}
if (recordCount <= 50) {
isAddRecord = false
}
if (isAddRecord) {
dispatch('setPageNumber', {
parentUuid,
containerUuid,
pageNumber: nextPage,
panelType: 'window',
isAddRecord,
isShowNotification: false
})
}
if (isAdd && isAdd !== isAddRecord) {
if (tab.isSortTab) {
const record = rootGetters.getDataRecordsList(containerUuid)
const recordToTab = record
.map(itemRecord => {
return {
...itemRecord
}
})
.sort((itemA, itemB) => {
return itemA[tab.sortOrderColumnName] - itemB[tab.sortOrderColumnName]
})
dispatch('setTabSequenceRecord', recordToTab)
}
}
})
},
/**
* Get references asociate to record
* @param {string} parentUuid as windowUuid
* @param {string} containerUuid
* @param {string} tableName
* @param {string} recordUuid
*/
getReferencesListFromServer({ commit, rootGetters }, {
parentUuid: windowUuid,
containerUuid,
tableName,
recordUuid
}) {
if (isEmptyValue(tableName)) {
tableName = rootGetters.getTab(windowUuid, containerUuid).tableName
}
return new Promise(resolve => {
getReferencesList({
windowUuid,
tableName,
recordUuid
})
.then(referenceResponse => {
const referencesList = referenceResponse.referencesList.map(item => {
return {
...item,
recordUuid,
type: 'reference'
}
})
const references = {
...referenceResponse,
windowUuid,
recordUuid,
referencesList
}
commit('addReferencesList', references)
resolve(referenceResponse)
})
.catch(error => {
console.warn(`References Load Error ${error.code}: ${error.message}.`)
})
})
},
setWindowOldRoute({ commit }, oldPath = { path: '', fullPath: '', query: {}}) {
commit('setWindowOldRoute', oldPath)
},
setTabSequenceRecord({ commit }, record) {
commit('setTabSequenceRecord', record)
},
/**
* Update records in tab sort
* @param {string} containerUuid
* @param {string} parentUuid
*/
updateSequence({ state, commit, dispatch, getters, rootGetters }, {
parentUuid,
containerUuid
}) {
const { tableName, sortOrderColumnName, sortYesNoColumnName, tabAssociatedUuid } = rootGetters.getTab(parentUuid, containerUuid)
const listSequenceToSet = getters.getTabSequenceRecord
const recordData = rootGetters.getDataRecordsList(containerUuid)
// scrolls through the logs and checks if there is a change to be sent to server
recordData.forEach(itemData => {
const dataSequence = listSequenceToSet.find(item => item.UUID === itemData.UUID)
if (itemData[sortOrderColumnName] === dataSequence[sortOrderColumnName]) {
return
}
const valuesToSend = [{
columnName: sortOrderColumnName,
value: dataSequence[sortOrderColumnName]
}]
if (itemData[sortYesNoColumnName] !== dataSequence[sortYesNoColumnName]) {
valuesToSend.push({
columnName: sortYesNoColumnName,
value: dataSequence[sortYesNoColumnName]
})
}
const countRequest = state.totalRequest + 1
commit('setTotalRequest', countRequest)
updateEntity({
tableName,
recordUuid: itemData.UUID,
attributesList: valuesToSend
})
.catch(error => {
showMessage({
message: error.message,
type: 'error'
})
console.warn(`Update Entity Table Error ${error.code}: ${error.message}`)
})
.finally(() => {
const countResponse = state.totalResponse + 1
commit('setTotalResponse', countResponse)
if (state.totalResponse === state.totalRequest) {
showMessage({
message: language.t('notifications.updateSuccessfully'),
type: 'success'
})
dispatch('setShowDialog', {
type: 'window',
action: undefined
})
commit('setTotalRequest', 0)
commit('setTotalResponse', 0)
dispatch('setRecordSelection', {
parentUuid,
containerUuid,
isLoaded: false
})
dispatch('setTabSequenceRecord', [])
// refresh record list in table source
dispatch('getDataListTab', {
parentUuid,
containerUuid: tabAssociatedUuid
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
}
})
})
}
},
getters: {
getInCreate: (state) => (containerUuid) => {
return state.inCreate.find(item => item.containerUuid === containerUuid)
},
getReferencesList: (state) => (windowUuid, recordUuid) => {
return state.references.find(item => item.windowUuid === windowUuid && item.recordUuid === recordUuid)
},
getReferencesInfo: (state, getters) => ({ windowUuid, recordUuid, referenceUuid }) => {
const references = getters.getReferencesList(windowUuid, recordUuid)
return references.referencesList.find(item => item.uuid === referenceUuid)
},
getTabSequenceRecord: (state) => {
return state.tabSequenceRecord
},
getDataLog: (state) => (containerUuid, recordUuid) => {
const current = state.dataLog
if (current.containerUuid === containerUuid &&
((current.recordUuid === recordUuid) ||
(current.eventType === 'DELETE' && recordUuid === 'create-new'))) {
return current
}
return undefined
}
}
}
export default windowControl

View File

@ -0,0 +1,452 @@
import {
getWindow as getWindowMetadata,
getTab as getTabMetadata
} from '@/api/ADempiere/dictionary'
import { showMessage } from '@/utils/ADempiere/notification'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import language from '@/lang'
import router from '@/router'
import { generateField } from '@/utils/ADempiere/dictionaryUtils'
import { getFieldTemplate } from '@/utils/ADempiere/lookupFactory'
const initStateWindow = {
window: [],
windowIndex: 0
}
const window = {
state: initStateWindow,
mutations: {
addWindow(state, payload) {
state.window.push(payload)
state.windowIndex++
},
dictionaryResetCacheWindow(state) {
state = initStateWindow
},
setCurrentTab(state, payload) {
payload.window.currentTab = payload.tab
payload.window.currentTabUuid = payload.tab.uuid
},
changeWindowAttribute(state, payload) {
let value = payload.attributeValue
if (payload.attributeNameControl) {
value = payload.window[payload.attributeNameControl]
}
payload.window[payload.attributeName] = value
},
changeTabAttribute(state, payload) {
let value = payload.attributeValue
if (payload.attributeNameControl) {
value = payload.tab[payload.attributeNameControl]
}
payload.tab[payload.attributeName] = value
}
},
actions: {
/**
* Get Window metadata from server
* @param {string} windowUuid
* @param {number} windowId
* @param {object} routeToDelete, route to close in tagView when fail
*/
getWindowFromServer({ commit, state, dispatch }, {
windowUuid,
windowId,
routeToDelete
}) {
return getWindowMetadata({
uuid: windowUuid,
id: windowId
})
.then(responseWindow => {
const firstTabTableName = responseWindow.tabsList[0].tableName
const firstTabUuid = responseWindow.tabsList[0].uuid
const tabsListParent = []
const tabsListChildren = []
const tabsSequence = []
// TODO Add source tab on the server for tabs Translation and Sort
const tabs = responseWindow.tabsList.filter(itemTab => {
if (itemTab.isSortTab) {
// TODO: Add convert tab as process function
tabsSequence.push({
uuid: itemTab.uuid,
id: itemTab.id,
parentUuid: windowUuid,
containerUuid: itemTab.uuid,
parentTabUuid: itemTab.parentTabUuid,
panelType: 'window',
type: 'sequence',
isSortTab: itemTab.isSortTab,
name: itemTab.name,
description: itemTab.description,
tableName: itemTab.tableName,
sortOrderColumnName: itemTab.sortOrderColumnName, // order column
sortYesNoColumnName: itemTab.sortYesNoColumnName // included column
})
}
// TODO: Add support to isAdvancedTab, isTranslationTab and isHasTree
return !itemTab.isTranslationTab
}).map((tabItem, index, list) => {
// let tab = tabItem
const tab = {
...tabItem,
containerUuid: tabItem.uuid,
parentUuid: windowUuid,
windowUuid,
tabGroup: tabItem.fieldGroup,
firstTabUuid,
// relations
isParentTab: Boolean(firstTabTableName === tabItem.tableName),
// app properties
isAssociatedTabSequence: false, // show modal with order tab
isShowedRecordNavigation: !(tabItem.isSingleRow),
isLoadFieldsList: false,
index
}
delete tab.processesList
// action is dispatch used in vuex
let actions = []
actions.push({
// action to set default values and enable fields not isUpdateable
name: language.t('window.newRecord'),
processName: language.t('window.newRecord'),
type: 'dataAction',
action: 'setDefaultValues',
uuidParent: windowUuid,
disabled: !tab.isInsertRecord || tab.isReadOnly
}, {
// action to delete record selected
name: language.t('window.deleteRecord'),
processName: language.t('window.deleteRecord'),
type: 'dataAction',
action: 'deleteEntity',
uuidParent: windowUuid,
disabled: tab.isReadOnly
}, {
// action to undo create, update, delete record
name: language.t('data.undo'),
processName: language.t('data.undo'),
type: 'dataAction',
action: 'undoModifyData',
uuidParent: windowUuid,
disabled: false
}, {
name: language.t('data.lockRecord'),
processName: language.t('data.lockRecord'),
type: 'dataAction',
action: 'lockRecord',
disabled: false,
hidden: true,
tableName: '',
recordId: null
}, {
name: language.t('data.unlockRecord'),
processName: language.t('data.unlockRecord'),
type: 'dataAction',
action: 'unlockRecord',
disabled: false,
hidden: true,
tableName: '',
recordId: null
})
if (tab.isSortTab) {
const tabParent = list.find(itemTab => itemTab.tableName === tab.tableName && !itemTab.isSortTab)
if (tabParent) {
tab.tabAssociatedUuid = tabParent.uuid // tab source uuid
tab.tabAssociatedName = tabParent.name // tab source name
}
} else {
// add tabs sequence associated as process in tab source
let orderTabs = tabsSequence.filter(itemTab => itemTab.tableName === tab.tableName)
if (orderTabs.length) {
orderTabs = orderTabs.map(itemTab => {
return {
...itemTab,
// appication attributes
tabAssociatedUuid: tab.uuid, // tab source
tabAssociatedName: tab.name, // tab source
action: 'orderSequence',
panelType: 'window',
type: 'application'
}
})
actions = actions.concat(orderTabs)
tab.isAssociatedTabSequence = true
tab.tabsOrder = orderTabs
}
}
// get processess associated in tab
if (tabItem.processesList && tabItem.processesList.length) {
const processList = tabItem.processesList.map(processItem => {
// TODO: No list of parameters
// add process associated in vuex store
// dispatch('addProcessAssociated', {
// processToGenerate: processItem,
// containerUuidAssociated: tabItem.uuid
// })
return {
id: processItem.id,
uuid: processItem.uuid,
name: processItem.name,
type: 'process',
panelType: 'process',
description: processItem.description,
help: processItem.help,
isReport: processItem.isReport,
isDirectPrint: processItem.isDirectPrint,
containerUuidAssociated: tabItem.uuid,
parentUuidAssociated: windowUuid,
panelTypeAssociated: 'window'
}
})
actions = actions.concat(processList)
}
// Add process menu
dispatch('setContextMenu', {
containerUuid: tab.uuid,
actions
})
if (tab.isParentTab) {
tabsListParent.push(tab)
return tab
}
if (!tab.isSortTab) {
tabsListChildren.push(tab)
}
return tab
})
const newWindow = {
...responseWindow,
tabsList: tabs,
currentTab: tabsListParent[0],
tabsListParent,
tabsListChildren,
// app attributes
currentTabUuid: tabsListParent[0].uuid,
firstTab: tabsListParent[0],
firstTabUuid,
windowIndex: state.windowIndex + 1,
// App properties
isShowedTabsChildren: Boolean(tabsListChildren.length),
isShowedRecordNavigation: undefined,
isShowedAdvancedQuery: false
}
commit('addWindow', newWindow)
return newWindow
})
.catch(error => {
router.push({ path: '/dashboard' })
dispatch('tagsView/delView', routeToDelete)
showMessage({
message: language.t('login.unexpectedError'),
type: 'error'
})
console.warn(`Dictionary Window (State Window) - Error ${error.code}: ${error.message}.`)
})
},
getTabAndFieldFromServer({ dispatch, getters }, {
parentUuid,
containerUuid,
tabId,
panelType = 'window',
panelMetadata,
isAdvancedQuery = false
}) {
return new Promise((resolve, reject) => {
getTabMetadata({
uuid: containerUuid,
id: tabId
})
.then(tabResponse => {
const additionalAttributes = {
parentUuid,
containerUuid,
isShowedFromUser: true,
panelType,
tableName: tabResponse.tableName,
//
isReadOnlyFromForm: false,
isAdvancedQuery,
isEvaluateValueChanges: !isAdvancedQuery
}
let isWithUuidField = false // indicates it contains the uuid field
let fieldLinkColumnName
// Convert and add to app attributes
const fieldsList = tabResponse.fieldsList.map((fieldItem, index) => {
fieldItem = generateField({
fieldToGenerate: fieldItem,
moreAttributes: {
...additionalAttributes,
fieldListIndex: index
}
})
if (!isWithUuidField && fieldItem.columnName === 'UUID') {
isWithUuidField = true
}
if (fieldItem.isParent) {
fieldLinkColumnName = fieldItem.columnName
}
return fieldItem
})
let isTabsChildren = false
if (!isAdvancedQuery) {
const window = getters.getWindow(parentUuid)
isTabsChildren = Boolean(window.tabsListChildren.length)
}
if (!isWithUuidField) {
const fieldUuid = getFieldTemplate({
...additionalAttributes,
isShowedFromUser: false,
name: 'UUID',
columnName: 'UUID',
componentPath: 'FieldText'
})
fieldsList.push(fieldUuid)
}
if (isEmptyValue(panelMetadata)) {
panelMetadata = getters.getTab(parentUuid, containerUuid)
}
// Panel for save on store
const panel = {
...panelMetadata,
isAdvancedQuery,
fieldLinkColumnName,
fieldList: fieldsList,
panelType,
// app attributes
isLoadFieldsList: true,
isShowedTotals: false,
isTabsChildren // to delete records assiciated
}
dispatch('addPanel', panel)
resolve(panel)
dispatch('changeTabAttribute', {
parentUuid,
containerUuid,
tab: panelMetadata,
attributeName: 'isLoadFieldsList',
attributeValue: true
})
})
.catch(error => {
showMessage({
message: language.t('login.unexpectedError'),
type: 'error'
})
console.warn(`Get Dictionary Tab (State Window) - Error ${error.code}: ${error.message}.`, error)
reject(error)
})
})
},
setCurrentTab({ commit, getters }, {
parentUuid,
containerUuid,
window,
tab
}) {
if (isEmptyValue(window)) {
window = getters.getWindow(parentUuid)
}
if (isEmptyValue(tab)) {
tab = window.tabsList.find(itemTab => itemTab.uuid === containerUuid)
}
commit('setCurrentTab', {
window,
tab
})
},
changeWindowAttribute({ commit, getters }, {
parentUuid,
window,
attributeName,
attributeNameControl,
attributeValue
}) {
if (isEmptyValue(window)) {
window = getters.getWindow(parentUuid)
}
commit('changeWindowAttribute', {
parentUuid,
window,
attributeName,
attributeNameControl,
attributeValue
})
},
changeTabAttribute({ commit, getters }, {
parentUuid,
containerUuid,
tab,
attributeName,
attributeNameControl,
attributeValue
}) {
if (isEmptyValue(tab)) {
tab = getters.getTab(parentUuid, containerUuid)
}
commit('changeTabAttribute', {
tab,
attributeName,
attributeValue,
attributeNameControl
})
}
},
getters: {
getWindow: (state) => (windowUuid) => {
return state.window.find(
item => item.uuid === windowUuid
)
},
getIsShowedRecordNavigation: (state, getters) => (windowUuid) => {
const window = getters.getWindow(windowUuid)
if (window) {
return window.isShowedRecordNavigation
}
return window
},
getTab: (state, getters) => (windowUuid, tabUuid) => {
const window = getters.getWindow(windowUuid)
if (window) {
return window.tabsList.find(tabItem => {
return tabItem.uuid === tabUuid
})
}
return window
},
getCurrentTab: (state, getters) => (windowUuid) => {
const window = getters.getWindow(windowUuid)
if (window) {
return window.tabsList.find(tabItem => {
return tabItem.uuid === window.currentTabUuid
})
}
return {
isInsertRecord: false
}
},
getTableNameFromTab: (state, getters) => (windowUuid, tabUuid) => {
return getters.getTab(windowUuid, tabUuid).tableName
}
}
}
export default window

View File

@ -157,7 +157,9 @@ const actions = {
// TODO: return #Date as long data type Date (5) // TODO: return #Date as long data type Date (5)
responseGetInfo.defaultContextMap.set('#Date', new Date()) responseGetInfo.defaultContextMap.set('#Date', new Date())
// set multiple context // set multiple context
dispatch('setMultipleContextMap', responseGetInfo.defaultContextMap, { dispatch('setMultiplePreference', {
values: responseGetInfo.defaultContextMap
}, {
root: true root: true
}) })
@ -295,7 +297,7 @@ const actions = {
console.warn(`Error ${error.code} getting Organizations list: ${error.message}.`) console.warn(`Error ${error.code} getting Organizations list: ${error.message}.`)
}) })
}, },
changeOrganization({ commit, dispatch }, { changeOrganization({ dispatch }, {
organizationUuid organizationUuid
}) { }) {
setCurrentOrganization(organizationUuid) setCurrentOrganization(organizationUuid)

View File

@ -1,4 +1,5 @@
import { isEmptyValue } from '@/utils/ADempiere/valueUtils' import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
import { convertBooleanToString } from '@/utils/ADempiere/valueFormat.js'
import evaluator from '@/utils/ADempiere/evaluator' import evaluator from '@/utils/ADempiere/evaluator'
import store from '@/store' import store from '@/store'
@ -10,13 +11,89 @@ export const getContext = ({
containerUuid, containerUuid,
columnName columnName
}) => { }) => {
return store.getters.getContext({ let value
const isPreferenceValue = columnName.startsWith('$') || columnName.startsWith('#')
if (isPreferenceValue || columnName.startsWith(`P|${parentUuid}`) || columnName.startsWith(`P|${columnName}`)) {
value = store.getters.getPreference({
parentUuid, parentUuid,
containerUuid, containerUuid,
columnName columnName
}) })
}
if (!isPreferenceValue && isEmptyValue(value)) {
value = store.getters.getValueOfContainer({
parentUuid,
containerUuid,
columnName
})
}
return value
} }
/**
* Get Preference.
* <pre>
* 0) Current Setting
* 1) Window Preference
* 2) Global Preference
* 3) Login settings
* 4) Accounting settings
* </pre>
* @param {string} parentUuid UUID Window
* @param {string} containerUuid UUID Tab, Process, SmartBrowser, Report and Form
* @param {string} columnName (context) Entity to search
* @return preference value
*/
export function getPreference({
parentUuid,
containerUuid,
columnName
}) {
let value
if (isEmptyValue(columnName)) {
console.warn('Require Context ColumnName')
return value
}
// USER PREFERENCES
// View Preferences
if (parentUuid) {
value = getContext({
parentUuid: 'P' + parentUuid,
containerUuid,
columnName
})
if (!isEmptyValue(value)) {
return value
}
}
// Global Preferences
value = getContext({
columnName: 'P|' + columnName
})
if (!isEmptyValue(value)) {
return value
}
// SYSTEM PREFERENCES
// Login setting
// get # globals context only window
value = getContext({
columnName: '#' + columnName
})
if (!isEmptyValue(value)) {
return value
}
// Accounting setting
value = getContext({
columnName: '$' + columnName
})
return value
} // getPreference
/** /**
* Extracts the associated fields from the logics or default values * Extracts the associated fields from the logics or default values
* @param {string} displayLogic * @param {string} displayLogic
@ -50,6 +127,12 @@ export function getParentFields({
return parentFields return parentFields
} }
export const specialColumns = [
'C_AcctSchema_ID',
'C_Currency_ID',
'C_Convertion_Type_ID'
]
/** /**
* Parse Context String * Parse Context String
* @param {string} value: (REQUIRED) String to parsing * @param {string} value: (REQUIRED) String to parsing
@ -71,17 +154,22 @@ export function parseContext({
}) { }) {
let isError = false let isError = false
const errorsList = [] const errorsList = []
value = String(value)
if (isEmptyValue(value)) { if (isEmptyValue(value)) {
value = undefined
if (specialColumns.includes(columnName)) {
value = contextInfo = getContext({
columnName: '$' + columnName
})
}
return { return {
value: undefined, value,
isError: true, isError: true,
errorsList: [] errorsList
} }
} }
if (value.includes('@SQL=')) { value = String(value).replace('@SQL=')
value = value.replace('@SQL=', '')
}
// const instances = value.length - value.replace('@', '').length // const instances = value.length - value.replace('@', '').length
// if ((instances > 0) && (instances % 2) !== 0) { // could be an email address // if ((instances > 0) && (instances % 2) !== 0) { // could be an email address
// return value // return value
@ -92,12 +180,6 @@ export function parseContext({
let outString = '' let outString = ''
let firstIndexTag = inString.indexOf('@') let firstIndexTag = inString.indexOf('@')
const convertBooleanToString = (booleanValue) => {
if (booleanValue) {
return 'Y'
}
return 'N'
}
while (firstIndexTag !== -1) { while (firstIndexTag !== -1) {
outString = outString + inString.substring(0, firstIndexTag) // up to @ outString = outString + inString.substring(0, firstIndexTag) // up to @
@ -122,23 +204,32 @@ export function parseContext({
containerUuid, containerUuid,
columnName columnName
}) // get context }) // get context
if (isEmptyValue(contextInfo)) {
// get global context
if (token.startsWith('#') || token.startsWith('$')) {
contextInfo = getContext({
columnName
})
} else {
// get accounting context
if (specialColumns.includes(columnName)) {
contextInfo = getContext({
columnName: '$' + columnName
})
}
}
}
// menu attribute isEmptyValue isSOTrx
if (!isEmptyValue(isSOTrxMenu) && token === 'IsSOTrx' && isEmptyValue(contextInfo)) {
contextInfo = isSOTrxMenu
}
if ((isBooleanToString || isSQL) && typeof contextInfo === 'boolean') { if ((isBooleanToString || isSQL) && typeof contextInfo === 'boolean') {
contextInfo = convertBooleanToString(contextInfo) contextInfo = convertBooleanToString(contextInfo)
} }
if (isEmptyValue(contextInfo) &&
(token.startsWith('#') || token.startsWith('$'))) {
contextInfo = getContext({
columnName
}) // get global context
}
// menu attribute isEmptyValue isSOTrx
if (!isEmptyValue(isSOTrxMenu) && token === 'IsSOTrx' && isEmptyValue(contextInfo)) {
contextInfo = isSOTrxMenu
if (isBooleanToString || isSQL) {
contextInfo = convertBooleanToString(contextInfo)
}
}
if (contextInfo === undefined || contextInfo.length === 0) { if (contextInfo === undefined || contextInfo.length === 0) {
// console.info(`No Context for: ${token}`) // console.info(`No Context for: ${token}`)
isError = true isError = true
@ -153,7 +244,8 @@ export function parseContext({
inString = inString.substring(secondIndexTag + 1, inString.length) // from second @ inString = inString.substring(secondIndexTag + 1, inString.length) // from second @
firstIndexTag = inString.indexOf('@') firstIndexTag = inString.indexOf('@')
} } // end while loop
if (!['object', 'boolean'].includes(typeof contextInfo)) { if (!['object', 'boolean'].includes(typeof contextInfo)) {
outString = outString + inString // add the rest of the string outString = outString + inString // add the rest of the string
} }
@ -173,67 +265,3 @@ export function parseContext({
value: outString value: outString
} }
} // parseContext } // parseContext
/**
* Get Preference.
* <pre>
* 0) Current Setting
* 1) Window Preference
* 2) Global Preference
* 3) Login settings
* 4) Accounting settings
* </pre>
* @param {string} parentUuid UUID Window
* @param {string} containerUuid UUID Tab, Process, SmartBrowser, Report and Form
* @param {string} columnName (context) Entity to search
* @return preference value
*/
export function getPreference({
parentUuid,
containerUuid,
columnName
}) {
let retValue
if (isEmptyValue(columnName)) {
console.warn('Require Context ColumnName')
return retValue
}
// USER PREFERENCES
// View Preferences
if (parentUuid && containerUuid) {
retValue = getContext({
parentUuid: 'P' + parentUuid,
containerUuid,
columnName: columnName
})
if (!isEmptyValue(retValue)) {
return retValue
}
}
// Global Preferences
retValue = getContext({
columnName: 'P|' + columnName
})
if (!isEmptyValue(retValue)) {
return retValue
}
// SYSTEM PREFERENCES
// Login setting
// get # globals context only window
retValue = getContext({
columnName: '#' + columnName
})
if (!isEmptyValue(retValue)) {
return retValue
}
// Accounting setting
retValue = getContext({
columnName: '$' + columnName
})
return retValue
} // getPreference

View File

@ -63,7 +63,7 @@ export function generateField({
...moreAttributes, ...moreAttributes,
columnName: fieldToGenerate.columnName, columnName: fieldToGenerate.columnName,
value: parsedDefaultValue, value: parsedDefaultValue,
isSOTrxMenu: isSOTrxMenu isSOTrxMenu
}).value }).value
} }
@ -88,7 +88,8 @@ export function generateField({
} }
parsedDefaultValue = parsedValueComponent({ parsedDefaultValue = parsedValueComponent({
fieldType: componentReference.componentPath, componentPath: componentReference.componentPath,
columnName: fieldToGenerate.columnName,
value: parsedDefaultValue, value: parsedDefaultValue,
displayType: fieldToGenerate.displayType, displayType: fieldToGenerate.displayType,
isMandatory: fieldToGenerate.isMandatory, isMandatory: fieldToGenerate.isMandatory,
@ -132,7 +133,8 @@ export function generateField({
} }
parsedDefaultValueTo = parsedValueComponent({ parsedDefaultValueTo = parsedValueComponent({
fieldType: componentReference.componentPath, componentPath: componentReference.componentPath,
columnName: fieldToGenerate.columnName,
value: parsedDefaultValueTo, value: parsedDefaultValueTo,
displayType: fieldToGenerate.displayType, displayType: fieldToGenerate.displayType,
isMandatory: fieldToGenerate.isMandatory, isMandatory: fieldToGenerate.isMandatory,
@ -170,12 +172,15 @@ export function generateField({
const field = { const field = {
...fieldToGenerate, ...fieldToGenerate,
...moreAttributes, ...moreAttributes,
columnNameTo: undefined,
elementNameTo: undefined,
isSOTrxMenu, isSOTrxMenu,
// displayed attributes // displayed attributes
componentPath: componentReference.componentPath, componentPath: componentReference.componentPath,
isSupported: componentReference.isSupported, isSupported: componentReference.isSupported,
size: componentReference.size || DEFAULT_SIZE, size: componentReference.size || DEFAULT_SIZE,
displayColumn: undefined, // link to value from selects and table displayColumn: undefined, // link to value from selects and table
displayColumnName: `DisplayColumn_${fieldToGenerate.columnName}`, // key to display column
// value attributes // value attributes
value: String(parsedDefaultValue).trim() === '' ? undefined : parsedDefaultValue, value: String(parsedDefaultValue).trim() === '' ? undefined : parsedDefaultValue,
oldValue: parsedDefaultValue, oldValue: parsedDefaultValue,
@ -211,9 +216,12 @@ export function generateField({
// Overwrite some values // Overwrite some values
if (field.isRange) { if (field.isRange) {
field.operator = 'GREATER_EQUAL' field.operator = 'GREATER_EQUAL'
field.columnNameTo = `${field.columnName}_To`
field.elementNameTo = `${field.elementNameTo}_To`
if (typeRange) { if (typeRange) {
field.uuid = `${field.uuid}_To` field.uuid = `${field.uuid}_To`
field.columnName = `${field.columnName}_To` field.columnName = field.columnNameTo
field.elementName = field.elementNameTo
field.name = `${field.name} To` field.name = `${field.name} To`
field.value = parsedDefaultValueTo field.value = parsedDefaultValueTo
field.defaultValue = field.defaultValueTo field.defaultValue = field.defaultValueTo
@ -491,24 +499,32 @@ export function sortFields({
/** /**
* Determinate if field is displayed * Determinate if field is displayed
* @param {boolean} field.isActive * @param {boolean} isActive
* @param {boolean} field.isDisplayed * @param {boolean} isDisplayed
* @param {boolean} field.isDisplayedFromLogic * @param {boolean} isDisplayedFromLogic
* @param {boolean} field.isQueryCriteria * @param {boolean} isQueryCriteria
* @param {string} field.panelType * @param {string} panelType
* @returns {boolean} * @returns {boolean}
*/ */
export function fieldIsDisplayed(field) { export function fieldIsDisplayed({
// if is Advanced Query panelType,
if (field.panelType === 'table') { isActive,
return field.isDisplayed && field.isDisplayedFromLogic isDisplayed,
isDisplayedFromLogic,
isQueryCriteria
}) {
// Verify if field is active
if (!isActive) {
return false
} }
const isBrowserDisplayed = field.isQueryCriteria // browser query criteria
const isWindowDisplayed = field.isDisplayed && field.isDisplayedFromLogic // window, process and report, browser result
const isDisplayedView = (field.panelType === 'browser' && isBrowserDisplayed) || (field.panelType !== 'browser' && isWindowDisplayed)
// Verify for displayed and is active // browser query criteria
return field.isActive && isDisplayedView if (panelType === 'browser') {
return isQueryCriteria
}
// window, table (advanced query), process and report, browser (table) result
return isDisplayed && isDisplayedFromLogic
} }
// Convert action to action name for route // Convert action to action name for route

View File

@ -1,3 +1,6 @@
import { convertStringToBoolean } from '@/utils/ADempiere/valueFormat.js'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
// This class is used for evaluate a conditional // This class is used for evaluate a conditional
// format := {expression} [{logic} {expression}]<br> // format := {expression} [{logic} {expression}]<br>
// expression := @{context}@{operand}{value} or @{context}@{operand}{value}<br> // expression := @{context}@{operand}{value} or @{context}@{operand}{value}<br>
@ -27,7 +30,7 @@ class evaluator {
defaultReturned = false defaultReturned = false
}) { }) {
// empty logic // empty logic
if (logic === undefined || logic === null || logic.trim() === '') { if (isEmptyValue(logic)) {
return defaultReturned return defaultReturned
} }
const st = logic.trim().replace('\n', '') const st = logic.trim().replace('\n', '')
@ -96,7 +99,7 @@ class evaluator {
logic logic
}) { }) {
// not context info, not logic // not context info, not logic
if (logic === undefined || logic === null || logic.trim() === '') { if (isEmptyValue(logic)) {
return defaultReturned return defaultReturned
} }
@ -140,14 +143,14 @@ class evaluator {
columnName: first columnName: first
}) })
// in context exists this column name // in context exists this column name
if (value === null || value === undefined) { if (isEmptyValue(value)) {
// console.info(`.The column ${first} not exists in context.`) // console.info(`.The column ${first} not exists in context.`)
return defaultReturned return defaultReturned
} }
firstEval = value // replace with it's value firstEval = value // replace with it's value
} }
if (firstEval === null || firstEval === undefined) { if (isEmptyValue(firstEval)) {
return defaultReturned return defaultReturned
} }
if (typeof firstEval === 'string') { if (typeof firstEval === 'string') {
@ -193,16 +196,6 @@ class evaluator {
* @return {boolean} * @return {boolean}
*/ */
static evaluateLogicTuple(value1, operand, value2) { static evaluateLogicTuple(value1, operand, value2) {
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 // Convert value 1 string value to boolean value
value1 = convertStringToBoolean(value1) value1 = convertStringToBoolean(value1)
@ -250,7 +243,7 @@ class evaluator {
*/ */
static parseDepends(parseString) { static parseDepends(parseString) {
const listFields = [] const listFields = []
if (parseString === null || parseString === undefined) { if (isEmptyValue(parseString)) {
// return array empty // return array empty
return listFields return listFields
} }

View File

@ -285,6 +285,7 @@ export function getFieldTemplate(overwriteDefinition) {
isKey: false, isKey: false,
isSelectionColumn: false, isSelectionColumn: false,
isUpdateable: true, isUpdateable: true,
//
formatPattern: undefined, formatPattern: undefined,
VFormat: undefined, VFormat: undefined,
value: undefined, value: undefined,
@ -293,6 +294,7 @@ export function getFieldTemplate(overwriteDefinition) {
parsedDefaultValue: undefined, parsedDefaultValue: undefined,
defaultValueTo: undefined, defaultValueTo: undefined,
parsedDefaultValueTo: undefined, parsedDefaultValueTo: undefined,
valueType: componentReference.valueType, // value type to convert with gGRPC
valueMin: undefined, valueMin: undefined,
valueMax: undefined, valueMax: undefined,
// //

View File

@ -1,10 +1,90 @@
// A util class for handle format for time, date and others values to beused to display information // A util class for handle format for time, date and others values to beused to display information
// Note that this file use moment library for a easy conversion // Note that this file use moment library for a easy conversion
import moment from 'moment' import moment from 'moment'
import { isEmptyValue } from '@/utils/ADempiere/valueUtils' import { isEmptyValue } from '@/utils/ADempiere/valueUtils.js'
import store from '@/store' import store from '@/store'
import { DATE, DATE_PLUS_TIME, TIME } from '@/utils/ADempiere/references' import { DATE, DATE_PLUS_TIME, TIME } from '@/utils/ADempiere/references'
export const convertStringToBoolean = (valueToParsed) => {
const valueString = String(valueToParsed).trim()
if (valueString === 'N' || valueString === 'false') {
return false
}
return Boolean(valueToParsed)
}
export const convertBooleanToString = (booleanValue) => {
if (booleanValue || booleanValue === 'true') {
return 'Y'
}
return 'N'
}
/**
* Convert a object to array pairs
* @param {object} object, object to convert
* @param {string} nameKey, name from key in pairs
* @param {string} nameValue, name from value in pairs
* @returns {array} [ { nameKey: key, nameValue: value } ]
*/
export function convertObjectToKeyValue({
object,
keyName = 'columnName',
valueName = 'value'
}) {
return Object.keys(object).map(key => {
const returnPairs = {}
returnPairs[keyName] = key
returnPairs[valueName] = object[key]
return returnPairs
})
}
/**
* Convert array pairs of object to literal object { key: value }
* @param {array} array, Array to convert
* @param {string} nameKey, name from key in pairs
* @param {string} nameValue, name from value in pairs
* @returns {object} { key: value, key2: value2 }
*/
export function convertArrayKeyValueObject({
array,
keyName = 'columnName',
valueName = 'value'
}) {
const result = {}
array.forEach(element => {
result[element[keyName]] = element[valueName]
})
return result
}
/**
* Convert map of pairs to literal object
* @param {object} object
* @returns {map}
*/
export function convertObjectToHasMap({ object }) {
return new Map(
Object.entries(object)
)
}
/**
* Convert map of pairs to literal object
* @param {map} hasMapToConvert
* @returns {object} { key: value, key2: value2 }
*/
export function convertHasMapToObject({ map }) {
return Object.fromEntries(map)
// const result = {}
// map.forEach((value, key) => {
// result[key] = value
// })
// return result
}
// This function just convert all java date format to moment format. // This function just convert all java date format to moment format.
// For know about java format pattern see: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html // For know about java format pattern see: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
// Also you can read moment docus: https://momentjs.com/docs/ // Also you can read moment docus: https://momentjs.com/docs/

View File

@ -1,4 +1,5 @@
import { TABLE, TABLE_DIRECT } from '@/utils/ADempiere/references' import { convertStringToBoolean, convertBooleanToString } from '@/utils/ADempiere/valueFormat.js'
import { TABLE, TABLE_DIRECT } from '@/utils/ADempiere/references.js'
/** /**
* Checks if value is empty. Deep-checks arrays and objects * Checks if value is empty. Deep-checks arrays and objects
@ -87,49 +88,6 @@ export function clientDateTime(date = null, type = '') {
return currentDateTime.date + ' ' + currentDateTime.time return currentDateTime.date + ' ' + currentDateTime.time
} }
/**
* Convert a object to array pairs
* @param {object} objectToConvert, object to convert
* @param {string} nameKey, name from key in pairs
* @param {string} nameValue, name from value in pairs
* @returns {array} [ { nameKey: key, nameValue: value } ]
*/
export function convertObjectToArrayPairs(objectToConvert, nameKey = 'columnName', nameValue = 'value') {
return Object.keys(objectToConvert).map(key => {
const returnPairs = {}
returnPairs[nameKey] = key
returnPairs[nameValue] = objectToConvert[key]
return returnPairs
})
}
/**
* Convert array pairs of object to simple object { key:value }
* @param {array} arrayToConvert, object to convert
* @param {string} nameKey, name from key in pairs
* @param {string} nameValue, name from value in pairs
*/
export function convertArrayPairsToObject({
arrayToConvert,
nameKey = 'columnName',
nameValue = 'value'
}) {
const result = {}
arrayToConvert.forEach(element => {
result[element[nameKey]] = element[nameValue]
})
return result
}
export function convertHasMapToObject(hasMapToConvert) {
const result = {}
hasMapToConvert.forEach((value, key) => {
result[key] = value
})
return result
}
export function convertFieldListToShareLink(fieldList) { export function convertFieldListToShareLink(fieldList) {
var attributesListLink = '' var attributesListLink = ''
fieldList.map(fieldItem => { fieldList.map(fieldItem => {
@ -230,28 +188,33 @@ export const recursiveTreeSearch = ({
/** /**
* Parsed value to component type * Parsed value to component type
* @param {mixed} value, value to parsed * @param {mixed} value, value to parsed
* @param {string} fieldType, or componentPath * @param {string} componentPath
* @param {number} displayType, reference in ADempiere * @param {number} displayType, reference in ADempiere
* @param {boolean} isMandatory, field is mandatory * @param {boolean} isMandatory, field is mandatory
* @param {boolean} isIdentifier, field is ID * @param {boolean} isIdentifier, field is ID
*/ */
export function parsedValueComponent({ export function parsedValueComponent({
fieldType, componentPath,
value, value,
columnName,
displayType, displayType,
isMandatory = false, isMandatory = false,
isIdentifier = false isIdentifier = false
}) { }) {
const isEmpty = isEmptyValue(value) const isEmpty = isEmptyValue(value)
if (isEmpty && !isMandatory) { if (isEmpty && !isMandatory) {
if (fieldType === 'FieldYesNo') { if (componentPath === 'FieldYesNo') {
if (columnName === 'IsActive') {
return true
}
// Processing, Processed, and any other columnName, return false by default
return Boolean(value) return Boolean(value)
} }
return undefined return undefined
} }
var returnValue var returnValue
switch (fieldType) { switch (componentPath) {
// data type Number // data type Number
case 'FieldNumber': case 'FieldNumber':
if (isEmpty) { if (isEmpty) {
@ -272,12 +235,10 @@ export function parsedValueComponent({
// data type Boolean // data type Boolean
case 'FieldYesNo': case 'FieldYesNo':
if (value === 'false' || value === 'N') { if (typeof value === 'object' && Object.prototype.hasOwnProperty.call(value, 'query')) {
value = false
} else if (typeof value === 'object' && Object.prototype.hasOwnProperty.call(value, 'query')) {
returnValue = value returnValue = value
} }
returnValue = Boolean(value) returnValue = convertStringToBoolean(value)
break break
// data type String // data type String
@ -312,7 +273,7 @@ export function parsedValueComponent({
value = undefined value = undefined
} }
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
value = value ? 'Y' : 'N' value = convertBooleanToString(value)
} }
// Table (18) or Table Direct (19) // Table (18) or Table Direct (19)
if (displayType === TABLE_DIRECT.id || (displayType === TABLE.id && isIdentifier)) { if (displayType === TABLE_DIRECT.id || (displayType === TABLE.id && isIdentifier)) {

View File

@ -117,8 +117,11 @@ export default {
isLoadedRecords() { isLoadedRecords() {
return this.$store.getters.getDataRecordAndSelection(this.browserUuid).isLoaded return this.$store.getters.getDataRecordAndSelection(this.browserUuid).isLoaded
}, },
getContainerIsReadyForSubmit() { isReadyToSearch() {
return !this.$store.getters.isNotReadyForSubmit(this.browserUuid) && !this.browserMetadata.awaitForValuesToQuery if (this.browserMetadata.awaitForValuesToQuery) {
return false
}
return !this.$store.getters.isNotReadyForSubmit(this.browserUuid)
}, },
isMobile() { isMobile() {
return this.$store.state.app.device === 'mobile' return this.$store.state.app.device === 'mobile'
@ -136,19 +139,15 @@ export default {
return 'content-help' return 'content-help'
}, },
isShowedCriteria() { isShowedCriteria() {
if (this.getterBrowser) { if (this.browserMetadata) {
return this.getterBrowser.isShowedCriteria return this.browserMetadata.isShowedCriteria
} }
return false return false
} }
}, },
watch: { watch: {
isShowedCriteria(value) { isShowedCriteria(value) {
const activeSearch = [] this.handleCollapse(value)
if (value) {
activeSearch.push('opened-criteria')
}
this.activeSearch = activeSearch
} }
}, },
created() { created() {
@ -166,6 +165,18 @@ export default {
attributeValue: showCriteria attributeValue: showCriteria
}) })
}, },
/**
* Manage open or closed component collapse of criteria
*/
handleCollapse(isShowedCriteria) {
// by default criteria if closed
const activeSearch = []
if (isShowedCriteria) {
// open criteria
activeSearch.push('opened-criteria')
}
this.activeSearch = activeSearch
},
getBrowser() { getBrowser() {
const browser = this.getterBrowser const browser = this.getterBrowser
if (browser) { if (browser) {
@ -181,6 +192,7 @@ export default {
}) })
.then(browserResponse => { .then(browserResponse => {
this.browserMetadata = browserResponse this.browserMetadata = browserResponse
this.handleCollapse(browserResponse.isShowedCriteria)
this.defaultSearch() this.defaultSearch()
}) })
.finally(() => { .finally(() => {
@ -188,26 +200,25 @@ export default {
}) })
}, },
defaultSearch() { defaultSearch() {
// open or closed show criteria if (this.isLoadedRecords) {
this.activeSearch = [] // not research
if (this.browserMetadata.isShowedCriteria) { return
this.activeSearch = ['opened-criteria'] } else {
} if (this.isReadyToSearch) {
// first search by default
if (!this.isLoadedRecords) {
if (this.getContainerIsReadyForSubmit) {
this.$store.dispatch('getBrowserSearch', { this.$store.dispatch('getBrowserSearch', {
containerUuid: this.browserUuid containerUuid: this.browserUuid
}) })
return
} }
} else { }
// set default values into data
this.$store.dispatch('setRecordSelection', { this.$store.dispatch('setRecordSelection', {
containerUuid: this.browserUuid, containerUuid: this.browserUuid,
panelType: this.panelType panelType: this.panelType
}) })
} }
} }
}
} }
</script> </script>