From c9a75e2f30d0baa4ac9d8845bf1b03842c0167c1 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Sat, 7 Dec 2019 03:25:25 +0700 Subject: [PATCH] domain: implement tree-view based domain list view (#53) Fixes #27 Signed-off-by: Rohit Yadav --- ui/src/components/header/UserMenu.vue | 14 +- ui/src/components/view/InfoCard.vue | 6 +- ui/src/components/view/ResourceView.vue | 3 +- ui/src/components/view/TreeView.vue | 590 ++++++++++++++++++++++++ ui/src/config/router.js | 4 +- ui/src/config/section/iam.js | 25 +- ui/src/views/AutogenView.vue | 112 ++++- 7 files changed, 718 insertions(+), 36 deletions(-) create mode 100644 ui/src/components/view/TreeView.vue diff --git a/ui/src/components/header/UserMenu.vue b/ui/src/components/header/UserMenu.vue index b53476c811b..1f33a0fb229 100644 --- a/ui/src/components/header/UserMenu.vue +++ b/ui/src/components/header/UserMenu.vue @@ -27,25 +27,19 @@ - + - Account + Profile - - - - Settings - - - + Help - + Logout diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index e4f973f0872..b8f4ab58dbb 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -17,7 +17,7 @@ 0)) || (dataView && action.dataView)) && + ('show' in action ? action.show(resource) : true)" :icon="action.icon" :type="action.icon === 'delete' ? 'danger' : (action.icon === 'plus' ? 'primary' : 'default')" shape="circle" @@ -59,7 +59,7 @@ style="width: unset" placeholder="Search" v-model="searchQuery" - v-if="!dataView" + v-if="!dataView && !treeView" @search="onSearch" /> @@ -191,14 +191,18 @@ -
- +
+
+ :items="items" + v-if="!treeView" /> + showSizeChanger + v-if="!treeView" /> +
@@ -225,6 +238,7 @@ import ChartCard from '@/components/widgets/ChartCard' import Status from '@/components/widgets/Status' import ListView from '@/components/view/ListView' import ResourceView from '@/components/view/ResourceView' +import TreeView from '@/components/view/TreeView' import { genericCompare } from '@/utils/sort.js' export default { @@ -234,6 +248,7 @@ export default { ChartCard, ResourceView, ListView, + TreeView, Status }, mixins: [mixinDevice], @@ -253,7 +268,11 @@ export default { currentAction: {}, showAction: false, dataView: false, - actions: [] + treeView: false, + actions: [], + treeData: [], + treeSelected: {}, + actionData: [] } }, computed: { @@ -291,6 +310,8 @@ export default { this.columns = [] this.columnKeys = [] this.items = [] + this.treeData = [] + this.treeSelected = {} var params = { listall: true } if (Object.keys(this.$route.query).length > 0) { Object.assign(params, this.$route.query) @@ -302,9 +323,12 @@ export default { params.keyword = this.searchQuery } + this.treeView = this.$route && this.$route.meta && this.$route.meta.treeView + if (this.$route && this.$route.params && this.$route.params.id) { this.resource = {} this.dataView = true + this.treeView = false } else { this.dataView = false } @@ -358,8 +382,16 @@ export default { params.name = this.$route.params.id } } - params.page = this.page - params.pagesize = this.pageSize + + if (!this.treeView) { + params.page = this.page + params.pagesize = this.pageSize + } else { + const domainId = this.$store.getters.userInfo.domainid + params.id = domainId + delete params.treeView + } + api(this.apiName, params).then(json => { var responseName var objectName @@ -381,33 +413,47 @@ export default { if (!this.items || this.items.length === 0) { this.items = [] } - for (let idx = 0; idx < this.items.length; idx++) { - this.items[idx].key = idx - for (const key in customRender) { - const func = customRender[key] - if (func && typeof func === 'function') { - this.items[idx][key] = func(this.items[idx]) + if (this.treeView) { + this.treeData = this.generateTreeData(this.items) + } else { + for (let idx = 0; idx < this.items.length; idx++) { + this.items[idx].key = idx + for (const key in customRender) { + const func = customRender[key] + if (func && typeof func === 'function') { + this.items[idx][key] = func(this.items[idx]) + } + } + if (this.$route.path.startsWith('/ssh')) { + this.items[idx].id = this.items[idx].name } - } - if (this.$route.path.startsWith('/ssh')) { - this.items[idx].id = this.items[idx].name } } if (this.items.length > 0) { this.resource = this.items[0] + this.treeSelected = this.treeView ? this.items[0] : {} } else { this.resource = {} + this.treeSelected = {} } }).catch(error => { - // handle error this.$notification.error({ message: 'Request Failed', description: error.response.headers['x-description'], duration: 0 }) - if (error.response.status === 431) { + + if ([401, 405].includes(error.response.status)) { + this.$router.push({ path: '/exception/403' }) + } + + if ([430, 431, 432].includes(error.response.status)) { this.$router.push({ path: '/exception/404' }) } + + if ([530, 531, 532, 533, 534, 535, 536, 537].includes(error.response.status)) { + this.$router.push({ path: '/exception/500' }) + } }).finally(f => { this.loading = false }) @@ -422,6 +468,7 @@ export default { this.currentAction = {} }, execAction (action) { + this.actionData = [] if (action.component && action.api && !action.popup) { this.$router.push({ name: action.api }) return @@ -581,6 +628,11 @@ export default { var hasJobId = false api(this.currentAction.api, params).then(json => { + // set action data for reload tree-view + if (this.treeView) { + this.actionData.push(json) + } + for (const obj in json) { if (obj.includes('response')) { for (const res in json[obj]) { @@ -630,6 +682,24 @@ export default { this.loading = false this.selectedRowKeys = [] }, 1000) + }, + generateTreeData (treeData) { + const result = [] + const rootItem = treeData + + rootItem[0].title = rootItem[0].title ? rootItem[0].title : rootItem[0].name + rootItem[0].key = rootItem[0].id ? rootItem[0].id : 0 + + if (!rootItem[0].haschild) { + rootItem[0].isLeaf = true + } + + result.push(rootItem[0]) + return result + }, + changeResource (resource) { + this.treeSelected = resource + this.resource = this.treeSelected } } }