mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
add backup viewer to dashboard
This commit is contained in:
parent
60c5a7e198
commit
c06cf2c001
4 changed files with 176 additions and 28 deletions
144
frontend/src/pages/Admin/Dashboard/BackupViewer.vue
Normal file
144
frontend/src/pages/Admin/Dashboard/BackupViewer.vue
Normal file
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<div>
|
||||
<ImportDialog
|
||||
:name="selectedName"
|
||||
:date="selectedDate"
|
||||
ref="import_dialog"
|
||||
@import="importBackup"
|
||||
@delete="deleteBackup"
|
||||
/>
|
||||
<StatCard icon="mdi-backup-restore" :color="color">
|
||||
<template v-slot:after-heading>
|
||||
<div class="ml-auto text-right">
|
||||
<div class="body-3 grey--text font-weight-light" v-text="'Backups'" />
|
||||
|
||||
<h3 class="display-2 font-weight-light text--primary">
|
||||
<small> {{ total }}</small>
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
<div class="d-flex row py-3 justify-end">
|
||||
<TheUploadBtn url="/api/backups/upload" @uploaded="getAvailableBackups">
|
||||
<template v-slot="{ isSelecting, onButtonClick }">
|
||||
<v-btn :loading="isSelecting" class="mx-2" small :color="color" @click="onButtonClick">
|
||||
<v-icon left> mdi-cloud-upload </v-icon> Upload
|
||||
</v-btn>
|
||||
</template>
|
||||
</TheUploadBtn>
|
||||
<v-btn :loading="loading" class="mx-2" small :color="color" @click="createBackup">
|
||||
<v-icon left> mdi-plus </v-icon> Create
|
||||
</v-btn>
|
||||
</div>
|
||||
<template v-slot:bottom>
|
||||
<v-virtual-scroll height="290" item-height="70" :items="availableBackups">
|
||||
<template v-slot:default="{ item }">
|
||||
<v-list-item @click.prevent="openDialog(item)">
|
||||
<v-list-item-avatar>
|
||||
<v-icon large dark :color="color">
|
||||
mdi-backup-restore
|
||||
</v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="item.name"></v-list-item-title>
|
||||
|
||||
<v-list-item-subtitle>
|
||||
{{ $d(Date.parse(item.date), "medium") }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
|
||||
<v-list-item-action class="ml-auto">
|
||||
<v-btn large icon @click.stop="deleteBackup(item.name)">
|
||||
<v-icon color="error">mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-virtual-scroll>
|
||||
</template>
|
||||
</StatCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TheUploadBtn from "@/components/UI/Buttons/TheUploadBtn";
|
||||
import { api } from "@/api";
|
||||
import StatCard from "./StatCard";
|
||||
import ImportDialog from "../Backup/ImportDialog";
|
||||
export default {
|
||||
components: { StatCard, ImportDialog, TheUploadBtn },
|
||||
data() {
|
||||
return {
|
||||
color: "secondary",
|
||||
selectedName: "",
|
||||
selectedDate: "",
|
||||
loading: false,
|
||||
events: [],
|
||||
availableBackups: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
total() {
|
||||
return this.availableBackups.length;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getAvailableBackups();
|
||||
},
|
||||
methods: {
|
||||
async getAvailableBackups() {
|
||||
const response = await api.backups.requestAvailable();
|
||||
this.availableBackups = response.imports;
|
||||
console.log(this.availableBackups);
|
||||
},
|
||||
|
||||
async deleteBackup(name) {
|
||||
this.loading = true;
|
||||
await api.backups.delete(name);
|
||||
this.loading = false;
|
||||
this.getAvailableBackups();
|
||||
},
|
||||
|
||||
openDialog(backup) {
|
||||
this.selectedDate = backup.date;
|
||||
this.selectedName = backup.name;
|
||||
this.$refs.import_dialog.open();
|
||||
},
|
||||
async importBackup(data) {
|
||||
this.loading = true;
|
||||
const response = await api.backups.import(data.name, data);
|
||||
if (response) {
|
||||
let importData = response.data;
|
||||
this.$emit("finished", importData);
|
||||
} else {
|
||||
this.$emit("finished");
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
async createBackup() {
|
||||
this.loading = true;
|
||||
|
||||
let data = {
|
||||
tag: this.tag,
|
||||
options: {
|
||||
recipes: true,
|
||||
settings: true,
|
||||
themes: true,
|
||||
users: true,
|
||||
groups: true,
|
||||
},
|
||||
templates: [],
|
||||
};
|
||||
|
||||
if (await api.backups.create(data)) {
|
||||
this.getAvailableBackups();
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -1,45 +1,47 @@
|
|||
<template>
|
||||
<div>
|
||||
<StatCard icon="mdi-bell-ring">
|
||||
<StatCard icon="mdi-bell-ring" :color="color">
|
||||
<template v-slot:after-heading>
|
||||
<div class="ml-auto text-right">
|
||||
<div class="body-3 grey--text font-weight-light" v-text="'Events'" />
|
||||
|
||||
<h3 class="display-2 font-weight-light text--primary">
|
||||
<small> {{ total }}</small>
|
||||
<small> {{ total }} </small>
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
<div class="d-flex row py-3 justify-end">
|
||||
<v-btn class="mx-2" small color="primary" @click="deleteAll">
|
||||
<v-btn class="mx-2" small :color="color" @click="deleteAll">
|
||||
<v-icon left> mdi-notification-clear-all </v-icon> Clear
|
||||
</v-btn>
|
||||
</div>
|
||||
<template v-slot:bottom>
|
||||
<v-list subheader two-line>
|
||||
<v-list-item v-for="(event, index) in events" :key="index">
|
||||
<v-list-item-avatar>
|
||||
<v-icon large dark :color="icons[event.category].color">
|
||||
{{ icons[event.category].icon }}
|
||||
</v-icon>
|
||||
</v-list-item-avatar>
|
||||
<v-virtual-scroll height="290" item-height="70" :items="events">
|
||||
<template v-slot:default="{ item }">
|
||||
<v-list-item>
|
||||
<v-list-item-avatar>
|
||||
<v-icon large dark :color="icons[item.category].color">
|
||||
{{ icons[item.category].icon }}
|
||||
</v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="event.title"></v-list-item-title>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="item.title"></v-list-item-title>
|
||||
|
||||
<v-list-item-subtitle v-text="event.text"></v-list-item-subtitle>
|
||||
<v-list-item-subtitle>
|
||||
{{ $d(Date.parse(event.timeStamp), "long") }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-subtitle v-text="item.text"></v-list-item-subtitle>
|
||||
<v-list-item-subtitle>
|
||||
{{ $d(Date.parse(item.timeStamp), "long") }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
|
||||
<v-list-item-action class="ml-auto">
|
||||
<v-btn large icon @click="deleteEvent(event.id)">
|
||||
<v-icon color="error">mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-list-item-action class="ml-auto">
|
||||
<v-btn large icon @click="deleteEvent(item.id)">
|
||||
<v-icon color="error">mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-virtual-scroll>
|
||||
</template>
|
||||
</StatCard>
|
||||
</div>
|
||||
|
@ -52,6 +54,7 @@ export default {
|
|||
components: { StatCard },
|
||||
data() {
|
||||
return {
|
||||
color: "secondary",
|
||||
total: 0,
|
||||
events: [],
|
||||
icons: {
|
||||
|
|
|
@ -9,7 +9,7 @@ w<template>
|
|||
class="text-start v-card--material__heading mb-n6 mt-n10 pa-7"
|
||||
dark
|
||||
>
|
||||
<v-icon v-if="icon" size="32" v-text="icon" />
|
||||
<v-icon v-if="icon" size="40" v-text="icon" />
|
||||
<div v-if="text" class="headline font-weight-thin" v-text="text" />
|
||||
</v-sheet>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="mt-10">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<StatCard icon="mdi-silverware-fork-knife">
|
||||
<template v-slot:after-heading>
|
||||
<div class="ml-auto text-right">
|
||||
|
@ -71,7 +71,7 @@
|
|||
<v-col cols="12" sm="12" lg="6">
|
||||
<EventViewer />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" lg="6"> </v-col>
|
||||
<v-col cols="12" sm="12" lg="6"> <BackupViewer /> </v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -80,8 +80,9 @@
|
|||
import { api } from "@/api";
|
||||
import StatCard from "./StatCard";
|
||||
import EventViewer from "./EventViewer";
|
||||
import BackupViewer from "./BackupViewer";
|
||||
export default {
|
||||
components: { StatCard, EventViewer },
|
||||
components: { StatCard, EventViewer, BackupViewer },
|
||||
data() {
|
||||
return {
|
||||
statistics: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue