mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-26 02:52:59 +01:00
Compare commits
No commits in common. "2aa53310368d1ff1a48b5d124f665d79482812f1" and "96a6e22072737964a2894e07f27bc10fa73c7e47" have entirely different histories.
2aa5331036
...
96a6e22072
@ -1,4 +1,3 @@
|
|||||||
import { randomUUID } from "crypto";
|
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { Message, MessageType } from "../types/message.js";
|
import { Message, MessageType } from "../types/message.js";
|
||||||
|
|
||||||
@ -9,7 +8,6 @@ class MessageManager {
|
|||||||
|
|
||||||
public addMessage(type: MessageType, message: string, detail?: string, isImportant = false) {
|
public addMessage(type: MessageType, message: string, detail?: string, isImportant = false) {
|
||||||
this.messages.push({
|
this.messages.push({
|
||||||
id: randomUUID(),
|
|
||||||
message: message,
|
message: message,
|
||||||
type: type,
|
type: type,
|
||||||
time: DateTime.now(),
|
time: DateTime.now(),
|
||||||
|
@ -9,7 +9,6 @@ export enum MessageType {
|
|||||||
|
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
id: string;
|
|
||||||
time: DateTime;
|
time: DateTime;
|
||||||
type: MessageType;
|
type: MessageType;
|
||||||
message: string;
|
message: string;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"pinia": "^2.0.23",
|
"pinia": "^2.0.23",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"vue": "^3.2.40",
|
"vue": "^3.2.40",
|
||||||
"vuetify": "3.0.0-beta.15",
|
"vuetify": "3.0.0-beta.14",
|
||||||
"webfontloader": "^1.0.0"
|
"webfontloader": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -24,7 +24,7 @@ specifiers:
|
|||||||
vite-plugin-vuetify: ^1.0.0-alpha.12
|
vite-plugin-vuetify: ^1.0.0-alpha.12
|
||||||
vue: ^3.2.40
|
vue: ^3.2.40
|
||||||
vue-tsc: 1.0.7
|
vue-tsc: 1.0.7
|
||||||
vuetify: 3.0.0-beta.15
|
vuetify: 3.0.0-beta.14
|
||||||
webfontloader: ^1.0.0
|
webfontloader: ^1.0.0
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -36,7 +36,7 @@ dependencies:
|
|||||||
pinia: 2.0.23_rg374xhldfcyvjtaj3qktyfz5y
|
pinia: 2.0.23_rg374xhldfcyvjtaj3qktyfz5y
|
||||||
roboto-fontface: 0.10.0
|
roboto-fontface: 0.10.0
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
vuetify: 3.0.0-beta.15_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
webfontloader: 1.6.28
|
webfontloader: 1.6.28
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@ -53,7 +53,7 @@ devDependencies:
|
|||||||
prettier: 2.7.1
|
prettier: 2.7.1
|
||||||
typescript: 4.7.4
|
typescript: 4.7.4
|
||||||
vite: 3.1.7
|
vite: 3.1.7
|
||||||
vite-plugin-vuetify: 1.0.0-alpha.17_g64smqxqrz57uhsly7clskj5fy
|
vite-plugin-vuetify: 1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla
|
||||||
vue-tsc: 1.0.7_typescript@4.7.4
|
vue-tsc: 1.0.7_typescript@4.7.4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
@ -482,7 +482,7 @@ packages:
|
|||||||
'@types/node': 16.11.65
|
'@types/node': 16.11.65
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vuetify/loader-shared/1.6.0_l2xw63bflzffxrhpro723k3mhy:
|
/@vuetify/loader-shared/1.6.0_ufv4csfzemzfiqpf5bhlrg5qhm:
|
||||||
resolution: {integrity: sha512-mRvswe5SIecagmKkL1c0UQx5V9ACKLyEGegOOe5vC3ccFH8rMbyI4AVZaAKm/EnGXKirWJ1umL8RQFcGd+C0tw==}
|
resolution: {integrity: sha512-mRvswe5SIecagmKkL1c0UQx5V9ACKLyEGegOOe5vC3ccFH8rMbyI4AVZaAKm/EnGXKirWJ1umL8RQFcGd+C0tw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.0.0
|
vue: ^3.0.0
|
||||||
@ -491,7 +491,7 @@ packages:
|
|||||||
find-cache-dir: 3.3.2
|
find-cache-dir: 3.3.2
|
||||||
upath: 2.0.1
|
upath: 2.0.1
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
vuetify: 3.0.0-beta.15_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
|
|
||||||
/acorn-jsx/5.3.2_acorn@8.8.0:
|
/acorn-jsx/5.3.2_acorn@8.8.0:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
@ -2150,18 +2150,18 @@ packages:
|
|||||||
spdx-expression-parse: 3.0.1
|
spdx-expression-parse: 3.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-vuetify/1.0.0-alpha.17_g64smqxqrz57uhsly7clskj5fy:
|
/vite-plugin-vuetify/1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla:
|
||||||
resolution: {integrity: sha512-lP4vG+Z3LnIEjI8nSE8/MJwDRQK5OnS2i4zHDu36yyD4E7wmPKyIkWJdkfBIsx/O+PU7dGc/3MeLARgr+RErEQ==}
|
resolution: {integrity: sha512-lP4vG+Z3LnIEjI8nSE8/MJwDRQK5OnS2i4zHDu36yyD4E7wmPKyIkWJdkfBIsx/O+PU7dGc/3MeLARgr+RErEQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.7.0 || ^3.0.0
|
vite: ^2.7.0 || ^3.0.0
|
||||||
vuetify: ^3.0.0-beta.4
|
vuetify: ^3.0.0-beta.4
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vuetify/loader-shared': 1.6.0_l2xw63bflzffxrhpro723k3mhy
|
'@vuetify/loader-shared': 1.6.0_ufv4csfzemzfiqpf5bhlrg5qhm
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
upath: 2.0.1
|
upath: 2.0.1
|
||||||
vite: 3.1.7
|
vite: 3.1.7
|
||||||
vuetify: 3.0.0-beta.15_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- vue
|
- vue
|
||||||
@ -2252,8 +2252,8 @@ packages:
|
|||||||
'@vue/server-renderer': 3.2.40_vue@3.2.40
|
'@vue/server-renderer': 3.2.40_vue@3.2.40
|
||||||
'@vue/shared': 3.2.40
|
'@vue/shared': 3.2.40
|
||||||
|
|
||||||
/vuetify/3.0.0-beta.15_vdkwhj2kz5kpysy3rwb432nm3y:
|
/vuetify/3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y:
|
||||||
resolution: {integrity: sha512-Tw4StO4JJxwzN7RIAJ+nBVTaftlk3TqfqCtMLwJY/SO/ciVru+sHtahOpXIbp8B43d/DIRql3mfnrz1ooTSXtQ==}
|
resolution: {integrity: sha512-7UX2rAcMPGdJ0SGAK+wUvlJTHR0KasYILhg7dV9hLyv9SfaTX4tbOQnSQVf4mXzdFB+5jDyaTs+bOYMVeoqXYg==}
|
||||||
engines: {node: ^12.20 || >=14.13}
|
engines: {node: ^12.20 || >=14.13}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite-plugin-vuetify: ^1.0.0-alpha.12
|
vite-plugin-vuetify: ^1.0.0-alpha.12
|
||||||
@ -2268,7 +2268,7 @@ packages:
|
|||||||
webpack-plugin-vuetify:
|
webpack-plugin-vuetify:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vite-plugin-vuetify: 1.0.0-alpha.17_g64smqxqrz57uhsly7clskj5fy
|
vite-plugin-vuetify: 1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
|
|
||||||
/webfontloader/1.6.28:
|
/webfontloader/1.6.28:
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<navbar-component></navbar-component>
|
<v-main>
|
||||||
<message-bar></message-bar>
|
<navbar-component></navbar-component>
|
||||||
<webdav-settings-menu></webdav-settings-menu>
|
<message-bar></message-bar>
|
||||||
<v-main> </v-main>
|
<webdav-settings-menu></webdav-settings-menu>
|
||||||
|
</v-main>
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
<v-responsive max-height="350px" class="overflow-y-auto">
|
<v-responsive max-height="350px" class="overflow-y-auto">
|
||||||
<v-list class="py-0">
|
<v-list class="py-0">
|
||||||
<template v-for="(item, index) in messages" :key="item.id">
|
<template v-for="(item, index) in messages" :key="item.message">
|
||||||
<v-divider v-if="index != 0"></v-divider>
|
<v-divider v-if="index != 0"></v-divider>
|
||||||
<v-list-item :class="{ 'bg-brown-darken-4': !item.viewed }">
|
<v-list-item :class="{ 'bg-brown-darken-4': !item.viewed }">
|
||||||
<v-list-item-title>
|
<v-list-item-title>
|
||||||
@ -67,22 +67,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getMessages } from "@/services/messageService";
|
import { getMessages } from "@/services/messageService";
|
||||||
import { useMessageStore } from "@/stores/message";
|
import { MessageType, type Message } from "@/types/messages";
|
||||||
import { MessageType } from "@/types/messages";
|
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { storeToRefs } from "pinia";
|
import { ref } from "vue";
|
||||||
import { onBeforeUnmount, ref } from "vue";
|
|
||||||
|
|
||||||
const messagesStore = useMessageStore();
|
const messages = ref<Message[]>([]);
|
||||||
const { messages } = storeToRefs(messagesStore);
|
|
||||||
|
|
||||||
const interval = setInterval(refreshMessages, 1000);
|
getMessages().then((values) => {
|
||||||
|
messages.value = values;
|
||||||
function refreshMessages() {
|
});
|
||||||
getMessages().then((values) => {
|
|
||||||
messages.value = values;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMessageColor(messageType: MessageType) {
|
function getMessageColor(messageType: MessageType) {
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
@ -139,10 +132,6 @@ function getTimeDelta(time: string) {
|
|||||||
} as any);
|
} as any);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const show = ref<boolean[]>([]);
|
|
||||||
refreshMessages();
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
const show = ref<boolean[]>([]);
|
||||||
clearInterval(interval);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,10 +9,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</v-app-bar-title>
|
</v-app-bar-title>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn icon id="message-btn" >
|
<v-btn icon id="message-btn">
|
||||||
<v-badge color="error" :content="countUnreadMessages">
|
<v-icon>mdi-bell</v-icon>
|
||||||
<v-icon :class="{ shake: haveUnreadMessages }">mdi-bell</v-icon>
|
|
||||||
</v-badge>
|
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-menu width="210px">
|
<v-menu width="210px">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
@ -38,13 +36,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useDialogStatusStore } from "@/stores/dialogStatus";
|
import { useDialogStatusStore } from "@/stores/dialogStatus";
|
||||||
import { useMessageStore } from "@/stores/message";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
import logoUrl from "../assets/logo.svg";
|
import logoUrl from "../assets/logo.svg";
|
||||||
|
|
||||||
const dialogStatusStore = useDialogStatusStore();
|
const dialogStatusStore = useDialogStatusStore();
|
||||||
const messagesStore = useMessageStore();
|
|
||||||
const { haveUnreadMessages, countUnreadMessages } = storeToRefs(messagesStore);
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.shake {
|
.shake {
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.url"
|
v-model="data.url"
|
||||||
:error-messages="errors.url"
|
:error-messages="errors.url"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@ -26,8 +24,6 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.webdavEndpoint.type"
|
v-model="data.webdavEndpoint.type"
|
||||||
:error-messages="errors.type"
|
:error-messages="errors.type"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
>
|
>
|
||||||
</v-select>
|
</v-select>
|
||||||
</v-col>
|
</v-col>
|
||||||
@ -43,22 +39,19 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.webdavEndpoint.customEndpoint"
|
v-model="data.webdavEndpoint.customEndpoint"
|
||||||
:error-messages="errors.customEndpoint"
|
:error-messages="errors.customEndpoint"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col class="d-flex align-content-end">
|
<v-col class="d-flex align-content-end">
|
||||||
<v-switch
|
<v-switch
|
||||||
|
color="warning"
|
||||||
label="Allow Self Signed Certificate"
|
label="Allow Self Signed Certificate"
|
||||||
v-model="data.allowSelfSignedCerts"
|
v-model="data.allowSelfSignedCerts"
|
||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
density="compact"
|
density="compact"
|
||||||
inset
|
inset
|
||||||
:error-messages="errors.allowSelfSignedCerts"
|
:error-messages="errors.allowSelfSignedCerts"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
></v-switch>
|
></v-switch>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@ -90,8 +83,6 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.username"
|
v-model="data.username"
|
||||||
:error-messages="errors.username"
|
:error-messages="errors.username"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
>
|
>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
@ -106,8 +97,6 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.password"
|
v-model="data.password"
|
||||||
:error-messages="errors.password"
|
:error-messages="errors.password"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@ -125,8 +114,6 @@
|
|||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
v-model="data.backupDir"
|
v-model="data.backupDir"
|
||||||
:error-messages="errors.backupDir"
|
:error-messages="errors.backupDir"
|
||||||
:loading="loading"
|
|
||||||
color="orange"
|
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@ -144,8 +131,6 @@ import {
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { HTTPError } from "ky";
|
import { HTTPError } from "ky";
|
||||||
|
|
||||||
const loading = ref(true);
|
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
title: "Nextcloud",
|
title: "Nextcloud",
|
||||||
@ -182,16 +167,13 @@ const emit = defineEmits<{
|
|||||||
(e: "success"): void;
|
(e: "success"): void;
|
||||||
(e: "fail"): void;
|
(e: "fail"): void;
|
||||||
(e: "loaded"): void;
|
(e: "loaded"): void;
|
||||||
(e: "loading"): void;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
loading.value = true;
|
|
||||||
clearErrors();
|
clearErrors();
|
||||||
saveWebdavConfig(data.value)
|
saveWebdavConfig(data.value)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
emit("success");
|
emit("success");
|
||||||
loading.value = false;
|
|
||||||
})
|
})
|
||||||
.catch(async (reason) => {
|
.catch(async (reason) => {
|
||||||
if (reason instanceof HTTPError) {
|
if (reason instanceof HTTPError) {
|
||||||
@ -204,7 +186,6 @@ function save() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit("fail");
|
emit("fail");
|
||||||
loading.value = false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +196,10 @@ function clearErrors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadData() {
|
function loadData() {
|
||||||
emit("loading");
|
console.log("ok");
|
||||||
getWebdavConfig().then((value) => {
|
getWebdavConfig().then((value) => {
|
||||||
data.value = value;
|
data.value = value;
|
||||||
emit("loaded");
|
emit("loaded");
|
||||||
loading.value = false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
@fail="saving = false"
|
@fail="saving = false"
|
||||||
@success="dialogStatusStore.webdav = false"
|
@success="dialogStatusStore.webdav = false"
|
||||||
@loaded="loading = false"
|
@loaded="loading = false"
|
||||||
@loading="loading = true"
|
|
||||||
></webdav-settings-form>
|
></webdav-settings-form>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
|
8
nextcloud_backup/frontend/src/stores/counter.ts
Normal file
8
nextcloud_backup/frontend/src/stores/counter.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { ref } from "vue";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import type { Message } from "@/types/messages";
|
||||||
|
|
||||||
|
export const useMessageStore = defineStore("message", () => {
|
||||||
|
const messages = ref<Message[]>([]);
|
||||||
|
return { messages };
|
||||||
|
});
|
@ -1,23 +0,0 @@
|
|||||||
import { computed, ref } from "vue";
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
import type { Message } from "@/types/messages";
|
|
||||||
|
|
||||||
export const useMessageStore = defineStore("message", () => {
|
|
||||||
const messages = ref<Message[]>([]);
|
|
||||||
const countUnreadMessages = computed(() => {
|
|
||||||
return messages.value.filter((value) => !value.viewed).length;
|
|
||||||
});
|
|
||||||
|
|
||||||
const haveUnreadMessages = computed(() => {
|
|
||||||
let unread = false;
|
|
||||||
for (const mess of messages.value) {
|
|
||||||
if (!mess.viewed) {
|
|
||||||
unread = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return unread;
|
|
||||||
});
|
|
||||||
|
|
||||||
return { messages, countUnreadMessages, haveUnreadMessages };
|
|
||||||
});
|
|
@ -8,7 +8,6 @@ export enum MessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
id: string;
|
|
||||||
time: string;
|
time: string;
|
||||||
type: MessageType;
|
type: MessageType;
|
||||||
message: string;
|
message: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user