1
0
mirror of https://github.com/PanJiaChen/vue-element-admin.git synced 2025-08-10 20:39:48 +08:00

Add the workflow phases sequence (#346)

* indicate new row

* add focus in field text

* add workflow line

* delete console.log

* width the step

* confi the width

* add width fixed

* add scroll

* minimal  change

* add the vue-resize library to control panel behavior

* change version

* add List Status Document

* process the document status from the workflow line

* change name file

Co-authored-by: Edwin Betancourt <EdwinBetanc0urt@hotmail.com>
This commit is contained in:
elsiosanchez 2020-02-27 19:28:21 -04:00 committed by GitHub
parent 647852f851
commit da08c71f01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 440 additions and 22 deletions

View File

@ -45,7 +45,7 @@
},
"dependencies": {
"@adempiere/grpc-access-client": "^1.1.8",
"@adempiere/grpc-data-client": "^2.1.0",
"@adempiere/grpc-data-client": "^2.1.1",
"@adempiere/grpc-dictionary-client": "^1.3.5",
"@adempiere/grpc-enrollment-client": "^1.0.7",
"autoprefixer": "^9.5.1",
@ -75,6 +75,7 @@
"vue-count-to": "1.0.13",
"vue-i18n": "7.3.2",
"vue-multipane": "^0.9.5",
"vue-resize": "^0.4.5",
"vue-router": "3.0.4",
"vue-shortkey": "^3.1.7",
"vue-split-panel": "^1.0.4",

View File

@ -520,3 +520,24 @@ export function requestListDocumentActions({ tableName, recordId, recordUuid, do
pageToken
})
}
/**
* Request Document Status List
* @param {string} tableName
* @param {number} recordId
* @param {string} recordUuid
* @param {string} documentStatus
* @param {string} documentAction
* @param {number} pageSize
* @param {string} pageToken
*/
export function requestListDocumentStatuses({ tableName, recordId, recordUuid, documentStatus, documentAction, pageSize, pageToken }) {
return Instance.call(this).requestListDocumentStatuses({
tableName,
recordId,
recordUuid,
documentStatus,
documentAction,
pageSize,
pageToken
})
}

View File

@ -22,6 +22,10 @@ export default {
name: 'FieldText',
mixins: [fieldMixin],
props: {
inTable: {
type: Boolean,
default: false
},
pattern: {
type: String,
default: undefined

View File

@ -60,6 +60,7 @@
:class="classField"
:metadata="fieldAttributes"
:value-model="recordDataFields"
:in-table="true"
/>
</template>

View File

@ -315,6 +315,7 @@ export default {
},
created() {
// get fields with uuid
this.$store.dispatch('listWorkflows', this.metadata.tableName)
this.getPanel()
},
methods: {
@ -614,6 +615,10 @@ export default {
return groupsList
},
setTagsViewTitle(actionValue) {
this.$store.dispatch('listDocumentStatus', {
recordUuid: this.$route.query.action,
recordId: this.$route.params.recordId
})
if (actionValue === 'create-new' || this.isEmptyValue(actionValue)) {
this.tagTitle.action = this.$t('tagsView.newRecord')
} else if (actionValue === 'advancedQuery') {

View File

@ -0,0 +1,249 @@
<template>
<el-steps v-if="!isEmptyValue(gettersNodeList)" :active="getActive" finish-status="success" simple :style="styleSteps">
<el-step
v-for="(node, index) in listDocumentStatus"
:key="index"
:icon="index < getActive ? 'el-icon-finished' : ( index === getActive ? 'el-icon-s-flag' : 'el-icon-d-arrow-right')"
>
<template slot="title">
<el-popover
v-if="index === getActive"
placement="top-start"
width="400"
trigger="click"
>
<el-select
v-model="valueActionDocument"
@change="documentActionChange"
@visible-change="listActionDocument"
>
<el-option
v-for="(item, key) in listDocumentActions"
:key="key"
:label="item.name"
:value="item.value"
/>
</el-select>
<el-tag
v-if="isEmptyValue(valueActionDocument)"
:type="tagStatus(getValueStatus)"
>
{{ getValue.displayColumn }}
</el-tag>
<el-tag
v-else
:type="tagStatus(valueActionDocument)"
>
{{ labelDocumentActions }}
</el-tag>
<p v-if="isEmptyValue(descriptionDocumentActions)"> {{ getValue.description }} </p>
<p v-else> {{ descriptionDocumentActions }} </p>
<el-button slot="reference" type="text" :autofocus="true" class="title"> {{ node.name }} </el-button>
</el-popover>
<span v-else> {{ node.name }} </span>
</template>
</el-step>
</el-steps>
</template>
<script>
export default {
name: 'WorkflowStatusBar',
props: {
styleSteps: {
type: Object,
default: () => {}
},
parentUuid: {
type: String,
default: ''
},
containerUuid: {
type: String,
default: ''
},
panelType: {
type: String,
default: 'window'
}
},
data() {
return {
currentKey: 100,
typeAction: 0,
chatNote: '',
documentStatusesList: [],
valueActionDocument: ''
}
},
computed: {
getPanelRight() {
return this.$store.getters.getPanelRight
},
getterPanel() {
return this.$store.getters.getPanel(this.containerUuid)
},
getValueStatus() {
if (!this.isEmptyValue(this.getterPanel)) {
var status = this.getterPanel.fieldList.find(field => {
if (field.columnName === 'DocStatus') {
return field
}
})
return status.value
}
return 'CL'
},
getValue() {
if (!this.isEmptyValue(this.getterPanel)) {
var value = this.getterPanel.fieldList.find(field => {
if (field.columnName === 'DocStatus') {
return field
}
})
return value
}
return 'CL'
},
getActive() {
const active = this.listDocumentStatus.findIndex(index => index.value === this.getValueStatus)
return active
},
gettersNodeList() {
var node = this.$store.getters.getNodeWorkflow
if (!this.isEmptyValue(node.workflowsList)) {
return node.workflowsList[0].workflowNodesList
}
return node.workflowsList
},
listDocumentStatus() {
return this.$store.getters.getListDocumentStatus.documentActionsList
},
typeStatus() {
if (this.getValueStatus === 'VO') {
return 'error'
} else {
return 'success'
}
},
documentActions() {
return this.$store.getters.getListDocumentActions
},
listDocumentActions() {
return this.documentActions.documentActionsList
},
labelDocumentActions() {
const found = this.listDocumentActions.find(element => {
if (element.value === this.valueActionDocument) {
return element
}
})
if (this.isEmptyValue(found)) {
return this.valueActionDocument
}
return found.name
},
descriptionDocumentActions() {
const found = this.listDocumentActions.find(element => {
if (element.value === this.valueActionDocument) {
return element
}
})
if (this.isEmptyValue(found)) {
return this.valueActionDocument
}
return found.description
},
processOrderUuid() {
return this.$store.getters.getOrders
}
},
created() {
this.gettersNodeList
},
methods: {
listActionDocument(isShowList) {
if (isShowList) {
if (!this.withoutRecord && this.$route.query.action !== this.documentActions.recordUuid) {
this.$store.dispatch('listDocumentActionStatus', {
recordUuid: this.$route.query.action,
recordId: this.$route.params.recordId
})
}
}
},
documentActionChange(value) {
this.$store.dispatch('notifyFieldChange', {
parentUuid: this.parentUuid,
containerUuid: this.containerUuid,
columnName: 'DocAction',
isSendToServer: true,
newValue: value
})
.then(response => {
const actionProcess = this.$store.getters.getOrders
this.$store.dispatch('startProcess', {
action: {
uuid: actionProcess.uuid,
id: actionProcess.id,
name: actionProcess.name
}, // process metadata
tableName: this.$route.params.tableName,
recordId: this.$route.params.recordId,
recordUuid: this.$route.query.action,
parametersList: [{
columnName: 'DocStatus',
value: this.valueActionDocument
}],
isActionDocument: true,
parentUuid: this.parentUuid,
panelType: this.panelType,
containerUuid: this.containerUuid// determinate if get table name and record id (window) or selection (browser)
})
this.valueActionDocument = ''
})
}
}
}
</script>
<style scoped>
.el-button--text {
border-color: transparent;
color: #000000;
}
</style>
<style>
.scroll-window-log-change {
max-height: 74vh !important;
}
.el-step.is-simple {
display: -webkit-box;
display: -ms-flexbox;
display: inline-flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 50%;
}
.el-step.is-simple .el-step__main {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: inline-block;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
/* -webkit-box-flex: 1; */
-ms-flex-positive: 1;
-webkit-box-flex: 1;
flex-grow: 1;
width: 15vw;
}
.title {
color: #000000;
text-size-adjust: 20px;
font-size: 100%;
font-weight: 605!important;
}
</style>

View File

@ -7,6 +7,8 @@ import 'normalize.css/normalize.css' // a modern alternative to CSS resets
import Element from 'element-ui'
import './styles/element-variables.scss'
import VueSplit from 'vue-split-panel'
import 'vue-resize/dist/vue-resize.css'
import VueResize from 'vue-resize'
/**
* TODO: Waiting for PR to:
* https://github.com/vue-extend/v-markdown/pull/4
@ -43,6 +45,7 @@ if (process.env.NODE_ENV === 'production') {
}
Vue.use(VMarkdown)
Vue.use(VueSplit)
Vue.use(VueResize)
Vue.use(Element, {
size: Cookies.get('size') || 'medium', // set element-ui default size
i18n: (key, value) => i18n.t(key, value)

View File

@ -17,7 +17,7 @@ const containerInfo = {
state.listworkflowLog = payload
},
addListWorkflows(state, payload) {
state.listworkflows = payload
state.listWorkflows = payload
},
addListRecordLogs(state, payload) {
state.listRecordLogs = payload
@ -124,9 +124,7 @@ const containerInfo = {
const recordId = params.recordId
const pageSize = 0
const pageToken = 0
dispatch('listWorkflows', {
tableName: tableName
})
dispatch('listWorkflows', tableName)
return requestListWorkflowsLogs({ tableName, recordId, pageSize, pageToken })
.then(response => {
var workflowLog = {
@ -140,13 +138,17 @@ const containerInfo = {
console.warn(`Error getting List workflow: ${error.message}. Code: ${error.code}.`)
})
},
listWorkflows({ commit, state }, params) {
const tableName = params.tableName
listWorkflows({ commit, state }, tableName) {
const pageSize = 0
const pageToken = 0
return requestListWorkflows({ tableName, pageSize, pageToken })
.then(response => {
commit('addListWorkflows', response)
var nodeWorflow = {
nextPageToken: response.nextPageToken,
recordCount: response.recordCount,
workflowsList: response.workflowsList
}
commit('addListWorkflows', nodeWorflow)
})
.catch(error => {
console.warn(`Error getting List workflow: ${error.message}. Code: ${error.code}.`)
@ -157,6 +159,9 @@ const containerInfo = {
getWorkflow: (state) => {
return state.listworkflowLog.workflowLogsList
},
getNodeWorkflow: (state) => {
return state.listWorkflows
},
getRecordLogs: (state) => {
return state.listRecordLogs
},

View File

@ -1,5 +1,5 @@
import { recursiveTreeSearch } from '@/utils/ADempiere/valueUtils.js'
import { requestListDocumentActions } from '@/api/ADempiere/data'
import { requestListDocumentActions, requestListDocumentStatuses } from '@/api/ADempiere/data'
// Store used for set all related to context menu
// for Window, Process, Smart Browser andother customized component
@ -17,6 +17,12 @@ import { requestListDocumentActions } from '@/api/ADempiere/data'
const contextMenu = {
state: {
contextMenu: [],
listDocumentStatus: {
defaultDocumentAction: undefined,
documentActionsList: [],
recordId: undefined,
recordUuid: undefined
},
listDocumentAction: {
defaultDocumentAction: undefined,
documentActionsList: [],
@ -33,6 +39,9 @@ const contextMenu = {
},
listDocumentAction(state, payload) {
state.listDocumentAction = payload
},
addlistDocumentStatus(state, payload) {
state.listDocumentStatus = payload
}
},
actions: {
@ -74,6 +83,35 @@ const contextMenu = {
.catch(error => {
console.warn(error)
})
},
listDocumentStatus({ commit }, {
tableName = 'C_Order',
recordId,
recordUuid,
documentAction,
documentStatus
}) {
requestListDocumentStatuses({
tableName,
recordId,
recordUuid,
documentAction,
documentStatus,
pageSize: 0,
pageToken: ''
})
.then(responseDocumentStatus => {
const documentStatus = {
documentActionsList: responseDocumentStatus.documentStatusesList,
recordId,
recordUuid
}
commit('addlistDocumentStatus', documentStatus)
return documentStatus
})
.catch(error => {
console.warn(error)
})
}
},
getters: {
@ -101,6 +139,9 @@ const contextMenu = {
getListDocumentActions: (state) => {
return state.listDocumentAction
},
getListDocumentStatus: (state) => {
return state.listDocumentStatus
},
getListDocumentActionByUuid: (state) => (recordUuid) => {
return state.listDocumentAction.find(itemDocumentAction => itemDocumentAction.recordUuid === recordUuid)
}

View File

@ -28,7 +28,8 @@ const utils = {
query: {},
isReaded: false,
isLoaded: false
}
},
panelRight: ''
},
mutations: {
setWidth(state, width) {
@ -88,6 +89,9 @@ const utils = {
setReadRoute(state, payload) {
Vue.set(state.openRoute, 'definedParameters', payload.parameters)
Vue.set(state.openRoute, 'isLoaded', true)
},
setPanelRight(state, payload) {
state.panelRight = payload
}
},
actions: {
@ -148,6 +152,9 @@ const utils = {
},
setOrder({ commit }, params) {
commit('setOrder', params)
},
setPanelRight({ commit }, panelRight) {
commit('setPanelRight', panelRight)
}
},
getters: {
@ -217,6 +224,9 @@ const utils = {
},
getMarkDown: (state) => {
return state.markDown
},
getPanelRight: (state) => {
return state.panelRight
}
}
}

View File

@ -54,18 +54,31 @@
</div>
</template>
<template slot="paneR">
<el-container style="height: 86vh;">
<el-container id="PanelRight" style="height: 86vh;">
<resize-observer @notify="handleResize" />
<Split v-shortkey="['f8']" direction="vertical" @onDrag="onDrag" @shortkey.native="handleChangeShowedRecordNavigation(!isShowedRecordNavigation)">
<SplitArea :size="sizeAreaStyle" :style="splitAreaStyle">
<el-header style="height: 39px;">
<context-menu
v-show="!isShowedRecordPanel"
:menu-parent-uuid="$route.meta.parentUuid"
:parent-uuid="windowUuid"
:container-uuid="windowMetadata.currentTabUuid"
:panel-type="panelType"
:is-insert-record="getterIsInsertRecord"
/>
<el-header style="height: 50px; background: #F5F7FA">
<el-container>
<el-aside width="100%" style="width: 78vw;overflow: hidden;">
<workflow-status-bar
:style-steps="styleStepsSimple"
:container-uuid="windowMetadata.currentTabUuid"
:parent-uuid="windowUuid"
:panel-type="panelType"
/>
</el-aside>
<el-main>
<context-menu
v-show="!isShowedRecordPanel"
:menu-parent-uuid="$route.meta.parentUuid"
:parent-uuid="windowUuid"
:container-uuid="windowMetadata.currentTabUuid"
:panel-type="panelType"
:is-insert-record="getterIsInsertRecord"
/>
</el-main>
</el-container>
</el-header>
<el-main :style="styleMainTab">
<tab-parent
@ -271,6 +284,9 @@ import splitPane from 'vue-splitpane'
import ChatEntries from '@/components/ADempiere/ContainerInfo/chatEntries'
import RecordLogs from '@/components/ADempiere/ContainerInfo/recordLogs'
import WorkflowLogs from '@/components/ADempiere/ContainerInfo/workflowLogs'
// Workflow
import WorkflowStatusBar from '@/components/ADempiere/WorkflowStatusBar'
export default {
name: 'WindowView',
components: {
@ -282,7 +298,14 @@ export default {
ModalDialog,
ChatEntries,
RecordLogs,
WorkflowLogs
WorkflowLogs,
WorkflowStatusBar
},
props: {
styleSteps: {
type: Object,
default: () => {}
}
},
data() {
return {
@ -393,13 +416,40 @@ export default {
splitAreaStyle() {
if (this.isShowedTabsChildren || this.isMobile) {
return {
overflow: 'auto'
overflowX: 'hidden',
overflowY: 'auto'
}
}
return {
overflow: 'hidden'
}
},
styleStepsSimple() {
if (this.isShowedRecordNavigation) {
return {
paddingTop: '0px',
paddingBottom: '0px',
paddingLeft: '0px',
paddingRight: '0px',
borderRadius: '4px',
background: '#F5F7FA',
overflowX: 'auto',
overflowY: 'hidden',
width: this.$store.getters.getPanelRight + 'px'
}
}
return {
paddingTop: '0px',
paddingBottom: '0px',
paddingLeft: '0px',
paddingRight: '0px',
borderRadius: '4px',
background: '#F5F7FA',
overflowX: 'auto',
overflowY: 'hidden',
width: 'auto'
}
},
sizeAreaStyle() {
if (this.isShowedTabsChildren) {
return 50
@ -494,13 +544,25 @@ export default {
},
created() {
this.getWindow()
if (this.isShowedRecordNavigation) {
this.handleResize()
}
},
methods: {
handleResize() {
var PanelRight = document.getElementById('PanelRight')
var resizeWidth = PanelRight
if (!this.isEmptyValue(resizeWidth)) {
var widthPanel = PanelRight.clientWidth - 350
this.$store.dispatch('setPanelRight', widthPanel)
}
},
conteInfo() {
this.showContainerInfo = !this.showContainerInfo
if (this.showContainerInfo) {
this.$store.dispatch('listWorkflowLogs', {
tableName: this.getTableName,
recordUuid: this.$route.query.action,
recordId: this.getRecord[this.getTableName + '_ID']
})
this.$store.dispatch(this.activeInfo, {
@ -762,6 +824,22 @@ export default {
}
</style>
<style>
.el-step.is-simple .el-step__icon-inner {
font-size: 18px;
padding-top: 30px;
}
.el-steps--simple {
/* padding: 13px 8%; */
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0%;
padding-right: 0px;
border-radius: 4px;
background: #F5F7FA;
overflow-x: auto;
overflow-y: hidden;
width: auto;
}
.scroll-window-log-change {
max-height: 74vh !important;
}