hassio-nextcloud-backup/nextcloud_backup/frontend/src/components/MessageBar.vue

184 lines
5.5 KiB
Vue
Raw Normal View History

<template>
<v-menu activator="#message-btn" :close-on-content-click="false">
<v-sheet width="500" border rounded>
2024-02-19 10:52:37 +01:00
<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">
2024-04-19 17:19:12 +02:00
<v-data-iterator
:items="messages"
item-value="id"
items-per-page="-1"
>
<template v-slot:default="{ items, isExpanded, toggleExpand }">
2024-02-19 10:52:37 +01:00
<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"
2024-04-19 17:19:12 +02:00
@click="toggleExpand(item as any)"
2024-02-19 10:52:37 +01:00
size="small"
>
<v-icon>
2024-04-19 17:19:12 +02:00
{{
isExpanded(item as any)
? "mdi-chevron-up"
: "mdi-information"
}}
2024-02-19 10:52:37 +01:00
</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>
2024-02-19 10:52:37 +01:00
<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">
2024-04-19 17:19:12 +02:00
<div v-if="isExpanded(item as any)">
2024-02-19 10:52:37 +01:00
<v-divider class="mx-3"></v-divider>
2024-04-19 17:19:12 +02:00
<v-card
class="mx-3 my-2"
variant="outlined"
color="secondary"
>
2024-02-19 10:52:37 +01:00
<v-card-text>
{{ item.raw.detail }}
</v-card-text>
</v-card>
</div>
</v-expand-transition>
</template>
2024-02-19 10:52:37 +01:00
</template>
</v-data-iterator>
</v-list>
</v-responsive>
</v-sheet>
</v-menu>
</template>
<script setup lang="ts">
2022-10-26 14:09:10 +02:00
import * as messageService from "@/services/messageService";
2024-02-18 17:19:37 +01:00
import { useMessageStore } from "@/store/message";
2022-10-26 12:06:29 +02:00
import { MessageType } from "@/types/messages";
import { DateTime } from "luxon";
2022-10-26 12:06:29 +02:00
import { storeToRefs } from "pinia";
import { onBeforeUnmount, ref } from "vue";
2022-10-26 12:06:29 +02:00
const messagesStore = useMessageStore();
const { messages } = storeToRefs(messagesStore);
2022-10-26 14:09:10 +02:00
const interval = setInterval(refreshMessages, 2000);
function refreshMessages() {
2022-10-26 14:09:10 +02:00
messageService.getMessages().then((values) => {
messages.value = values;
});
}
function getMessageColor(messageType: MessageType) {
switch (messageType) {
case MessageType.ERROR:
return "red";
case MessageType.WARN:
return "yellow";
case MessageType.INFO:
return "primary";
case MessageType.SUCCESS:
return "success";
}
}
function getMessageIcon(messageType: MessageType) {
switch (messageType) {
case MessageType.ERROR:
return "mdi-alert-octagram";
case MessageType.WARN:
return "mdi-alert";
case MessageType.INFO:
return "mdi-alert-circle";
case MessageType.SUCCESS:
return "mdi-check-circle";
}
}
function getTimeDelta(time: string) {
let duration = DateTime.now().diff(DateTime.fromISO(time), ["seconds"]);
if (duration.seconds < 60) {
return duration.toHuman({
maximumFractionDigits: 0,
unitDisplay: "short",
} as any);
}
duration = duration.shiftTo("minutes");
if (duration.minutes < 60) {
return duration.toHuman({
maximumFractionDigits: 0,
unitDisplay: "short",
} as any);
}
duration = duration.shiftTo("hours");
if (duration.hours < 24) {
return duration.toHuman({
maximumFractionDigits: 0,
unitDisplay: "short",
} as any);
} else {
return duration.shiftTo("days").toHuman({
maximumFractionDigits: 0,
unitDisplay: "short",
} as any);
}
}
const show = ref<boolean[]>([]);
refreshMessages();
2022-10-26 14:09:10 +02:00
function markReaded(id: string) {
messageService.markRead(id).then((values) => {
messages.value = values;
});
}
2024-04-19 17:19:12 +02:00
function markAllReaded() {
2024-02-19 10:52:37 +01:00
messageService.markAllRead().then((value) => {
messages.value = value;
2024-04-19 17:19:12 +02:00
});
2024-02-19 10:52:37 +01:00
}
onBeforeUnmount(() => {
clearInterval(interval);
});
2024-04-19 17:19:12 +02:00
</script>