updated vmail-ui

This commit is contained in:
Paul 2021-04-05 21:33:58 +02:00
parent 0e11b00087
commit dcfc49919c
20 changed files with 2616 additions and 2366 deletions

4244
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,14 +18,14 @@
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-router": "^4.4.6",
"@vue/cli-plugin-router": "^4.5.12",
"@vue/cli-service": "~4.4.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "^2.0.6",
"vue-cli-plugin-vuetify": "^2.3.1",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
},

View File

@ -8,15 +8,15 @@
</div>
<div class="routers">
<v-icon small>mdi-account-settings</v-icon>
<router-link to="/admin">Admin</router-link>
<router-link to="/admin">Admins</router-link>
</div>
<div class="routers">
<v-icon small>mdi-email-box</v-icon>
<router-link to="/mailbox">Mailbox</router-link>
<router-link to="/mailbox">Mailboxes</router-link>
</div>
<div class="routers">
<v-icon small>mdi-at</v-icon>
<router-link to="/alias">Alias</router-link>
<router-link to="/alias">Aliases</router-link>
</div>
<div class="routers">
<v-icon small>mdi-format-list-checkbox</v-icon>

View File

@ -1 +1,26 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100">
<defs>
<style>
.cls-1 {
fill: #1697f6;
}
.cls-2 {
fill: #7bc6ff;
}
.cls-3 {
fill: #1867c0;
}
.cls-4 {
fill: #aeddff;
}
</style>
</defs>
<title>Artboard 46</title>
<polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32" />
<polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5" />
<polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32" />
<polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58" />
</svg>

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 779 B

View File

@ -1,21 +0,0 @@
import Axios from "axios";
import VmailApi from "@/classes/vmailapi.js"
export default class Admin {
constructor(url) {
this.vmailapi = new VmailApi(url);
this.apipath = "/api/admin";
}
GetList() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath)
}
GetItem(name) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
DeleteItem(name) {
return Axios.delete(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
}

View File

@ -1,21 +0,0 @@
import Axios from "axios";
import VmailApi from "@/classes/vmailapi.js"
export default class Alias {
constructor(url) {
this.vmailapi = new VmailApi(url);
this.apipath = "/api/alias";
}
GetList() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath)
}
GetItem(name) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
DeleteItem(name) {
return Axios.delete(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
}

View File

@ -1,14 +0,0 @@
import Axios from "axios";
import VmailApi from "@/classes/vmailapi.js"
export default class Log {
constructor(url) {
this.vmailapi = new VmailApi(url);
this.apipath = "/api/log";
this.readonly = true;
}
GetList() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath)
}
}

View File

@ -1,21 +0,0 @@
import Axios from "axios";
import VmailApi from "@/classes/vmailapi.js"
export default class Mailbox {
constructor(url) {
this.vmailapi = new VmailApi(url);
this.apipath = "/api/mailbox";
}
GetList() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath)
}
GetItem(name) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
DeleteItem(name) {
return Axios.delete(this.vmailapi.GetUrl() + this.apipath + "/" + name)
}
}

View File

@ -3,6 +3,10 @@ export default class VmailApi {
this.url = url;
}
Auth() {
return this;
}
GetUrl() {
return this.url;
}

View File

@ -0,0 +1,34 @@
import Axios from "axios";
import VmailApi from "@/classes/vmailapi.js"
export default class VmailObject {
constructor(url, objecttype, readonly) {
this.vmailapi = new VmailApi(url);
this.apipath = `/api/${objecttype}`;
this.readonly = readonly;
}
GetModel() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + "model")
}
GetList() {
return Axios.get(this.vmailapi.GetUrl() + this.apipath)
}
GetItem(id) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + id)
}
CreateItem(data) {
return Axios.post(this.vmailapi.GetUrl() + this.apipath, data)
}
ModifyItem(id, data) {
return Axios.put(this.vmailapi.GetUrl() + this.apipath + "/" + id, data)
}
DeleteItem(id) {
return Axios.delete(this.vmailapi.GetUrl() + this.apipath + "/" + id)
}
}

View File

View File

@ -1,7 +1,10 @@
<template>
<div class="List">
<div class="list">
<v-data-table :headers="headers" :items="itemlist" :items-per-page="20" class="elevation-1">
<template v-slot:item.actions="{ item }">
<template v-slot:[`item.active`]="{ item }">
<v-simple-checkbox v-model="item.active" disabled></v-simple-checkbox>
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-icon small class="mr-2" @click="editItem(item)">
mdi-pencil
</v-icon>
@ -21,8 +24,10 @@
<v-row v-for="item in headers" :key="item">
<template v-if="item.editable">
<v-col cols="16" sm="8" md="6">
<v-checkbox v-if="typeof editedItem[item.value] == 'boolean'" v-model="editedItem[item.value]" v-bind:label="item.text"></v-checkbox>
<v-text-field v-if="typeof editedItem[item.value] == 'string'" v-model="editedItem[item.value]" v-bind:label="item.text"></v-text-field>
<v-checkbox v-if="typeof editedItem[item.value] == 'boolean'" v-model="editedItem[item.value]"
v-bind:label="item.text"></v-checkbox>
<v-text-field v-if="typeof editedItem[item.value] == 'string'" v-model="editedItem[item.value]"
v-bind:label="item.text"></v-text-field>
</v-col>
</template>
</v-row>
@ -35,6 +40,15 @@
</v-card-actions>
</v-card>
</v-dialog>
<v-snackbar v-model="snackbarshow" :timeout="snackbartimeout">
{{ snackbartext }}
<template v-slot:action="{ attrs }">
<v-btn color="blue" text v-bind="attrs" @click="snackbarshow=false">
Close
</v-btn>
</template>
</v-snackbar>
</div>
</template>
@ -43,6 +57,9 @@
name: 'List',
data() {
return {
snackbarshow: false,
snackbartext: "",
snackbartimeout: 10000,
colsize: 3,
editedItem: {}
}
@ -53,9 +70,11 @@
}
},
methods: {
createItem(item) {
return item;
},
/*createItem(name) {
this.editedIndex = this.itemlist.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},*/
editItem(item) {
this.editedIndex = this.itemlist.indexOf(item);
this.editedItem = Object.assign({}, item);
@ -64,7 +83,8 @@
deleteItem(item) {
const index = this.itemlist.indexOf(item);
// Assuming that first elem of item is the primary key
confirm('Are you sure you want to delete this item?') && this.object.DeleteItem(item[Object.keys(item)[0]]).then(() => {
confirm('Are you sure you want to delete this item?') && this.object.DeleteItem(item[Object.keys(item)[0]])
.then(() => {
this.itemlist.splice(index, 1);
});
},
@ -77,18 +97,22 @@
},
save() {
if (this.editedIndex > -1) {
Object.assign(this.desserts[this.editedIndex], this.editedItem)
Object.assign(this.itemlist[this.editedIndex], this.editedItem)
} else {
this.desserts.push(this.editedItem)
this.itemlist.push(this.editedItem)
}
this.close()
this.object.ModifyItem(this.editedItem.id, this.editedItem).then((response) => {
this.snackbarshow = true;
this.snackbartext = response;
this.$parent.RefreshData();
});
this.close();
},
},
props: ["headers", "itemlist", "object"]
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;

View File

@ -1,23 +1,13 @@
<template>
<div class="text-center">
<v-menu offset-y
>
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
<v-btn color="primary" dark v-bind="attrs" v-on="on">
Create
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
@click="test"
>
<v-list-item v-for="(item, index) in items" :key="index" @click="opendialog(item.dest)" link>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
@ -26,15 +16,37 @@
</template>
<script>
import Vmailobject from '@/classes/vmailobject.js'
export default {
export default {
name: 'Menu',
data: () => ({
items: [
{ title: 'Alias' },
{ title: 'Mailbox' },
{ title: 'Domain' },
items: [{
title: 'Admin',
dest: 'admin',
cls: Vmailobject
},
{
title: 'Alias',
dest: 'alias',
cls: Vmailobject
},
{
title: 'Domain',
dest: 'domain',
cls: Vmailobject
},
{
title: 'Mailbox',
dest: 'mailbox',
cls: Vmailobject
},
]
})
}
}),
methods: {
opendialog(item) {
console.log(item);
},
}
}
</script>

View File

@ -4,8 +4,7 @@ import Mailbox from '../views/Mailbox.vue'
import Alias from '../views/Alias.vue'
import Log from '../views/Log.vue'
const routes = [
{
const routes = [{
path: '/',
component: Home,
},

View File

@ -1,25 +1,59 @@
<template>
<div class="Admin">
<List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
<div class="admin">
<List :headers="attrs" :itemlist="itemlist" :object="admin" />
</div>
</template>
<script>
import List from '@/components/list.vue'
import Admin from '@/classes/admin.js'
import Vmailobject from '@/classes/vmailobject.js'
import List from '@/components/list.vue'
export default {
export default {
name: 'Admins',
data() {
return {
attrs : [
{text: "Username", value:"username", sortable: true, editable: true},
{text: "Created", value:"created", sortable: true, editable: true},
{text: "Modified", value:"modified", sortable: true, editable: true},
{text: "Active", value:"active", sortable: true, editable: true},
{text: "Superadmin", value:"superadmin", sortable: true, editable: true},
{text: "Phone", value:"phone", sortable: true, editable: true},
{text: "Actions", value:"actions", sortable: false, editable: false},
attrs: [{
text: "Username",
value: "username",
sortable: true,
editable: true
},
{
text: "Created",
value: "created",
sortable: true,
editable: false
},
{
text: "Modified",
value: "modified",
sortable: true,
editable: false
},
{
text: "Active",
value: "active",
sortable: true,
editable: true
},
{
text: "Super administrator",
value: "superadmin",
sortable: true,
editable: true
},
{
text: "Phone",
value: "phone",
sortable: true,
editable: true
},
{
text: "Actions",
value: "actions",
sortable: false,
editable: false
},
],
itemlist: [],
item: {}
@ -29,19 +63,26 @@ export default {
List
},
props: ["vmailapi"],
mounted () {
let admin = new Admin(this.vmailapi.GetUrl())
admin.GetList().then(response => {
this.itemlist = response.data;
})
mounted() {
this.admin = new Vmailobject(this.vmailapi.GetUrl(), this.$el.className)
this.RefreshData();
},
methods: {
DeleteItem (name) {
this.admin = new Admin(this.vmailapi.GetUrl());
this.admin.DeleteItem(name).then(response => {
RefreshData() {
this.admin.GetList().then(response => {
this.itemlist = response.data;
});
},
ModifyItem(id, item) {
this.admin.ModifyItem(id, item).then(response => {
return response;
});
},
DeleteItem(id) {
this.admin.DeleteItem(id).then(response => {
return response;
});
}
}
}
}
</script>

View File

@ -1,25 +1,59 @@
<template>
<div class="alias">
<List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist" :object="alias"/>
<List :headers="attrs" :itemlist="itemlist" :object="alias" />
</div>
</template>
<script>
import List from '@/components/list.vue'
import Alias from '@/classes/alias.js'
import Vmailobject from '@/classes/vmailobject.js'
import List from '@/components/list.vue'
export default {
export default {
name: 'Alias',
data() {
return {
attrs : [
{text: "Address", value:"address", sortable: true, editable: true},
{text: "Destination", value:"goto", sortable: true, editable: true},
{text: "Domain", value:"domain", sortable: true, editable: true},
{text: "Created", value:"created", sortable: true, editable: true},
{text: "Modified", value:"modified", sortable: true, editable: true},
{text: "Active", value:"active", sortable: true, editable: true},
{text: "Actions", value:"actions", sortable: false, editable: false},
attrs: [{
text: "Address",
value: "address",
sortable: true,
editable: true
},
{
text: "Destination",
value: "goto",
sortable: true,
editable: true
},
{
text: "Domain",
value: "domain",
sortable: true,
editable: true
},
{
text: "Created",
value: "created",
sortable: true,
editable: false
},
{
text: "Modified",
value: "modified",
sortable: true,
editable: false
},
{
text: "Active",
value: "active",
sortable: true,
editable: false
},
{
text: "Actions",
value: "actions",
sortable: false,
editable: false
},
],
itemlist: [],
item: {}
@ -29,19 +63,26 @@ export default {
List
},
props: ["vmailapi"],
mounted () {
this.alias = new Alias(this.vmailapi.GetUrl())
mounted() {
this.alias = new Vmailobject(this.vmailapi.GetUrl(), this.$el.className)
this.RefreshData();
},
methods: {
RefreshData() {
this.alias.GetList().then(response => {
this.itemlist = response.data;
})
},
methods: {
DeleteItem (name) {
this.alias = new Alias(this.vmailapi.GetUrl());
this.alias.DeleteItem(name).then(response => {
ModifyItem(id, item) {
this.alias.ModifyItem(id, item).then(response => {
return response;
});
},
DeleteItem(id) {
this.alias.DeleteItem(id).then(response => {
return response;
});
}
}
}
}
</script>

View File

@ -6,14 +6,12 @@
</template>
<script>
export default {
export default {
name: 'Home',
data() {
return {
}
},
components: {
return {}
},
components: {},
props: ["vmailapi"]
}
}
</script>

View File

@ -1,24 +1,37 @@
<template>
<div class="log">
<List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
<List :headers="attrs" :itemlist="itemlist" :object="log" />
</div>
</template>
<script>
import List from '@/components/list.vue'
import Log from '@/classes/log.js'
import Vmailobject from '@/classes/vmailobject.js'
import List from '@/components/list.vue'
export default {
export default {
name: 'Log',
data() {
return {
attrs : [
{text: "ID", value:"id"},
{text: "Timestamp", value:"timestamp"},
{text: "Username", value:"username"},
{text: "Domain", value:"domain"},
{text: "Action", value:"action"},
{text: "Data", value:"data"},
attrs: [{
text: "Date",
value: "timestamp"
},
{
text: "Username / IP",
value: "username"
},
{
text: "Domain",
value: "domain"
},
{
text: "Action",
value: "action"
},
{
text: "Modified Data",
value: "data"
},
],
itemlist: [],
item: {}
@ -28,11 +41,16 @@ export default {
List
},
props: ["vmailapi"],
mounted () {
let log = new Log(this.vmailapi.GetUrl())
log.GetList().then(response => {
mounted() {
this.log = new Vmailobject(this.vmailapi.GetUrl(), this.$el.className)
this.RefreshData()
},
methods: {
RefreshData() {
this.log.GetList().then(response => {
this.itemlist = response.data;
})
}
}
}
}
</script>

View File

@ -1,29 +1,83 @@
<template>
<div class="mailbox">
<List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
<List :headers="attrs" :itemlist="itemlist" :object="mailbox" />
</div>
</template>
<script>
import List from '@/components/list.vue'
import Mailbox from '@/classes/mailbox.js'
import Vmailobject from '@/classes/vmailobject.js'
import List from '@/components/list.vue'
export default {
export default {
name: 'Mailbox',
data() {
return {
attrs : [
{text: "Username", value:"username", sortable: true, editable: true},
{text: "Name", value:"name", sortable: true, editable: true},
{text: "Maildir", value:"maildir", sortable: true, editable: true},
{text: "Quota", value:"quota", sortable: true, editable: true},
{text: "Created", value:"created", sortable: true, editable: true},
{text: "Modified", value:"modified", sortable: true, editable: true},
{text: "Active", value:"active", sortable: true, editable: true},
{text: "Domain", value:"domain", sortable: true, editable: true},
{text: "LocalPart", value:"localpart", sortable: true, editable: true},
{text: "Phone", value:"phone", sortable: true, editable: true},
{text: "Actions", value:"actions", sortable: false, editable: false},
attrs: [{
text: "Username",
value: "username",
sortable: true,
editable: true
},
{
text: "Name",
value: "name",
sortable: true,
editable: true
},
{
text: "Mail directory",
value: "maildir",
sortable: true,
editable: true
},
{
text: "Quota",
value: "quota",
sortable: true,
editable: true
},
{
text: "Created",
value: "created",
sortable: true,
editable: false
},
{
text: "Modified",
value: "modified",
sortable: true,
editable: false
},
{
text: "Active",
value: "active",
sortable: true,
editable: false
},
{
text: "Domain",
value: "domain",
sortable: true,
editable: true
},
{
text: "Email local part",
value: "localpart",
sortable: true,
editable: true
},
{
text: "Phone",
value: "phone",
sortable: true,
editable: true
},
{
text: "Actions",
value: "actions",
sortable: false,
editable: false
},
],
itemlist: [],
item: {}
@ -33,19 +87,26 @@ export default {
List
},
props: ["vmailapi"],
mounted () {
let mailbox = new Mailbox(this.vmailapi.GetUrl())
mailbox.GetList().then(response => {
mounted() {
this.mailbox = new Vmailobject(this.vmailapi.GetUrl(), this.$el.className)
this.RefreshData()
},
methods: {
RefreshData() {
this.mailbox.GetList().then(response => {
this.itemlist = response.data;
})
},
methods: {
DeleteItem (name) {
this.mailbox = new Mailbox(this.vmailapi.GetUrl());
this.mailbox.DeleteItem(name).then(response => {
ModifyItem(id, item) {
this.mailbox.ModifyItem(id, item).then(response => {
return response;
});
},
DeleteItem(id) {
this.mailbox.DeleteItem(id).then(response => {
return response;
});
}
}
}
}
</script>