blob: bbf9ae7720329b4c830aa82c6404cfa41e3e6807 [file] [log] [blame]
<template>
<div class="app-container">
<div class="createPost-container">
<el-form :inline="true" :model="postForm" class="form-container">
<el-form-item class="postInfo-container-item" label="Tenant">
<el-select v-model="postForm.tenant" placeholder="select tenant" @change="getNamespacesList(postForm.tenant)">
<el-option v-for="(item,index) in tenantsListOptions" :key="item+index" :label="item" :value="item"/>
</el-select>
</el-form-item>
</el-form>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="Namespaces" name="namespaces">
<div class="filter-container">
<el-input
:placeholder="$t('table.namespace')"
v-model="searchNamespace"
style="width: 200px;"
@keyup.enter.native="handleFilterNamespace"/>
<el-button type="primary" icon="el-icon-search" @click="handleFilterNamespace"/>
<el-button type="primary" icon="el-icon-plus" @click="handleCreateNamespace">New Namespace</el-button>
</div>
<el-row :gutter="24">
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 24}" :xl="{span: 24}">
<el-table
v-loading="listLoading"
:key="tableKey"
:data="listNamespaces"
border
fit
highlight-current-row
style="width: 100%;">
<el-table-column :label="$t('table.namespace')" align="center">
<template slot-scope="scope">
<router-link :to="'/management/namespaces/' + scope.row.tenant +'/' + scope.row.namespace + '/namespace?tab=overview'" class="link-type">
<span>{{ scope.row.namespace }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column label="topics" align="center">
<template slot-scope="scope">
<router-link :to="'/management/namespaces/' + scope.row.tenant + '/' + scope.row.namespace + '/namespace?tab=topics'" class="link-type">
<span>{{ scope.row.topics }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column :label="$t('table.actions')" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<router-link :to="'/management/namespaces/' + scope.row.tenant +'/' + scope.row.namespace + '/namespace'">
<el-button type="primary" size="mini">{{ $t('table.edit') }}</el-button>
</router-link>
<el-button v-if="scope.row.status!='deleted'" size="mini" type="danger" @click="handleDeleteNamespace(scope.row)">{{ $t('table.delete') }}</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="Configuration" name="configuration">
<el-row :gutter="24">
<el-col :span="24">
<div slot="header" class="clearfix">
<h2>Tenant Info</h2>
</div>
<h4>Clusters</h4>
<hr class="split-line">
<div class="component-item">
<div class="section-title">
<span>Allowed Clusters</span>
<el-tooltip :content="allowedClustersContent" class="item" effect="dark" placement="top">
<i class="el-icon-info"/>
</el-tooltip>
</div>
<el-select
v-model="clusterValue"
style="width:500px;margin-top:20px"
multiple
placeholder="Please Select Cluster"
@change="handleSelectClusters()">
<el-option v-for="item in clusterOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<h4>Permissions</h4>
<hr class="split-line">
<div class="component-item">
<div class="section-title">
<span>Admin Roles</span>
<el-tooltip :content="adminRolesContent" class="item" effect="dark" placement="top">
<i class="el-icon-info"/>
</el-tooltip>
</div>
<div class="section-content">
<el-tag
v-for="tag in dynamicRoles"
:key="tag"
:disable-transitions="false"
closable
@close="handleClose(tag)">
{{ tag }}
</el-tag>
<el-input
v-if="inputVisible"
ref="saveTagInput"
v-model="inputValue"
size="small"
class="input-new-tag"
@keyup.enter.native="handleInputConfirm"/>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Role</el-button>
</div>
</div>
<h4 style="color:#E57470">Danger Zone</h4>
<hr class="danger-line">
<el-button type="danger" class="button" @click="handleDeleteTenant">Delete Tenant</el-button>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="30%">
<el-form ref="temp" :model="temp" :rules="rules" label-position="top">
<el-form-item v-if="dialogStatus==='createNamespace'" :label="$t('table.namespace')" prop="namespace">
<el-input v-model="temp.namespace" placeholder="Please input namespace"/>
</el-form-item>
<el-form-item v-if="dialogStatus==='deleteNamespace'">
<h4>Are you sure you want to delete this namespace {{ temp.tenant }}/{{ temp.namespace }}?</h4>
</el-form-item>
<el-form-item v-if="dialogStatus==='deleteTenant'">
<h4>Are you sure you want to delete this tenant?</h4>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleOptions()">{{ $t('table.confirm') }}</el-button>
<el-button @click="dialogFormVisible=false">{{ $t('table.cancel') }}</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import { fetchClusters } from '@/api/clusters'
import { fetchTenants, fetchTenantsInfo, updateTenant, deleteTenant } from '@/api/tenants'
import {
fetchNamespaces,
putNamespace,
deleteNamespace
} from '@/api/namespaces'
import { validateEmpty } from '@/utils/validate'
const defaultForm = {
tenant: ''
}
export default {
name: 'TenantInfo',
data() {
return {
postForm: Object.assign({}, defaultForm),
dynamicRoles: [],
inputVisible: false,
inputValue: '',
adminRoles: '',
allowedClustersContent: 'This is Allowed Clusters',
adminRolesContent: 'This is Admin Roles',
clusterValue: [],
clusterOptions: [],
activeName: 'configuration',
tenantsListOptions: [],
listQuery: {
namespace: '',
page: 1,
limit: 20
},
listLoading: false,
tableKey: 0,
total: 0,
listNamespaces: [],
temp: {
tenant: '',
namespace: '',
limit: '',
actions: [],
clusters: []
},
dialogFormVisible: false,
dialogStatus: '',
rules: {
namespace: [{ required: true, message: 'namespace is required', trigger: 'blur' }]
},
currentTabName: '',
textMap: {
createNamespace: 'New Namespace',
deleteNamespace: 'Delete Namespace',
deleteTenant: 'Delete Tenant'
},
tempNamespacesList: [],
searchNamespace: '',
searchList: []
}
},
created() {
this.postForm.tenant = this.$route.params && this.$route.params.tenant
if (this.$route.query && this.$route.query.tab) {
this.activeName = this.$route.query.tab
this.currentTabName = this.$route.query.tab
}
this.getRemoteTenantsList()
this.getNamespacesList()
this.getClustersList()
this.getTenantsInfo()
},
methods: {
handleClose(tag) {
this.dynamicRoles.splice(this.dynamicRoles.indexOf(tag), 1)
const data = {}
data.adminRoles = this.dynamicRoles
updateTenant(this.postForm.tenant, data).then(() => {
this.$notify({
title: 'success',
message: 'Update role success',
type: 'success',
duration: 2000
})
})
},
showInput() {
this.inputVisible = true
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus()
})
},
getRemoteTenantsList() {
fetchTenants().then(response => {
if (!response.data) return
for (var i = 0; i < response.data.total; i++) {
this.tenantsListOptions.push(response.data.data[i].tenant)
}
})
},
handleInputConfirm() {
const inputValue = this.inputValue
if (inputValue) {
if (this.dynamicRoles.indexOf(this.inputValue) >= 0) {
this.$notify({
title: 'error',
message: 'Role is exists',
type: 'error',
duration: 2000
})
return
}
this.dynamicRoles.push(inputValue)
}
this.inputVisible = false
this.inputValue = ''
const data = {}
data.adminRoles = this.dynamicRoles
data.allowedClusters = this.clusterValue
updateTenant(this.postForm.tenant, data).then(() => {
this.$notify({
title: 'success',
message: 'Update role success',
type: 'success',
duration: 2000
})
})
},
getClustersList() {
fetchClusters().then(response => {
for (var i in response.data.data) {
this.clusterOptions.push({
value: response.data.data[i].cluster,
label: response.data.data[i].cluster
})
}
})
},
getTenantsInfo() {
fetchTenantsInfo(this.postForm.tenant).then(response => {
this.clusterValue = response.data.allowedClusters
this.dynamicRoles = response.data.adminRoles
})
},
handleSelectClusters() {
const data = {}
data.allowedClusters = this.clusterValue
data.adminRoles = this.dynamicRoles
updateTenant(this.postForm.tenant, data).then(() => {
this.$notify({
title: 'success',
message: 'Update cluster success',
type: 'success',
duration: 2000
})
})
},
handleDeleteTenant() {
this.dialogStatus = 'deleteTenant'
this.dialogFormVisible = true
},
deleteTenant() {
deleteTenant(this.postForm.tenant).then((response) => {
this.$notify({
title: 'success',
message: 'delete success',
type: 'success',
duration: 2000
})
this.$router.push({ path: '/management/tenants' })
})
},
getNamespacesList() {
fetchNamespaces(this.postForm.tenant, this.listQuery).then(response => {
this.listNamespaces = []
for (var i = 0; i < response.data.data.length; i++) {
this.listNamespaces.push({
'tenant': this.postForm.tenant,
'namespace': response.data.data[i].namespace,
'topics': response.data.data[i].topics
})
}
this.total = this.listNamespaces.length
// Just to simulate the time of the request
setTimeout(() => {
this.listLoading = false
}, 1.5 * 1000)
})
},
handleClick(tab, event) {
this.currentTabName = tab.name
this.$router.push({ query: { 'tab': tab.name }})
},
handleFilterNamespace() {
if (this.tempNamespacesList.length <= 0) {
for (var t = 0; t < this.listNamespaces.length; t++) {
this.tempNamespacesList.push(this.listNamespaces[t])
}
}
if (!validateEmpty(this.searchNamespace)) {
this.searchList = []
for (var i = 0; i < this.listNamespaces.length; i++) {
if (this.listNamespaces[i]['namespace'].indexOf(this.searchNamespace) !== -1) {
this.searchList.push(this.listNamespaces[i])
}
}
this.listNamespaces = this.searchList
} else {
this.listNamespaces = this.tempNamespacesList
}
},
handleCreateNamespace() {
this.temp.namespace = ''
this.dialogStatus = 'createNamespace'
this.dialogFormVisible = true
},
createNamespace() {
putNamespace(this.postForm.tenant, this.temp.namespace, this.temp).then(() => {
this.listNamespaces = []
this.getNamespacesList()
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'create success',
type: 'success',
duration: 2000
})
})
},
handleOptions() {
this.$refs['temp'].validate((valid) => {
if (valid) {
switch (this.dialogStatus) {
case 'createNamespace':
this.createNamespace()
break
case 'deleteNamespace':
this.deleteNamespace()
break
case 'deleteTenant':
this.deleteTenant()
break
}
}
})
},
handleDeleteNamespace(row) {
this.dialogStatus = 'deleteNamespace'
this.dialogFormVisible = true
this.temp.tenant = row.tenant
this.temp.namespace = row.namespace
},
deleteNamespace() {
var tenantNamespace = this.temp.tenant + '/' + this.temp.namespace
deleteNamespace(tenantNamespace).then((response) => {
this.$notify({
title: 'success',
message: 'delete success',
type: 'success',
duration: 2000
})
this.dialogFormVisible = false
this.listNamespaces = []
this.getNamespacesList()
})
}
}
}
</script>
<style scoped>
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
.section-content {
margin-top: 15px;
}
.confirm-button {
margin-top: 10px;
}
.section-title {
color: rgba(0,0,0,.45);
font-size: 16px;
}
.component-item{
min-height: 60px;
}
.split-line {
background: #e6e9f3;
border: none;
height: 1px;
}
.danger-line {
background: red;
border: none;
height: 1px;
}
</style>