mirror of
https://github.com/PanJiaChen/vue-element-admin.git
synced 2025-08-10 12:01:57 +08:00
Support workflow activities (#972)
* support workflow activities * minimal changes * add Workflows and services * add state semantics * rename fille * add info the node Co-authored-by: elsiosanchez <elsiossanches@gmail.com>
This commit is contained in:
parent
4364c01262
commit
ebd568cfb6
@ -66,6 +66,7 @@
|
|||||||
"vue-shortkey": "^3.1.7",
|
"vue-shortkey": "^3.1.7",
|
||||||
"vue-split-panel": "^1.0.4",
|
"vue-split-panel": "^1.0.4",
|
||||||
"vue-splitpane": "1.0.6",
|
"vue-splitpane": "1.0.6",
|
||||||
|
"vue-workflow-chart": "^0.4.5",
|
||||||
"vuedraggable": "2.24.3",
|
"vuedraggable": "2.24.3",
|
||||||
"vuex": "3.6.2",
|
"vuex": "3.6.2",
|
||||||
"xlsx": "0.16.9"
|
"xlsx": "0.16.9"
|
||||||
|
56
src/api/ADempiere/form/workflow-activity.js
Normal file
56
src/api/ADempiere/form/workflow-activity.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// ADempiere-Vue (Frontend) for ADempiere ERP & CRM Smart Business Solution
|
||||||
|
// Copyright (C) 2017-Present E.R.P. Consultores y Asociados, C.A.
|
||||||
|
// Contributor(s): Yamel Senih ysenih@erpya.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/>.
|
||||||
|
|
||||||
|
// Get Instance for connectionimport {
|
||||||
|
import { request } from '@/utils/ADempiere/request'
|
||||||
|
|
||||||
|
// List Activity
|
||||||
|
export function listActivity({
|
||||||
|
formUuid
|
||||||
|
}) {
|
||||||
|
return request({
|
||||||
|
url: '/form/addons/activitys',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
form_uuid: formUuid
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(listActivityResponse => {
|
||||||
|
return listActivityResponse
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send Activity
|
||||||
|
export function sendActivity({
|
||||||
|
formUuid,
|
||||||
|
activity,
|
||||||
|
message,
|
||||||
|
forward
|
||||||
|
}) {
|
||||||
|
return request({
|
||||||
|
url: '/form/addons/send-activity',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
form_uuid: formUuid,
|
||||||
|
activity,
|
||||||
|
message,
|
||||||
|
forward
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(listActivityResponse => {
|
||||||
|
return listActivityResponse
|
||||||
|
})
|
||||||
|
}
|
@ -92,3 +92,28 @@ export function requestListDocumentActions({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request a list of Activities from the user's Workflows
|
||||||
|
export function workflowActivities({
|
||||||
|
userUuid,
|
||||||
|
pageSize,
|
||||||
|
pageToken
|
||||||
|
}) {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/workflow-activities',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
user_uuid: userUuid,
|
||||||
|
// Page Data
|
||||||
|
pageToken,
|
||||||
|
pageSize
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(listWorkflowActivities => {
|
||||||
|
return {
|
||||||
|
nextPageToken: listWorkflowActivities.next_page_token,
|
||||||
|
recordCount: listWorkflowActivities.record_count,
|
||||||
|
listWorkflowActivities: listWorkflowActivities.records
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
76
src/components/ADempiere/Form/WorkflowActivity/fieldsList.js
Normal file
76
src/components/ADempiere/Form/WorkflowActivity/fieldsList.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
// List of fields to send in search
|
||||||
|
// import language from '@/lang'
|
||||||
|
import language from '@/lang'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
// History
|
||||||
|
{
|
||||||
|
elementColumnName: 'History',
|
||||||
|
isFromDictionary: true,
|
||||||
|
overwriteDefinition: {
|
||||||
|
handleFocusGained: true,
|
||||||
|
handleFocusLost: true,
|
||||||
|
handleKeyPressed: true,
|
||||||
|
handleKeyReleased: true,
|
||||||
|
handleActionKeyPerformed: true,
|
||||||
|
handleActionPerformed: true,
|
||||||
|
name: language.t('form.activity.filtersSearch.history'),
|
||||||
|
componentPath: 'FieldText',
|
||||||
|
size: 24,
|
||||||
|
sequence: 4,
|
||||||
|
isActiveLogics: true,
|
||||||
|
isMandatory: true,
|
||||||
|
isReadOnly: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Messages
|
||||||
|
{
|
||||||
|
elementColumnName: 'TextMsg',
|
||||||
|
isFromDictionary: true,
|
||||||
|
overwriteDefinition: {
|
||||||
|
handleFocusGained: true,
|
||||||
|
handleFocusLost: true,
|
||||||
|
handleKeyPressed: true,
|
||||||
|
handleKeyReleased: true,
|
||||||
|
handleActionKeyPerformed: true,
|
||||||
|
handleActionPerformed: true,
|
||||||
|
size: 24,
|
||||||
|
sequence: 5,
|
||||||
|
isActiveLogics: true,
|
||||||
|
isMandatory: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Forward
|
||||||
|
{
|
||||||
|
elementColumnName: 'Forward',
|
||||||
|
isFromDictionary: true,
|
||||||
|
overwriteDefinition: {
|
||||||
|
size: 24,
|
||||||
|
sequence: 6,
|
||||||
|
name: language.t('form.activity.filtersSearch.forward'),
|
||||||
|
handleFocusGained: true,
|
||||||
|
handleFocusLost: true,
|
||||||
|
handleKeyPressed: true,
|
||||||
|
handleKeyReleased: true,
|
||||||
|
handleActionKeyPerformed: true,
|
||||||
|
handleActionPerformed: true,
|
||||||
|
componentPath: 'FieldSelect'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
384
src/components/ADempiere/Form/WorkflowActivity/index.vue
Normal file
384
src/components/ADempiere/Form/WorkflowActivity/index.vue
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
<!--
|
||||||
|
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 esanchez@erpya.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-container style="height: 100% !important;">
|
||||||
|
<el-header class="header" :style="!collapse ? 'height: 35% !important;' : 'height: 10%!important'">
|
||||||
|
<el-card :style="!collapse ? 'height: 100% !important;' : 'height: auto'">
|
||||||
|
<div slot="header">
|
||||||
|
<span> {{ $t('form.activity.title') }} </span>
|
||||||
|
<el-button style="float: right; padding: 3px 0" type="text" :icon="collapse ? 'el-icon-arrow-down' : 'el-icon-arrow-up'" @click="collapse = !collapse" />
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-show="!collapse"
|
||||||
|
ref="WorkflowActivity"
|
||||||
|
v-loading="isEmptyValue(activityList)"
|
||||||
|
:data="activityList"
|
||||||
|
highlight-current-row
|
||||||
|
style="width: 100%;height: 85% !important;"
|
||||||
|
border
|
||||||
|
height="90% !important"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(valueOrder) in orderLineDefinition"
|
||||||
|
:key="valueOrder.columnName"
|
||||||
|
:column-key="valueOrder.columnName"
|
||||||
|
:label="valueOrder.name"
|
||||||
|
:align="valueOrder.isNumeric ? 'right' : 'left'"
|
||||||
|
:prop="valueOrder.columnName"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="main">
|
||||||
|
<transition name="el-zoom-in-center">
|
||||||
|
<el-card v-show="show" :style="{position: 'absolute', zIndex: '5', left: leftContextualMenu + 'px', top: topContextualMenu + 'px'}" class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>
|
||||||
|
<b> {{ infoNode.name }} </b>
|
||||||
|
</span>
|
||||||
|
<el-button style="float: right; padding: 3px 0" type="text" icon="el-icon-close" @click="show = !show" />
|
||||||
|
</div>
|
||||||
|
<div class="text item" style="padding: 20px">
|
||||||
|
<el-timeline class="info">
|
||||||
|
<el-timeline-item :timestamp="currentWorkflow.created" placement="top">
|
||||||
|
<el-card style="padding: 20px!important;">
|
||||||
|
<b> Usuario: </b> {{ currentWorkflow.user_name }} <br>
|
||||||
|
<b> {{ $t('table.ProcessActivity.Description') }}: </b> {{ infoNode.description }}
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</transition>
|
||||||
|
<workflow-chart
|
||||||
|
v-if="!isEmptyValue(node) && !isEmptyValue(currentWorkflow)"
|
||||||
|
:transitions="listWorkflowTransition"
|
||||||
|
:states="node"
|
||||||
|
:state-semantics="currentNode"
|
||||||
|
@state-click="onLabelClicked(node, $event)"
|
||||||
|
/>
|
||||||
|
<el-scrollbar v-if="!isEmptyValue(currentWorkflow)" wrap-class="scroll-child">
|
||||||
|
<el-timeline class="info">
|
||||||
|
<el-timeline-item
|
||||||
|
v-for="(nodes, key) in currentWorkflow.workflow_process.workflow_events"
|
||||||
|
:key="key"
|
||||||
|
:timestamp="translateDate(nodes.log_date)"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<b> {{ nodes.node_name }} </b> {{ nodes.text_message }}
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-main>
|
||||||
|
<el-footer :class="styleFooter">
|
||||||
|
<el-card shadow="hover" class="search">
|
||||||
|
<el-form v-if="!isEmptyValue(fieldsList)" :disabled="isEmptyValue(currentActivity)" label-position="top" class="from-main">
|
||||||
|
<el-form-item>
|
||||||
|
<el-row>
|
||||||
|
<el-col v-for="(field, index) in fieldsList" :key="index" :span="6">
|
||||||
|
<field
|
||||||
|
:key="field.columnName"
|
||||||
|
:metadata-field="field"
|
||||||
|
:v-model="field.value"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-button type="primary" icon="el-icon-check" style="float: right;" :disabled="isEmptyValue(currentActivity)" />
|
||||||
|
</el-card>
|
||||||
|
</el-footer>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import formMixin from '@/components/ADempiere/Form/formMixin.js'
|
||||||
|
import fieldsList from './fieldsList.js'
|
||||||
|
import WorkflowChart from 'vue-workflow-chart'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WorkflowActivity',
|
||||||
|
components: {
|
||||||
|
WorkflowChart
|
||||||
|
},
|
||||||
|
mixins: [
|
||||||
|
formMixin
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
metadata: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
uuid: 'WF-Activity',
|
||||||
|
containerUuid: 'WF-Activity',
|
||||||
|
fieldsList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fieldsList,
|
||||||
|
node: [],
|
||||||
|
transitions: [],
|
||||||
|
topContextualMenu: 0,
|
||||||
|
leftContextualMenu: 0,
|
||||||
|
infoNode: {},
|
||||||
|
show: false,
|
||||||
|
collapse: false,
|
||||||
|
currentNode: [{
|
||||||
|
classname: 'delete',
|
||||||
|
id: ''
|
||||||
|
}],
|
||||||
|
currentWorkflow: {},
|
||||||
|
listWorkflowTransition: [],
|
||||||
|
orderLineDefinition: [
|
||||||
|
{
|
||||||
|
columnName: 'workflow.name',
|
||||||
|
name: 'Nombre',
|
||||||
|
isNumeric: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnName: 'node.name',
|
||||||
|
name: this.$t('form.activity.table.node'),
|
||||||
|
isNumeric: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnName: 'node.description',
|
||||||
|
name: 'Descripcion',
|
||||||
|
isNumeric: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
styleFooter() {
|
||||||
|
const showTitle = this.$store.getters.getIsShowTitleForm
|
||||||
|
if (showTitle) {
|
||||||
|
return 'show-title-footer'
|
||||||
|
}
|
||||||
|
return 'footer'
|
||||||
|
},
|
||||||
|
activityList() {
|
||||||
|
const list = this.$store.getters.getActivity
|
||||||
|
if (!this.isEmptyValue(list)) {
|
||||||
|
return list.filter(activity => !this.isEmptyValue(activity.uuid))
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
currentActivity() {
|
||||||
|
return this.$store.getters.getCurrentActivity
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$store.dispatch('serverListActivity')
|
||||||
|
if (!this.isEmptyValue(this.currentActivity)) {
|
||||||
|
this.setCurrent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setCurrent() {
|
||||||
|
const activity = this.activityList.find(activity => activity.node === this.currentActivity.node)
|
||||||
|
this.$refs.WorkflowActivity.setCurrentRow(activity)
|
||||||
|
},
|
||||||
|
handleCurrentChange(activity) {
|
||||||
|
this.listWorkflow(activity)
|
||||||
|
this.$store.dispatch('selectedActivity', activity)
|
||||||
|
},
|
||||||
|
onLabelClicked(type, id) {
|
||||||
|
this.infoNode = type.find(node => node.id === id)
|
||||||
|
const menuMinWidth = 105
|
||||||
|
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
|
||||||
|
const offsetWidth = this.$el.offsetWidth // container width
|
||||||
|
const maxLeft = offsetWidth - menuMinWidth // left boundary
|
||||||
|
const left = event.clientX - offsetLeft + 15 // 15: margin right
|
||||||
|
|
||||||
|
this.leftContextualMenu = left
|
||||||
|
if (left > maxLeft) {
|
||||||
|
this.leftContextualMenu = maxLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
const offsetTop = this.$el.getBoundingClientRect().top
|
||||||
|
let top = event.clientY - offsetTop
|
||||||
|
if (this.panelType === 'browser' && this.panelMetadata.isShowedCriteria) {
|
||||||
|
top = event.clientY - 200
|
||||||
|
}
|
||||||
|
this.topContextualMenu = top
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
listWorkflow(activity) {
|
||||||
|
// Highlight Current Node
|
||||||
|
this.currentWorkflow = activity
|
||||||
|
this.transitions = []
|
||||||
|
if (!this.isEmptyValue(activity.node.uuid)) {
|
||||||
|
this.currentNode = [{
|
||||||
|
classname: 'delete',
|
||||||
|
id: activity.node.uuid
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
const nodes = activity.workflow.workflow_nodes.filter(node => !this.isEmptyValue(node.uuid))
|
||||||
|
this.listNodeTransitions(nodes)
|
||||||
|
if (!this.isEmptyValue(nodes)) {
|
||||||
|
this.node = nodes.map((workflow, key) => {
|
||||||
|
return {
|
||||||
|
...workflow,
|
||||||
|
transitions: workflow.transitions,
|
||||||
|
id: workflow.uuid,
|
||||||
|
key,
|
||||||
|
label: workflow.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.node = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listNodeTransitions(nodes) {
|
||||||
|
nodes.forEach(element => {
|
||||||
|
const uuid = element.uuid
|
||||||
|
const id = element.value
|
||||||
|
if (!this.isEmptyValue(element.transitions)) {
|
||||||
|
element.transitions.forEach((nextNode, key) => {
|
||||||
|
if (!this.isEmptyValue(nextNode.node_next_uuid)) {
|
||||||
|
if (this.isEmptyValue(nextNode.description)) {
|
||||||
|
this.transitions.push({
|
||||||
|
id: id + key,
|
||||||
|
target: uuid,
|
||||||
|
source: nextNode.node_next_uuid
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.transitions.push({
|
||||||
|
id: id + key,
|
||||||
|
label: nextNode.description,
|
||||||
|
target: uuid,
|
||||||
|
source: nextNode.node_next_uuid
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const blon = nodes.map(item => {
|
||||||
|
return {
|
||||||
|
uuid: item.uuid
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.listWorkflowTransition = this.transitions.filter(data => {
|
||||||
|
const verificar = blon.find(mode => mode.uuid === data.source)
|
||||||
|
if (!this.isEmptyValue(verificar)) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
translateDate(value) {
|
||||||
|
return this.$d(new Date(value), 'long', this.language)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.from-main {
|
||||||
|
padding-right: 1% !important;
|
||||||
|
padding-bottom: 0px !important;
|
||||||
|
padding-top: 0px !important;
|
||||||
|
padding-left: 1% !important;
|
||||||
|
}
|
||||||
|
.card-form {
|
||||||
|
height: 100% !important;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
padding-bottom: 2%;
|
||||||
|
padding-top: 1.5%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding-left: 1%;
|
||||||
|
padding-right: 1%;
|
||||||
|
}
|
||||||
|
.from-footer {
|
||||||
|
height: 5% !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
padding-top: 0px;
|
||||||
|
height: 10% !important;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
padding-bottom: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.show-title-footer {
|
||||||
|
padding-top: 0px;
|
||||||
|
height: 8% !important;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style scoped>
|
||||||
|
.info {
|
||||||
|
margin: 0px;
|
||||||
|
font-size: 14px;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.vue-workflow-chart-state {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #11353d;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: Open Sans;
|
||||||
|
/* font-weight: 600; */
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
max-width: 15%;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-box-shadow: 0 2px 4px 0 rgb(0 0 0 / 20%);
|
||||||
|
box-shadow: 0 2px 4px 0 rgb(0 0 0 / 20%);
|
||||||
|
}
|
||||||
|
.panel_main {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang='scss'>
|
||||||
|
.el-card {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #e6ebf5;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #303133;
|
||||||
|
-webkit-transition: 0.3s;
|
||||||
|
transition: 0.3s;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
@import '~vue-workflow-chart/dist/vue-workflow-chart.css';
|
||||||
|
.vue-workflow-chart-state-delete {
|
||||||
|
color: white;
|
||||||
|
background: #AED5FE;
|
||||||
|
}
|
||||||
|
.vue-workflow-chart-transition-arrow-delete {
|
||||||
|
fill: #AED5FE;
|
||||||
|
}
|
||||||
|
.vue-workflow-chart-transition-path-delete {
|
||||||
|
stroke: #AED5FE;
|
||||||
|
}
|
||||||
|
</style>
|
@ -54,6 +54,9 @@ export default {
|
|||||||
case 'ProductInfo':
|
case 'ProductInfo':
|
||||||
form = import('@/components/ADempiere/Form/ProductInfo')
|
form = import('@/components/ADempiere/Form/ProductInfo')
|
||||||
break
|
break
|
||||||
|
case 'WFActivity':
|
||||||
|
form = import('@/components/ADempiere/Form/WorkflowActivity')
|
||||||
|
break
|
||||||
case 'VPOS':
|
case 'VPOS':
|
||||||
form = import('@/components/ADempiere/Form/VPOS')
|
form = import('@/components/ADempiere/Form/VPOS')
|
||||||
break
|
break
|
||||||
|
@ -556,6 +556,17 @@ export default {
|
|||||||
toolsPoint: {
|
toolsPoint: {
|
||||||
title: 'Point of Sale Tools'
|
title: 'Point of Sale Tools'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
activity: {
|
||||||
|
title: 'Your Workflow Activities',
|
||||||
|
filtersSearch: {
|
||||||
|
history: 'History records',
|
||||||
|
forward: 'Re-send'
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
priority: 'Priority',
|
||||||
|
node: 'Node'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,6 +531,17 @@ export default {
|
|||||||
toolsPoint: {
|
toolsPoint: {
|
||||||
title: 'Herramientas del Punto de Venta'
|
title: 'Herramientas del Punto de Venta'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
activity: {
|
||||||
|
title: 'Sus Actividades de Flujo de Trabajo',
|
||||||
|
filtersSearch: {
|
||||||
|
history: 'Registros históricos',
|
||||||
|
forward: 'Re-enviar'
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
priority: 'Prioridad',
|
||||||
|
node: 'Nodo'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包
|
|||||||
import VueSplit from 'vue-split-panel'
|
import VueSplit from 'vue-split-panel'
|
||||||
import 'vue-resize/dist/vue-resize.css'
|
import 'vue-resize/dist/vue-resize.css'
|
||||||
import VueResize from 'vue-resize'
|
import VueResize from 'vue-resize'
|
||||||
|
import WorkflowChart from 'vue-workflow-chart'
|
||||||
/**
|
/**
|
||||||
* TODO: Waiting for PR to:
|
* TODO: Waiting for PR to:
|
||||||
* https://github.com/vue-extend/v-markdown/pull/4
|
* https://github.com/vue-extend/v-markdown/pull/4
|
||||||
@ -53,6 +54,7 @@ Vue.use(VMarkdown)
|
|||||||
Vue.use(VueShortkey)
|
Vue.use(VueShortkey)
|
||||||
Vue.use(VueSplit)
|
Vue.use(VueSplit)
|
||||||
Vue.use(VueResize)
|
Vue.use(VueResize)
|
||||||
|
Vue.use(WorkflowChart)
|
||||||
Vue.use(Element, {
|
Vue.use(Element, {
|
||||||
size: Cookies.get('size') || 'medium', // set element-ui default size
|
size: Cookies.get('size') || 'medium', // set element-ui default size
|
||||||
i18n: (key, value) => i18n.t(key, value),
|
i18n: (key, value) => i18n.t(key, value),
|
||||||
|
51
src/store/modules/ADempiere/WorkflowActivity.js
Normal file
51
src/store/modules/ADempiere/WorkflowActivity.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
workflowActivities
|
||||||
|
} from '@/api/ADempiere/workflow.js'
|
||||||
|
import { showMessage } from '@/utils/ADempiere/notification.js'
|
||||||
|
|
||||||
|
const activity = {
|
||||||
|
listActivity: [],
|
||||||
|
currentActivity: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
state: activity,
|
||||||
|
mutations: {
|
||||||
|
setActivity(state, activity) {
|
||||||
|
state.listActivity = activity
|
||||||
|
},
|
||||||
|
setCurrentActivity(state, activity) {
|
||||||
|
state.currentActivity = activity
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
serverListActivity({ commit, getters, rootGetters }) {
|
||||||
|
workflowActivities({
|
||||||
|
userUuid: rootGetters['user/getUserUuid']
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
const { listWorkflowActivities } = response
|
||||||
|
commit('setActivity', listWorkflowActivities)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.warn(`serverListActivity: ${error.message}. Code: ${error.code}.`)
|
||||||
|
showMessage({
|
||||||
|
type: 'error',
|
||||||
|
message: error.message,
|
||||||
|
showClose: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selectedActivity({ commit }, activity) {
|
||||||
|
commit('setCurrentActivity', activity)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
getCurrentActivity: (state) => {
|
||||||
|
return state.currentActivity
|
||||||
|
},
|
||||||
|
getActivity: (state) => {
|
||||||
|
return state.listActivity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user