mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Added store and additional actions.
This commit is contained in:
@@ -18,7 +18,8 @@
|
||||
"js-cookie": "^2.2.0",
|
||||
"vue": "^2.5.2",
|
||||
"vue-resource": "^1.5.0",
|
||||
"vue-router": "^3.0.1"
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.2",
|
||||
|
||||
+40
-16
@@ -1,29 +1,20 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div class="container is-fluid">
|
||||
<div id="main-container" class="container is-fluid">
|
||||
<div class="columns">
|
||||
<div class="column is-3">
|
||||
<div class="column is-2">
|
||||
<aside class="menu">
|
||||
<p class="menu-label">
|
||||
Admin
|
||||
Admin
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<router-link tag="li" :to="{ name: 'DomainList' }">
|
||||
<a>Domains</a>
|
||||
</router-link>
|
||||
<router-link tag="li" :to="{ name: 'DomainList' }">
|
||||
<a><b-icon icon="account"></b-icon>Identities</a>
|
||||
</router-link>
|
||||
<router-link tag="li" :to="{ name: 'DomainList' }">
|
||||
<a>Logs</a>
|
||||
</router-link>
|
||||
<router-link tag="li" :to="{ name: 'DomainList' }">
|
||||
<a>Settings</a>
|
||||
<router-link v-for="(item, index) in menu" :key="index" tag="li" :to="{ name: item.route }">
|
||||
<a><b-icon :icon="item.icon" size="is-large"></b-icon><br> {{ item.label }}</a>
|
||||
</router-link>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
<div class="column is-9">
|
||||
<div class="column is-10 app-content">
|
||||
<router-view/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,6 +24,39 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
name: 'App',
|
||||
data () {
|
||||
return {
|
||||
menu: [{
|
||||
route: 'DomainList',
|
||||
icon: 'domain',
|
||||
label: 'Domains'
|
||||
}, {
|
||||
route: 'DomainList',
|
||||
icon: 'account',
|
||||
label: 'Identities'
|
||||
}, {
|
||||
route: 'DomainList',
|
||||
icon: 'database-search',
|
||||
label: 'Logs'
|
||||
}, {
|
||||
route: 'DomainList',
|
||||
icon: 'tune',
|
||||
label: 'Settings'
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#main-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.app-content {
|
||||
background: #ECF0F3;
|
||||
}
|
||||
.menu-list {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,3 +12,7 @@ export const getDomains = () => {
|
||||
export const createDomain = (data) => {
|
||||
return domainResource.save(data)
|
||||
}
|
||||
|
||||
export const updateDomain = (data) => {
|
||||
return domainResource.update({pk: data.pk}, data)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
<div>
|
||||
<h1 class="title">Add domain</h1>
|
||||
<form>
|
||||
<b-field label="Name">
|
||||
<b-field label="Name" :type="formErrors && formErrors.name ? 'is-danger' : ''"
|
||||
:message="formErrors && formErrors.name ? formErrors.name[0] : ''">
|
||||
<b-input v-model="domain.name"></b-input>
|
||||
</b-field>
|
||||
<b-field label="Quota">
|
||||
<b-field label="Quota" :type="formErrors && formErrors.quota ? 'is-danger' : ''"
|
||||
:message="formErrors && formErrors.quota ? formErrors.quota[0] : ''">
|
||||
<b-input v-model="domain.quota"></b-input>
|
||||
</b-field>
|
||||
<b-field>
|
||||
@@ -16,18 +18,50 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as api from '@/api'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
formErrors: {},
|
||||
domain: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
var domainPk = this.$route.params.domainPk
|
||||
if (domainPk) {
|
||||
if (!this.$store.state.domainsLoaded) {
|
||||
this.$store.dispatch('getDomains').then(response => {
|
||||
this.loadDomain(domainPk)
|
||||
})
|
||||
} else {
|
||||
this.loadDomain(domainPk)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadDomain (pk) {
|
||||
this.domain = JSON.parse(JSON.stringify(this.$store.getters.getDomainByPk(pk)))
|
||||
},
|
||||
onSaveError (response) {
|
||||
this.formErrors = response.data
|
||||
},
|
||||
saveDomain () {
|
||||
api.createDomain(this.domain).then(response => {
|
||||
})
|
||||
var action
|
||||
var msg
|
||||
if (this.domain.pk) {
|
||||
action = 'updateDomain'
|
||||
msg = 'Domain updated.'
|
||||
} else {
|
||||
action = 'createDomain'
|
||||
msg = 'Domain created.'
|
||||
}
|
||||
this.$store.dispatch(action, this.domain).then(response => {
|
||||
this.$router.push({ name: 'DomainList' })
|
||||
this.$toast.open({
|
||||
message: msg,
|
||||
type: 'is-success',
|
||||
position: 'is-bottom'
|
||||
})
|
||||
}, this.onSaveError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,16 @@
|
||||
<h1 class="title">Domains</h1>
|
||||
</div>
|
||||
<div class="column">
|
||||
<router-link :to="{ name: 'DomainAdd' }">Add</router-link>
|
||||
<router-link :to="{ name: 'DomainAdd' }" class="button is-primary">Add</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<b-table :data="domains" checkable>
|
||||
<template slot-scope="props">
|
||||
<b-table-column>
|
||||
<router-link :to="{ name: 'DomainEdit', params: { domainPk: props.row.pk }}">
|
||||
<b-icon icon="pencil"></b-icon>
|
||||
</router-link>
|
||||
</b-table-column>
|
||||
<b-table-column field="name" label="Name">
|
||||
{{ props.row.name }}
|
||||
</b-table-column>
|
||||
@@ -22,13 +27,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as api from '@/api'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
computed: mapGetters([
|
||||
'domains'
|
||||
]),
|
||||
data () {
|
||||
return {
|
||||
domains: [],
|
||||
columns: [
|
||||
{},
|
||||
{
|
||||
field: 'name',
|
||||
label: 'Name'
|
||||
@@ -41,9 +49,7 @@ export default {
|
||||
}
|
||||
},
|
||||
created () {
|
||||
api.getDomains().then(response => {
|
||||
this.domains = response.data
|
||||
})
|
||||
this.$store.dispatch('getDomains')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,6 +7,7 @@ import Cookies from 'js-cookie'
|
||||
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
Vue.use(Buefy)
|
||||
|
||||
@@ -20,6 +21,7 @@ Vue.http.headers.common['X-CSRFTOKEN'] = csrftoken
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
components: { App },
|
||||
template: '<App/>'
|
||||
})
|
||||
|
||||
@@ -16,6 +16,12 @@ export default new Router({
|
||||
path: '/domains/add/',
|
||||
name: 'DomainAdd',
|
||||
component: DomainForm
|
||||
},
|
||||
{
|
||||
path: '/domains/:domainPk([0-9]+)/',
|
||||
name: 'DomainEdit',
|
||||
component: DomainForm
|
||||
}
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import domains from './modules/domains'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const options = {
|
||||
modules: {
|
||||
domains
|
||||
},
|
||||
strict: process.env.NODE_ENV !== 'production'
|
||||
}
|
||||
|
||||
export default new Vuex.Store(options)
|
||||
export { options }
|
||||
@@ -0,0 +1,70 @@
|
||||
import Vue from 'vue'
|
||||
import * as api from '@/api'
|
||||
|
||||
// mutation types
|
||||
const SET_DOMAINS = 'SET_DOMAINS'
|
||||
const ADD_DOMAIN = 'ADD_DOMAIN'
|
||||
const UPDATE_DOMAIN = 'UPDATE_DOMAIN'
|
||||
|
||||
// initial state
|
||||
const state = {
|
||||
domainsLoaded: false,
|
||||
domains: []
|
||||
}
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
domains: state => state.domains,
|
||||
getDomainByPk: state => pk => {
|
||||
for (var domain of state.domains) {
|
||||
if (domain.pk === parseInt(pk, 10)) {
|
||||
return domain
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
getDomains ({ commit }) {
|
||||
return api.getDomains().then(response => {
|
||||
commit(SET_DOMAINS, { domains: response.data })
|
||||
})
|
||||
},
|
||||
createDomain ({ commit }, data) {
|
||||
return api.createDomain(data).then(response => {
|
||||
commit(ADD_DOMAIN, { domain: response.data })
|
||||
})
|
||||
},
|
||||
updateDomain ({ commit }, data) {
|
||||
return api.updateDomain(data).then(response => {
|
||||
commit(UPDATE_DOMAIN, { domain: response.data })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
[SET_DOMAINS] (state, { domains }) {
|
||||
state.domainsLoaded = true
|
||||
state.domains = domains
|
||||
},
|
||||
[ADD_DOMAIN] (state, { domain }) {
|
||||
state.domains.push(domain)
|
||||
},
|
||||
[UPDATE_DOMAIN] (state, { domain }) {
|
||||
state.domains.filter(function (item, pos) {
|
||||
if (item.pk === domain.pk) {
|
||||
Vue.set(state.domains, pos, domain)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
||||
@@ -4,8 +4,10 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.views import generic
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
|
||||
class AdminIndexView(generic.TemplateView):
|
||||
|
||||
class AdminIndexView(auth_mixins.LoginRequiredMixin, generic.TemplateView):
|
||||
"""Admin index view."""
|
||||
|
||||
template_name = "admin/index.html"
|
||||
|
||||
Reference in New Issue
Block a user