1
0
mirror of https://github.com/PanJiaChen/vue-element-admin.git synced 2025-08-07 18:25:45 +08:00

Add Change Log option in field (#822)

* Add Change Log option in field

* support mobile

* minimal changes

* sort logs

* fix style

Co-authored-by: elsiosanchez <elsiossanches@gmail.com>
This commit is contained in:
Elsio Sanchez 2021-05-07 16:57:25 -04:00 committed by GitHub
parent dc5d3df181
commit b406b8a3fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 242 additions and 10 deletions

View File

@ -24,11 +24,11 @@
<el-scrollbar :wrap-class="classIsMobilePanel">
<el-timeline>
<el-timeline-item
v-for="(listLogs, key) in gettersListRecordLogs"
:key="key"
v-for="(listLogs, key) in gettersListRecordLogs.sort(sortSequence)"
:key="listLogs.logId"
:type="listLogs.type"
:timestamp="translateDate(listLogs.logDate)"
placement="top"
color="#008fd3"
>
<el-card shadow="hover" class="clearfix">
<div>
@ -108,7 +108,25 @@ export default {
return 'panel'
},
gettersListRecordLogs() {
return this.$store.getters.getRecordLogs.entityLogs
const log = this.$store.getters.getRecordLogs.entityLogs
if (log) {
return log.map(element => {
let type
if (!this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
type = 'success'
} else if (this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && !this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
type = 'danger'
} else {
type = 'primary'
}
return {
...element,
columnName: element.changeLogsList[0].columnName,
type
}
})
}
return []
},
getIsChangeLog() {
if (this.isEmptyValue(this.gettersListRecordLogs)) {
@ -118,6 +136,9 @@ export default {
}
},
methods: {
sortSequence(itemA, itemB) {
return new Date().setTime(new Date(itemB.logDate).getTime()) - new Date().setTime(new Date(itemA.logDate).getTime())
},
showkey(key, index) {
if (key === this.currentKey && index === this.typeAction) {
this.currentKey = 1000
@ -141,6 +162,6 @@ export default {
height: 57vh;
}
.panel {
height: 100vh;
height: 75vh;
}
</style>

View File

@ -0,0 +1,176 @@
<!--
ADempiere-Vue (Frontend) for ADempiere ERP & CRM Smart Business Solution
Copyright (C) 2017-Present E.R.P. Consultores y Asociados, C.A.
Contributor(s): Elsio Sanchez elsiosanches@gmail.com www.erpya.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https:www.gnu.org/licenses/>.
-->
<template>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>
{{ $t('field.logsField') }}
<b> {{ fieldAttributes.name }} </b>
</span>
</div>
<div>
<el-scrollbar v-if="!isEmptyValue(listLogsField)" :wrap-class="classIsMobilePanel">
<el-timeline>
<el-timeline-item
v-for="(listLogs) in listLogsField.sort(sortSequence)"
:key="listLogs.logId"
:type="listLogs.type"
:timestamp="translateDate(listLogs.logDate)"
placement="top"
>
<el-card shadow="hover" class="clearfix">
<div>
{{ listLogs.userName }}
</div>
<!-- <el-collapse-transition> -->
<div>
<span v-for="(list, index) in listLogs.changeLogsList" :key="index">
<p v-if="list.columnName === 'DocStatus'">
<b> {{ list.displayColumnName }} :</b>
<strike>
<el-tag :type="tagStatus(list.oldValue)">
{{ list.oldDisplayValue }}
</el-tag>
</strike>
<el-tag :type="tagStatus(list.newValue)">
{{ list.newDisplayValue }}
</el-tag>
</p>
<p v-else>
<b> {{ list.displayColumnName }} :</b>
<strike>
<el-link type="danger">
{{ list.oldDisplayValue }}
</el-link>
</strike>
<el-link type="success">
{{ list.newDisplayValue }}
</el-link>
</p>
</span>
</div>
<!-- </el-collapse-transition> -->
</el-card>
</el-timeline-item>
</el-timeline>
</el-scrollbar>
</div>
</el-card>
</template>
<script>
export default {
name: 'FieldChangeLogs',
props: {
fieldAttributes: {
type: Object,
required: true
},
recordUuid: {
type: String,
default: undefined
}
},
data() {
return {
isLoading: false,
currentKey: 0,
typeAction: 0
}
},
computed: {
language() {
return this.$store.getters.language
},
listLogsField() {
const log = this.$store.getters.getRecordLogs.entityLogs
if (log) {
const logsField = log.map(element => {
let type
if (!this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
type = 'success'
} else if (this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && !this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
type = 'danger'
} else {
type = 'primary'
}
return {
...element,
columnName: element.changeLogsList[0].columnName,
type
}
})
return logsField.filter(field => field.columnName === this.fieldAttributes.columnName)
}
return []
},
isMobile() {
return this.$store.state.app.device === 'mobile'
},
classIsMobilePanel() {
if (this.isMobile) {
return 'panel-mobile'
}
return 'scroll-child'
}
},
methods: {
sortSequence(itemA, itemB) {
return new Date().setTime(new Date(itemB.logDate).getTime()) - new Date().setTime(new Date(itemA.logDate).getTime())
},
translateDate(value) {
return this.$d(new Date(value), 'long', this.language)
},
showkey(key, index) {
if (key === this.currentKey && index === this.typeAction) {
this.currentKey = 1000
} else {
this.currentKey = key
this.typeAction = index
}
}
}
}
</script>
<style lang="scss" scoped>
.custom-tittle-popover {
font-size: 14px;
font-weight: bold;
}
</style>
<style lang="scss">
/**
* Separation between elements (item) of the form
*/
.el-form-item {
margin-bottom: 10px !important;
margin-left: 10px;
margin-right: 10px;
}
/**
* Reduce the spacing between the form element and its label
*/
.el-form--label-top .el-form-item__label {
padding-bottom: 0px !important;
}
.panel-mobile {
height: 80vh;
}
</style>

View File

@ -74,7 +74,7 @@
/>
<el-button slot="reference" type="text" style="color: #606266;">
<div class="contents">
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
<i :class="option.icon" style="font-weight: bolder;" />
</div>
<div v-else style="margin-right: 5%">
@ -91,7 +91,7 @@
</el-button>
</el-popover>
<div v-if="isMobile" class="contents">
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
<i :class="option.icon" style="font-weight: bolder;" />
</div>
<div v-else style="margin-right: 5%">
@ -142,10 +142,13 @@
/>
<el-button slot="reference" type="text" style="color: #606266;">
<div class="contents">
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
<div
v-if="!option.svg"
style="margin-right: 5%;padding-top: 3%;"
>
<i :class="option.icon" style="font-weight: bolder;" />
</div>
<div v-else style="margin-right: 5%; padding-left: 8%;">
<div v-else style="margin-right: 5%;; padding-left: 2%;">
<svg-icon :icon-class="option.icon" style="margin-right: 5px;" />
</div>
<div>
@ -159,7 +162,7 @@
</el-button>
</el-popover>
<div v-if="false" class="contents">
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
<i :class="option.icon" style="font-weight: bolder;" />
</div>
<div v-else style="margin-right: 5%">
@ -297,6 +300,9 @@ export default {
case this.$t('field.preference'):
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
break
case this.$t('field.logsField'):
component = () => import('@/components/ADempiere/Field/contextMenuField/changeLogs/index')
break
}
return component
},
@ -554,18 +560,21 @@ export default {
name: this.$t('field.info'),
enabled: true,
fieldAttributes: this.fieldAttributes,
svg: false,
icon: 'el-icon-info'
},
{
name: this.$t('table.ProcessActivity.zoomIn'),
enabled: this.isContextInfo,
fieldAttributes: this.fieldAttributes,
svg: false,
icon: 'el-icon-files'
},
{
name: this.$t('language'),
enabled: this.field.isTranslatedField,
fieldAttributes: this.fieldAttributes,
svg: true,
icon: 'language'
},
{
@ -574,6 +583,7 @@ export default {
fieldAttributes: this.fieldAttributes,
recordDataFields: this.recordDataFields,
valueField: this.valueField,
svg: false,
icon: 'el-icon-s-operation'
},
{
@ -581,7 +591,16 @@ export default {
enabled: true,
fieldAttributes: this.fieldAttributes,
valueField: this.valueField,
svg: false,
icon: 'el-icon-notebook-2'
},
{
name: this.$t('field.logsField'),
enabled: true,
fieldAttributes: this.fieldAttributes,
valueField: this.valueField,
svg: true,
icon: 'tree-table'
}
]
},

View File

@ -330,6 +330,7 @@ export default {
info: 'Information',
calculator: 'Calculator',
preference: 'Preference',
logsField: 'Field Change Log',
codeTranslation: 'Translation Of ',
container: {
help: 'Help',

View File

@ -307,6 +307,7 @@ export default {
calculator: 'Calculadora',
preference: 'Preferencia',
codeTranslation: 'Traduccion de ',
logsField: 'Bitácora de Cambios',
container: {
help: 'Ayuda',
description: 'Descripción'

View File

@ -3,6 +3,7 @@ import {
requestListWorkflowsLogs,
requestListWorkflows
} from '@/api/ADempiere/window'
import { isEmptyValue } from '@/utils/ADempiere'
const initStateContainerInfo = {
listworkflowLog: [],
@ -34,6 +35,9 @@ const containerInfo = {
}) {
const pageSize = 0
const pageToken = 0
if (isEmptyValue(tableName) && (isEmptyValue(recordId) || isEmptyValue(recordUuid))) {
return
}
return requestListEntityLogs({
tableName,
recordId,

View File

@ -110,6 +110,9 @@ export default {
case this.$t('field.preference'):
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
break
case this.$t('field.logsField'):
component = () => import('@/components/ADempiere/Field/contextMenuField/changeLogs/index')
break
}
return component
},
@ -355,6 +358,13 @@ export default {
}
},
getRecord(value) {
if (value && this.getTableName && this.recordId && this.isEmptyValue(this.gettersListRecordLogs)) {
this.$store.dispatch('listRecordLogs', {
tableName: this.getTableName,
recordId: this.recordId,
recordUuid: value.UUID
})
}
if (!this.isEmptyValue(this.windowMetadata.currentTab.tableName) && !this.isEmptyValue(value) && (!this.isEmptyValue(this.$route.query) && this.$route.query.typeAction === 'recordAccess')) {
this.$store.commit('setRecordAccess', true)
}