show addresses in front
This commit is contained in:
parent
6b4264fccc
commit
fd253197cc
@ -101,9 +101,9 @@ export async function getMessages(roomId) {
|
|||||||
export async function getMembers(roomId) {
|
export async function getMembers(roomId) {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
address.address_id,
|
address.address_id AS id,
|
||||||
address.address_name,
|
address.address_name AS name,
|
||||||
address.email
|
address.email AS email
|
||||||
FROM app_room_member
|
FROM app_room_member
|
||||||
INNER JOIN address ON address.address_id = app_room_member.member_id
|
INNER JOIN address ON address.address_id = app_room_member.member_id
|
||||||
WHERE app_room_member.room_id = ?
|
WHERE app_room_member.room_id = ?
|
||||||
|
140
back/db/database.dart
Normal file
140
back/db/database.dart
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
Table "addresses" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"name" text
|
||||||
|
"localpart" text [not null]
|
||||||
|
"domain" text [not null]
|
||||||
|
"email" text [not null]
|
||||||
|
|
||||||
|
Indexes {
|
||||||
|
email [unique]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "mailboxes" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"name" text [not null]
|
||||||
|
"uidnext" int [not null, default: 1]
|
||||||
|
"nextmodseq" bigint [not null, default: 1]
|
||||||
|
"first_recent" int [not null, default: 1]
|
||||||
|
"uidvalidity" int [not null, default: 1]
|
||||||
|
|
||||||
|
Indexes {
|
||||||
|
name [unique]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "messages" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"messageID" text [pk, not null]
|
||||||
|
"idate" timestamp [not null]
|
||||||
|
"rfc822size" int
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "mailbox_messages" {
|
||||||
|
"mailbox" int [not null]
|
||||||
|
"uid" int [pk, not null]
|
||||||
|
"message" int [pk, not null]
|
||||||
|
"modseq" bigint [not null]
|
||||||
|
"seen" boolean [not null, default: false]
|
||||||
|
"deleted" boolean [not null, default: false]
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref: mailbox_messages.mailbox > mailboxes.id
|
||||||
|
Ref: mailbox_messages.message - messages.id
|
||||||
|
|
||||||
|
Table "bodyparts" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"bytes" int [not null]
|
||||||
|
"hash" text [not null]
|
||||||
|
"text" text
|
||||||
|
"data" binary
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "part_numbers" {
|
||||||
|
"message" int [pk, not null]
|
||||||
|
"part" text [not null]
|
||||||
|
"bodypart" int [not null]
|
||||||
|
"bytes" int
|
||||||
|
"nb_lines" int
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo on delete cascade
|
||||||
|
Ref: part_numbers.message > messages.id
|
||||||
|
Ref: part_numbers.bodypart - bodyparts.id
|
||||||
|
|
||||||
|
Table "field_names" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"name" text [not null]
|
||||||
|
|
||||||
|
Indexes {
|
||||||
|
name [unique]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "header_fields" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"message" int [pk, not null]
|
||||||
|
"part" text [not null]
|
||||||
|
"position" int [not null]
|
||||||
|
"field" int [not null]
|
||||||
|
"value" text
|
||||||
|
|
||||||
|
Indexes {
|
||||||
|
message [unique]
|
||||||
|
part [unique]
|
||||||
|
position [unique]
|
||||||
|
field [unique]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref: header_fields.message > messages.id
|
||||||
|
Ref: header_fields.part > part_numbers.part
|
||||||
|
Ref: header_fields.field > field_names.id
|
||||||
|
|
||||||
|
Table "address_fields" {
|
||||||
|
"message" int [not null]
|
||||||
|
"part" text [not null]
|
||||||
|
"position" int [not null]
|
||||||
|
"field" int [not null]
|
||||||
|
"number" int
|
||||||
|
"address" int [not null]
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref: address_fields.message > messages.id
|
||||||
|
Ref: address_fields.part > part_numbers.part
|
||||||
|
Ref: address_fields.field > field_names.id
|
||||||
|
Ref: address_fields.address > addresses.id
|
||||||
|
|
||||||
|
// app table
|
||||||
|
Table "front_threads" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"room" int [not null]
|
||||||
|
"name" text
|
||||||
|
"notSeen" int [not null, default: true]
|
||||||
|
"lastUpdate" timestamp [not null]
|
||||||
|
"isDm" bool [not null, default: true]
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref: front_threads.room > front_rooms.id
|
||||||
|
|
||||||
|
Table "front_rooms" {
|
||||||
|
"id" int [pk, not null, increment]
|
||||||
|
"name" text
|
||||||
|
"isGroup" bool [not null, default: false]
|
||||||
|
"notSeen" int [not null]
|
||||||
|
"lastUpdate" timestamp [not null]
|
||||||
|
}
|
||||||
|
|
||||||
|
Table "front_room_messages" {
|
||||||
|
"room" int [not null]
|
||||||
|
"thread" int [not null]
|
||||||
|
"message" int [not null]
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref: front_room_messages.room > front_rooms.id
|
||||||
|
Ref: front_room_messages.message - messages.id
|
||||||
|
Ref: front_room_messages.thread > front_threads.id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
108
back/db/database.sql
Normal file
108
back/db/database.sql
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
CREATE TABLE `addresses` (
|
||||||
|
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` text,
|
||||||
|
`localpart` text NOT NULL,
|
||||||
|
`domain` text NOT NULL,
|
||||||
|
`email` text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `mailboxes` (
|
||||||
|
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` text NOT NULL,
|
||||||
|
`uidnext` int NOT NULL DEFAULT 1,
|
||||||
|
`nextmodseq` bigint NOT NULL DEFAULT 1,
|
||||||
|
`first_recent` int NOT NULL DEFAULT 1,
|
||||||
|
`uidvalidity` int NOT NULL DEFAULT 1
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `messages` (
|
||||||
|
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||||
|
`idate` timestamp NOT NULL,
|
||||||
|
`rfc822size` int
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `mailbox_messages` (
|
||||||
|
`mailbox` int NOT NULL,
|
||||||
|
`uid` int NOT NULL,
|
||||||
|
`message` int NOT NULL,
|
||||||
|
`modseq` bigint NOT NULL,
|
||||||
|
`seen` boolean NOT NULL DEFAULT false,
|
||||||
|
`deleted` boolean NOT NULL DEFAULT false,
|
||||||
|
PRIMARY KEY (`uid`, `message`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `bodyparts` (
|
||||||
|
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||||
|
`bytes` int NOT NULL,
|
||||||
|
`hash` text NOT NULL,
|
||||||
|
`text` text,
|
||||||
|
`data` binary
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `part_numbers` (
|
||||||
|
`message` int PRIMARY KEY NOT NULL,
|
||||||
|
`part` text NOT NULL,
|
||||||
|
`bodypart` int NOT NULL,
|
||||||
|
`bytes` int,
|
||||||
|
`nb_lines` int
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `field_names` (
|
||||||
|
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `header_fields` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`message` int NOT NULL,
|
||||||
|
`part` text NOT NULL,
|
||||||
|
`position` int NOT NULL,
|
||||||
|
`field` int NOT NULL,
|
||||||
|
`value` text,
|
||||||
|
PRIMARY KEY (`id`, `message`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `address_fields` (
|
||||||
|
`message` int NOT NULL,
|
||||||
|
`part` text NOT NULL,
|
||||||
|
`position` int NOT NULL,
|
||||||
|
`field` int NOT NULL,
|
||||||
|
`number` int,
|
||||||
|
`address` int NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `addresses_index_0` ON `addresses` (`email`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `mailboxes_index_1` ON `mailboxes` (`name`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `field_names_index_2` ON `field_names` (`name`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `header_fields_index_3` ON `header_fields` (`message`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `header_fields_index_4` ON `header_fields` (`part`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `header_fields_index_5` ON `header_fields` (`position`);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX `header_fields_index_6` ON `header_fields` (`field`);
|
||||||
|
|
||||||
|
ALTER TABLE `mailbox_messages` ADD FOREIGN KEY (`mailbox`) REFERENCES `mailboxes` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `messages` ADD FOREIGN KEY (`id`) REFERENCES `mailbox_messages` (`message`);
|
||||||
|
|
||||||
|
ALTER TABLE `part_numbers` ADD FOREIGN KEY (`message`) REFERENCES `messages` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `bodyparts` ADD FOREIGN KEY (`id`) REFERENCES `part_numbers` (`bodypart`);
|
||||||
|
|
||||||
|
ALTER TABLE `header_fields` ADD FOREIGN KEY (`message`) REFERENCES `messages` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `header_fields` ADD FOREIGN KEY (`part`) REFERENCES `part_numbers` (`part`);
|
||||||
|
|
||||||
|
ALTER TABLE `header_fields` ADD FOREIGN KEY (`field`) REFERENCES `field_names` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `address_fields` ADD FOREIGN KEY (`message`) REFERENCES `messages` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `address_fields` ADD FOREIGN KEY (`part`) REFERENCES `part_numbers` (`part`);
|
||||||
|
|
||||||
|
ALTER TABLE `address_fields` ADD FOREIGN KEY (`field`) REFERENCES `field_names` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `address_fields` ADD FOREIGN KEY (`address`) REFERENCES `addresses` (`id`);
|
@ -1,5 +1,5 @@
|
|||||||
export function removeDuplicates(array: []) {
|
export function removeDuplicates(array: []) {
|
||||||
let unique = [];
|
const unique = [];
|
||||||
for (let i = 0; i < array.length; i++) {
|
for (let i = 0; i < array.length; i++) {
|
||||||
if (!unique.includes(array[i])) {
|
if (!unique.includes(array[i])) {
|
||||||
unique.push(array[i]);
|
unique.push(array[i]);
|
||||||
|
@ -30,5 +30,7 @@ export interface Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Address {
|
export interface Address {
|
||||||
todo: boolean;
|
id: number;
|
||||||
|
name: string | null;
|
||||||
|
email: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import API from "@/services/imapAPI";
|
import API from "@/services/imapAPI";
|
||||||
import { decodeEmojis } from "@/utils/string";
|
import { decodeEmojis } from "@/utils/string";
|
||||||
|
import { AxiosError, AxiosResponse } from "axios";
|
||||||
import { createStore, Store } from "vuex";
|
import { createStore, Store } from "vuex";
|
||||||
import { Room, Account, Address, RoomType, Message } from "./models/model";
|
import { Room, Account, Address, RoomType, Message } from "./models/model";
|
||||||
|
|
||||||
@ -103,6 +104,12 @@ const store = createStore<State>({
|
|||||||
const room = state.rooms.find((room) => room.id == roomId);
|
const room = state.rooms.find((room) => room.id == roomId);
|
||||||
return room;
|
return room;
|
||||||
},
|
},
|
||||||
|
address:
|
||||||
|
(state) =>
|
||||||
|
(addressId: number): Address | undefined => {
|
||||||
|
const address = state.addresses.find((address) => address.id == addressId);
|
||||||
|
return address;
|
||||||
|
},
|
||||||
messages:
|
messages:
|
||||||
(state) =>
|
(state) =>
|
||||||
(roomId: number): Message[] => {
|
(roomId: number): Message[] => {
|
||||||
@ -117,21 +124,21 @@ const store = createStore<State>({
|
|||||||
actions: {
|
actions: {
|
||||||
fetchAccounts: async (context) => {
|
fetchAccounts: async (context) => {
|
||||||
API.getAccounts()
|
API.getAccounts()
|
||||||
.then((res) => {
|
.then((res: AxiosResponse) => {
|
||||||
context.commit("addAccounts", res.data);
|
context.commit("addAccounts", res.data);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err: AxiosError) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fetchRooms: async (context, data) => {
|
fetchRooms: async (context, data) => {
|
||||||
if (data.account?.fetched == false) {
|
if (data.account?.fetched == false) {
|
||||||
API.getRooms(data.accountId)
|
API.getRooms(data.accountId)
|
||||||
.then((res) => {
|
.then((res: AxiosResponse) => {
|
||||||
data.account.fetched = true;
|
data.account.fetched = true;
|
||||||
context.commit("addRooms", { rooms: res.data });
|
context.commit("addRooms", { rooms: res.data });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err: AxiosError) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -140,20 +147,20 @@ const store = createStore<State>({
|
|||||||
if (!data.room || data.room?.fetched == false) {
|
if (!data.room || data.room?.fetched == false) {
|
||||||
store.dispatch("fetchRoomMembers", { roomId: data.roomId });
|
store.dispatch("fetchRoomMembers", { roomId: data.roomId });
|
||||||
API.getMessages(data.roomId)
|
API.getMessages(data.roomId)
|
||||||
.then((res) => {
|
.then((res: AxiosResponse) => {
|
||||||
context.commit("addMessages", { messages: res.data, roomId: data.roomId });
|
context.commit("addMessages", { messages: res.data, roomId: data.roomId });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err: AxiosError) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchRoomMembers: async (context, data) => {
|
fetchRoomMembers: async (context, data) => {
|
||||||
API.getMembers(data.roomId)
|
API.getMembers(data.roomId)
|
||||||
.then((res) => {
|
.then((res: AxiosResponse) => {
|
||||||
context.commit("addAddress", { addresses: res.data, roomId: data.roomId });
|
context.commit("addAddress", { addresses: res.data, roomId: data.roomId });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err: AxiosError) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
9
front/src/utils/array.ts
Normal file
9
front/src/utils/array.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export function removeDuplicates(array: []) {
|
||||||
|
const unique: [] = [];
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
if (!unique.includes(array[i])) {
|
||||||
|
unique.push(array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unique;
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, onMounted, ref } from "vue";
|
import { defineProps, onMounted, ref } from "vue";
|
||||||
import { decodeEmojis } from "../../utils/string";
|
import { decodeEmojis } from "../../utils/string";
|
||||||
|
import { removeDuplicates } from "../../utils/array";
|
||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
|
import store from "@/store/store";
|
||||||
|
|
||||||
const props = defineProps({ data: Object });
|
const props = defineProps({ data: Object });
|
||||||
const date = new Date(props.data.date);
|
const date = new Date(props.data.date);
|
||||||
@ -30,6 +32,17 @@ onMounted(() => {
|
|||||||
`);
|
`);
|
||||||
doc.close();
|
doc.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const displayAddresses = (addressesId) => {
|
||||||
|
// todo store members in rooms ?
|
||||||
|
addressesId = removeDuplicates(addressesId);
|
||||||
|
let res = "";
|
||||||
|
addressesId.forEach((addressId) => {
|
||||||
|
const address = store.getters.address(addressId);
|
||||||
|
if (address) res += address.email;
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<!-- to if to is more than me
|
<!-- to if to is more than me
|
||||||
cc -->
|
cc -->
|
||||||
@ -39,7 +52,9 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<div id="context">
|
<div id="context">
|
||||||
<div class="left" id="profile">{{ props.data.fromA }}</div>
|
<div class="left" id="profile">
|
||||||
|
{{ displayAddresses(props.data.fromA?.split(",")) }} - {{ props.data.fromA }}
|
||||||
|
</div>
|
||||||
<div class="middle">{{ decodeEmojis(props.data.subject) }}</div>
|
<div class="middle">{{ decodeEmojis(props.data.subject) }}</div>
|
||||||
<div class="right" id="date">
|
<div class="right" id="date">
|
||||||
{{
|
{{
|
||||||
|
@ -1,44 +1,25 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"types": [
|
"types": ["webpack-env", "jest"],
|
||||||
"webpack-env",
|
"paths": {
|
||||||
"jest"
|
"@/*": ["src/*"]
|
||||||
],
|
},
|
||||||
"paths": {
|
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
|
||||||
"@/*": [
|
|
||||||
"src/*",
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lib": [
|
|
||||||
"esnext",
|
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"scripthost"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
|
||||||
"src/**/*.ts",
|
"exclude": ["node_modules"]
|
||||||
"src/**/*.tsx",
|
}
|
||||||
"src/**/*.vue",
|
|
||||||
"tests/**/*.ts",
|
|
||||||
"tests/**/*.tsx"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user