Compare commits
2 Commits
6ea0d4e02e
...
569c271c6c
Author | SHA1 | Date | |
---|---|---|---|
|
569c271c6c | ||
|
833eacc91d |
@ -1,8 +1,9 @@
|
|||||||
import statusCode from "../utils/statusCodes";
|
import statusCode from "../utils/statusCodes";
|
||||||
import { getMessages } from "../db/api";
|
import { getMessages } from "../db/api";
|
||||||
import logger from "../system/Logger";
|
import logger from "../system/Logger";
|
||||||
|
import { Response } from "express";
|
||||||
|
|
||||||
export async function messages(body, res) {
|
export async function messages(body, res: Response) {
|
||||||
const { roomId } = body;
|
const { roomId } = body;
|
||||||
getMessages(roomId).then((messages) => {
|
getMessages(roomId).then((messages) => {
|
||||||
res.status(statusCode.OK).json(messages);
|
res.status(statusCode.OK).json(messages);
|
||||||
|
@ -35,6 +35,7 @@ export async function getRooms(mailboxId) {
|
|||||||
address.email AS user,
|
address.email AS user,
|
||||||
app_room.owner_id AS userId,
|
app_room.owner_id AS userId,
|
||||||
app_room.notSeen,
|
app_room.notSeen,
|
||||||
|
app_room.room_type AS roomType,
|
||||||
mailbox_message.mailbox_id AS mailboxId
|
mailbox_message.mailbox_id AS mailboxId
|
||||||
FROM app_room
|
FROM app_room
|
||||||
INNER JOIN message
|
INNER JOIN message
|
||||||
@ -91,7 +92,7 @@ export async function getMessages(roomId) {
|
|||||||
|
|
||||||
WHERE msg.room_id = ?
|
WHERE msg.room_id = ?
|
||||||
GROUP BY msg.message_id
|
GROUP BY msg.message_id
|
||||||
ORDER BY message.idate;
|
ORDER BY message.idate DESC;
|
||||||
`;
|
`;
|
||||||
const values = [roomId];
|
const values = [roomId];
|
||||||
return await execQueryAsync(query, values);
|
return await execQueryAsync(query, values);
|
||||||
|
@ -1,25 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="wrapper">
|
<span :class="['badge', type]" :style="{ backgroundColor: color }">
|
||||||
<slot class="badge" name="body"> 0 </slot>
|
{{ value }}
|
||||||
</div>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: "#007bff",
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "badge-primary",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.wrapper {
|
.badge {
|
||||||
display: flex;
|
display: inline-block;
|
||||||
justify-content: center;
|
padding: 0.25em 0.4em;
|
||||||
align-items: center;
|
font-size: 75%;
|
||||||
background-color: #4d5970;
|
font-weight: 700;
|
||||||
height: 1.6rem;
|
/* line-height: 1; */
|
||||||
width: 1.6rem;
|
text-align: center;
|
||||||
min-width: 1.6rem;
|
white-space: nowrap;
|
||||||
min-height: 1.6rem;
|
vertical-align: baseline;
|
||||||
border-radius: 1.6rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.badge-primary {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 1.1rem;
|
background-color: #007bff;
|
||||||
line-height: 1.4rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add more type classes for other types/colors */
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
|
|
||||||
export enum RoomType {
|
export enum RoomType {
|
||||||
ROOM = 0,
|
ROOM = 0,
|
||||||
CHANNEL = 1,
|
CHANNEL = 1,
|
||||||
GROUP = 2,
|
GROUP = 2,
|
||||||
DM = 3,
|
DM = 3,
|
||||||
THREAD = 4,
|
THREAD = 4,
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
|
todo: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Room {
|
export interface Room {
|
||||||
@ -32,4 +31,4 @@ export interface Account {
|
|||||||
|
|
||||||
export interface Address {
|
export interface Address {
|
||||||
todo: boolean;
|
todo: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import API from "@/services/imapAPI";
|
import API from "@/services/imapAPI";
|
||||||
|
import { decodeEmojis } from "@/utils/string";
|
||||||
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";
|
||||||
|
|
||||||
@ -19,9 +20,10 @@ interface AccountFromBack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createRoom(options: RoomFromBack): Room {
|
function createRoom(options: RoomFromBack): Room {
|
||||||
|
console.log(options.roomType);
|
||||||
return {
|
return {
|
||||||
id: options.id,
|
id: options.id,
|
||||||
roomName: options.roomName,
|
roomName: decodeEmojis(options.roomName),
|
||||||
roomType: options.roomType,
|
roomType: options.roomType,
|
||||||
mailboxId: options.mailboxId,
|
mailboxId: options.mailboxId,
|
||||||
userId: options.userId,
|
userId: options.userId,
|
||||||
@ -91,18 +93,26 @@ const store = createStore<State>({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
rooms: (state) => () => {
|
rooms: (state) => (): Room[] => {
|
||||||
if (state.activeAccount === 0) return state.rooms;
|
if (state.activeAccount === 0) return state.rooms;
|
||||||
return state.rooms.filter((room) => room.mailboxId == state.activeAccount);
|
return state.rooms.filter((room) => room.mailboxId == state.activeAccount);
|
||||||
},
|
},
|
||||||
messages: (state) => (roomId: number) => {
|
room:
|
||||||
const room = state.rooms.find((room) => room.id == roomId);
|
(state) =>
|
||||||
if (!room) return [];
|
(roomId: number): Room | undefined => {
|
||||||
if (!room.messagesFetched) {
|
const room = state.rooms.find((room) => room.id == roomId);
|
||||||
store.dispatch("fetchMessages", { roomId: room.id });
|
return room;
|
||||||
}
|
},
|
||||||
return room.messages;
|
messages:
|
||||||
},
|
(state) =>
|
||||||
|
(roomId: number): Message[] => {
|
||||||
|
const room = state.rooms.find((room) => room.id == roomId);
|
||||||
|
if (!room) return [];
|
||||||
|
if (!room.messagesFetched) {
|
||||||
|
store.dispatch("fetchMessages", { roomId: room.id });
|
||||||
|
}
|
||||||
|
return room.messages;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
fetchAccounts: async (context) => {
|
fetchAccounts: async (context) => {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// todo optimize
|
||||||
|
|
||||||
export function decodeEmojis(text: string): string {
|
export function decodeEmojis(text: string): string {
|
||||||
if (!text) return text;
|
if (!text) return text;
|
||||||
const regex = /\\u{([^}]+)}/g;
|
const regex = /\\u{([^}]+)}/g;
|
||||||
|
@ -1,22 +1,54 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { defineProps } from "vue";
|
import store from "../../store/store";
|
||||||
const props = defineProps({ room: Object });
|
import { defineProps, ref, watch } from "vue";
|
||||||
|
import Badge from "@/components/Badge.vue";
|
||||||
|
import { RoomType } from "@/store/models/model";
|
||||||
|
|
||||||
|
const props = defineProps({ id: Number });
|
||||||
|
const room = ref(store.getters.room(props.id));
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.id,
|
||||||
|
(newId) => {
|
||||||
|
room.value = store.getters.room(newId);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const roomTitle = () => {
|
||||||
|
const type = room.value?.roomType;
|
||||||
|
if (type === RoomType.DM || type == RoomType.CHANNEL || type == RoomType.ROOM) {
|
||||||
|
return room.value?.user;
|
||||||
|
}
|
||||||
|
return room.value?.roomName;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div>
|
<div class="infos">
|
||||||
{{ props }}
|
<Badge :value="RoomType[room?.roomType]" />
|
||||||
type: name / sender
|
{{ roomTitle() }}
|
||||||
</div>
|
</div>
|
||||||
<div>action: threads message important</div>
|
<div class="action">action: threads message important</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.main {
|
.main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
border-bottom: 1px solid #505050;
|
border-bottom: 1px solid #505050;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 51px;
|
height: 51px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.infos {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
||||||
import { onBeforeMount } from "vue";
|
import { onBeforeMount, ref } from "vue";
|
||||||
import Header from "./Header.vue";
|
import Header from "./Header.vue";
|
||||||
import Message from "./Message.vue";
|
import Message from "./Message.vue";
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
let { id } = route.params;
|
const id = ref(parseInt(route.params?.id));
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
console.log(id);
|
||||||
// get data
|
// get data
|
||||||
let room = store.state.rooms.find((room) => room.id === id);
|
let room = store.getters.room(id);
|
||||||
console.log(room);
|
|
||||||
if (!room || room?.fetched === false) {
|
if (!room || room?.fetched === false) {
|
||||||
// todo
|
// todo
|
||||||
// await store.dispatch("fetchMessages", );
|
// await store.dispatch("fetchMessages", );
|
||||||
@ -21,7 +21,8 @@ onBeforeMount(async () => {
|
|||||||
|
|
||||||
onBeforeRouteUpdate(async (to, from) => {
|
onBeforeRouteUpdate(async (to, from) => {
|
||||||
if (to.params.id !== from.params.id) {
|
if (to.params.id !== from.params.id) {
|
||||||
id = to.params.id;
|
id.value = parseInt(to.params.id);
|
||||||
|
console.log(id);
|
||||||
store.commit("setActiveRoom", id);
|
store.commit("setActiveRoom", id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -29,7 +30,7 @@ onBeforeRouteUpdate(async (to, from) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<Header :room="room"></Header>
|
<Header :id="id"></Header>
|
||||||
<div id="RoomViewBody">
|
<div id="RoomViewBody">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<Message v-for="(message, index) in store.getters.messages(id)" :key="index" :data="message" />
|
<Message v-for="(message, index) in store.getters.messages(id)" :key="index" :data="message" />
|
||||||
@ -64,7 +65,7 @@ onBeforeRouteUpdate(async (to, from) => {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column-reverse;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Accounts />
|
<Accounts class="accounts" />
|
||||||
<Rooms id="rooms" />
|
<Rooms class="rooms" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -24,9 +24,11 @@ div {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rooms {
|
.accounts {
|
||||||
max-width: 300px;
|
width: 82px;
|
||||||
min-width: 250px;
|
}
|
||||||
|
.rooms {
|
||||||
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* todo setup max size */
|
/* todo setup max size */
|
||||||
|
@ -5,7 +5,6 @@ import BaseAvatar from "../../avatars/BaseAvatar.vue";
|
|||||||
import Badge from "../../../components/Badge.vue";
|
import Badge from "../../../components/Badge.vue";
|
||||||
import ThreadList from "./threads/ThreadList.vue";
|
import ThreadList from "./threads/ThreadList.vue";
|
||||||
import store from "@/store/store";
|
import store from "@/store/store";
|
||||||
import { decodeEmojis } from "@/utils/string";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@ -32,7 +31,7 @@ const router = useRouter();
|
|||||||
<BaseAvatar url="vue.png" />
|
<BaseAvatar url="vue.png" />
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<div id="sender">{{ props.data.user }}</div>
|
<div id="sender">{{ props.data.user }}</div>
|
||||||
<div id="object">{{ decodeEmojis(props.data.roomName) }}</div>
|
<div id="object">{{ props.data.roomName }}</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge class="badge" v-if="props.data.unseen > 0"
|
<Badge class="badge" v-if="props.data.unseen > 0"
|
||||||
><template v-slot:body>{{ props.data.unseen }}</template>
|
><template v-slot:body>{{ props.data.unseen }}</template>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
|
"allowJs": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@ -19,7 +20,7 @@
|
|||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
"src/*"
|
"src/*",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lib": [
|
"lib": [
|
||||||
|
Loading…
Reference in New Issue
Block a user