add modal to add new imap mailbox
This commit is contained in:
@@ -12,15 +12,15 @@ import { RouterView } from "vue-router";
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from './views/sidebar/Sidebar';
|
||||
import RoomView from './views/room/RoomView';
|
||||
import Sidebar from './views/sidebar/Sidebar'
|
||||
import RoomView from './views/room/RoomView'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Sidebar,
|
||||
RoomView
|
||||
}
|
||||
RoomView,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
3
front/src/assets/close.svg
Normal file
3
front/src/assets/close.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.2756 4.69628C21.8922 4.07969 21.8922 3.08 21.2756 2.46342C20.659 1.84683 19.6593 1.84683 19.0427 2.46342L11.8917 9.61447L4.74063 2.46342C4.12404 1.84683 3.12436 1.84683 2.50777 2.46342C1.89118 3.08 1.89118 4.07969 2.50777 4.69628L9.65882 11.8473L2.20145 19.3047C1.58487 19.9213 1.58487 20.921 2.20145 21.5376C2.81804 22.1541 3.81773 22.1541 4.43431 21.5376L11.8917 14.0802L19.349 21.5375C19.9656 22.1541 20.9653 22.1541 21.5819 21.5375C22.1985 20.921 22.1985 19.9213 21.5819 19.3047L14.1245 11.8473L21.2756 4.69628Z" fill="#737D8C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 650 B |
7
front/src/services/API.js
Normal file
7
front/src/services/API.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default(url='localhost') => {
|
||||
return axios.create({
|
||||
baseURL: url,
|
||||
});
|
||||
}
|
||||
7
front/src/services/imapAPI.js
Normal file
7
front/src/services/imapAPI.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import API from './API'
|
||||
|
||||
export default {
|
||||
getQuote() {
|
||||
return API().get('/');
|
||||
}
|
||||
}
|
||||
222
front/src/views/modals/AddMailboxModal.vue
Normal file
222
front/src/views/modals/AddMailboxModal.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<script setup>
|
||||
import { ref, computed, watchEffect } from 'vue'
|
||||
import Modal from './Modal'
|
||||
import API from '../../services/imapAPI';
|
||||
|
||||
const modal = ref(true);
|
||||
|
||||
const email = ref("");
|
||||
const pwd = ref("");
|
||||
const xoauth = ref("");
|
||||
const xoauth2 = ref("");
|
||||
const host = ref("");
|
||||
const port = ref("993");
|
||||
|
||||
const error = ref("");
|
||||
|
||||
const knownHosts = {
|
||||
'outlook.com': {
|
||||
'host': 'outlook.office365.com',
|
||||
},
|
||||
'hotmail.com': {
|
||||
'host': 'outlook.office365.com',
|
||||
},
|
||||
'live.com': {
|
||||
'host': 'outlook.office365.com',
|
||||
},
|
||||
'zoho.com': {
|
||||
'host': 'imap.zoho.eu',
|
||||
},
|
||||
'yahoo.com': {
|
||||
'host': 'imap.mail.yahoo.com',
|
||||
},
|
||||
'icloud.com': {
|
||||
'host': 'imap.mail.me.com',
|
||||
},
|
||||
}
|
||||
|
||||
const refHost = computed({
|
||||
set: (val) => {
|
||||
host.value = val
|
||||
}
|
||||
});
|
||||
|
||||
const err = computed({
|
||||
set: (val) => { error.value = val }
|
||||
});
|
||||
|
||||
function validateEmail(email) {
|
||||
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(String(email).toLowerCase());
|
||||
}
|
||||
|
||||
function checkError() {
|
||||
if (!validateEmail(email.value)) {
|
||||
err.value = "The email is not valid.";
|
||||
} else if (pwd.value == xoauth.value == xoauth2.value == "") {
|
||||
err.value = "You need at least one authentification method.";
|
||||
} else if ([pwd.value, xoauth.value, xoauth2.value].filter((val) => val != "").length > 1) {
|
||||
err.value = "You need only one authentification method.";
|
||||
} else if (host.value == "" || port.value == "") {
|
||||
err.value = "You need to complete the port and the host.";
|
||||
} else {
|
||||
err.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
function addMailboxRequest(event) {
|
||||
console.log(event.target.disabled = true)
|
||||
checkError();
|
||||
API.getQuote().then((res) => {
|
||||
console.log(res.status);
|
||||
}).catch((err) => {
|
||||
console.log(err.request.status)
|
||||
});
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (error.value != "") {
|
||||
checkError();
|
||||
}
|
||||
});
|
||||
|
||||
function mailChange() {
|
||||
if (email.value.includes('@')) {
|
||||
const domain = email.value.split('@')[1];
|
||||
if (!knownHosts[domain]) {
|
||||
refHost.value = ("imap."+domain);
|
||||
} else {
|
||||
refHost.value = (knownHosts[domain].host);
|
||||
}
|
||||
// todo check if manual
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<button
|
||||
@click="modal = true"
|
||||
>
|
||||
Open Modal!
|
||||
</button>
|
||||
<Modal
|
||||
v-if="modal"
|
||||
title="Add mailbox"
|
||||
@close-modal="modal = false"
|
||||
>
|
||||
<template v-slot:body>
|
||||
<div class="field">
|
||||
<label>Email: </label>
|
||||
<input @change="mailChange" v-model="email" type="email" required>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>Authentification method</legend>
|
||||
<div class="field">
|
||||
<label>Plain password:</label>
|
||||
<input v-model="pwd" type="password">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Xoauth:</label>
|
||||
<input v-model="xoauth" type="text">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Xoauth2:</label>
|
||||
<input v-model="xoauth2" type="text">
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<div class="config">
|
||||
<input v-model="host" id="host" type="text" placeholder="imap host">
|
||||
<input v-model="port" id="port" type="number" placeholder="port">
|
||||
</div>
|
||||
<!-- tls -->
|
||||
<div>
|
||||
<button :disabled="error != ''" @click="addMailboxRequest">Add</button>
|
||||
{{ error }}
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.field > input {
|
||||
margin-top: 2px;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin-top: 5px;
|
||||
border-radius: 5px;
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.config {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
#host {
|
||||
margin-right: 8px;
|
||||
width: calc(95% - 100px);
|
||||
}
|
||||
|
||||
#port {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 5px;
|
||||
padding: 7px 18px;
|
||||
background-color: #09a35b;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
input {
|
||||
-webkit-box-flex: 1;
|
||||
background-color: #303a46;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
font-family: inherit;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 400;
|
||||
min-width: 0;
|
||||
padding: 8px 9px;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
80
front/src/views/modals/Modal.vue
Normal file
80
front/src/views/modals/Modal.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<script setup>
|
||||
import { vOnClickOutside } from '@vueuse/components'
|
||||
import { defineEmits, defineProps } from 'vue'
|
||||
|
||||
const emit = defineEmits(['close-modal']);
|
||||
const props = defineProps({ title: String });
|
||||
|
||||
function close() {
|
||||
emit('close-modal');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal" v-on-click-outside="close">
|
||||
<header class="modal-header">
|
||||
<h2>{{ props.title }}</h2>
|
||||
<div class="close-button" @click="close"></div>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="modal-body">
|
||||
<slot name="body">
|
||||
This is the default body!
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.modal-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 4000;
|
||||
|
||||
background-color: #000;
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
background-color: #1D1D23;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: inline-block;
|
||||
font-size: 2.4rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
background-color: #9fa9ba;
|
||||
cursor: pointer;
|
||||
height: 18px;
|
||||
mask: url(../../assets/close.svg);
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: cover;
|
||||
width: 18px;
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<Folders />
|
||||
<Mailboxes />
|
||||
<Users id="users"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Folders from './folders/Folders';
|
||||
import Users from './users/Users.vue';
|
||||
import Mailboxes from './mailboxes/Mailboxes'
|
||||
import Users from './users/Users.vue'
|
||||
|
||||
export default {
|
||||
name: 'Sidebar',
|
||||
components: {
|
||||
Folders,
|
||||
Mailboxes,
|
||||
Users,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<template>
|
||||
<div id="main" @click="setActiveMailbox(data.id)">
|
||||
{{ data.mail }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Folder',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
data: {mail: String, id: Number}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setActiveMailbox'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#main {
|
||||
max-width: 32px;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
padding: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div:hover {
|
||||
background-color: aqua !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<div id="userMenu">
|
||||
<!-- deconnect -->
|
||||
</div>
|
||||
<span class="divider"></span>
|
||||
<Folder :data="{'id': -1, 'mail': 'all'}"/>
|
||||
<Folder v-for="(mailbox, index) in mailboxes" :key="index" :data="mailbox"/>
|
||||
<span class="divider"></span>
|
||||
<!-- <h5>Folders: </h5> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import Folder from './Folder.vue'
|
||||
|
||||
export default {
|
||||
name: 'Folders',
|
||||
components: {
|
||||
Folder
|
||||
},
|
||||
computed: {
|
||||
...mapState(['mailboxes'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 5px;
|
||||
background-color: #2A2A33;
|
||||
}
|
||||
|
||||
#userMenu {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: yellow !important;
|
||||
|
||||
}
|
||||
.divider {
|
||||
border-top: 1px solid #bbb;
|
||||
margin: 3px 0;
|
||||
}
|
||||
</style>
|
||||
48
front/src/views/sidebar/mailboxes/Mailbox.vue
Normal file
48
front/src/views/sidebar/mailboxes/Mailbox.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="container" @click="setActiveMailbox(data.id)" :class="activeMailbox == data.id && 'active'">
|
||||
{{ data.mail }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations, mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Mailbox',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
data: {mail: String, id: Number}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['activeMailbox'])
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setActiveMailbox'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
max-width: 32px;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
padding: 5px;
|
||||
margin: 1px 0;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.container:hover {
|
||||
background-color: aqua !important;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 2px solid white;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
54
front/src/views/sidebar/mailboxes/Mailboxes.vue
Normal file
54
front/src/views/sidebar/mailboxes/Mailboxes.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<div id="userMenu">
|
||||
<!-- deconnect -->
|
||||
</div>
|
||||
<span class="divider"></span>
|
||||
<Mailbox :data="{'id': -1, 'mail': 'all'}"/>
|
||||
<Mailbox v-for="(mailbox, index) in mailboxes" :key="index" :data="mailbox"/>
|
||||
<span class="divider"></span>
|
||||
|
||||
<AddMailboxModal />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import Mailbox from './Mailbox'
|
||||
import AddMailboxModal from '../../modals/AddMailboxModal'
|
||||
|
||||
export default {
|
||||
name: 'Mailboxes',
|
||||
components: {
|
||||
Mailbox,
|
||||
AddMailboxModal
|
||||
},
|
||||
computed: {
|
||||
...mapState(['mailboxes'])
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
background-color: #2A2A33;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#userMenu {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: yellow !important;
|
||||
|
||||
}
|
||||
.divider {
|
||||
border-top: 1px solid #bbb;
|
||||
margin: 5px 0;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
@@ -5,7 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters } from 'vuex'
|
||||
import User from './User'
|
||||
|
||||
export default {
|
||||
|
||||
Reference in New Issue
Block a user