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:
parent
d55dbb1bab
commit
d6f52a70e3
@ -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"
|
||||
|
@ -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
|
||||
},
|
||||
|
@ -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') }}
|
||||
|
@ -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 []
|
||||
}
|
||||
}
|
||||
}
|
44
src/components/ADempiere/ContextMenu/relationsMixin.js
Normal file
44
src/components/ADempiere/ContextMenu/relationsMixin.js
Normal 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 []
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
@ -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
|
||||
}
|
||||
|
@ -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'
|
||||
})
|
||||
},
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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
|
||||
})
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user