1
0
mirror of https://github.com/PanJiaChen/vue-element-admin.git synced 2025-08-14 16:02:34 +08:00
Elsio Sanchez b87826415d
Bugfix/validate private access (#655)
* fix private acces

* Fixes: # 156 Fix Private Access

Co-authored-by: Elsio Sanchez <elsiosanche@gmail.com>
2021-03-10 11:29:57 -04:00

867 lines
25 KiB
JavaScript

import {
requestGetEntity,
requestListEntities
} from '@/api/ADempiere/persistence.js'
import {
requestDefaultValue,
requestGetContextInfoValue
} from '@/api/ADempiere/values'
import {
requestGetPrivateAccess,
requestLockPrivateAccess,
requestUnlockPrivateAccess
} from '@/api/ADempiere/private-access'
import {
extractPagingToken,
isEmptyValue
} from '@/utils/ADempiere/valueUtils.js'
import { convertArrayKeyValueToObject } from '@/utils/ADempiere/valueFormat.js'
import { typeValue } from '@/utils/ADempiere/valueUtils.js'
import {
parseContext,
getPreference
} from '@/utils/ADempiere/contextUtils'
import { showMessage } from '@/utils/ADempiere/notification'
import { TABLE, TABLE_DIRECT } from '@/utils/ADempiere/references'
import language from '@/lang'
const actions = {
/**
* Set page number of pagination list
* @param {string} parameters.parentUuid
* @param {string} parameters.containerUuid
* @param {integer} parameters.panelType
* @param {string} parameters.pageNumber
*/
setPageNumber({ commit, state, dispatch, rootGetters }, parameters) {
const {
parentUuid, containerUuid, panelType = 'window', pageNumber,
isAddRecord = false, isShowNotification = true
} = parameters
const data = state.recordSelection.find(recordItem => {
return recordItem.containerUuid === containerUuid
})
commit('setPageNumber', {
data: data,
pageNumber: pageNumber
})
// refresh list table with data from server
if (panelType === 'window') {
dispatch('getDataListTab', {
parentUuid,
containerUuid,
isAddRecord,
isShowNotification
})
.catch(error => {
console.warn(`Error getting data list tab. Message: ${error.message}, code ${error.code}.`)
})
} else if (panelType === 'browser') {
if (!rootGetters.isNotReadyForSubmit(containerUuid)) {
dispatch('getBrowserSearch', {
containerUuid,
isClearSelection: true
})
}
}
},
/**
* Insert new row bottom list table, used only from window
* @param {string} parentUuid
* @param {string} containerUuid
* @param {boolean} isPanelValues, define if used values form panel
* @param {boolean} isEdit, define if used values form panel
*/
async addNewRow({ commit, getters, rootGetters, dispatch }, {
parentUuid,
containerUuid,
isPanelValues = false,
isEdit = true,
isNew = true,
fieldsList,
row
}) {
const dataStore = getters.getDataRecordsList(containerUuid)
let values = {}
const currentNewRow = dataStore.find(itemData => {
return isEmptyValue(itemData.UUID) && itemData.isNew
})
if (!isEmptyValue(currentNewRow)) {
values = currentNewRow
return values
}
if (isEmptyValue(row)) {
const tabPanel = rootGetters.getPanel(containerUuid)
if (isEmptyValue(fieldsList)) {
fieldsList = tabPanel.fieldsList
}
// add row with default values to create new record
if (isPanelValues) {
// add row with values used from record in panel
values = rootGetters.getColumnNamesAndValues({
containerUuid,
propertyName: 'value',
isObjectReturn: true,
isAddDisplayColumn: true,
fieldsList
})
} else {
values = rootGetters.getParsedDefaultValues({
parentUuid,
containerUuid,
fieldsList,
formatToReturn: 'object'
})
}
values.isNew = isNew
values.isEdit = isEdit
values.isSendServer = false
// get the link column name from the tab
let linkColumnName = tabPanel.linkColumnName
if (isEmptyValue(linkColumnName)) {
// get the link column name from field list
linkColumnName = tabPanel.fieldLinkColumnName
}
let valueLink
// get context value if link column exists and does not exist in row
if (!isEmptyValue(linkColumnName)) {
valueLink = getPreference({
parentUuid,
containerUuid,
columnName: linkColumnName
})
if (!isEmptyValue(valueLink)) {
valueLink = parseInt(valueLink, 10)
}
}
// get display column and/or sql value
if (fieldsList.length) {
fieldsList
// TODO: Evaluate if is field is read only and FieldSelect
.filter(itemField => {
return itemField.componentPath === 'FieldSelect' ||
typeValue(values[itemField.columnName]) === 'OBJECT' ||
itemField.isSQLValue
})
.map(async itemField => {
const { columnName, componentPath } = itemField
let valueGetDisplayColumn = values[columnName]
if (typeValue(values[columnName]) === 'OBJECT') {
if (componentPath === 'FieldSelect') {
values[columnName] = ' '
values[itemField.displayColumnName] = ' '
} else if (componentPath === 'FieldNumber') {
values[columnName] = 0
}
}
// overwrite value with column link
if (!isEmptyValue(linkColumnName) && linkColumnName === columnName) {
valueGetDisplayColumn = valueLink
if (isEmptyValue(values[columnName])) {
values[columnName] = valueGetDisplayColumn
}
}
// break this itineration if is empty
if (isEmptyValue(valueGetDisplayColumn)) {
return
}
// always the values for these types of fields are integers
// Table (18) or Table Direct (19)
if ([TABLE.id, TABLE_DIRECT.id].includes(itemField.diplayType)) {
valueGetDisplayColumn = parseInt(valueGetDisplayColumn, 10)
} else {
if (!isNaN(valueGetDisplayColumn)) {
valueGetDisplayColumn = parseInt(valueGetDisplayColumn, 10)
}
}
if (!isEmptyValue(valueGetDisplayColumn) &&
typeValue(valueGetDisplayColumn) === 'OBJECT' &&
valueGetDisplayColumn.isSQL) {
// get value from Query
valueGetDisplayColumn = await dispatch('getValueBySQL', {
parentUuid,
containerUuid,
query: itemField.defaultValue
})
values[columnName] = valueGetDisplayColumn
}
// break to next itineration if not select field
if (componentPath !== 'FieldSelect') {
return
}
// get label (DisplayColumn) from vuex store
const options = rootGetters.getLookupAll({
parentUuid,
containerUuid,
tableName: itemField.reference.tableName,
query: itemField.reference.query,
directQuery: itemField.reference.directQuery,
value: valueGetDisplayColumn
})
const option = options.find(itemOption => itemOption.key === valueGetDisplayColumn)
// if there is a lookup option, assign the display column with the label
if (option) {
values[itemField.displayColumnName] = option.label
// if (isEmptyValue(option.label) && !itemField.isMandatory) {
// values[columnName] = undefined
// }
return
}
if (linkColumnName === columnName) {
// get context value if link column exists and does not exist in row
const nameParent = getPreference({
parentUuid,
containerUuid,
columnName: 'Name'
})
if (!isEmptyValue(nameParent)) {
values[itemField.displayColumnName] = nameParent
return
}
}
// get value to displayed from server
const { label } = await dispatch('getLookupItemFromServer', {
parentUuid,
containerUuid,
columnName: itemField.columnName,
tableName: itemField.reference.tableName,
directQuery: itemField.reference.directQuery,
value: valueGetDisplayColumn
})
values[itemField.displayColumnName] = label
})
}
// overwrite value with column link
if (isEmptyValue(values[linkColumnName])) {
values[linkColumnName] = valueLink
}
} else {
values = row
}
commit('addNewRow', {
values,
data: dataStore
})
},
/**
* Is load context in true when panel is set context
* @param {string} containerUuid
*/
setIsloadContext({ commit, state }, { containerUuid }) {
const dataStore = state.recordSelection.find(recordItem => {
return recordItem.containerUuid === containerUuid
})
if (dataStore) {
commit('setIsloadContext', {
data: dataStore,
isLoadedContext: true
})
}
},
/**
* Set record, selection, page number, token, and record count, with container uuid
* @param {string} parameters.containerUuid
* @param {array} parameters.record
* @param {array} parameters.selection
* @param {integer} parameters.pageNumber
* @param {integer} parameters.recordCount
* @param {string} parameters.nextPageToken
* @param {string} parameters.panelType
*/
setRecordSelection({ state, commit }, parameters) {
const {
parentUuid, containerUuid, panelType = 'window', record = [],
query, whereClause, orderByClause,
selection = [], pageNumber = 1, recordCount = 0, nextPageToken,
originalNextPageToken, isAddRecord = false, isLoaded = true
} = parameters
const dataStore = state.recordSelection.find(recordItem => {
return recordItem.containerUuid === containerUuid
})
const newDataStore = {
parentUuid,
containerUuid,
record,
selection,
pageNumber,
recordCount,
nextPageToken,
originalNextPageToken,
panelType,
isLoaded,
isLoadedContext: false,
query,
whereClause,
orderByClause
}
if (dataStore) {
if (isAddRecord) {
newDataStore.record = dataStore.record.concat(newDataStore.record)
}
commit('setRecordSelection', {
dataStore,
newDataStore
})
} else {
commit('addRecordSelection', newDataStore)
}
},
/**
* Set selection in data list associated in container
* @param {string} containerUuid
* @param {array} selection
*/
setSelection({ commit, getters }, {
containerUuid,
selection = []
}) {
const recordSelection = getters.getDataRecordAndSelection(containerUuid)
commit('setSelection', {
newSelection: selection,
data: recordSelection
})
},
/**
* Delete record result in container
* @param {string} viewUuid // As parentUuid in window
* @param {array} withOut
* @param {boolean} isNew
*/
deleteRecordContainer({ commit, state, dispatch }, {
viewUuid,
withOut = [],
isNew = false
}) {
const setNews = []
const record = state.recordSelection.filter(itemRecord => {
// ignore this uuid
if (withOut.includes(itemRecord.containerUuid)) {
return true
}
// remove window and tabs data
if (itemRecord.parentUuid) {
if (isNew) {
setNews.push(itemRecord.containerUuid)
}
return itemRecord.parentUuid !== viewUuid
}
// remove browser data
return itemRecord.containerUuid !== viewUuid
})
commit('deleteRecordContainer', record)
dispatch('setTabSequenceRecord', [])
if (setNews.length) {
setNews.forEach(uuid => {
dispatch('setRecordSelection', {
parentUuid: viewUuid,
containerUuid: uuid
})
})
}
},
/**
* @param {string} tableName
* @param {string} recordUuid
* @param {number} recordId
*/
getEntity({ commit }, {
tableName,
recordUuid,
recordId
}) {
return new Promise(resolve => {
requestGetEntity({
tableName,
recordUuid,
recordId
})
.then(responseGetEntity => {
resolve(responseGetEntity.attributes)
})
.catch(error => {
console.warn(`Error Get Entity ${error.message}. Code: ${error.code}.`)
})
})
},
/**
* Request list to view in table
* TODO: Join with getDataListTab action
* @param {string} parentUuid, uuid from window
* @param {string} containerUuid, uuid from tab
* @param {string} tableName, table name to search record data
* @param {string} query, criteria to search record data
* @param {string} whereClause, criteria to search record data
* @param {string} orderByClause, criteria to search record data
* @param {array} conditionsList, conditions list to criteria
* @param {boolean} isShowNotification, show searching and response records
* @param {boolean} isParentTab, conditions list to criteria
* @param {boolean} isAddRecord, join store records with server records (used with sequence tab)
* @param {boolean} isAddDefaultValues, add default fields values
*/
getObjectListFromCriteria({ dispatch, getters, rootGetters }, {
parentUuid, containerUuid,
tableName, query, whereClause, orderByClause, conditionsList = [],
isShowNotification = true, isParentTab = true, isAddRecord = false,
isAddDefaultValues = true
}) {
if (isShowNotification) {
showMessage({
title: language.t('notifications.loading'),
message: language.t('notifications.searching'),
type: 'info'
})
}
const replaceTable = (value) => {
return value.replace('table_', '')
}
parentUuid = replaceTable(parentUuid)
containerUuid = replaceTable(containerUuid)
const dataStore = getters.getDataRecordAndSelection(containerUuid)
let nextPageToken
if (!isEmptyValue(dataStore.nextPageToken)) {
nextPageToken = dataStore.nextPageToken + '-' + dataStore.pageNumber
}
let inEdited = []
if (!isParentTab) {
// TODO: Evaluate peformance to evaluate records to edit
inEdited = dataStore.record.filter(itemRecord => {
return itemRecord.isEdit && !itemRecord.isNew
})
}
// gets the default value of the fields (including whether it is empty or undefined)
let defaultValues = {}
if (isAddDefaultValues) {
defaultValues = rootGetters.getParsedDefaultValues({
parentUuid,
containerUuid,
formatToReturn: 'object',
isGetServer: false
})
}
return requestListEntities({
tableName,
query,
whereClause,
conditionsList,
orderByClause,
pageToken: nextPageToken
})
.then(dataResponse => {
const recordsList = dataResponse.recordsList.map(record => {
const values = record.attributes
let isEdit = false
if (isAddDefaultValues) {
if (inEdited.find(itemEdit => itemEdit.UUID === values.UUID)) {
isEdit = true
}
}
// overwrite default values and sets the values obtained from the
// server (empty fields are not brought from the server)
return {
...defaultValues,
...values,
// datatables attributes
isNew: false,
isEdit,
isReadOnlyFromRow: false
}
})
const originalNextPageToken = dataResponse.nextPageToken
let token = originalNextPageToken
if (isEmptyValue(token)) {
token = dataStore.nextPageToken
} else {
token = extractPagingToken(token)
}
if (isShowNotification) {
let searchMessage = 'searchWithOutRecords'
if (recordsList.length) {
searchMessage = 'succcessSearch'
}
showMessage({
title: language.t('notifications.succesful'),
message: language.t(`notifications.${searchMessage}`),
type: 'success'
})
}
dispatch('setRecordSelection', {
parentUuid,
containerUuid,
record: recordsList,
selection: dataStore.selection,
recordCount: dataResponse.recordCount,
nextPageToken: token,
originalNextPageToken,
isAddRecord,
pageNumber: dataStore.pageNumber,
tableName,
query,
whereClause
})
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', {
parentUuid,
containerUuid
})
if (isShowNotification) {
showMessage({
title: language.t('notifications.error'),
message: error.message,
type: 'error'
})
}
console.warn(`Error Get Object List ${error.message}. Code: ${error.code}.`)
})
},
/**
* @param {string} parentUuid
* @param {string} containerUuid
* @param {string} query
*/
getValueBySQL({ commit }, {
parentUuid,
containerUuid,
query
}) {
// TODO: Change to promise all
return new Promise(resolve => {
if (query.includes('@')) {
query = parseContext({
parentUuid,
containerUuid,
isSQL: true,
value: query
}).query
}
requestDefaultValue(query)
.then(defaultValueResponse => {
resolve(defaultValueResponse)
})
.catch(error => {
console.warn(`Error getting default value from server. Error code ${error.code}: ${error.message}.`)
})
})
},
/**
* TODO: Add support to tab children
* @param {string} parentUuid
* @param {string} containerUuid
* @param {boolean} isEdit, if the row displayed to edit mode
* @param {boolean} isNew, if insert data to new row
* @param {objec} row, new data to change
*/
notifyRowTableChange({ commit, getters, rootGetters }, {
parentUuid,
containerUuid,
isEdit = true,
isNew,
row
}) {
let values = {}
if (row) {
values = row
} else {
values = rootGetters.getColumnNamesAndValues({
parentUuid,
containerUuid,
propertyName: 'value',
isObjectReturn: true,
isAddDisplayColumn: true
})
}
if (Array.isArray(values)) {
values = convertArrayKeyValueToObject({
arrayToConvert: values
})
}
const currentRow = getters.getRowData({
containerUuid,
recordUuid: values.UUID
})
const newRow = {
...values,
isEdit
}
commit('notifyRowTableChange', {
isNew,
newRow,
row: currentRow
})
},
notifyCellTableChange({ commit, state, dispatch, rootGetters }, {
parentUuid,
containerUuid,
field,
columnName,
rowKey,
keyColumn,
panelType = 'window',
isSendToServer = true,
isSendCallout = true,
newValue,
displayColumn,
withOutColumnNames = []
}) {
// dispatch('setPreferenceContext', {
// parentUuid,
// containerUuid,
// columnName,
// value: newValue
// })
const recordSelection = state.recordSelection.find(recordItem => {
return recordItem.containerUuid === containerUuid
})
let row = {}
if (!isEmptyValue(field.tableIndex)) {
row = recordSelection.record[field.tableIndex]
} else {
row = recordSelection.record.find(itemRecord => {
return itemRecord[keyColumn] === rowKey
})
}
// the field has not changed, then the action is broken
if (row[columnName] === newValue) {
return
}
commit('notifyCellTableChange', {
row,
value: newValue,
columnName,
displayColumn
})
if (panelType === 'browser') {
const rowSelection = recordSelection.selection.find(itemRecord => {
return itemRecord[keyColumn] === rowKey
})
commit('notifyCellSelectionChange', {
row: rowSelection,
value: newValue,
columnName,
displayColumn
})
} else if (panelType === 'window') {
// request callouts
if (isSendCallout && !withOutColumnNames.includes(field.columnName) &&
!isEmptyValue(newValue) && !isEmptyValue(field.callout)) {
withOutColumnNames.push(field.columnName)
dispatch('runCallout', {
parentUuid,
containerUuid,
tableName: field.tableName,
columnName: field.columnName,
callout: field.callout,
value: newValue,
valueType: field.valueType,
withOutColumnNames,
row,
inTable: true
})
}
if (isSendToServer) {
const fieldNotReady = rootGetters.isNotReadyForSubmit(containerUuid, row)
if (!fieldNotReady) {
if (!isEmptyValue(row.UUID)) {
dispatch('updateCurrentEntityFromTable', {
parentUuid,
containerUuid,
row
})
} else {
dispatch('createEntityFromTable', {
parentUuid,
containerUuid,
row
})
}
} else {
const fieldsEmpty = rootGetters.getFieldsListEmptyMandatory({
containerUuid,
row
})
showMessage({
message: language.t('notifications.mandatoryFieldMissing') + fieldsEmpty,
type: 'info'
})
}
}
}
},
getContextInfoValueFromServer({ commit, getters }, {
contextInfoId,
contextInfoUuid,
sqlStatement
}) {
const contextInforField = getters.getContextInfoField(contextInfoUuid, sqlStatement)
if (contextInforField) {
return contextInforField
}
return requestGetContextInfoValue({
id: contextInfoId,
uuid: contextInfoUuid,
query: sqlStatement
})
.then(contextInfoResponse => {
commit('setContextInfoField', {
contextInfoUuid,
sqlStatement,
...contextInfoResponse
})
return contextInfoResponse
})
.catch(error => {
console.warn(`Error ${error.code} getting context info value for field ${error.message}.`)
})
},
getPrivateAccessFromServer({ rootGetters }, {
tableName,
recordId,
recordUuid
}) {
return requestGetPrivateAccess({
tableName,
recordId,
recordUuid
})
.then(privateAccessResponse => {
// TODO: Evaluate uuid record
if (!isEmptyValue(privateAccessResponse.tableName)) {
return {
isLocked: false,
tableName,
recordId,
recordUuid
}
}
return {
...privateAccessResponse,
isLocked: true
}
})
.catch(error => {
console.warn(`Error get private access: ${error.message}. Code: ${error.code}.`)
})
},
lockRecord({ rootGetters }, {
tableName,
recordId,
recordUuid
}) {
return requestLockPrivateAccess({
tableName,
recordId,
recordUuid
})
.then(privateAccessResponse => {
if (!isEmptyValue(privateAccessResponse.recordId)) {
const recordLocked = {
isPrivateAccess: true,
isLocked: true,
...privateAccessResponse
}
showMessage({
title: language.t('notifications.succesful'),
message: language.t('notifications.recordLocked'),
type: 'success'
})
return recordLocked
}
})
.catch(error => {
showMessage({
title: language.t('notifications.error'),
message: language.t('login.unexpectedError') + error.message,
type: 'error'
})
console.warn(`Error lock private access: ${error.message}. Code: ${error.code}.`)
})
},
unlockRecord({ rootGetters }, {
tableName,
recordId,
recordUuid
}) {
return requestUnlockPrivateAccess({
tableName,
recordId,
recordUuid
})
.then(privateAccessResponse => {
if (!isEmptyValue(privateAccessResponse.recordId)) {
const recordUnlocked = {
isPrivateAccess: true,
isLocked: false,
...privateAccessResponse
}
showMessage({
title: language.t('notifications.succesful'),
message: language.t('notifications.recordUnlocked'),
type: 'success'
})
return recordUnlocked
}
})
.catch(error => {
showMessage({
title: language.t('notifications.error'),
message: language.t('login.unexpectedError') + error.message,
type: 'error'
})
console.warn(`Error unlock private access: ${error.message}. Code: ${error.code}.`)
})
},
resetStateBusinessData({ commit }) {
commit('resetStateContainerInfo')
commit('setInitialContext', {})
commit('resetStateTranslations')
commit('resetStateBusinessData')
commit('resetContextMenu')
commit('resetStateTranslations')
commit('resetStateLookup')
commit('resetStateProcessControl')
commit('resetStateUtils')
commit('resetStateWindowControl')
}
}
export default actions