start to load messages from rooms

This commit is contained in:
grimhilt 2023-03-20 21:28:13 +01:00
parent 9b3ddd291e
commit d6f06f3ca6
15 changed files with 4441 additions and 4401 deletions

View File

@ -0,0 +1,16 @@
const statusCode = require("../utils/statusCodes").statusCodes;
const { getMessages } = require("../db/api.js");
async function messages(body, res) {
const { roomId } = body;
getMessages(roomId).then((messages) => {
res.status(statusCode.OK).json(messages.data);
}).catch((err) => {
console.log(err)
res.status(statusCode.INTERNAL_SERVER_ERROR);
});
}
module.exports = {
messages,
};

View File

@ -4,7 +4,6 @@ const { getRooms } = require("../db/api.js");
async function rooms(body, res) { async function rooms(body, res) {
const { mailboxId, offset, limit } = body; const { mailboxId, offset, limit } = body;
getRooms(mailboxId).then((rooms) => { getRooms(mailboxId).then((rooms) => {
console.log(rooms)
res.status(statusCode.OK).json(rooms); res.status(statusCode.OK).json(rooms);
}).catch((err) => { }).catch((err) => {
console.log(err) console.log(err)

View File

@ -44,8 +44,39 @@ async function getRooms(mailboxId) {
return await execQueryAsync(query, values); return await execQueryAsync(query, values);
} }
async function getMessages(roomId) {
// todo attachements name
const query = `
SELECT
address_field.address_id,
bodypart.text,
header_field.value
FROM bodypart
INNER JOIN header_field
INNER JOIN address_field
INNER JOIN field_name
WHERE
(
header_field.field_id = field_name.field_id OR
address_field.field_id = field_name.field_id
) AND
(
field_name.field_name = 'html' OR
field_name.field_name = 'text' OR
field_name.field_name = 'textAsHtml' OR
field_name.field_name = 'to' OR
field_name.field_name = 'cc' OR
field_name.field_name = 'subject'
)
`;
// todo roomID
const values = [];
return await execQueryAsync(query, values);
}
module.exports = { module.exports = {
registerMailbox, registerMailbox,
getMailboxes, getMailboxes,
getRooms getRooms,
getMessages
}; };

View File

@ -16,6 +16,7 @@ function registerMailbox_message(mailboxId, uid, messageId, modseq, seen, delete
INSERT IGNORE INTO mailbox_message INSERT IGNORE INTO mailbox_message
(mailbox_id, uid, message_id, modseq, seen, deleted) VALUES (1, 19, 10, '12450', 0, 0) (mailbox_id, uid, message_id, modseq, seen, deleted) VALUES (1, 19, 10, '12450', 0, 0)
`; `;
// todo
const values = [mailboxId, uid, messageId, modseq, seen, deleted]; const values = [mailboxId, uid, messageId, modseq, seen, deleted];
execQuery(query, values); execQuery(query, values);
} }
@ -30,7 +31,7 @@ function registerBodypart(messageId, part, bodypartId, bytes, nbLines) {
} }
async function saveBodypart(bytes, hash, text, data) { async function saveBodypart(bytes, hash, text, data) {
const query = `INSERT IGNORE INTO bodypart (bytes, hash, text, data) VALUES (?, ?, ?,)`; const query = `INSERT IGNORE INTO bodypart (bytes, hash, text, data) VALUES (?, ?, ?, ?)`;
const values = [bytes, hash, text, data]; const values = [bytes, hash, text, data];
return await execQueryAsyncWithId(query, values); return await execQueryAsyncWithId(query, values);
} }

View File

@ -83,7 +83,7 @@ async function saveFromParsedData(parsed, messageId) {
}), }),
); );
} else if (["subject", "inReplyTo"].includes(key)) { } else if (["subject", "inReplyTo"].includes(key)) {
// todo : "references" // todo : "references" (array)
promises.push( promises.push(
getFieldId(key).then(async (fieldId) => { getFieldId(key).then(async (fieldId) => {
await saveHeader_fields(messageId, fieldId, undefined, undefined, parsed[key]); await saveHeader_fields(messageId, fieldId, undefined, undefined, parsed[key]);
@ -92,22 +92,22 @@ async function saveFromParsedData(parsed, messageId) {
} else if (["html", "text", "textAsHtml"].includes(key)) { } else if (["html", "text", "textAsHtml"].includes(key)) {
const hash = "0"; const hash = "0";
const size = "0"; const size = "0";
// saveBodypart(size, hash, parsed[key], "").then((bodypartId) => { saveBodypart(size, hash, parsed[key], "").then((bodypartId) => {
// getFieldId(key).then((fieldId) => { getFieldId(key).then((fieldId) => {
// saveHeader_fields( saveHeader_fields(
// messageId, messageId,
// fieldId, fieldId,
// bodypartId, bodypartId,
// undefined, // todo ? undefined, // todo ?
// undefined undefined
// ); );
// }); });
// }); });
} else if (key == "attachments") { } else if (key == "attachments") {
// todo // todo
} else if (["date", "messageId", "headers", "headerLines"].includes(key)) { } else if (["date", "messageId", "headers", "headerLines"].includes(key)) {
// messageId and date are already saved // messageId and date are already saved
// other field are not improted and can be retrieved in source // other field are not important and can be retrieved in source
return; return;
} else { } else {
DEBUG.log("doesn't know key: " + key); DEBUG.log("doesn't know key: " + key);

View File

@ -10,6 +10,7 @@ const schema_mailbox = require("../schemas/mailbox_schema.json");
const { addMailbox } = require("../controllers/addMailbox.js"); const { addMailbox } = require("../controllers/addMailbox.js");
const { getMailboxes } = require("../db/api.js"); const { getMailboxes } = require("../db/api.js");
const { rooms } = require("../controllers/rooms.js"); const { rooms } = require("../controllers/rooms.js");
const { messages } = require("../controllers/messages.js");
const validate_mailbox = ajv.compile(schema_mailbox); const validate_mailbox = ajv.compile(schema_mailbox);
@ -37,6 +38,13 @@ router.get("/:mailboxId/rooms", async (req, res) => {
}); });
router.get("/:roomId/messages", async (req, res) => {
const { roomId } = req.params;
console.log("called")
// todo check token
await messages(req.params, res);
});
/** /**
* Register a new mailbox inside the app * Register a new mailbox inside the app
*/ */

View File

@ -1,11 +1,11 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import router from './router' import router from './router'
import App from './App.vue' import App from './App.vue'
import roomsStore from './store/rooms' import store from './store/store'
const app = createApp(App); const app = createApp(App);
app.use(router); app.use(router);
app.use(roomsStore); app.use(store);
app.mount('#app'); app.mount('#app');

View File

@ -19,7 +19,6 @@ const routes = [
}, },
{ {
path: "/:id", path: "/:id",
name: "test",
component: RoomView component: RoomView
} }
]; ];

View File

@ -9,5 +9,8 @@ export default {
}, },
getRooms(mailboxId) { getRooms(mailboxId) {
return API().get(`/mail/${mailboxId}/rooms`); return API().get(`/mail/${mailboxId}/rooms`);
},
getMessages(roomId) {
return API().get(`/mail/${roomId}/messages`);
} }
} }

View File

@ -1,7 +1,7 @@
import API from "@/services/imapAPI"; import API from "@/services/imapAPI";
import { createStore } from "vuex"; import { createStore } from "vuex";
const roomsStore = createStore({ const store = createStore({
state() { state() {
return { return {
rooms: [ rooms: [
@ -9,40 +9,50 @@ const roomsStore = createStore({
id: 0, id: 0,
user: "clemnce", user: "clemnce",
userId: 0, userId: 0,
name: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.", roomName: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.",
mailboxId: 1, mailboxId: 1,
}, },
{ {
id: 1,
user: "juliette", user: "juliette",
name: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.", roomName: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.",
mailboxId: 1, mailboxId: 1,
}, },
{ {
id: 2,
user: "jean", user: "jean",
name: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.", roomName: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.",
mailboxId: 2, mailboxId: 2,
}, },
{ {
id: 3,
user: "luc", user: "luc",
name: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.", roomName: "Lorem magna minim cillum labore ex eiusmod proident excepteur sint irure ipsum.",
mailboxId: 2, mailboxId: 2,
}, },
],
messages: [
], ],
mailboxes: [], mailboxes: [],
activeMailbox: -1, activeMailbox: 0,
activeRoom: 0
}; };
}, },
mutations: { mutations: {
setActiveMailbox(state, payload) { setActiveMailbox(state, payload) {
state.activeMailbox = payload; state.activeMailbox = payload;
// todo call actions
// fetch rooms for this mailboxes if not already fetched
const mailbox = state.mailboxes.find((mailbox) => mailbox.id == payload); const mailbox = state.mailboxes.find((mailbox) => mailbox.id == payload);
// todo fetched mailbox all // todo fetched mailbox all
if (mailbox?.fetched == false) { if (mailbox?.fetched == false) {
mailbox.fetched = true;
console.log("add messages")
API.getRooms(payload).then((res) => { API.getRooms(payload).then((res) => {
// todo add if not exist // todo add if not exist
mailbox.fetched = true;
res.data.forEach((room) => { res.data.forEach((room) => {
room.fetched = false;
state.rooms.push(room); state.rooms.push(room);
}); });
}).catch((err) => { }).catch((err) => {
@ -50,6 +60,24 @@ const roomsStore = createStore({
}); });
} }
}, },
setActiveRoom(state, payload) {
state.activeRoom = payload;
// todo call actions
// fetch messages for this room if not already fetched
const room = state.rooms.find((room) => room.id == payload);
if (!room || room?.fetched == false) {
console.log("add messages")
API.getMessages(payload).then((res) => {
// todo add if not exist
room.fetched = true;
res.data.forEach((msg) => {
state.messages.push(msg);
});
}).catch((err) => {
console.log(err)
});
}
},
addMailboxes(state, payload) { addMailboxes(state, payload) {
payload.forEach((mailbox) => { payload.forEach((mailbox) => {
mailbox.fetched = false; mailbox.fetched = false;
@ -59,10 +87,16 @@ const roomsStore = createStore({
}, },
getters: { getters: {
rooms: (state) => () => { rooms: (state) => () => {
console.log(state.rooms.length) if (state.activeMailbox === 0) return state.rooms;
if (state.activeMailbox == 0) return state.rooms;
return state.rooms.filter((room) => room.mailboxId == state.activeMailbox); return state.rooms.filter((room) => room.mailboxId == state.activeMailbox);
}, },
messages: (state) => (roomId) => {
const room = state.rooms.find((room) => room.id === roomId);
if (room?.fetched === false) {
console.log("ok")
}
return [1, 2];
}
}, },
actions: { actions: {
async fetchMailboxes(context) { async fetchMailboxes(context) {
@ -75,7 +109,10 @@ const roomsStore = createStore({
console.log(err); console.log(err);
}); });
}, },
async fetchMessages(context) {
console.log(context)
},
}, },
}); });
export default roomsStore; export default store;

View File

@ -0,0 +1,30 @@
<script setup>
const data = {
html: "<div dir=\"ltr\">new content<br><div><br><div class=\"gmail_quote\"><div dir=\"ltr\" class=\"gmail_attr\">---------- Forwarded message ---------<br>De : <b class=\"gmail_sendername\" dir=\"auto\">Ulysse Carlier</b> <span dir=\"auto\">&lt;<a href=\"mailto:carlierulysse@gmail.com\">carlierulysse@gmail.com</a>&gt;</span><br>Date: ven. 10 mars 2023 à 14:52<br>Subject: message to transfer<br>To: Hugueprime M &lt;<a href=\"mailto:hugueprime@gmail.com\">hugueprime@gmail.com</a>&gt;<br></div><br><br><div dir=\"ltr\">content to transfer<br></div>\n</div></div></div>\n",
text: "new content\n\n---------- Forwarded message ---------\nDe : Ulysse Carlier <carlierulysse@gmail.com>\nDate: ven. 10 mars 2023 à 14:52\nSubject: message to transfer\nTo: Hugueprime M <hugueprime@gmail.com>\n\n\ncontent to transfer\n",
textAsHtml: "<p>new content</p><p>---------- Forwarded message ---------<br/>De : Ulysse Carlier &lt;<a href=\"mailto:carlierulysse@gmail.com\">carlierulysse@gmail.com</a>&gt;<br/>Date: ven. 10 mars 2023 &agrave; 14:52<br/>Subject: message to transfer<br/>To: Hugueprime M &lt;<a href=\"mailto:hugueprime@gmail.com\">hugueprime@gmail.com</a>&gt;</p><p>content to transfer</p>",
subject: "Fwd: message to transfer",
references: "<CAAGJdR0i=4w1i2Nb9=zx5bCPqkR+2eUCs=_qbXTSzugZu4EXFQ@mail.gmail.com>",
date: "2023-03-10T13:52:21.000Z",
}
</script>
<!-- to if to is more than me
cc -->
<!-- object (channel only)
content
attachments -->
<template>
<div class="message">
<!-- <div v-html="data.html"></div> -->
<!-- <div v-html="data.text"></div> -->
<div></div>
<div v-html="data.textAsHtml"></div>
</div>
</template>
<style scoped>
.message {
width: 100%;
border: white 1px solid;
}
</style>

View File

@ -1,35 +1,47 @@
<script setup> <script setup>
import { useRoute } from "vue-router" import { useStore } from "vuex";
import { onBeforeMount } from "vue" import { useRoute, onBeforeRouteUpdate } from "vue-router";
import Header from './Header.vue' import { onBeforeMount } from "vue";
import Header from "./Header.vue";
import Message from "./Message.vue";
const route = useRoute(); const store = useStore();
const route = useRoute();
onBeforeMount(() => { let { id } = route.params;
let messages = [];
onBeforeMount(async () => {
// get data // get data
}); console.log(store.state.rooms.find((room) => room.id === id)?.fetched);
let room = store.state.rooms.find((room) => room.id === id);
const { id } = route.params; if (!room || room?.fetched === false) {
await store.dispatch("fetchMessages");
}
store.commit("setActiveRoom", id);
});
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
id = to.params.id;
store.commit("setActiveRoom", id);
}
});
</script> </script>
<template> <template>
<div> <div>
<Header></Header> <Header></Header>
<div> <div>
Room <Message v-for="(message, index) in store.getters.messages(id)" :key="index" :data="message" />
is thread
<b>{{ id }}</b> <b>{{ id }}</b>
{{ messages.length }}
</div> </div>
</div> </div>
</template> </template>
<style scoped> <style scoped>
div { div {
background-color: #1D1D23; background-color: #1d1d23;
color: white; color: white;
width: 100%; width: 100%;
} }
</style> </style>

View File

@ -17,7 +17,7 @@
import { mapState } from 'vuex' import { mapState } from 'vuex'
import Mailbox from './Mailbox' import Mailbox from './Mailbox'
import AddMailboxModal from '../../modals/AddMailboxModal' import AddMailboxModal from '../../modals/AddMailboxModal'
import roomsStore from '@/store/rooms' import store from '@/store/store'
export default { export default {
name: 'Mailboxes', name: 'Mailboxes',
@ -30,7 +30,7 @@ export default {
}, },
created() { created() {
console.log("call api get mailboxes"); console.log("call api get mailboxes");
roomsStore.dispatch('fetchMailboxes'); store.dispatch('fetchMailboxes');
} }
} }

View File

@ -1,29 +1,11 @@
<script setup> <script setup>
import { useRouter } from "vue-router" import { useRouter } from "vue-router"
import { defineProps } from 'vue'
const router = useRouter();
</script>
<template>
<div>
<div id="user" @click="router.push(`/${data.id}`)">
<BaseAvatar url="vue.png"/>
<div id="content">
<div id="sender">{{ data.user }}</div>
<div id="object">{{ data.roomName }}</div>
</div>
</div>
<ThreadList />
</div>
</template>
<script>
import BaseAvatar from '../../avatars/BaseAvatar.vue' import BaseAvatar from '../../avatars/BaseAvatar.vue'
import ThreadList from './threads/ThreadList.vue' import ThreadList from './threads/ThreadList.vue'
import store from "@/store/store";
export default { const props = defineProps({
name: 'User',
props: {
data: { data: {
id: Number, id: Number,
roomName: String, roomName: String,
@ -32,16 +14,27 @@ export default {
notSeen: Number, notSeen: Number,
mailboxId: Number mailboxId: Number
} }
}, })
components: {
BaseAvatar, const router = useRouter();
ThreadList
}
}
</script> </script>
<template>
<div>
<div class="room" @click="router.push(`/${props.data.id}`)" v-bind:class = " store.state.activeRoom == props.data.id ? 'selected' : ''">
<BaseAvatar url="vue.png"/>
<div id="content">
<div id="sender">{{ props.data.user }}</div>
<div id="object">{{ props.data.roomName }}</div>
</div>
</div>
<ThreadList />
</div>
</template>
<style scoped> <style scoped>
#user { .room {
box-sizing: border-box; box-sizing: border-box;
contain: content; contain: content;
display: flex; display: flex;
@ -51,7 +44,7 @@ export default {
cursor: pointer; cursor: pointer;
} }
#user:hover { .room:hover, .selected {
background-color: #41474f;; background-color: #41474f;;
border-radius: 8px; border-radius: 8px;
} }

File diff suppressed because it is too large Load Diff