updated vmail-ui

This commit is contained in:
Paul 2020-07-11 15:57:02 +02:00
parent fe7e45dece
commit 528855a5ab
22 changed files with 455 additions and 200 deletions

5
package-lock.json generated
View File

@ -1065,6 +1065,11 @@
"postcss": "7.0.32" "postcss": "7.0.32"
} }
}, },
"@mdi/font": {
"version": "5.3.45",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-5.3.45.tgz",
"integrity": "sha512-SD5d2vHEKRvDCInZQFXOwiFpBlzpuZOiqwxKf6E+zCt7UDc52TUSrL0+TXqY57VQh/SnTpZVXM+Uvs21OdPFWg=="
},
"@mrmlnc/readdir-enhanced": { "@mrmlnc/readdir-enhanced": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",

View File

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@mdi/font": "^5.3.45",
"axios": "^0.19.2", "axios": "^0.19.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"vue": "^2.6.11", "vue": "^2.6.11",
@ -24,7 +25,7 @@
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"sass": "^1.19.0", "sass": "^1.19.0",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "~2.0.6", "vue-cli-plugin-vuetify": "^2.0.6",
"vue-template-compiler": "^2.6.11", "vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0" "vuetify-loader": "^1.3.0"
}, },

View File

@ -9,6 +9,8 @@
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head> </head>
<body> <body>
<noscript> <noscript>

View File

@ -1,17 +1,39 @@
<template> <template>
<div id="app"> <div id="app">
<div id="nav"> <div id="nav">
<router-link to="/">Home</router-link> <div class="routers">
<router-link to="/admin">Admin</router-link> <v-icon small>mdi-home</v-icon>
<router-link to="/mailbox">Mailbox</router-link> <router-link to="/">Home</router-link>
<router-link to="/alias">Alias</router-link> </div>
<div class="routers">
<v-icon small>mdi-account-settings</v-icon>
<router-link to="/admin">Admin</router-link>
</div>
<div class="routers">
<v-icon small>mdi-email-box</v-icon>
<router-link to="/mailbox">Mailbox</router-link>
</div>
<div class="routers">
<v-icon small>mdi-at</v-icon>
<router-link to="/alias">Alias</router-link>
</div>
<div class="routers">
<v-icon small>mdi-format-list-checkbox</v-icon>
<router-link to="/log">Logs</router-link>
</div>
<div id="menu">
<Menu/>
</div>
<div id="view">
<router-view :vmailapi="vmailapi"/> <router-view :vmailapi="vmailapi"/>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import VmailApi from "@/classes/VmailApi.js" import VmailApi from "@/classes/vmailapi.js"
import Menu from "@/components/menu.vue"
export default { export default {
name: 'App', name: 'App',
@ -24,6 +46,7 @@ export default {
} }
}, },
components: { components: {
Menu
}, },
mounted: function() { mounted: function() {
this.vmailapi = new VmailApi(this.config.apiurl); this.vmailapi = new VmailApi(this.config.apiurl);
@ -38,19 +61,33 @@ export default {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
/*text-align: center;*/ /*text-align: center;*/
color: #2c3e50; color: #2c4e50;
} }
#nav { #nav {
padding: 0px; padding: 10px;
}
#view {
padding-top: 50px;
} }
#nav a { #nav a {
font-weight: bold; font-weight: bold;
color: #2c3e50; color: #151d25;
} }
#nav a.router-link-exact-active { #nav a.router-link-exact-active {
color: #42b983; color: #0fb1e2;
}
#menu {
float: right;
}
.routers {
float: left;
padding-left: 5px;
padding-right: 5px;
} }
</style> </style>

View File

@ -1,5 +1,5 @@
import Axios from "axios"; import Axios from "axios";
import VmailApi from "@/classes/VmailApi.js" import VmailApi from "@/classes/vmailapi.js"
export default class Admin { export default class Admin {
constructor(url) { constructor(url) {
@ -11,7 +11,7 @@ export default class Admin {
return Axios.get(this.vmailapi.GetUrl() + this.apipath) return Axios.get(this.vmailapi.GetUrl() + this.apipath)
} }
Get(name) { GetItem(name) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name) return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name)
} }
} }

View File

@ -1,5 +1,5 @@
import Axios from "axios"; import Axios from "axios";
import VmailApi from "@/classes/VmailApi.js" import VmailApi from "@/classes/vmailapi.js"
export default class Alias { export default class Alias {
constructor(url) { constructor(url) {

14
src/classes/log.js Normal file
View File

@ -0,0 +1,14 @@
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,5 +1,5 @@
import Axios from "axios"; import Axios from "axios";
import VmailApi from "@/classes/VmailApi.js" import VmailApi from "@/classes/vmailapi.js"
export default class Mailbox { export default class Mailbox {
constructor(url) { constructor(url) {
@ -11,7 +11,7 @@ export default class Mailbox {
return Axios.get(this.vmailapi.GetUrl() + this.apipath) return Axios.get(this.vmailapi.GetUrl() + this.apipath)
} }
Get(name) { GetItem(name) {
return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name) return Axios.get(this.vmailapi.GetUrl() + this.apipath + "/" + name)
} }
} }

View File

@ -0,0 +1,151 @@
<template>
<v-container>
<v-row class="text-center">
<v-col cols="12">
<v-img
:src="require('../assets/logo.svg')"
class="my-3"
contain
height="200"
/>
</v-col>
<v-col class="mb-4">
<h1 class="display-2 font-weight-bold mb-3">
Welcome to Vuetify
</h1>
<p class="subheading font-weight-regular">
For help and collaboration with other Vuetify developers,
<br>please join our online
<a
href="https://community.vuetifyjs.com"
target="_blank"
>Discord Community</a>
</p>
</v-col>
<v-col
class="mb-5"
cols="12"
>
<h2 class="headline font-weight-bold mb-3">
What's next?
</h2>
<v-row justify="center">
<a
v-for="(next, i) in whatsNext"
:key="i"
:href="next.href"
class="subheading mx-3"
target="_blank"
>
{{ next.text }}
</a>
</v-row>
</v-col>
<v-col
class="mb-5"
cols="12"
>
<h2 class="headline font-weight-bold mb-3">
Important Links
</h2>
<v-row justify="center">
<a
v-for="(link, i) in importantLinks"
:key="i"
:href="link.href"
class="subheading mx-3"
target="_blank"
>
{{ link.text }}
</a>
</v-row>
</v-col>
<v-col
class="mb-5"
cols="12"
>
<h2 class="headline font-weight-bold mb-3">
Ecosystem
</h2>
<v-row justify="center">
<a
v-for="(eco, i) in ecosystem"
:key="i"
:href="eco.href"
class="subheading mx-3"
target="_blank"
>
{{ eco.text }}
</a>
</v-row>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'HelloWorld',
data: () => ({
ecosystem: [
{
text: 'vuetify-loader',
href: 'https://github.com/vuetifyjs/vuetify-loader',
},
{
text: 'github',
href: 'https://github.com/vuetifyjs/vuetify',
},
{
text: 'awesome-vuetify',
href: 'https://github.com/vuetifyjs/awesome-vuetify',
},
],
importantLinks: [
{
text: 'Documentation',
href: 'https://vuetifyjs.com',
},
{
text: 'Chat',
href: 'https://community.vuetifyjs.com',
},
{
text: 'Made with Vuetify',
href: 'https://madewithvuejs.com/vuetify',
},
{
text: 'Twitter',
href: 'https://twitter.com/vuetifyjs',
},
{
text: 'Articles',
href: 'https://medium.com/vuetify',
},
],
whatsNext: [
{
text: 'Explore components',
href: 'https://vuetifyjs.com/components/api-explorer',
},
{
text: 'Select a layout',
href: 'https://vuetifyjs.com/getting-started/pre-made-layouts',
},
{
text: 'Frequently Asked Questions',
href: 'https://vuetifyjs.com/getting-started/frequently-asked-questions',
},
],
}),
}
</script>

View File

@ -1,50 +0,0 @@
<template>
<div class="AdminsList">
<v-data-table
:headers="headers"
:items="list"
:items-per-page="5"
class="elevation-1"
></v-data-table>
</div>
</template>
<script>
import Admin from "@/classes/Admin.js"
export default {
name: 'AdminsList',
data: function () {
return {
list: [],
item: {}
}
},
props: ["vmailapi", "headers"],
mounted () {
let admin = new Admin(this.vmailapi.GetUrl())
admin.GetList().then(response => {
this.list = response.data;
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -1,50 +0,0 @@
<template>
<div class="Alias">
<v-data-table
:headers="headers"
:items="list"
:items-per-page="5"
class="elevation-1"
></v-data-table>
</div>
</template>
<script>
import Alias from "@/classes/Alias.js"
export default {
name: 'Alias',
data: function () {
return {
list: [],
item: {}
}
},
props: ["vmailapi", "headers"],
mounted () {
let alias = new Alias(this.vmailapi.GetUrl())
alias.GetList().then(response => {
this.list = response.data;
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

73
src/components/list.vue Normal file
View File

@ -0,0 +1,73 @@
<template>
<div class="List">
<v-data-table
:headers="headers"
:items="itemlist"
:items-per-page="20"
class="elevation-1">
<template v-slot:item.actions="{ item }">
<v-icon
small
class="mr-2"
@click="editItem(item)"
>
mdi-pencil
</v-icon>
<v-icon
small
@click="deleteItem(item)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</div>
</template>
<script>
export default {
name: 'List',
data () {
return {
colsize: 3,
editedItem: {}
}
},
computed: {
position() {
return this.itemlist.length() + 1
}
},
methods: {
editItem (item) {
this.editedIndex = this.itemlist.indexOf(item)
this.editedItem = Object.assign({}, item)
this.dialog = true
},
deleteItem (item) {
const index = this.itemlist.indexOf(item)
confirm('Are you sure you want to delete this item?') && this.itemlist.splice(index, 1)
}
},
props: ["vmailapi", "headers", "itemlist"]
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -1,50 +0,0 @@
<template>
<div class="Mailbox">
<v-data-table
:headers="headers"
:items="list"
:items-per-page="5"
class="elevation-1"
></v-data-table>
</div>
</template>
<script>
import Mailbox from "@/classes/Mailbox.js"
export default {
name: 'Mailbox',
data: function () {
return {
list: [],
item: {}
}
},
props: ["vmailapi", "headers"],
mounted () {
let mailbox = new Mailbox(this.vmailapi.GetUrl())
mailbox.GetList().then(response => {
this.list = response.data;
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

39
src/components/menu.vue Normal file
View File

@ -0,0 +1,39 @@
<template>
<div class="text-center">
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
Menu
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
</template>
<script>
export default {
name: 'Menu',
data: () => ({
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' },
],
}),
}
</script>

View File

@ -4,6 +4,7 @@ import router from './router'
import vuetify from './plugins/vuetify'; import vuetify from './plugins/vuetify';
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.config.silent = true;
new Vue({ new Vue({
router, router,

View File

@ -4,6 +4,7 @@ import Home from '../views/Home.vue'
import Admin from '../views/Admin.vue' import Admin from '../views/Admin.vue'
import Mailbox from '../views/Mailbox.vue' import Mailbox from '../views/Mailbox.vue'
import Alias from '../views/Alias.vue' import Alias from '../views/Alias.vue'
import Log from '../views/Log.vue'
Vue.use(VueRouter) Vue.use(VueRouter)
@ -20,6 +21,12 @@ Vue.use(VueRouter)
component: Admin, component: Admin,
props: true props: true
}, },
{
path: '/alias',
name: 'Alias',
component: Alias,
props: true
},
{ {
path: '/mailbox', path: '/mailbox',
name: 'Mailbox', name: 'Mailbox',
@ -27,9 +34,9 @@ Vue.use(VueRouter)
props: true props: true
}, },
{ {
path: '/alias', path: '/log',
name: 'Alias', name: 'Log',
component: Alias, component: Log,
props: true props: true
} }
] ]

View File

@ -1,26 +1,39 @@
<template> <template>
<div class="Admin"> <div class="Admin">
<admin :vmailapi="vmailapi" :headers="attrs"/> <List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
</div> </div>
</template> </template>
<script> <script>
// @ is an alias to /src import List from '@/components/list.vue'
import admin from '@/components/admin.vue' import Admin from '@/classes/admin.js'
export default { export default {
name: 'Admins', name: 'Admins',
data() { data() {
return { return {
attrs : [ attrs : [
{text: "Username", value:"Username"}, {text: "Username", value:"username"},
{text: "Active", value:"Active"}, {text: "Created", value:"created"},
] {text: "Modified", value:"modified"},
{text: "Active", value:"active"},
{text: "Superadmin", value:"superadmin"},
{text: "Phone", value:"phone"},
{text: "Actions", value:"actions", sortable: false},
],
itemlist: [],
item: {}
} }
}, },
components: { components: {
admin List
}, },
props: ["vmailapi"] props: ["vmailapi"],
mounted () {
let admin = new Admin(this.vmailapi.GetUrl())
admin.GetList().then(response => {
this.itemlist = response.data;
})
}
} }
</script> </script>

View File

@ -1,28 +1,39 @@
<template> <template>
<div class="alias"> <div class="alias">
<alias :vmailapi="vmailapi" :headers="attrs"/> <List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
</div> </div>
</template> </template>
<script> <script>
// @ is an alias to /src import List from '@/components/list.vue'
import alias from '@/components/alias.vue' import Alias from '@/classes/alias.js'
export default { export default {
name: 'Alias', name: 'Alias',
data() { data() {
return { return {
attrs : [ attrs : [
{text: "Address", value:"Address"}, {text: "Address", value:"address"},
{text: "Destination", value:"Goto"}, {text: "Destination", value:"goto"},
{text: "Domain", value:"Domain"}, {text: "Domain", value:"domain"},
{text: "Active", value:"Active"}, {text: "Created", value:"created"},
] {text: "Modified", value:"modified"},
{text: "Active", value:"active"},
{text: "Actions", value:"actions", sortable: false},
],
itemlist: [],
item: {}
} }
}, },
components: { components: {
alias List
}, },
props: ["vmailapi"] props: ["vmailapi"],
mounted () {
let alias = new Alias(this.vmailapi.GetUrl())
alias.GetList().then(response => {
this.itemlist = response.data;
})
}
} }
</script> </script>

View File

@ -1,11 +1,10 @@
<template> <template>
<div class="Home"> <div class="Home">
<h1>Vmail Application</h1>
</div> </div>
</template> </template>
<script> <script>
// @ is an alias to /src
export default { export default {
name: 'Home', name: 'Home',
data() { data() {

38
src/views/Log.vue Normal file
View File

@ -0,0 +1,38 @@
<template>
<div class="log">
<List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
</div>
</template>
<script>
import List from '@/components/list.vue'
import Log from '@/classes/log.js'
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"},
],
itemlist: [],
item: {}
}
},
components: {
List
},
props: ["vmailapi"],
mounted () {
let log = new Log(this.vmailapi.GetUrl())
log.GetList().then(response => {
this.itemlist = response.data;
})
}
}
</script>

View File

@ -1,29 +1,43 @@
<template> <template>
<div class="mailbox"> <div class="mailbox">
<mailbox :vmailapi="vmailapi" :headers="attrs"/> <List :vmailapi="vmailapi" :headers="attrs" :itemlist="itemlist"/>
</div> </div>
</template> </template>
<script> <script>
// @ is an alias to /src import List from '@/components/list.vue'
import mailbox from '@/components/mailbox.vue' import Mailbox from '@/classes/mailbox.js'
export default { export default {
name: 'Mailbox', name: 'Mailbox',
data() { data() {
return { return {
attrs : [ attrs : [
{text: "Username", value:"Username"}, {text: "Username", value:"username"},
{text: "Active", value:"Active"}, {text: "Name", value:"name"},
{text: "Maildir", value:"Maildir"}, {text: "Maildir", value:"maildir"},
{text: "Created", value:"Created"}, {text: "Quota", value:"quota"},
{text: "Modified", value:"Modified"}, {text: "Created", value:"created"},
] {text: "Modified", value:"modified"},
{text: "Active", value:"active"},
{text: "Domain", value:"domain"},
{text: "LocalPart", value:"localpart"},
{text: "Phone", value:"phone"},
{text: "Actions", value:"actions", sortable: false},
],
itemlist: [],
item: {}
} }
}, },
components: { components: {
mailbox List
}, },
props: ["vmailapi"] props: ["vmailapi"],
mounted () {
let mailbox = new Mailbox(this.vmailapi.GetUrl())
mailbox.GetList().then(response => {
this.itemlist = response.data;
})
}
} }
</script> </script>