🔨 Add mark all read to message

This commit is contained in:
SebClem 2024-02-19 10:52:37 +01:00
parent 21895edd8d
commit 17a6f1cbec
Signed by: sebclem
GPG Key ID: 5A4308F6A359EA50
4 changed files with 105 additions and 75 deletions

View File

@ -3,16 +3,21 @@ import messageManager from "../tools/messageManager.js";
const messageRouter = express.Router();
messageRouter.get('/', (req, res, next)=>{
res.json(messageManager.get())
messageRouter.get("/", (req, res) => {
res.json(messageManager.get());
});
messageRouter.patch('/:messageId/readed', (req, res, next)=>{
if(messageManager.markReaded(req.params.messageId)){
messageRouter.patch("/:messageId/readed", (req, res) => {
if (messageManager.markReaded(req.params.messageId)) {
res.json(messageManager.get());
}else{
} else {
res.status(404).send();
}
});
messageRouter.post("/allReaded", (req, res) => {
messageManager.markAllReaded();
res.json(messageManager.get());
});
export default messageRouter;

View File

@ -7,14 +7,19 @@ const maxMessageLength = 255;
class MessageManager {
private messages: Message[] = [];
public addMessage(type: MessageType, message: string, detail?: string, isImportant = false) {
this.messages.push({
public addMessage(
type: MessageType,
message: string,
detail?: string,
isImportant = false
) {
this.messages.unshift({
id: randomUUID(),
message: message,
type: type,
time: DateTime.now(),
viewed: !isImportant,
detail: detail
detail: detail,
});
if (this.messages.length > maxMessageLength) {
this.messages.shift();
@ -37,24 +42,28 @@ class MessageManager {
this.addMessage(MessageType.SUCCESS, message, detail);
}
public get(){
public get() {
return this.messages;
}
public getById(id: string){
return this.messages.find(value=>value.id == id);
}
public getById(id: string) {
return this.messages.find((value) => value.id == id);
}
public markReaded(id: string){
const index = this.messages.findIndex(value=>value.id == id);
if(index == -1){
public markReaded(id: string) {
const index = this.messages.findIndex((value) => value.id == id);
if (index == -1) {
return false;
}
this.messages[index].viewed = true;
return true;
}
public markAllReaded() {
this.messages.forEach((value: Message) => {
value.viewed = true;
});
}
}
const messageManager = new MessageManager();
export default messageManager;

View File

@ -1,69 +1,76 @@
<template>
<v-menu activator="#message-btn" :close-on-content-click="false">
<v-sheet width="500" border rounded>
<v-toolbar color="surface" density="compact">
<div class="d-flex justify-center w-100">
<h4>Messages</h4>
</div>
<v-toolbar color="surface" density="comfortable" border>
<v-toolbar-title>Messages</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon @click="markAllReaded">
<v-icon color="success">mdi-check-all</v-icon>
</v-btn>
</v-toolbar>
<v-divider></v-divider>
<v-responsive max-height="350px" class="overflow-y-auto">
<v-list class="py-0">
<template v-for="(item, index) in messages" :key="item.id">
<v-divider v-if="index != 0"></v-divider>
<v-list-item :class="{ 'bg-brown-darken-4': !item.viewed }">
<v-list-item-title>
{{ item.message }}
</v-list-item-title>
<template v-slot:prepend>
<v-icon
:icon="getMessageIcon(item.type)"
:color="getMessageColor(item.type)"
class="mr-3"
></v-icon>
</template>
<template v-slot:append>
<v-btn
v-if="item.detail"
variant="text"
icon
color="secondary"
@click="show[index] = show[index] ? false : true"
size="small"
>
<v-icon>
{{ show[index] ? "mdi-chevron-up" : "mdi-information" }}
</v-icon>
</v-btn>
<v-scroll-x-transition>
<v-btn
color="success"
variant="text"
@click="markReaded(item.id)"
icon
v-show="!item.viewed"
size="small"
>
<v-icon>mdi-check</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-data-iterator :items="messages" item-value="id" items-per-page="-1">
<template v-slot:default="{ items, isExpanded, toggleExpand}">
<template v-for="(item, index) in items" :key="item.raw.id">
<v-divider v-if="index != 0"></v-divider>
<v-list-item :class="{ 'bg-brown-darken-4': !item.raw.viewed }">
<v-list-item-title>
{{ item.raw.message }}
</v-list-item-title>
<template v-slot:prepend>
<v-icon
:icon="getMessageIcon(item.raw.type)"
:color="getMessageColor(item.raw.type)"
class="mr-3"
></v-icon>
</template>
<template v-slot:append>
<v-btn
v-if="item.raw.detail"
variant="text"
icon
color="secondary"
@click="toggleExpand(item)"
size="small"
>
<v-icon>
{{ isExpanded(item) ? "mdi-chevron-up" : "mdi-information" }}
</v-icon>
</v-btn>
<v-scroll-x-transition>
<v-btn
color="success"
variant="text"
@click="markReaded(item.raw.id)"
icon
v-show="!item.raw.viewed"
size="small"
>
<v-icon>mdi-check</v-icon>
</v-btn>
</v-scroll-x-transition>
<div class="text-caption text-disabled ml-1">
{{ getTimeDelta(item.time) }}
</div>
<div class="text-caption text-disabled ml-1">
{{ getTimeDelta(item.raw.time) }}
</div>
</template>
</v-list-item>
<v-expand-transition v-if="item.raw.detail">
<div v-if="isExpanded(item)">
<v-divider class="mx-3"></v-divider>
<v-card class="mx-3 my-2" variant="outlined" color="secondary">
<v-card-text>
{{ item.raw.detail }}
</v-card-text>
</v-card>
</div>
</v-expand-transition>
</template>
</v-list-item>
<v-expand-transition v-if="item.detail">
<div v-show="show[index]">
<v-divider class="mx-3"></v-divider>
<v-card class="mx-3 my-2" variant="outlined" color="secondary">
<v-card-text>
{{ item.detail }}
</v-card-text>
</v-card>
</div>
</v-expand-transition>
</template>
</template>
</v-data-iterator>
</v-list>
</v-responsive>
</v-sheet>
@ -153,8 +160,13 @@ function markReaded(id: string) {
});
}
function markAllReaded(){
messageService.markAllRead().then((value) => {
messages.value = value;
})
}
onBeforeUnmount(() => {
clearInterval(interval);
});
</script>
@/store/message
</script>

View File

@ -8,3 +8,7 @@ export function getMessages() {
export function markRead(id: string) {
return kyClient.patch(`messages/${encodeURI(id)}/readed`).json<Message[]>();
}
export function markAllRead(){
return kyClient.post(`messages/allReaded`).json<Message[]>();
}