add modal to add new imap mailbox

This commit is contained in:
grimhilt
2023-02-27 22:34:36 +01:00
parent b0a0fe2f83
commit ea0bfd5a54
18 changed files with 673 additions and 97 deletions

View 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>

View 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>

View File

@@ -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,
}
}

View File

@@ -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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -5,7 +5,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import { mapGetters } from 'vuex'
import User from './User'
export default {