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

fix: Relations in context menu. (#545)

* fix: Relations in context menu.

* fix comments.

Co-authored-by: EdwinBetanc0urt <EdwinBetanco0urt@outlook.com>
This commit is contained in:
Edwin Betancourt 2020-11-23 10:17:02 -04:00 committed by GitHub
parent d55dbb1bab
commit d6f52a70e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 161 additions and 90 deletions

View File

@ -11,18 +11,20 @@
unique-opened
@shortkey.native="actionContextMenu"
>
<el-submenu v-if="!isEmptyValue(relationsList)" class="el-menu-item" index="1">
<!-- menu relations -->
<el-submenu v-if="!isEmptyChilds" class="el-menu-item" index="1">
<template slot="title">
{{ $t('components.contextMenuRelations') }}
</template>
<el-scrollbar wrap-class="scroll">
<item v-for="(relation, index) in relationsList" :key="index" :item="relation" />
<items-relations v-for="(relation, index) in relationsList" :key="index" :item="relation" />
</el-scrollbar>
</el-submenu>
<el-menu-item v-else disabled index="relations">
{{ $t('components.contextMenuRelations') }}
</el-menu-item>
<!-- actions or process on container -->
<el-submenu v-if="!isEmptyValue(actions)" class="el-menu-item" index="actions" @click.native="runAction(actions[0])">
<template slot="title">
{{ $t('components.contextMenuActions') }}
@ -100,6 +102,7 @@
{{ $t('components.contextMenuActions') }}
</el-menu-item>
<!-- references of record -->
<el-submenu
:disabled="!(isReferecesContent && isLoadedReferences)"
class="el-menu-item"

View File

@ -1,13 +1,17 @@
import { showNotification } from '@/utils/ADempiere/notification.js'
import Item from './items'
import ItemsRelations from './itemsRelations'
import { convertFieldsListToShareLink, recursiveTreeSearch } from '@/utils/ADempiere/valueUtils.js'
import { supportedTypes, exportFileFromJson } from '@/utils/ADempiere/exportUtil.js'
import ROUTES from '@/utils/ADempiere/zoomWindow'
import relationsMixin from './relationsMixin.js'
export default {
name: 'MixinContextMenu',
mixins: [
relationsMixin
],
components: {
Item
ItemsRelations
},
props: {
menuParentUuid: {
@ -94,17 +98,6 @@ export default {
}
return []
},
relationsList() {
let menuUuid = this.$route.params.menuParentUuid
if (this.isEmptyValue(menuUuid)) {
menuUuid = this.menuParentUuid
}
const relations = this.$store.getters.getRelations(menuUuid)
if (relations) {
return relations.children
}
return []
},
permissionRoutes() {
return this.$store.getters.permission_routes
},

View File

@ -13,18 +13,23 @@
unique-opened
style="width: 258px; float: right;"
>
<el-submenu index="relations">
<!-- menu relations -->
<el-submenu v-if="!isEmptyChilds" index="relations">
<template slot="title">
<svg-icon icon-class="tree" />
{{ $t('components.contextMenuRelations') }}
</template>
<el-menu-item-group>
<el-scrollbar wrap-class="scroll">
<item v-for="(relation, index) in relationsList" :key="index" :item="relation" />
<items-relations v-for="(relation, index) in relationsList" :key="index" :item="relation" />
</el-scrollbar>
</el-menu-item-group>
</el-submenu>
<el-menu-item v-else disabled index="relations">
{{ $t('components.contextMenuRelations') }}
</el-menu-item>
<!-- actions or process on container -->
<el-submenu index="actions">
<template slot="title">
<svg-icon icon-class="link" />
@ -93,6 +98,7 @@
</el-menu-item-group>
</el-submenu>
<!-- references of record -->
<el-submenu :disabled="!(isReferecesContent && isLoadedReferences)" class="el-menu-item" index="references">
<template slot="title">
{{ $t('components.contextMenuReferences') }}

View File

@ -1,4 +1,5 @@
<template>
<!-- summary elememts view -->
<el-submenu
v-if="item.meta.type === 'summary'"
key="is-summary"
@ -9,10 +10,18 @@
<svg-icon v-if="isMobile" icon-class="nested" />
{{ item.meta.title }}
</template>
<item v-for="(child, subKey) in item.children" :key="subKey" :item="child">
{{ child.meta.title }}
</item>
<el-scrollbar wrap-class="scroll-child">
<el-menu-item
v-for="(child, subKey) in getChilds(item)"
:key="subKey"
:index="child.meta.uuid"
>
{{ child.meta.title }}
</el-menu-item>
</el-scrollbar>
</el-submenu>
<!-- item menu views -->
<el-menu-item
v-else
v-show="item.meta.uuid !== $route.meta.uuid"
@ -29,7 +38,7 @@
import { icon } from '@/components/ADempiere/ContextMenu/icon'
export default {
name: 'Item',
name: 'ItemsContextMenu',
props: {
item: {
type: Object,
@ -55,6 +64,15 @@ export default {
tabParent: 0
}
}, () => {})
},
getChilds(item) {
if (!this.isEmptyValue(item.children)) {
return item.children
}
if (item.meta && !this.isEmptyValue(item.meta.childs)) {
return item.meta.childs
}
return []
}
}
}

View File

@ -0,0 +1,44 @@
export default {
name: 'RelationsMixin',
computed: {
relationsList() {
let menuUuid = this.$route.params.menuParentUuid
if (this.isEmptyValue(menuUuid)) {
menuUuid = this.menuParentUuid
}
const relations = this.$store.getters.getRelations(menuUuid)
if (!this.isEmptyValue(relations.children)) {
return relations.children
}
if (relations.meta && !this.isEmptyValue(relations.meta.childs)) {
return relations.meta.childs
}
return []
},
isEmptyChilds() {
const childs = this.relationsList
const len = childs.length
if (len < 1) {
return true
}
if (len === 1) {
// diferent to current view
return childs[0].meta.uuid === this.$route.meta.uuid
}
return false
}
},
methods: {
getChilds(item) {
if (!this.isEmptyValue(item.children)) {
return item.children
}
if (item.meta && !this.isEmptyValue(item.meta.childs)) {
return item.meta.childs
}
return []
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<el-col v-if="items.children" key="is-desktop-dropdown" :span="24">
<el-col v-if="!isEmptyValue(items.children)" key="is-desktop-dropdown" :span="24">
<el-collapse v-model="activeNames">
<el-collapse-item :title="title" name="1" class="collapse-item">
<el-row justify="space-around">
@ -46,7 +46,7 @@
<script>
export default {
name: 'Dropdown',
name: 'DropdownMenu',
props: {
items: {
type: Object,

View File

@ -4,7 +4,13 @@ import staticRoutes from '@/router/modules/ADempiere/staticRoutes.js'
/* Layout */
import Layout from '@/layout'
// Get Menu from server
/**
* Get Menu from server
* @author Edwin Betancourt <EdwinBetanc0urt@outlook.com>
* @param {string} sessionUuid
* @param {string} roleUuid
* @param {string} organizationUuid
*/
export function loadMainMenu({
sessionUuid,
roleUuid = 0,
@ -32,7 +38,6 @@ export function loadMainMenu({
organizationUuid
})
optionMenu.children.push(childsSumaryConverted)
optionMenu.children[0].meta.childs.push(childsSumaryConverted)
optionMenu.meta.childs.push(childsSumaryConverted)
})
} else {
@ -58,15 +63,16 @@ export function loadMainMenu({
/**
* Get Only Child
* @author Edwin Betancourt <EdwinBetanc0urt@outlook.com>
* @param {object} menu
* @param {number} index
* @param {number} roleUuid
* @param {number} organizationUuid
* @param {string} roleUuid
* @param {string} organizationUuid
*/
function getChildFromAction({ menu, index, roleUuid, organizationUuid }) {
const { component, icon, name, isIndex } = convertAction(menu.action)
const routeIdentifier = name + '/' + menu.id
const { component, icon, name: type } = convertAction(menu.action)
const routeIdentifier = type + '/' + menu.id
const isIndex = menu.is_summary
const option = {
path: '/' + roleUuid + '/' + organizationUuid + '/' + routeIdentifier,
component,
@ -85,14 +91,14 @@ function getChildFromAction({ menu, index, roleUuid, organizationUuid }) {
referenceUuid: menu.reference_uuid,
tabUuid: '',
title: menu.name,
type: name,
type,
uuid: menu.reference_uuid,
childs: []
}
},
children: []
}
if (isIndex || name === 'summary') {
option['children'] = []
if (isIndex) {
menu.childs.forEach(child => {
const menuConverted = getChildFromAction({
menu: child,
@ -111,50 +117,34 @@ function getChildFromAction({ menu, index, roleUuid, organizationUuid }) {
/**
* Convert menu item from server to Route
* @author elsiosanchez <elsiosanches@gmail.com>
* @author Edwin Betancourt <EdwinBetanc0urt@outlook.com>
* @param {object} menu
* @param {number} roleUuid
* @param {number} organizationUuid
* @param {string} roleUuid
* @param {string} organizationUuid
*/
function getRouteFromMenuItem({ menu, roleUuid, organizationUuid }) {
const { component, icon, name, isIndex } = convertAction(menu.action)
// use component of convertAction
const { icon, name: type } = convertAction(menu.action)
const isIndex = menu.is_summary
const optionMenu = {
path: '/' + roleUuid + '/' + organizationUuid + '/' + menu.id,
redirect: '/' + menu.id + '/index',
redirect: '/' + menu.id,
component: Layout,
name: menu.uuid,
meta: {
description: menu.description,
icon,
isIndex,
isReadOnly: menu.is_read_only,
isSummary: menu.is_summary,
isSalesTransaction: menu.is_sales_transaction,
noCache: true,
referenceUuid: menu.reference_uuid,
title: menu.name,
type: name,
type,
childs: []
},
children: [{
path: 'index',
component,
name: menu.uuid + '-index',
hidden: true,
meta: {
breadcrumb: false,
description: menu.description,
icon,
isIndex,
isReadOnly: menu.is_read_only,
isSalesTransaction: menu.is_sales_transaction,
noCache: true,
parentUuid: menu.uuid,
referenceUuid: menu.reference_uuid,
title: menu.name,
type: name,
childs: []
}
}]
children: []
}
return optionMenu
}

View File

@ -145,12 +145,12 @@ const contextMenu = {
getContextMenu: (state) => (containerUuid) => {
return state.contextMenu.find(item => item.containerUuid === containerUuid)
},
getRelations: (state, getters, rootState, rootGetters) => (containerUuid) => {
getRelations: (state, getters, rootState, rootGetters) => (containerOrMenuUuid) => {
const dataTree = rootGetters.permission_routes
return recursiveTreeSearch({
treeData: dataTree,
attributeName: 'name',
attributeValue: containerUuid,
attributeValue: containerOrMenuUuid,
attributeChilds: 'children'
})
},

View File

@ -24,30 +24,25 @@ const mutations = {
}
const actions = {
generateRoutes({ commit, rootGetters }, organizationId = 0) {
generateRoutes({ commit, rootGetters }) {
return new Promise(resolve => {
const organization = rootGetters['user/getOrganization']
let organizationUuid
if (!isEmptyValue(organization)) {
organizationId = organization.id
organizationUuid = organization.uuid
}
const role = rootGetters['user/getRole']
let roleUuid
let clientId = 0
if (!isEmptyValue(role)) {
roleUuid = role.uuid
clientId = role.clientId
}
const sessionUuid = getToken()
loadMainMenu({
sessionUuid,
clientId,
roleUuid,
organizationId,
organizationUuid
}).then(menuResponse => {
commit('SET_ROUTES', menuResponse)
@ -55,7 +50,7 @@ const actions = {
})
})
},
sendRequestMenu({ commit, dispatch }, organizationId = null) {
sendRequestMenu({ commit, dispatch }) {
commit('clearTimeOutMenu')
const timeOutMenu = setTimeout(async() => {
NProgress
@ -66,7 +61,7 @@ const actions = {
.start()
resetRouter()
dispatch('generateRoutes', organizationId)
dispatch('generateRoutes')
.then(accessRoutes => {
router.addRoutes(accessRoutes)
})

View File

@ -424,7 +424,7 @@ const actions = {
console.warn(`Error change role: ${error.message}. Code: ${error.code}.`)
})
.finally(() => {
dispatch('permission/sendRequestMenu', organizationId, {
dispatch('permission/sendRequestMenu', null, {
root: true
})
})

View File

@ -177,29 +177,35 @@ export function convertFieldsListToShareLink(fieldsList) {
/**
* Find element in an array recursively
* @param {object|array} treeData
* @param {string} attributeName, key to get value, default id
* @author Edwin Betancourt <EdwinBetanc0urt@outlook.com>
* @param {object|array} treeData object recursive array
* @param {string} attributeName, key to get value, default 'id'
* @param {string} secondAttributeName, key to get value, default 'meta'
* @param {mixed} attributeValue, value to compare with search
* @param {string} attributeChilds, childs list into element
* @param {string} attributeChilds, 'childs' list into element
*/
export const recursiveTreeSearch = ({
treeData,
attributeValue,
attributeName = 'id',
secondAttribute = false,
secondAttributeName = '',
attributeChilds = 'childsList',
isParent = false
}) => {
if (Array.isArray(treeData)) {
// search in childs attribute
let index = 0
const length = treeData.length
while (index < length) {
let value = treeData[index]
if (!isEmptyValue(value) && Object.prototype.hasOwnProperty.call(value, attributeName)) {
if (!isEmptyValue(value) &&
Object.prototype.hasOwnProperty.call(value, attributeName)) {
value = value[attributeName]
}
if (!isEmptyValue(value) && secondAttribute && Object.prototype.hasOwnProperty.call(value, secondAttribute)) {
value = value[secondAttribute]
if (!isEmptyValue(value) &&
secondAttributeName &&
Object.prototype.hasOwnProperty.call(value, secondAttributeName)) {
value = value[secondAttributeName]
}
// compare item to search
@ -208,11 +214,12 @@ export const recursiveTreeSearch = ({
}
if (treeData[index] && treeData[index][attributeChilds]) {
const newTree = treeData[index][attributeChilds]
const found = recursiveTreeSearch({
treeData: treeData[index][attributeChilds],
treeData: newTree,
attributeValue,
attributeName,
secondAttribute,
secondAttributeName,
attributeChilds,
isParent
})
@ -223,12 +230,16 @@ export const recursiveTreeSearch = ({
index++
}
} else {
// search into meta attribute
let value = treeData
if (!isEmptyValue(value) && Object.prototype.hasOwnProperty.call(value, attributeName)) {
if (!isEmptyValue(value) &&
Object.prototype.hasOwnProperty.call(value, attributeName)) {
value = value[attributeName]
}
if (!isEmptyValue(value) && secondAttribute && Object.prototype.hasOwnProperty.call(value, secondAttribute)) {
value = value[secondAttribute]
if (!isEmptyValue(value) &&
secondAttributeName &&
Object.prototype.hasOwnProperty.call(value, secondAttributeName)) {
value = value[secondAttributeName]
}
// compare item to search
@ -240,7 +251,7 @@ export const recursiveTreeSearch = ({
treeData: treeData[attributeChilds],
attributeValue,
attributeName,
secondAttribute,
secondAttributeName,
attributeChilds
})
return found
@ -400,6 +411,7 @@ export function tagStatus(tag) {
}
return type
}
/**
* add a tab depending on the status of the document
* @param {string} tag, document status key

View File

@ -10,14 +10,24 @@
/>
<h3 v-popover:routeDescription class="description">{{ $route.meta.title }}</h3>
<el-row :gutter="10">
<template v-if="optionList.children">
<template v-if="!isEmptyValue(optionList.children)">
<template v-for="(item, key) in optionList.children">
<dropdown v-if="$route.name !== item.name" :key="key" :items="item" :title="item.meta.title" />
<dropdown-menu
v-if="$route.name !== item.name"
:key="key"
:items="item"
:title="item.meta.title"
/>
</template>
</template>
<template v-else>
<template v-for="(item, key) in optionList">
<dropdown v-if="$route.name !== item.name" :key="key" :items="item" :title="item.meta.title" />
<dropdown-menu
v-if="$route.name !== item.name"
:key="key"
:items="item"
:title="item.meta.title"
/>
</template>
</template>
</el-row>
@ -28,12 +38,12 @@
</template>
<script>
import Dropdown from '@/components/ADempiere/Dropdown'
import DropdownMenu from '@/components/ADempiere/DropdownMenu'
export default {
name: 'Summary',
name: 'SummaryView',
components: {
Dropdown
DropdownMenu
},
data() {
return {