Compare commits
No commits in common. "adb7a1161ad5fa90beff42e70bb557e213428cb9" and "edddf9afbfac4e5a34fa6761b359fd87d8c3e6a7" have entirely different histories.
adb7a1161a
...
edddf9afbf
@ -12,10 +12,10 @@ export default class Account {
|
||||
}
|
||||
|
||||
static async register(body, res: Response) {
|
||||
const { email, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls } = body;
|
||||
const { email, pwd, xoauth, xoauth2, host, port, tls } = body;
|
||||
getAddressId(email).then((addressId) => {
|
||||
registerAccount(addressId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls)
|
||||
.then((mailboxId) => {0
|
||||
registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls)
|
||||
.then((mailboxId) => {
|
||||
res.status(statusCodes.OK).json({ id: mailboxId });
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { execQueryAsync, execQueryAsyncWithId } from "./db";
|
||||
import { queryCcId, queryToId, queryFromId } from "./utils/addressQueries";
|
||||
|
||||
export async function registerAccount(userId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls) {
|
||||
export async function registerAccount(userId, pwd, xoauth, xoauth2, host, port, tls) {
|
||||
const query = `
|
||||
INSERT INTO app_account
|
||||
(user_id, account_pwd, xoauth, xoauth2, imap_host, smtp_host, imap_port, smtp_port, tls) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
(user_id, account_pwd, xoauth, xoauth2, host, port, tls) VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
const values = [userId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls];
|
||||
const values = [userId, pwd, xoauth, xoauth2, host, port, tls];
|
||||
return await execQueryAsyncWithId(query, values);
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,8 @@ CREATE TABLE app_account (
|
||||
account_pwd BINARY(22),
|
||||
xoauth VARCHAR(116),
|
||||
xoauth2 VARCHAR(116),
|
||||
imap_host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
||||
imap_port INT(5) NOT NULL DEFAULT 993,
|
||||
smtp_host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
||||
smtp_port INT(5) NOT NULL DEFAULT 465,
|
||||
host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
||||
port INT(5) NOT NULL DEFAULT 143,
|
||||
tls BOOLEAN NOT NULL DEFAULT true,
|
||||
PRIMARY KEY (account_id),
|
||||
FOREIGN KEY (user_id) REFERENCES address(address_id) ON DELETE CASCADE
|
||||
|
@ -6,11 +6,9 @@ export async function getAllAccounts() {
|
||||
app_account.account_id AS id,
|
||||
address.email AS user,
|
||||
app_account.account_pwd AS password,
|
||||
app_account.imap_host,
|
||||
app_account.imap_port,
|
||||
app_account.smtp_host,
|
||||
app_account.smtp_port,
|
||||
app_account.tls
|
||||
app_account.host AS host,
|
||||
app_account.port AS port,
|
||||
app_account.tls AS tls
|
||||
FROM app_account INNER JOIN address
|
||||
WHERE address.address_id = app_account.user_id
|
||||
`;
|
||||
|
@ -14,9 +14,9 @@ export class ImapInstance {
|
||||
this.imap = new Imap({
|
||||
user: account.user,
|
||||
password: account.password,
|
||||
tlsOptions: { servername: account.imap_host },
|
||||
host: account.imap_host,
|
||||
port: account.imap_port,
|
||||
tlsOptions: { servername: account.host },
|
||||
host: account.host,
|
||||
port: account.port,
|
||||
tls: account.tls,
|
||||
});
|
||||
this.account = account;
|
||||
|
@ -5,11 +5,12 @@ export class SmtpInstance {
|
||||
transporter: Transporter;
|
||||
user: string;
|
||||
|
||||
constructor(account: { user: string; password: string, smtp_host: string, smtp_port: number }) {
|
||||
constructor(account: { user: string; password: string }) {
|
||||
// todo store other data
|
||||
this.user = account.user;
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: account.smtp_host,
|
||||
port: account.smtp_port,
|
||||
host: "smtp.gmail.com",
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: account.user,
|
||||
|
@ -5,12 +5,10 @@
|
||||
"pwd": { "type": "string" },
|
||||
"xoauth": { "type": "string" },
|
||||
"xoauth2": { "type": "string" },
|
||||
"imapHost": { "type": "string", "format": "hostname" },
|
||||
"smtpHost": { "type": "string", "format": "hostname" },
|
||||
"imapPort": { "type": "number", "maximum": 65535 },
|
||||
"smtpPort": { "type": "number", "maximum": 65535 },
|
||||
"host": { "type": "string", "format": "hostname" },
|
||||
"port": { "type": "number", "maximum": 65535 },
|
||||
"tls": { "type": "boolean" }
|
||||
},
|
||||
"required": ["email", "imapHost", "smtpHost", "imapPort", "smtpPort", "tls"],
|
||||
"required": ["email", "host", "port", "tls"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -142,11 +142,11 @@ function mailChange() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<Input label="Plain password:" v-model="pwd" type="password" />
|
||||
</div>
|
||||
<!-- <fieldset>
|
||||
<legend>Authentification method</legend>
|
||||
<div class="field">
|
||||
<Input label="Plain password:" v-model="pwd" type="password" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<Input label="Xoauth:" v-model="xoauth" type="text" />
|
||||
</div>
|
||||
|
@ -1,59 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { Address, Message, Room } from "@/store/models/model";
|
||||
import { ref, Ref, watch, defineProps, PropType } from "vue";
|
||||
import { Message } from "@/store/models/model";
|
||||
import { ref, watch, defineProps, PropType } from "vue";
|
||||
import Content from "../structure/message/Content.vue";
|
||||
import Modal from "./Modal.vue";
|
||||
import MemberList from "@/views/room/MemberList.vue";
|
||||
import { removeDuplicates } from "@/utils/array";
|
||||
import { decodeEmojis } from "@/utils/string";
|
||||
|
||||
const props = defineProps({
|
||||
messageId: { type: Number, require: true },
|
||||
message: Object as PropType<Message>,
|
||||
room: Object as PropType<Room>,
|
||||
});
|
||||
const props = defineProps({ messageId: { type: Number, require: true }, message: Object as PropType<Message> });
|
||||
|
||||
const messageId = ref(-1);
|
||||
const fromA = ref<Address[]>([]);
|
||||
const toA = ref<Address[]>([]);
|
||||
const ccA = ref<Address[]>([]);
|
||||
|
||||
const getAddr = (ids: string | undefined, addrs: Address[] | undefined, res: Ref<Address[]>) => {
|
||||
res.value = [];
|
||||
if (!ids || !addrs) return;
|
||||
let idsClean = removeDuplicates(ids.split(","));
|
||||
idsClean.forEach((id) => {
|
||||
let addr = addrs.find((member) => member.id === parseInt(id));
|
||||
if (addr) {
|
||||
res.value.push(addr);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.messageId,
|
||||
(newMessageId: number | undefined) => {
|
||||
if (!newMessageId) return;
|
||||
messageId.value = newMessageId;
|
||||
getAddr(props.message?.fromA, props.room?.members, fromA);
|
||||
getAddr(props.message?.toA, props.room?.members, toA);
|
||||
getAddr(props.message?.ccA, props.room?.members, ccA);
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<Modal v-if="messageId != -1" @close-modal="() => $emit('close')" id="modal">
|
||||
<template v-slot:header>
|
||||
<h2 id="header">
|
||||
{{ decodeEmojis(props.message?.subject) ?? "No Object" }}
|
||||
</h2>
|
||||
</template>
|
||||
<Modal v-if="messageId != -1" @close-modal="() => $emit('close')">
|
||||
<template v-slot:body>
|
||||
<MemberList type="from" :members="fromA" />
|
||||
<MemberList type="to" :members="toA" />
|
||||
<MemberList v-if="ccA.length > 0" type="cc" :members="ccA" />
|
||||
<div>{{ props.message?.subject ?? "No Object" }}</div>
|
||||
<Content type="large" :content="props.message?.content" class="content" />
|
||||
</template>
|
||||
</Modal>
|
||||
@ -64,11 +31,6 @@ watch(
|
||||
.main {
|
||||
min-width: 700px;
|
||||
}
|
||||
|
||||
#header {
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
/* todo define size automatically */
|
||||
.content {
|
||||
width: 700px;
|
||||
|
@ -26,9 +26,7 @@ onUnmounted(() => {
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal" v-on-click-outside="close">
|
||||
<header class="modal-header">
|
||||
<slot name="header">
|
||||
<h2>{{ props.title }}</h2>
|
||||
</slot>
|
||||
<h2>{{ props.title }}</h2>
|
||||
<div class="close-button" @click="close"></div>
|
||||
</header>
|
||||
|
||||
|
@ -190,19 +190,19 @@ const getClasses = (isActive, disabled = false) => {
|
||||
svg="align-center"
|
||||
@click="editor.chain().focus().setTextAlign('center').run()"
|
||||
:classes="getClasses(editor.isActive({ textAlign: 'center' }))"
|
||||
v-tooltip="{ text: 'Align Center', shortcut: ['Ctrl', 'Shift', 'E'] }"
|
||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'E'] }"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="align-right"
|
||||
@click="editor.chain().focus().setTextAlign('right').run()"
|
||||
:classes="getClasses(editor.isActive({ textAlign: 'right' }))"
|
||||
v-tooltip="{ text: 'Align Right', shortcut: ['Ctrl', 'Shift', 'R'] }"
|
||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'R'] }"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="align-justify"
|
||||
@click="editor.chain().focus().setTextAlign('justify').run()"
|
||||
:classes="getClasses(editor.isActive({ textAlign: 'justify' }))"
|
||||
v-tooltip="{ text: 'Justify', shortcut: ['Ctrl', 'Shift', 'J'] }"
|
||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'J'] }"
|
||||
/>
|
||||
</span>
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { defineProps, withDefaults, ref } from "vue";
|
||||
import { decodeEmojis } from "../../../utils/string";
|
||||
import { removeDuplicates } from "../../../utils/array";
|
||||
import { Address, Message } from "@/store/models/model";
|
||||
import Content from "./Content.vue";
|
||||
import Options from "./Options.vue";
|
||||
import { isSeenFc } from "@/utils/flagsUtils";
|
||||
import SvgLoader from "@/components/utils/SvgLoader.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { displayAddresses } from "@/utils/address";
|
||||
|
||||
export interface Props {
|
||||
msg: Message;
|
||||
@ -21,6 +21,17 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const compact = ref(props.compact);
|
||||
|
||||
const displayAddresses = (addressIds: string[] | undefined): string => {
|
||||
if (!addressIds) return "";
|
||||
addressIds = removeDuplicates(addressIds);
|
||||
let res = "";
|
||||
addressIds.forEach((addressId) => {
|
||||
const address = props.members?.find((member) => member.id === parseInt(addressId));
|
||||
if (address) res += address.email;
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
const classes = (): string => {
|
||||
const flags = props.msg?.flags;
|
||||
|
||||
@ -34,15 +45,6 @@ const classes = (): string => {
|
||||
return "msg-basic";
|
||||
};
|
||||
|
||||
const style = (prop: string): string => {
|
||||
// get color of the member that send the message
|
||||
let member = props.members?.find((member) => member.id === parseInt(props.msg?.fromA?.split(",")[0]));
|
||||
if (member?.color) {
|
||||
return `${prop}: ${member.color} !important`;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const router = useRouter();
|
||||
</script>
|
||||
<!-- to if to is more than me
|
||||
@ -52,9 +54,9 @@ const router = useRouter();
|
||||
attachments -->
|
||||
<template>
|
||||
<div class="message" @dblclick="$emit('openMessageView', props.msg?.id)">
|
||||
<div id="context" :style="style('background-color')">
|
||||
<div id="context">
|
||||
<div class="left" id="profile">
|
||||
{{ displayAddresses(props.msg?.fromA?.split(","), props.members) }} - {{ props.msg?.fromA }}
|
||||
{{ displayAddresses(props.msg?.fromA?.split(",")) }} - {{ props.msg?.fromA }}
|
||||
</div>
|
||||
<div class="middle">{{ decodeEmojis(props.msg?.subject) }}</div>
|
||||
<div class="right" id="date">
|
||||
@ -71,7 +73,7 @@ const router = useRouter();
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" :class="[classes()]" :style="style('border-color')">
|
||||
<div class="content" :class="[classes()]">
|
||||
<Content v-if="!compact" :content="props.msg?.content" />
|
||||
<SvgLoader
|
||||
v-if="compact"
|
||||
@ -84,6 +86,7 @@ const router = useRouter();
|
||||
</div>
|
||||
<div id="thread-link" v-if="props.msg?.thread" @click="router.push(`/${props.msg?.thread}`)">
|
||||
<SvgLoader svg="expand-left-fill" />
|
||||
<!-- <SvgLoader svg="expand-left-fill" :loading="true" /> -->
|
||||
<span>Go to the full conversation.</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -130,11 +133,8 @@ const router = useRouter();
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
padding: 6px;
|
||||
padding-top: 6px;
|
||||
flex-direction: row;
|
||||
border: solid 4px var(--quaternary-background);
|
||||
border-top: 0;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.expand-contract {
|
||||
|
@ -15,7 +15,7 @@ export interface Message {
|
||||
content: string;
|
||||
date: string;
|
||||
flags: string[];
|
||||
thread: number | null;
|
||||
threads: number | null;
|
||||
}
|
||||
|
||||
export enum LoadingState {
|
||||
@ -47,6 +47,5 @@ export interface Address {
|
||||
id: number;
|
||||
name: string | null;
|
||||
email: string;
|
||||
color: string | undefined;
|
||||
type: string;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import { decodeEmojis } from "@/utils/string";
|
||||
import { AxiosError, AxiosResponse } from "axios";
|
||||
import { createStore } from "vuex";
|
||||
import { Room, Account, Address, RoomType, Message, LoadingState } from "./models/model";
|
||||
import { removeDuplicates } from "@/utils/array";
|
||||
|
||||
interface RoomFromBack {
|
||||
id: number;
|
||||
@ -155,10 +154,6 @@ const store = createStore<State>({
|
||||
if (!roomMessage) return;
|
||||
payload.messages.forEach((message: any) => {
|
||||
message.flags = message.flags?.split(",") ?? [];
|
||||
// todo fix upstream
|
||||
// message.fromA = message.fromA ? removeDuplicates(message.fromA.split(",").join(",")) : null;
|
||||
// message.toA = message.toA ? removeDuplicates(message.toA.split(",").join(",")) : null;
|
||||
// message.ccA = message.ccA ? removeDuplicates(message.ccA.split(",").join(",")) : null;
|
||||
roomMessage?.messages.push(message);
|
||||
});
|
||||
},
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { Address } from "@/store/models/model";
|
||||
import { removeDuplicates } from "./array";
|
||||
|
||||
export const displayAddresses = (addressIds: string[] | undefined, members: Address[]): string => {
|
||||
if (!addressIds) return "";
|
||||
addressIds = removeDuplicates(addressIds);
|
||||
let res = "";
|
||||
addressIds.forEach((addressId) => {
|
||||
const address = members?.find((member) => member.id === parseInt(addressId));
|
||||
if (address) res += address.email;
|
||||
});
|
||||
return res;
|
||||
};
|
@ -72,12 +72,7 @@ provide("room", room);
|
||||
/>
|
||||
</div>
|
||||
<Composer v-if="shouldDisplayComposer() || true" />
|
||||
<MessageViewModal
|
||||
:room="room"
|
||||
:message="message"
|
||||
:messageId="messageIdView"
|
||||
@close="() => openMessageView(-1)"
|
||||
/>
|
||||
<MessageViewModal :message="message" :messageId="messageIdView" @close="() => openMessageView(-1)" />
|
||||
<!-- todo -->
|
||||
<!-- <ConfirmationModal /> -->
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user