add modal to add new imap mailbox
This commit is contained in:
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