mirror of
https://github.com/cupcakearmy/ora.git
synced 2026-04-02 12:05:23 +00:00
consolidate all views
This commit is contained in:
@@ -4,17 +4,36 @@
|
||||
import Dev from './components/Dev.svelte'
|
||||
import Dashboard from './pages/Dashboard.svelte'
|
||||
import Limits from './pages/Limits.svelte'
|
||||
import Footer from '../shared/footer.svelte'
|
||||
import Footer from './components/Footer.svelte'
|
||||
import Options from './components/Options.svelte'
|
||||
|
||||
import { isDev } from '../shared/utils'
|
||||
|
||||
const routes = {
|
||||
'/': Dashboard,
|
||||
|
||||
'/options': Options,
|
||||
'/limits': Limits,
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if isDev}
|
||||
<Dev />
|
||||
{/if}
|
||||
<main>
|
||||
<div class="mb-8">
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<a use:link={'/'}><button class="btn">Dashboard</button></a>
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<a use:link={'/limits'}><button class="btn">Limits</button></a>
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<a use:link={'/options'}><button class="btn">Options</button></a>
|
||||
</div>
|
||||
|
||||
<Router {routes} />
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
padding: 1em;
|
||||
@@ -23,18 +42,3 @@
|
||||
max-width: 50em;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if isDev}
|
||||
<Dev />
|
||||
{/if}
|
||||
<main>
|
||||
<div class="mb-8">
|
||||
<a href="../options/index.html"><button class="btn">Options</button></a>
|
||||
<a use:link={'/'}><button class="btn">Dashboard</button></a>
|
||||
<a use:link={'/limits'}><button class="btn">Limits</button></a>
|
||||
</div>
|
||||
|
||||
<Router {routes} />
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
onMount(render)
|
||||
</script>
|
||||
|
||||
<svg bind:this={wrapper} preserveAspectRatio="xMidYMid meet" />
|
||||
|
||||
<style>
|
||||
svg {
|
||||
width: 100%;
|
||||
@@ -98,5 +100,3 @@
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg bind:this={wrapper} preserveAspectRatio="xMidYMid meet" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import faker from 'faker'
|
||||
import faker from 'faker/dist/faker.js'
|
||||
import day from 'dayjs'
|
||||
import { range, random } from 'lodash'
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
await insertLog({ host, timestamp, seconds })
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
@@ -36,6 +38,11 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="p-2">
|
||||
<button class="btn btn-sm" class:loading disabled={loading} on:click={fill}>Add Random Data</button>
|
||||
<button class="btn btn-sm btn-error" class:loading disabled={loading} on:click={clear}>Delete data</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
position: absolute;
|
||||
@@ -43,8 +50,3 @@
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="p-2">
|
||||
<button class="btn btn-sm" class:loading disabled={loading} on:click={fill}>Add Random Data</button>
|
||||
<button class="btn btn-sm btn-error" class:loading disabled={loading} on:click={clear}>Delete data</button>
|
||||
</div>
|
||||
|
||||
47
src/dashboard/components/FileUpload.svelte
Normal file
47
src/dashboard/components/FileUpload.svelte
Normal file
@@ -0,0 +1,47 @@
|
||||
<script>
|
||||
import { isEqual } from 'lodash'
|
||||
|
||||
let text = 'Select File'
|
||||
|
||||
export let value = undefined
|
||||
|
||||
let input
|
||||
let error
|
||||
|
||||
function validate() {
|
||||
if (!input || !input.files.length) return
|
||||
|
||||
const 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>
|
||||
|
||||
<style>
|
||||
label {
|
||||
width: 18em;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
label input[type='file'] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<label class="btn">
|
||||
{#if error}Invalid file{:else}{text}{/if}
|
||||
<input bind:this={input} on:change={validate} class="input" accept="application/json" type="file" />
|
||||
</label>
|
||||
15
src/dashboard/components/Footer.svelte
Normal file
15
src/dashboard/components/Footer.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<footer>
|
||||
<a href="https://github.com/cupcakearmy/ora" target="_blank" rel="noreferrer">Source Code</a>
|
||||
- v0.7
|
||||
<br />
|
||||
Made with ❤️ by
|
||||
<a href="https://nicco.io" target="_blank" rel="noreferrer">🐘</a>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
margin-top: 3rem;
|
||||
text-align: center;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
93
src/dashboard/components/Options.svelte
Normal file
93
src/dashboard/components/Options.svelte
Normal file
@@ -0,0 +1,93 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import browser from 'webextension-polyfill'
|
||||
import { saveAs } from 'file-saver'
|
||||
import dj from 'dayjs'
|
||||
|
||||
import FileUpload from './FileUpload.svelte'
|
||||
|
||||
import { dump as dumpDB, load as loadDB, clear as clearDB, validate } from '../../shared/db'
|
||||
import { longPress } from '../../shared/lib'
|
||||
|
||||
const DEFAULT = {
|
||||
retention: 90,
|
||||
}
|
||||
|
||||
let settings = DEFAULT
|
||||
let uploaded
|
||||
let disabled = true
|
||||
|
||||
async function read() {
|
||||
settings = {
|
||||
...DEFAULT,
|
||||
...(await browser.storage.local.get()),
|
||||
}
|
||||
}
|
||||
|
||||
function write() {
|
||||
return browser.storage.local.set(settings)
|
||||
}
|
||||
|
||||
async function reset() {
|
||||
await browser.storage.local.clear()
|
||||
await read()
|
||||
}
|
||||
|
||||
async function dump() {
|
||||
const data = await dumpDB()
|
||||
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)
|
||||
}
|
||||
|
||||
async function clear() {
|
||||
await clearDB()
|
||||
alert('Done')
|
||||
}
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
await loadDB(uploaded)
|
||||
alert('Imported')
|
||||
} catch {
|
||||
alert('Error importing')
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
disabled = !validate(uploaded)
|
||||
}
|
||||
|
||||
onMount(read)
|
||||
</script>
|
||||
|
||||
<h2 class="mt-8 text-2xl">Settings</h2>
|
||||
<form class="mt-2" on:submit|preventDefault={write}>
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Retention
|
||||
<small>(Days)</small>
|
||||
<input
|
||||
id="retention"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="3"
|
||||
max="365"
|
||||
step="1"
|
||||
bind:value={settings.retention}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="mt-2">
|
||||
<button type="reset" class="btn" on:click={reset}>Reset</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<h2 class="mt-8 text-2xl">Your Data</h2>
|
||||
<div class="mt-2">
|
||||
<FileUpload bind:value={uploaded} />
|
||||
<button class="btn btn-primary" on:click={load} {disabled}>Import</button>
|
||||
<button class="btn btn-primary" on:click={dump}>Export</button>
|
||||
<button class="btn btn-error tooltip" data-tooltip="Hold to delete" use:longPress={clear}>Delete all data</button>
|
||||
</div>
|
||||
@@ -3,16 +3,26 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link href="../../node_modules/spectre.css/dist/spectre.min.css" rel="stylesheet" />
|
||||
<link href="../../node_modules/tailwindcss/dist/tailwind.css" rel="stylesheet" />
|
||||
<link href="../../node_modules/tailwindcss/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
|
||||
'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
#root {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
<title>Ora</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="./main.js"></script>
|
||||
<div id="root" />
|
||||
<script type="module" src="./main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -53,21 +53,6 @@
|
||||
onMount(calculate)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
table td,
|
||||
table th {
|
||||
padding: 0.25rem 0.06rem;
|
||||
}
|
||||
|
||||
table td.same {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
table td :global(a:visited) {
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<h2 class="text-2xl">Dashboard</h2>
|
||||
<RangeChooser bind:start bind:end />
|
||||
@@ -91,3 +76,18 @@
|
||||
{/each}
|
||||
</table>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
table td,
|
||||
table th {
|
||||
padding: 0.25rem 0.06rem;
|
||||
}
|
||||
|
||||
table td.same {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
table td :global(a:visited) {
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -30,12 +30,6 @@
|
||||
onMount(load)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
|
||||
<RulesEditor bind:limit on:update={load} />
|
||||
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
@@ -70,3 +64,9 @@
|
||||
{:else}
|
||||
<div class="loading loading-lg" />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user