blob: 4b589964ff81f558a29bb950f2b58af4edaf15fc [file] [log] [blame]
<template>
<div class="app-container">
<div class="createPost-container">
<el-form ref="postForm" :model="postForm" class="form-container">
<div class="createPost-main-container">
<el-row>
<el-col :span="12">
<div class="postInfo-container">
<el-row>
<el-col :span="8">
<el-form-item class="postInfo-container-item">
<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-col>
<el-col :span="8">
<el-form-item class="postInfo-container-item">
<el-select v-model="postForm.namespace" placeholder="select namespace" @change="getTopicsList(postForm.tenant, postForm.namespace)">
<el-option v-for="(item,index) in namespacesListOptions" :key="item+index" :label="item" :value="item"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item class="postInfo-container-item">
<el-select v-model="postForm.topic" placeholder="select topic" @change="getSubscriptionsList(postForm.tenant, postForm.namespace, postForm.topic)">
<el-option v-for="(item,index) in topicsListOptions" :key="item+index" :label="item" :value="item"/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
</el-form>
</div>
<div class="filter-container">
<el-input :placeholder="$t('table.subscription')" v-model="listQuery.subscription" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">{{ $t('table.subscription') }}</el-button>
<el-autocomplete
v-model="postForm.otherOptions"
:fetch-suggestions="querySearch"
class="filter-item inline-input"
style="margin-left: 10px; width:400px"
placeholder="select options"
clearable
@select="moreListOptionsChange"
/>
</div>
<el-row :gutter="8">
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 24}" :xl="{span: 24}" style="padding-right:8px;margin-bottom:30px;">
<el-table
v-loading="listLoading"
:key="tableKey"
:data="list"
border
fit
highlight-current-row
style="width: 100%;"
@row-click="getCurrentRow">
<el-table-column :label="$t('table.tenant')" min-width="100px" align="center">
<template slot-scope="scope">
<span>{{ scope.row.tenant }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.namespace')" min-width="100px" align="center">
<template slot-scope="scope">
<span>{{ scope.row.namespace }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.topic')" min-width="100px" align="center">
<template slot-scope="scope">
<span>{{ scope.row.topic }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.subscription')" min-width="100px" align="center">
<template slot-scope="scope">
<span>{{ scope.row.subscription }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.actions')" align="center" width="360" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button v-if="scope.row.status!='deleted'" class="el-button el-button--primary el-button--medium" type="danger" @click="handleDelete(scope.row)">{{ $t('table.unsubscription') }}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getSubscriptions" />
</el-col>
</el-row>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form ref="temp" :rules="rules" :model="temp" label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<div v-if="dialogStatus==='create'">
<el-form-item label="messageId" prop="messageId">
<el-input v-model="temp.messageId"/>
</el-form-item>
<el-form-item :label="$t('table.subscription')" prop="subscription">
<el-input v-model="temp.subscription"/>
</el-form-item>
</div>
<div v-else-if="dialogStatus==='skip'">
<el-form-item label="count" prop="count">
<el-input v-model="temp.count"/>
</el-form-item>
</div>
<div v-else-if="dialogStatus==='expire-messages'">
<el-form-item label="expireTime" prop="expireTime">
<el-input v-model="temp.expireTime"/>
</el-form-item>
</div>
<div v-else-if="dialogStatus==='expire-messages-all-subscriptions'">
<el-form-item label="expireTime" prop="expireTime">
<el-input v-model="temp.expireTime"/>
</el-form-item>
</div>
<div v-else-if="dialogStatus==='reset-cursor'">
<el-form-item label="messageId" prop="messageId">
<el-input v-model="temp.messageId"/>
</el-form-item>
<el-form-item label="time" prop="time">
<el-input v-model="temp.time"/>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">{{ $t('table.cancel') }}</el-button>
<el-button type="primary" @click="handleOptions()">{{ $t('table.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { fetchTenants } from '@/api/tenants'
import { fetchNamespaces } from '@/api/namespaces'
import { fetchSubscriptions, putSubscription, deleteSubscription } from '@/api/subscriptions'
import {
fetchTopics,
fetchPersistentPartitonsTopics,
fetchNonPersistentPartitonsTopics,
skip,
expireMessage,
expireMessagesAllSubscriptions,
resetPersistentCursor
} from '@/api/topics'
// import { parsePulsarSchema } from '@/utils'
import waves from '@/directive/waves' // Waves directive
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import jsonEditor from '@/components/JsonEditor'
import { validateEmpty } from '@/utils/validate'
const defaultForm = {
tenant: '',
namespace: '',
otherOptions: ''
}
export default {
name: 'Topics',
components: {
Pagination,
jsonEditor
},
directives: { waves },
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
props: {
isEdit: {
type: Boolean,
default: false
}
},
data() {
return {
postForm: Object.assign({}, defaultForm),
loading: false,
tenantsListOptions: [],
namespacesListOptions: [],
topicsListOptions: [],
moreListOptions: [],
tableKey: 0,
list: null,
localList: [],
searchList: [],
total: 0,
listLoading: false,
jsonValue: {},
tenant: '',
namespace: '',
topic: '',
currentSub: '',
currentTenant: '',
currentNamespace: '',
currentTopic: '',
listQuery: {
subscription: '',
page: 1,
limit: 10
},
temp: {
messageId: '',
subscription: '',
count: 0,
expireTime: 0,
time: ''
},
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
rules: {
messageId: [{ required: true, message: 'messageId is required', trigger: 'blur' }],
subscription: [{ required: true, message: 'subscription is required', trigger: 'blur' }],
count: [{ required: true, message: 'count is required', trigger: 'blur' }],
expireTime: [{ required: true, message: 'expireTime is required', trigger: 'blur' }],
time: [{ required: true, message: 'time is required', trigger: 'blur' }]
}
// tempRoute: {}
}
},
computed: {
},
created() {
if (this.isEdit) {
// const id = this.$route.params && this.$route.params.id
// this.fetchData(id)
} else {
this.postForm = Object.assign({}, defaultForm)
}
this.getRemoteTenantsList()
},
mounted() {
this.moreListOptions = this.loadAllOptions()
},
methods: {
getSubscriptions() {
if (this.localList.length > 0) {
setTimeout(() => {
this.localPaging()
}, 0)
} else {
this.listLoading = true
if (this.tenant.length <= 0 || this.namespace.length <= 0 || this.topic.length <= 0) {
this.tenant = 'public'
this.namespace = 'default'
this.topic = 'test'
}
fetchSubscriptions(this.tenant, this.namespace, this.topic, this.listQuery).then(response => {
for (var i = 0; i < response.data.length; i++) {
this.localList.push({
'tenant': this.tenant,
'namespace': this.namespace,
'topic': this.topic,
'subscription': response.data[i]
})
}
this.total = this.localList.length
this.list = this.localList.slice((this.listQuery.page - 1) * this.listQuery.limit, this.listQuery.limit * this.listQuery.page)
// this.localPaging()
// Just to simulate the time of the request
setTimeout(() => {
}, 1.5 * 1000)
})
this.listLoading = false
}
},
localPaging() {
this.listLoading = true
if (!validateEmpty(this.listQuery.subscription)) {
this.searchList = []
for (var i = 0; i < this.localList.length; i++) {
if (this.localList[i]['subscription'].indexOf(this.listQuery.subscription) !== -1) {
this.searchList.push(this.localList[i])
}
}
this.total = this.searchList.length
this.list = this.searchList.slice((this.listQuery.page - 1) * this.listQuery.limit, this.listQuery.limit * this.listQuery.page)
} else {
this.total = this.localList.length
this.list = this.localList.slice((this.listQuery.page - 1) * this.listQuery.limit, this.listQuery.limit * this.listQuery.page)
}
this.listLoading = false
},
handleFilter() {
this.getSubscriptions()
},
resetTemp() {
this.temp = {
subscription: ''
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = 'create'
this.dialogFormVisible = true
},
createData() {
if (this.tenant.length <= 0 || this.namespace <= 0 || this.topic.length <= 0) {
this.$notify({
title: 'error',
message: 'please select tenant and namespace and topic',
type: 'success',
duration: 2000
})
return
}
putSubscription(
this.tenant,
this.namespace,
this.topic,
this.temp.subscription
).then(() => {
this.localList = []
this.getSubscriptions()
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'create success',
type: 'success',
duration: 2000
})
})
},
handleDelete(row) {
this.temp = Object.assign({}, row) // copy obj
deleteSubscription(
this.temp.tenant,
this.temp.namespace,
this.temp.topic,
this.temp.subscription
).then(response => {
this.$notify({
title: 'success',
message: 'delete success',
type: 'success',
duration: 2000
})
this.localList = []
this.getSubscriptions()
})
},
getRemoteTenantsList() {
fetchTenants().then(response => {
if (!response.data) return
this.tenantsListOptions = response.data
})
},
getNamespacesList(tenant) {
this.tenant = tenant
fetchNamespaces(tenant, this.query).then(response => {
let namespace = []
for (var i = 0; i < response.data.length; i++) {
namespace = response.data[i].split('/')
this.namespacesListOptions.push(namespace.splice(1, namespace.length).join('/'))
}
})
},
getTopicsList(tenant, namespace) {
this.tenant = tenant
this.namespace = namespace
this.topicsListOptions = []
fetchPersistentPartitonsTopics(this.tenant, this.namespace).then(response => {
for (var i = 0; i < response.data.length; i++) {
this.topicsListOptions.push(response.data[i].split('/' + this.namespace + '/')[1])
}
})
fetchNonPersistentPartitonsTopics(this.tenant, this.namespace).then(response => {
for (var i = 0; i < response.data.length; i++) {
this.topicsListOptions.push(response.data[i].split('/' + this.namespace + '/')[1])
}
})
fetchTopics(this.tenant, this.namespace, this.listQuery).then(response => {
for (var i = 0; i < response.data.length; i++) {
this.topicsListOptions.push(response.data[i].split('/' + this.namespace + '/')[1])
}
})
},
getSubscriptionsList(tenant, namespace, topic) {
this.tenant = tenant
this.namespace = namespace
this.topic = topic
this.localList = []
this.getSubscriptions()
},
moreListOptionsChange(item) {
if (item.value === 'expire-messages-all-subscriptions') {
this.dialogStatus = item.value
this.dialogFormVisible = true
return
}
if (this.currentSub.length <= 0) {
this.$notify({
title: 'error',
message: 'Please select any one namespace in table',
type: 'error',
duration: 3000
})
this.postForm.otherOptions = ''
return
}
this.dialogStatus = item.value
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['temp'].clearValidate()
})
},
querySearch(queryString, cb) {
var moreListOptions = this.moreListOptions
var results = moreListOptions.filter(this.createFilterOptions(queryString))
cb(results)
},
createFilterOptions(queryString) {
return (moreListOptions) => {
return (moreListOptions.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
}
},
loadAllOptions() {
return [
{ 'value': 'skip' },
{ 'value': 'expire-messages' },
{ 'value': 'expire-messages-all-subscriptions' },
{ 'value': 'reset-cursor' }
]
},
getCurrentRow(item) {
this.currentTenant = item.tenant
this.currentNamespace = item.namespace
this.currentTopic = item.topic
this.currentSub = item.subscription
},
handleOptions() {
this.$refs['temp'].validate((valid) => {
if (valid) {
switch (this.dialogStatus) {
case 'create':
this.createData()
break
case 'skip':
this.confirmSkip()
break
case 'expire-messages':
this.confirmExpireMessage()
break
case 'expire-messages-all-subscriptions':
this.confirmExpireMessagesAllSubscriptions()
break
case 'reset-cursor':
this.confirmResetCursor()
break
}
}
})
},
confirmSkip() {
const tenantNamespaceTopic = this.currentTenant + '/' + this.currentNamespace + '/' + this.currentTopic
skip(tenantNamespaceTopic, this.currentSub, this.temp.count).then(response => {
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'Skip success for this topic',
type: 'success',
duration: 3000
})
})
},
confirmExpireMessage() {
const tenantNamespaceTopic = this.currentTenant + '/' + this.currentNamespace + '/' + this.currentTopic
expireMessage(tenantNamespaceTopic, this.currentSub, this.temp.expireTime).then(response => {
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'Expire message for this topic',
type: 'success',
duration: 3000
})
})
},
confirmExpireMessagesAllSubscriptions() {
const tenantNamespaceTopic = this.tenant + '/' + this.namespace + '/' + this.topic
expireMessagesAllSubscriptions(tenantNamespaceTopic, this.temp.expireTime).then(response => {
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'Expire all message for this topic',
type: 'success',
duration: 3000
})
})
},
confirmResetCursor() {
const tenantNamespaceTopic = this.currentTenant + '/' + this.currentNamespace + '/' + this.currentTopic
resetPersistentCursor(tenantNamespaceTopic, this.currentSub, this.temp.time, this.temp.messageId).then(response => {
this.dialogFormVisible = false
this.$notify({
title: 'success',
message: 'resetCursor for this topic',
type: 'success',
duration: 3000
})
})
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss";
.createPost-container {
position: relative;
.createPost-main-container {
.postInfo-container {
position: relative;
@include clearfix;
margin-bottom: 10px;
.postInfo-container-item {
float: left;
}
}
}
}
</style>