-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6652916
commit c93bef1
Showing
4 changed files
with
190 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<script lang="ts" setup> | ||
export interface PageHeaderProps { | ||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | ||
} | ||
const props = withDefaults(defineProps<PageHeaderProps>(), { | ||
as: 'h1' | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<component | ||
:is="props.as" | ||
class="text-2xl font-bold leading-10 tracking-tight text-base-content-highlight" | ||
> | ||
<slot name="title" /> | ||
</component> | ||
|
||
<p | ||
v-if="$slots.text" | ||
class="text-base-content" | ||
> | ||
<slot name="text" /> | ||
</p> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
<script lang="ts" setup> | ||
import { ArrowDownTrayIcon, ArrowUturnLeftIcon } from '@heroicons/vue/24/solid' | ||
import PageHeader from '~/components/layout/PageHeader.vue' | ||
import { toast } from 'vue-sonner' | ||
import type { ISavedPost } from '~/store/SavedPosts' | ||
import type { ITagCollection } from 'assets/js/tagCollection.dto' | ||
interface IBackupState { | ||
version: number | ||
saved_posts: ISavedPost[] | ||
tag_collections: ITagCollection[] | ||
settings: undefined | ||
} | ||
const fileInputElement = ref<HTMLInputElement | null>(null) | ||
function downloadBlob(blob: Blob, filename: string) { | ||
const objectURL = window.URL.createObjectURL(blob) | ||
// Create anchor element | ||
const anchorElement = document.createElement('a') | ||
anchorElement.href = objectURL | ||
anchorElement.target = '_blank' | ||
anchorElement.download = filename | ||
anchorElement.style.display = 'none' | ||
// Download | ||
anchorElement.click() | ||
// Clean up | ||
anchorElement.remove() | ||
window.URL.revokeObjectURL(objectURL) | ||
} | ||
function createBackup() { | ||
const currentDateString = new Date() | ||
.toLocaleString([], { | ||
timeZone: 'UTC', | ||
hour12: false, | ||
second: '2-digit', | ||
minute: '2-digit', | ||
hour: '2-digit', | ||
day: '2-digit', | ||
month: '2-digit', | ||
year: 'numeric' | ||
}) | ||
.replaceAll(', ', '_') | ||
.replaceAll('/', '-') | ||
.replaceAll(':', '-') | ||
// TODO: Do versioning, or maybe not? | ||
const STATE: IBackupState = { | ||
version: 1, | ||
saved_posts: [], | ||
tag_collections: [], | ||
settings: undefined | ||
} | ||
const blob = new Blob([JSON.stringify(STATE)], { type: 'application/json' }) | ||
const fileName = `R34App_${currentDateString}_Backup.json` | ||
downloadBlob(blob, fileName) | ||
} | ||
async function restoreBackup() { | ||
if (!fileInputElement.value) { | ||
toast.error('No file selected') | ||
return | ||
} | ||
const file = fileInputElement.value.files?.[0] | ||
if (!file) { | ||
toast.error('No file selected') | ||
return | ||
} | ||
const backupData: IBackupState = JSON.parse(await file.text()) | ||
if (backupData.version !== 1) { | ||
toast.error('Invalid backup file') | ||
return | ||
} | ||
if (backupData.saved_posts) { | ||
// TODO | ||
} | ||
if (backupData.tag_collections) { | ||
// TODO | ||
} | ||
if (backupData.settings) { | ||
// TODO | ||
} | ||
toast.success('Backup restored') | ||
} | ||
useSeoMeta({ | ||
title: 'Backup' | ||
}) | ||
definePageMeta({ middleware: 'auth' }) | ||
</script> | ||
|
||
<template> | ||
<main class="container relative mx-auto max-w-3xl flex-1 px-4 sm:px-6 lg:px-8"> | ||
<!-- --> | ||
|
||
<!-- Header --> | ||
<PageHeader class="mt-4"> | ||
<template #title>Backup & Restore</template> | ||
<template #text> | ||
<div class="text-sm"> | ||
Backup your saved posts, tag collections and settings. | ||
|
||
<span class="italic"> This is a manual process. Remember to backup your data regularly. </span> | ||
</div> | ||
</template> | ||
</PageHeader> | ||
|
||
<section class="mt-8 flex justify-around"> | ||
<!-- --> | ||
|
||
<!-- Backup --> | ||
<button | ||
class="focus-visible:focus-util hover:hover-text-util hover:hover-bg-util inline-flex min-w-[5rem] flex-col items-center gap-1.5 rounded-md p-2 ring-1 ring-base-0/20" | ||
type="button" | ||
@click="createBackup" | ||
> | ||
<ArrowDownTrayIcon class="h-6 w-6" /> | ||
|
||
Backup | ||
</button> | ||
|
||
<!-- Restore --> | ||
<input | ||
ref="fileInputElement" | ||
accept="application/json" | ||
style="display: none" | ||
type="file" | ||
@change="restoreBackup" | ||
/> | ||
|
||
<button | ||
class="focus-visible:focus-util hover:hover-text-util hover:hover-bg-util inline-flex min-w-[5rem] flex-col items-center gap-1.5 rounded-md p-2 ring-1 ring-base-0/20" | ||
type="button" | ||
@click="$refs.fileInputElement.click()" | ||
> | ||
<ArrowUturnLeftIcon class="h-6 w-6" /> | ||
|
||
Restore | ||
</button> | ||
</section> | ||
</main> | ||
</template> |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.