This commit is contained in:
2021-11-23 01:45:19 +01:00
parent 57b9b875ba
commit 2fbdea00a6
15 changed files with 357 additions and 263 deletions

View File

@@ -1,6 +1,7 @@
<script>
import Router, { link } from 'svelte-spa-router'
import Toasts from './components/Toasts.svelte'
import Dev from './components/Dev.svelte'
import Dashboard from './pages/Dashboard.svelte'
import Limits from './pages/Limits.svelte'
@@ -30,7 +31,7 @@
</div>
<Router {routes} />
<Toasts />
<Footer />
</main>

View File

@@ -1,35 +1,18 @@
<script>
let text = 'Select File'
export let value = undefined
export let file
let input
let error
function validate() {
if (!input || !input.files.length) return
const file = input.files[0]
file = input.files[0]
text = file.name
const reader = new FileReader()
reader.onload = (data) => {
try {
error = false
const text = data.target.result
const parsed = JSON.parse(text)
value = parsed
} catch {
error = true
value = undefined
}
}
reader.readAsText(file)
}
</script>
<label class="btn">
{#if error}Invalid file{:else}{text}{/if}
{text}
<input bind:this={input} on:change={validate} class="input" accept="application/json" type="file" />
</label>

View File

@@ -0,0 +1,19 @@
<script>
import { onMount } from 'svelte'
import { scale } from 'svelte/transition'
export let toast
let show = true
onMount(() => {
setTimeout(() => {
show = false
}, 3000)
})
</script>
{#if show}
<div class="toast toast-{toast.type}" transition:scale>
{toast.message}
</div>
{/if}

View File

@@ -0,0 +1,24 @@
<script>
import { toasts } from '../toasts'
import Toast from './Toast.svelte'
</script>
<div class="wrapper">
{#each $toasts as toast}
<div class="mt-2">
<Toast {toast} />
</div>
{/each}
</div>
<style>
.wrapper {
position: fixed;
bottom: 0;
right: 0;
z-index: 100;
padding: 1rem;
display: flex;
flex-direction: column-reverse;
}
</style>

7
src/dashboard/toasts.js Normal file
View File

@@ -0,0 +1,7 @@
import { writable } from 'svelte/store'
export const toasts = writable([])
export function notify(message, type = 'success') {
toasts.update((toasts) => [...toasts, { message, type }])
}

View File

@@ -2,20 +2,20 @@
import { onMount } from 'svelte'
import { DB } from '../../shared/db'
import { SettingsValidator } from '../../shared/validation'
import { getSettingsWithDefaults } from '../../shared/lib'
import { notify } from '../toasts'
let settings = null
async function load() {
const values = await DB.settings.toArray()
const fromDB = Object.fromEntries(values.map((v) => [v.key, v.value]))
settings = SettingsValidator.validate(fromDB).value
settings = await getSettingsWithDefaults()
}
async function save() {
for (const [key, value] of Object.entries(settings)) {
await DB.settings.put({ key, value })
}
notify('Saved')
}
onMount(load)

View File

@@ -4,17 +4,23 @@
import FileUpload from '../components/FileUpload.svelte'
import { dump, load, clear } from '../../shared/db'
import { checkForErrors, DBValidator } from '../../shared/validation'
import { clear, DB } from '../../shared/db'
import { longPress } from '../../shared/lib'
import { notify } from '../toasts'
let uploaded
let file
let loading = false
async function exportDB() {
const data = await dump()
const blob = new Blob([JSON.stringify(data)], { type: 'application/json;charset=utf-8' })
const filename = `Ora [${dj().format('YYYY-MM-DD HH-mm-ss')}].json`
saveAs(blob, filename)
try {
loading = true
const blob = await DB.export()
const filename = `Ora [${dj().format('YYYY-MM-DD HH-mm-ss')}].json`
saveAs(blob, filename)
notify('Exported')
} finally {
loading = false
}
}
async function clearDB() {
@@ -24,26 +30,24 @@
async function importDB() {
try {
await load(uploaded)
alert('Imported')
} catch {
alert('Error importing')
loading = true
await clear()
await DB.import(file)
notify('Imported')
} catch (e) {
notify('Error importing', 'error')
} finally {
loading = false
}
}
$: disabled = uploaded && !checkForErrors(DBValidator, uploaded)
</script>
<h2 class="mt-8 text-2xl">Your Data</h2>
<div class="mt-2">
<FileUpload bind:value={uploaded} />
<button class="btn btn-primary" on:click={importDB} {disabled}>
{#if uploaded && disabled}
Invalid data
{:else}
Import
{/if}
<FileUpload bind:file />
<button class="btn btn-primary" class:loading on:click={importDB} disabled={!file}>Import</button>
<button class="btn btn-primary" class:loading on:click={exportDB}>Export</button>
<button class="btn btn-error tooltip" class:loading data-tooltip="Hold to delete" use:longPress={clearDB}>
Delete all data
</button>
<button class="btn btn-primary" on:click={exportDB}>Export</button>
<button class="btn btn-error tooltip" data-tooltip="Hold to delete" use:longPress={clearDB}>Delete all data</button>
</div>