Replace CSS classes with semantic HTML
This commit is contained in:
@@ -82,85 +82,83 @@ const delete_reporter = async (email) => {
|
||||
onMount(get_reporters);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button class:button_highlight={creating} on:click={() => {creating = !creating}}>
|
||||
<i class="icon">create</i> Add abuse reporter
|
||||
</button>
|
||||
</div>
|
||||
{#if creating}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_reporter}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>E-mail address</td>
|
||||
<td><input type="text" bind:this={new_reporter_email}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td><input type="text" bind:this={new_reporter_name} value="Anonymous tip"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>
|
||||
<input id="reporter_type_individual" name="reporter_type" type="radio" bind:group={new_reporter_type} value="individual" />
|
||||
<label for="reporter_type_individual">Individual</label>
|
||||
<br/>
|
||||
<input id="reporter_type_org" name="reporter_type" type="radio" bind:group={new_reporter_type} value="org" />
|
||||
<label for="reporter_type_org">Organisation</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<div class="limit_width">
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button class:button_highlight={creating} on:click={() => {creating = !creating}}>
|
||||
<i class="icon">create</i> Add abuse reporter
|
||||
</button>
|
||||
</div>
|
||||
{#if creating}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_reporter}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>E-mail address</td>
|
||||
<td><input type="text" bind:this={new_reporter_email}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td><input type="text" bind:this={new_reporter_name} value="Anonymous tip"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>
|
||||
<input id="reporter_type_individual" name="reporter_type" type="radio" bind:group={new_reporter_type} value="individual" />
|
||||
<label for="reporter_type_individual">Individual</label>
|
||||
<br/>
|
||||
<input id="reporter_type_org" name="reporter_type" type="radio" bind:group={new_reporter_type} value="org" />
|
||||
<label for="reporter_type_org">Organisation</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td>Name</td>
|
||||
<td>Blocked</td>
|
||||
<td>Type</td>
|
||||
<td>Last used</td>
|
||||
<td>Created</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{#each reporters as reporter (reporter.email)}
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td>Name</td>
|
||||
<td>Blocked</td>
|
||||
<td>Type</td>
|
||||
<td>Last used</td>
|
||||
<td>Created</td>
|
||||
<td></td>
|
||||
<td>{reporter.email}</td>
|
||||
<td>{reporter.name}</td>
|
||||
<td>{reporter.files_blocked}</td>
|
||||
<td>{reporter.type}</td>
|
||||
<td>{formatDate(reporter.last_used, true, true, false)}</td>
|
||||
<td>{formatDate(reporter.created, false, false, false)}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {delete_reporter(reporter.email)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{#each reporters as reporter (reporter.email)}
|
||||
<tr>
|
||||
<td>{reporter.email}</td>
|
||||
<td>{reporter.name}</td>
|
||||
<td>{reporter.files_blocked}</td>
|
||||
<td>{reporter.type}</td>
|
||||
<td>{formatDate(reporter.last_used, true, true, false)}</td>
|
||||
<td>{formatDate(reporter.created, false, false, false)}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {delete_reporter(reporter.email)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@@ -91,38 +91,36 @@ onMount(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="limit_width">
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<div>Start:</div>
|
||||
<input type="date" bind:this={startPicker}/>
|
||||
<div>End:</div>
|
||||
<input type="date" bind:this={endPicker}/>
|
||||
<button on:click={get_reports}>Go</button>
|
||||
</div>
|
||||
|
||||
<h2>Pending</h2>
|
||||
{#each reports_pending as report (report.id)}
|
||||
{#if report.status === "pending"}
|
||||
<AbuseReport report={report} on:refresh={get_reports}/>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
<h2>Resolved</h2>
|
||||
{#each reports_processed as report (report.id)}
|
||||
{#if report.status !== "pending"}
|
||||
<AbuseReport report={report} on:refresh={get_reports}/>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<div>Start:</div>
|
||||
<input type="date" bind:this={startPicker}/>
|
||||
<div>End:</div>
|
||||
<input type="date" bind:this={endPicker}/>
|
||||
<button on:click={get_reports}>Go</button>
|
||||
</div>
|
||||
|
||||
<h2>Pending</h2>
|
||||
{#each reports_pending as report (report.id)}
|
||||
{#if report.status === "pending"}
|
||||
<AbuseReport report={report} on:refresh={get_reports}/>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
<h2>Resolved</h2>
|
||||
{#each reports_processed as report (report.id)}
|
||||
{#if report.status !== "pending"}
|
||||
<AbuseReport report={report} on:refresh={get_reports}/>
|
||||
{/if}
|
||||
{/each}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -65,17 +65,12 @@ onMount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="limit_width">
|
||||
<h2>File removal</h2>
|
||||
<p>
|
||||
Paste any pixeldrain file links in here to remove them
|
||||
</p>
|
||||
<div class="highlight_dark">
|
||||
<Form config={block_form}></Form>
|
||||
</div>
|
||||
<section>
|
||||
<h2>File removal</h2>
|
||||
<p>
|
||||
Paste any pixeldrain file links in here to remove them
|
||||
</p>
|
||||
<div class="highlight_dark">
|
||||
<Form config={block_form}></Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</section>
|
||||
|
@@ -159,168 +159,160 @@ onDestroy(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="limit_width">
|
||||
<h3>Bandwidth usage and file views</h3>
|
||||
</div>
|
||||
<div class="highlight_dark" style="margin-bottom: 6px;">
|
||||
<button on:click={() => { loadGraph(1440, 1, true) }}>Day</button>
|
||||
<button on:click={() => { loadGraph(10080, 10, false) }}>Week</button>
|
||||
<button on:click={() => { loadGraph(20160, 60, false) }}>Two Weeks</button>
|
||||
<button on:click={() => { loadGraph(43200, 60, false) }}>Month</button>
|
||||
<button on:click={() => { loadGraph(131400, 1440, false) }}>Quarter</button>
|
||||
<button on:click={() => { loadGraph(262800, 1440, false) }}>Half-year</button>
|
||||
<button on:click={() => { loadGraph(525600, 1440, false) }}>Year</button>
|
||||
<button on:click={() => { loadGraph(1051200, 1440, false) }}>Two Years</button>
|
||||
</div>
|
||||
<Chart bind:this={graphBandwidth} data_type="bytes" legend={false} />
|
||||
<Chart bind:this={graphViews} data_type="number" legend={false} />
|
||||
<div class="highlight_dark">
|
||||
Total usage from {start_time} to {end_time}<br/>
|
||||
{formatDataVolume(total_bandwidth, 3)} bandwidth,
|
||||
{formatDataVolume(total_bandwidth_paid, 3)} paid bandwidth,
|
||||
{formatThousands(total_views, 3)} views and
|
||||
{formatThousands(total_downloads, 3)} downloads
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<a class="button" href="/api/admin/call_stack">Call stack</a>
|
||||
<a class="button" href="/api/admin/heap_profile">Heap profile</a>
|
||||
<a class="button" href="/api/admin/cpu_profile">CPU profile (wait 1 min)</a>
|
||||
<br/>
|
||||
|
||||
<div class="limit_width">
|
||||
<table>
|
||||
<tr>
|
||||
<td>DB Time</td>
|
||||
<td>{formatDate(new Date(status.db_time), true, true, true)}</td>
|
||||
<td>DB Latency</td>
|
||||
<td>{formatNumber(status.db_latency / 1000, 3)} ms</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Pixelstore peers</h3>
|
||||
<div class="table_scroll">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Address</td>
|
||||
<td>Pos</td>
|
||||
<td>Alive</td>
|
||||
<td>Err</td>
|
||||
<td>1m</td>
|
||||
<td>5m</td>
|
||||
<td>15m</td>
|
||||
<td>Ping</td>
|
||||
<td>Free</td>
|
||||
<td>Min free</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each status.peers as peer}
|
||||
<tr class="peer_row"
|
||||
class:highlight_red={peer.free_space < peer.min_free_space / 2 || !peer.reachable}
|
||||
class:highlight_yellow={peer.free_space < peer.min_free_space}
|
||||
class:highlight_green={peer.reachable}
|
||||
>
|
||||
<td>{peer.address}</td>
|
||||
<td>{peer.position}</td>
|
||||
<td>{peer.reachable}</td>
|
||||
<td>{peer.unreachable_count}</td>
|
||||
<td>{peer.load_1_min.toFixed(1)}</td>
|
||||
<td>{peer.load_5_min.toFixed(1)}</td>
|
||||
<td>{peer.load_15_min.toFixed(1)}</td>
|
||||
<td>{formatDuration(peer.latency, 3)}</td>
|
||||
<td>{formatDataVolume(peer.free_space, 4)}</td>
|
||||
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3>Pixelstore stats</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Local reads</td>
|
||||
<td>Local read size</td>
|
||||
<td>Remote reads</td>
|
||||
<td>Remote read size</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{status.local_reads}</td>
|
||||
<td>{formatDataVolume(status.local_read_size, 4)}</td>
|
||||
<td>{status.remote_reads}</td>
|
||||
<td>{formatDataVolume(status.remote_read_size, 4)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{status.local_reads_per_sec.toPrecision(4)} / s</td>
|
||||
<td>{formatDataVolume(status.local_read_size_per_sec, 4)} / s</td>
|
||||
<td>{status.remote_reads_per_sec.toPrecision(4)} / s</td>
|
||||
<td>{formatDataVolume(status.remote_read_size_per_sec, 4)} /s</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Socket statistics</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Watcher</td>
|
||||
<td>Threads</td>
|
||||
<td>Listeners</td>
|
||||
<td>Avg</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>File statistics</td>
|
||||
<td>{status.stats_watcher_threads}</td>
|
||||
<td>{status.stats_watcher_listeners}</td>
|
||||
<td>{(status.stats_watcher_listeners / status.stats_watcher_threads).toPrecision(3)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Downloads</td>
|
||||
<td>{status.download_clients}</td>
|
||||
<td>{status.download_connections}</td>
|
||||
<td>{(status.download_connections / status.download_clients).toPrecision(3)}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Query statistics</h3>
|
||||
<div class="table_scroll" style="text-align: left;">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('query_name') }}>Query</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('calls') }}>Calls</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('average_duration') }}>Avg dur</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('total_duration') }}>Total dur</td>
|
||||
<td>Callers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tstat_body">
|
||||
{#each status.query_statistics as q}
|
||||
<tr>
|
||||
<td>{q.query_name}</td>
|
||||
<td>{q.calls}</td>
|
||||
<td>{q.average_duration}ms</td>
|
||||
<td>{formatDuration(q.total_duration, 0)}</td>
|
||||
<td>
|
||||
{#each q.callers as caller}
|
||||
{caller.count}x {caller.name}<br/>
|
||||
{/each}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<section>
|
||||
<h3>Bandwidth usage and file views</h3>
|
||||
</section>
|
||||
<div class="highlight_dark" style="margin-bottom: 6px;">
|
||||
<button on:click={() => { loadGraph(1440, 1, true) }}>Day</button>
|
||||
<button on:click={() => { loadGraph(10080, 10, false) }}>Week</button>
|
||||
<button on:click={() => { loadGraph(20160, 60, false) }}>Two Weeks</button>
|
||||
<button on:click={() => { loadGraph(43200, 60, false) }}>Month</button>
|
||||
<button on:click={() => { loadGraph(131400, 1440, false) }}>Quarter</button>
|
||||
<button on:click={() => { loadGraph(262800, 1440, false) }}>Half-year</button>
|
||||
<button on:click={() => { loadGraph(525600, 1440, false) }}>Year</button>
|
||||
<button on:click={() => { loadGraph(1051200, 1440, false) }}>Two Years</button>
|
||||
</div>
|
||||
<Chart bind:this={graphBandwidth} data_type="bytes" legend={false} />
|
||||
<Chart bind:this={graphViews} data_type="number" legend={false} />
|
||||
<div class="highlight_dark">
|
||||
Total usage from {start_time} to {end_time}<br/>
|
||||
{formatDataVolume(total_bandwidth, 3)} bandwidth,
|
||||
{formatDataVolume(total_bandwidth_paid, 3)} paid bandwidth,
|
||||
{formatThousands(total_views, 3)} views and
|
||||
{formatThousands(total_downloads, 3)} downloads
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.peer_row {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
<br/>
|
||||
<a class="button" href="/api/admin/call_stack">Call stack</a>
|
||||
<a class="button" href="/api/admin/heap_profile">Heap profile</a>
|
||||
<a class="button" href="/api/admin/cpu_profile">CPU profile (wait 1 min)</a>
|
||||
<br/>
|
||||
|
||||
<section>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DB Time</td>
|
||||
<td>{formatDate(new Date(status.db_time), true, true, true)}</td>
|
||||
<td>DB Latency</td>
|
||||
<td>{formatNumber(status.db_latency / 1000, 3)} ms</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Pixelstore peers</h3>
|
||||
<div class="table_scroll">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Address</td>
|
||||
<td>Pos</td>
|
||||
<td>Alive</td>
|
||||
<td>Err</td>
|
||||
<td>1m</td>
|
||||
<td>5m</td>
|
||||
<td>15m</td>
|
||||
<td>Ping</td>
|
||||
<td>Free</td>
|
||||
<td>Min free</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each status.peers as peer}
|
||||
<tr style="text-align: left"
|
||||
class:highlight_red={peer.free_space < peer.min_free_space / 2 || !peer.reachable}
|
||||
class:highlight_yellow={peer.free_space < peer.min_free_space}
|
||||
class:highlight_green={peer.reachable}
|
||||
>
|
||||
<td>{peer.address}</td>
|
||||
<td>{peer.position}</td>
|
||||
<td>{peer.reachable}</td>
|
||||
<td>{peer.unreachable_count}</td>
|
||||
<td>{peer.load_1_min.toFixed(1)}</td>
|
||||
<td>{peer.load_5_min.toFixed(1)}</td>
|
||||
<td>{peer.load_15_min.toFixed(1)}</td>
|
||||
<td>{formatDuration(peer.latency, 3)}</td>
|
||||
<td>{formatDataVolume(peer.free_space, 4)}</td>
|
||||
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3>Pixelstore stats</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Local reads</td>
|
||||
<td>Local read size</td>
|
||||
<td>Remote reads</td>
|
||||
<td>Remote read size</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{status.local_reads}</td>
|
||||
<td>{formatDataVolume(status.local_read_size, 4)}</td>
|
||||
<td>{status.remote_reads}</td>
|
||||
<td>{formatDataVolume(status.remote_read_size, 4)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{status.local_reads_per_sec.toPrecision(4)} / s</td>
|
||||
<td>{formatDataVolume(status.local_read_size_per_sec, 4)} / s</td>
|
||||
<td>{status.remote_reads_per_sec.toPrecision(4)} / s</td>
|
||||
<td>{formatDataVolume(status.remote_read_size_per_sec, 4)} /s</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Socket statistics</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Watcher</td>
|
||||
<td>Threads</td>
|
||||
<td>Listeners</td>
|
||||
<td>Avg</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>File statistics</td>
|
||||
<td>{status.stats_watcher_threads}</td>
|
||||
<td>{status.stats_watcher_listeners}</td>
|
||||
<td>{(status.stats_watcher_listeners / status.stats_watcher_threads).toPrecision(3)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Downloads</td>
|
||||
<td>{status.download_clients}</td>
|
||||
<td>{status.download_connections}</td>
|
||||
<td>{(status.download_connections / status.download_clients).toPrecision(3)}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Query statistics</h3>
|
||||
<div class="table_scroll" style="text-align: left;">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('query_name') }}>Query</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('calls') }}>Calls</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('average_duration') }}>Avg dur</td>
|
||||
<td style="cursor: pointer;" on:click={() => { getStats('total_duration') }}>Total dur</td>
|
||||
<td>Callers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tstat_body">
|
||||
{#each status.query_statistics as q}
|
||||
<tr>
|
||||
<td>{q.query_name}</td>
|
||||
<td>{q.calls}</td>
|
||||
<td>{q.average_duration}ms</td>
|
||||
<td>{formatDuration(q.total_duration, 0)}</td>
|
||||
<td>
|
||||
{#each q.callers as caller}
|
||||
{caller.count}x {caller.name}<br/>
|
||||
{/each}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
@@ -80,91 +80,89 @@ const delete_ban = async (addr) => {
|
||||
onMount(get_bans);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button class:button_highlight={creating} on:click={() => {creating = !creating}}>
|
||||
<i class="icon">create</i> Add IP ban
|
||||
</button>
|
||||
</div>
|
||||
{#if creating}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_ban}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>IP address</td>
|
||||
<td><input type="text" bind:this={new_ban_address}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reason</td>
|
||||
<td>
|
||||
<input id="reason_unknown" name="reporter_type" type="radio" bind:group={new_ban_reason} value="unknown" />
|
||||
<label for="reason_unknown">unknown</label>
|
||||
<br/>
|
||||
<input id="reason_copyright" name="reporter_type" type="radio" bind:group={new_ban_reason} value="copyright" />
|
||||
<label for="reason_copyright">copyright</label>
|
||||
<br/>
|
||||
<input id="reason_child_abuse" name="reporter_type" type="radio" bind:group={new_ban_reason} value="child_abuse" />
|
||||
<label for="reason_child_abuse">child_abuse</label>
|
||||
<br/>
|
||||
<input id="reason_terrorism" name="reporter_type" type="radio" bind:group={new_ban_reason} value="terorrism" />
|
||||
<label for="reason_terrorism">terrorism</label>
|
||||
<br/>
|
||||
<input id="reason_gore" name="reporter_type" type="radio" bind:group={new_ban_reason} value="gore" />
|
||||
<label for="reason_gore">gore</label>
|
||||
<br/>
|
||||
<input id="reason_malware" name="reporter_type" type="radio" bind:group={new_ban_reason} value="malware" />
|
||||
<label for="reason_malware">malware</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<div class="limit_width">
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button class:button_highlight={creating} on:click={() => {creating = !creating}}>
|
||||
<i class="icon">create</i> Add IP ban
|
||||
</button>
|
||||
</div>
|
||||
{#if creating}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_ban}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>IP address</td>
|
||||
<td><input type="text" bind:this={new_ban_address}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reason</td>
|
||||
<td>
|
||||
<input id="reason_unknown" name="reporter_type" type="radio" bind:group={new_ban_reason} value="unknown" />
|
||||
<label for="reason_unknown">unknown</label>
|
||||
<br/>
|
||||
<input id="reason_copyright" name="reporter_type" type="radio" bind:group={new_ban_reason} value="copyright" />
|
||||
<label for="reason_copyright">copyright</label>
|
||||
<br/>
|
||||
<input id="reason_child_abuse" name="reporter_type" type="radio" bind:group={new_ban_reason} value="child_abuse" />
|
||||
<label for="reason_child_abuse">child_abuse</label>
|
||||
<br/>
|
||||
<input id="reason_terrorism" name="reporter_type" type="radio" bind:group={new_ban_reason} value="terorrism" />
|
||||
<label for="reason_terrorism">terrorism</label>
|
||||
<br/>
|
||||
<input id="reason_gore" name="reporter_type" type="radio" bind:group={new_ban_reason} value="gore" />
|
||||
<label for="reason_gore">gore</label>
|
||||
<br/>
|
||||
<input id="reason_malware" name="reporter_type" type="radio" bind:group={new_ban_reason} value="malware" />
|
||||
<label for="reason_malware">malware</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<tr>
|
||||
<td>Address</td>
|
||||
<td>Reason</td>
|
||||
<td>Ban time</td>
|
||||
<td>Expire time</td>
|
||||
<td>Offences</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{#each rows as row (row.address)}
|
||||
<tr>
|
||||
<td>Address</td>
|
||||
<td>Reason</td>
|
||||
<td>Ban time</td>
|
||||
<td>Expire time</td>
|
||||
<td>Offences</td>
|
||||
<td></td>
|
||||
<td>{row.address}</td>
|
||||
<td>{row.reason}</td>
|
||||
<td>{formatDate(row.ban_time, true, true, false)}</td>
|
||||
<td>{formatDate(row.expire_time, true, true, false)}</td>
|
||||
<td>{row.offences}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {delete_ban(row.address)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{#each rows as row (row.address)}
|
||||
<tr>
|
||||
<td>{row.address}</td>
|
||||
<td>{row.reason}</td>
|
||||
<td>{formatDate(row.ban_time, true, true, false)}</td>
|
||||
<td>{formatDate(row.expire_time, true, true, false)}</td>
|
||||
<td>{row.offences}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {delete_ban(row.address)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@@ -26,7 +26,7 @@ onMount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="checkers inset">
|
||||
<header>
|
||||
<h1>Admin Panel</h1>
|
||||
|
||||
<div class="tab_bar">
|
||||
@@ -77,7 +77,7 @@ onMount(() => {
|
||||
Update global settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{#if page === "status"}
|
||||
<Home></Home>
|
||||
|
@@ -173,7 +173,7 @@ onMount(get_coupons)
|
||||
|
||||
</script>
|
||||
|
||||
<div class="limit_width">
|
||||
<section>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
@@ -221,7 +221,7 @@ onMount(get_coupons)
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -386,18 +386,18 @@ const keydown = (e) => {
|
||||
<div>
|
||||
<!-- If the user is logged in and has used more than 50% of their storage space we will show a progress bar -->
|
||||
{#if window.user.username !== "" && window.user.storage_space_used/window.user.subscription.storage_space > 0.5}
|
||||
<div class="limit_width">
|
||||
<section>
|
||||
<StorageProgressBar used={window.user.storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<div class="instruction limit_width" style="margin-top: 0; border-top: none;">
|
||||
<section class="instruction" style="margin-top: 0; border-top: none;">
|
||||
<span class="big_number">1</span>
|
||||
<span class="instruction_text">Select files to upload</span>
|
||||
<br/>
|
||||
You can also drop files on this page from your file manager or
|
||||
paste an image from your clipboard
|
||||
</div>
|
||||
</section>
|
||||
<br/>
|
||||
|
||||
<input bind:this={file_input_field} on:change={file_input_change} type="file" name="file" multiple="multiple"/>
|
||||
@@ -416,7 +416,7 @@ const keydown = (e) => {
|
||||
<a href="/about#content-policy">content policy</a>.
|
||||
<p>
|
||||
|
||||
<div class="instruction limit_width" style="margin-bottom: 0;">
|
||||
<section class="instruction" style="margin-bottom: 0;">
|
||||
<span class="big_number">2</span>
|
||||
<span class="instruction_text">Wait for the files to finish uploading</span>
|
||||
<br/>
|
||||
@@ -426,7 +426,7 @@ const keydown = (e) => {
|
||||
<div>ETA {formatDuration(remaining_time, 0)}</div>
|
||||
<div>Rate {formatDataVolume(total_rate, 3)}/s</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="progress_bar_outer" style="margin-bottom: 1.5em;">
|
||||
<div bind:this={progress_bar_inner} class="progress_bar_inner"></div>
|
||||
</div>
|
||||
@@ -441,10 +441,10 @@ const keydown = (e) => {
|
||||
<UploadProgressBar bind:this={file.component} job={file}></UploadProgressBar>
|
||||
{/each}
|
||||
|
||||
<div class="instruction limit_width">
|
||||
<section class="instruction">
|
||||
<span class="big_number">3</span>
|
||||
<span class="instruction_text">Share the files</span>
|
||||
</div>
|
||||
</section>
|
||||
<br/>
|
||||
|
||||
{#if upload_queue.length > 1}
|
||||
@@ -518,11 +518,11 @@ const keydown = (e) => {
|
||||
<br/>
|
||||
|
||||
{#if window.user.subscription.name === ""}
|
||||
<div class="instruction limit_width">
|
||||
<span class="big_number">4</span>
|
||||
<span class="instruction_text">Support me on Patreon!</span>
|
||||
</div>
|
||||
<div class="limit_width">
|
||||
<section>
|
||||
<div class="instruction">
|
||||
<span class="big_number">4</span>
|
||||
<span class="instruction_text">Support me on Patreon!</span>
|
||||
</div>
|
||||
<p>
|
||||
Pixeldrain is struggling to get by financially. Because anyone
|
||||
can upload anything it's hard to find reputable advertisers who
|
||||
@@ -537,13 +537,15 @@ const keydown = (e) => {
|
||||
help with making pixeldrain the easiest and fastest way to share
|
||||
files online!
|
||||
</p>
|
||||
</div>
|
||||
<br/>
|
||||
<a href="#pro" class="button big_button" style="min-width: 350px;">
|
||||
<i class="icon">arrow_downward</i>
|
||||
Check out Pro
|
||||
<i class="icon">arrow_downward</i>
|
||||
</a>
|
||||
<br/>
|
||||
<div style="text-align: center;">
|
||||
<a href="#pro" class="button big_button" style="min-width: 350px;">
|
||||
<i class="icon">arrow_downward</i>
|
||||
Check out Pro
|
||||
<i class="icon">arrow_downward</i>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@@ -1,13 +1,10 @@
|
||||
<script>
|
||||
import { fs_delete_bucket } from "../filesystem/FilesystemAPI.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import Expandable from "../util/Expandable.svelte";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let bucket
|
||||
let details_hidden = true
|
||||
const expand_bucket = () => {
|
||||
details_hidden = !details_hidden
|
||||
}
|
||||
|
||||
const save_bucket = () => {
|
||||
alert("save")
|
||||
@@ -32,21 +29,14 @@ const delete_bucket = async () => {
|
||||
|
||||
</script>
|
||||
|
||||
<div class="bucket">
|
||||
<div class="bucket_header">
|
||||
<Expandable>
|
||||
<div slot="header">
|
||||
<a href={'/d/' + bucket.id} class="bucket_title">
|
||||
<img class="bucket_icon" src="/res/img/mime/folder-remote.png" alt="Bucket icon"/>
|
||||
{bucket.name}
|
||||
</a>
|
||||
<button class="bucket_expand" on:click={expand_bucket}>
|
||||
{#if details_hidden}
|
||||
<i class="icon">expand_more</i>
|
||||
{:else}
|
||||
<i class="icon">expand_less</i>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
<div class="bucket_details" class:hidden={details_hidden}>
|
||||
<div>
|
||||
<form on:submit|preventDefault={save_bucket}>
|
||||
<table class="form">
|
||||
<tr class="form">
|
||||
@@ -66,26 +56,9 @@ const delete_bucket = async () => {
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</Expandable>
|
||||
|
||||
<style>
|
||||
.bucket {
|
||||
text-decoration: none;
|
||||
background-color: var(--layer_3_color);
|
||||
transition: box-shadow 0.5s;
|
||||
box-shadow: 1px 1px 5px 0 var(--shadow_color);
|
||||
margin: 1em 0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bucket_header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
color: var(--text_color);
|
||||
}
|
||||
.bucket_header:hover {
|
||||
background-color: var(--input_color_dark)
|
||||
}
|
||||
.bucket_title {
|
||||
flex: 1 1 auto;
|
||||
align-self: center;
|
||||
@@ -98,18 +71,4 @@ const delete_bucket = async () => {
|
||||
margin: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.bucket_expand {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.bucket_details {
|
||||
display: flex;
|
||||
padding: 0.4em;
|
||||
flex-direction: column;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid var(--layer_3_color_border);
|
||||
color: var(--text_color);
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
@@ -41,51 +41,49 @@ const create_bucket = async () => {
|
||||
onMount(get_buckets);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<div class="toolbar" style="text-align: right;">
|
||||
<button
|
||||
class:button_highlight={creating_bucket}
|
||||
on:click={() => {creating_bucket = !creating_bucket}}
|
||||
>
|
||||
<i class="icon">create_new_folder</i> New bucket
|
||||
</button>
|
||||
</div>
|
||||
{#if creating_bucket}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_bucket}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>
|
||||
Name
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" bind:this={new_bucket_name}/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="limit_width">
|
||||
<div class="toolbar" style="text-align: right;">
|
||||
<button
|
||||
class:button_highlight={creating_bucket}
|
||||
on:click={() => {creating_bucket = !creating_bucket}}
|
||||
>
|
||||
<i class="icon">create_new_folder</i> New bucket
|
||||
</button>
|
||||
</div>
|
||||
{#if creating_bucket}
|
||||
<div class="highlight_light">
|
||||
<form on:submit|preventDefault={create_bucket}>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<td>
|
||||
Name
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" bind:this={new_bucket_name}/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button class="button_highlight" type="submit" style="float: right;">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each buckets as bucket}
|
||||
<UserBucket bucket={bucket} on:refresh={get_buckets}></UserBucket>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{#each buckets as bucket (bucket.id)}
|
||||
<UserBucket bucket={bucket} on:refresh={get_buckets}></UserBucket>
|
||||
{/each}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -82,87 +82,85 @@ const logout = async (key) => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
{#if !loaded}
|
||||
<div class="highlight_yellow">
|
||||
<h2>Warning</h2>
|
||||
<p>
|
||||
API keys are sensitive information. They can be used to gain
|
||||
full control over your account. Do not show your API keys to
|
||||
someone or something you don't trust!
|
||||
</p>
|
||||
<button class="button_red" on:click={load_keys}>
|
||||
<i class="icon">lock_open</i> Show API keys
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button on:click={create_key}>
|
||||
<i class="icon">add</i> Create new API key
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="limit_width">
|
||||
{#if !loaded}
|
||||
<div class="highlight_yellow">
|
||||
<h2>Warning</h2>
|
||||
<p>
|
||||
API keys are sensitive information. They can be used to gain
|
||||
full control over your account. Do not show your API keys to
|
||||
someone or something you don't trust!
|
||||
</p>
|
||||
<button class="button_red" on:click={load_keys}>
|
||||
<i class="icon">lock_open</i> Show API keys
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="toolbar" style="text-align: left;">
|
||||
<div class="toolbar_spacer"></div>
|
||||
<button on:click={create_key}>
|
||||
<i class="icon">add</i> Create new API key
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<p>
|
||||
If you delete the API key that you are currently using you will be
|
||||
logged out of your account. API keys expire 90 days after the last
|
||||
time they're used. If you think someone is using your account
|
||||
without your authorization it's probably a good idea to delete all
|
||||
your keys.
|
||||
</p>
|
||||
</div>
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<tr>
|
||||
<td>Key</td>
|
||||
<td>Created</td>
|
||||
<td>Last used ▼</td>
|
||||
<td>IP address</td>
|
||||
<td></td>
|
||||
<p>
|
||||
If you delete the API key that you are currently using you will be
|
||||
logged out of your account. API keys expire 90 days after the last
|
||||
time they're used. If you think someone is using your account
|
||||
without your authorization it's probably a good idea to delete all
|
||||
your keys.
|
||||
</p>
|
||||
</section>
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<tr>
|
||||
<td>Key</td>
|
||||
<td>Created</td>
|
||||
<td>Last used ▼</td>
|
||||
<td>IP address</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{#each rows as row (row.auth_key)}
|
||||
<tr style="border-bottom: none;">
|
||||
<td>{row.auth_key}</td>
|
||||
<td>{formatDate(row.creation_time, true, true, false)}</td>
|
||||
<td>{formatDate(row.last_used_time, true, true, false)}</td>
|
||||
<td>{row.creation_ip_address}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {logout(row.auth_key)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{#each rows as row (row.auth_key)}
|
||||
<tr style="border-bottom: none;">
|
||||
<td>{row.auth_key}</td>
|
||||
<td>{formatDate(row.creation_time, true, true, false)}</td>
|
||||
<td>{formatDate(row.last_used_time, true, true, false)}</td>
|
||||
<td>{row.creation_ip_address}</td>
|
||||
<td>
|
||||
<button on:click|preventDefault={() => {logout(row.auth_key)}} class="button button_red round">
|
||||
<i class="icon">delete</i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
{#if row.app_name === "website login"}
|
||||
<img src="/res/img/pixeldrain_32.png" alt="Pixeldrain logo" class="app_icon"/>
|
||||
Pixeldrain website
|
||||
{:else if row.app_name === "website keys page"}
|
||||
<i class="icon">vpn_key</i>
|
||||
Pixeldrain keys page
|
||||
{:else if row.app_name === "sharex"}
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
|
||||
ShareX
|
||||
{:else if row.app_name === "jdownloader"}
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
|
||||
JDownloader
|
||||
{:else}
|
||||
Unknown app: {row.app_name}
|
||||
{/if}
|
||||
</td>
|
||||
<td colspan="4">User-Agent: {row.user_agent}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
{#if row.app_name === "website login"}
|
||||
<img src="/res/img/pixeldrain_32.png" alt="Pixeldrain logo" class="app_icon"/>
|
||||
Pixeldrain website
|
||||
{:else if row.app_name === "website keys page"}
|
||||
<i class="icon">vpn_key</i>
|
||||
Pixeldrain keys page
|
||||
{:else if row.app_name === "sharex"}
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
|
||||
ShareX
|
||||
{:else if row.app_name === "jdownloader"}
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
|
||||
JDownloader
|
||||
{:else}
|
||||
Unknown app: {row.app_name}
|
||||
{/if}
|
||||
</td>
|
||||
<td colspan="4">User-Agent: {row.user_agent}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@@ -137,29 +137,24 @@ let delete_account = {
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="limit_width">
|
||||
<h2>Change password</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={password_change}></Form>
|
||||
</div>
|
||||
|
||||
<h2>Change e-mail address</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={email_change}></Form>
|
||||
</div>
|
||||
|
||||
<h2>Change name</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={name_change}></Form>
|
||||
</div>
|
||||
|
||||
<h2>Delete account</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={delete_account}></Form>
|
||||
</div>
|
||||
<section>
|
||||
<h2>Change password</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={password_change}></Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<h2>Change e-mail address</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={email_change}></Form>
|
||||
</div>
|
||||
|
||||
<h2>Change name</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={name_change}></Form>
|
||||
</div>
|
||||
|
||||
<h2>Delete account</h2>
|
||||
<div class="highlight_dark">
|
||||
<Form config={delete_account}></Form>
|
||||
</div>
|
||||
</section>
|
||||
|
@@ -56,114 +56,113 @@ onMount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="limit_width">
|
||||
{#if app_name === "jdownloader"}
|
||||
<h2>
|
||||
Connect
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon_small"/>
|
||||
JDownloader to your pixeldrain account
|
||||
</h2>
|
||||
<p>
|
||||
To connect JDownloader to pixeldrain you need to generate an API
|
||||
key and enter it in JDownloader's Account Manager.
|
||||
<br/>
|
||||
<strong>Do not show the generated key to anyone</strong>, it can
|
||||
be used to gain access to your pixeldrain account!
|
||||
</p>
|
||||
|
||||
{#if !api_key}
|
||||
<div class="center">
|
||||
<button class="button_highlight" on:click={create_key}>
|
||||
<i class="icon">add</i>
|
||||
Generate key
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<h3>Key created</h3>
|
||||
|
||||
<div class="copy_container">
|
||||
<button on:click={copy_key} class="copy_button" class:button_highlight={copied}>
|
||||
<i class="icon">content_copy</i>
|
||||
{#if copied}
|
||||
Copied!
|
||||
{:else}
|
||||
Copy key to clipboard
|
||||
{/if}
|
||||
</button>
|
||||
<button on:click={toggle_show_key} class="copy_button" class:button_highlight={show_key !== ""}>
|
||||
<i class="icon">visibility</i>
|
||||
{#if show_key === ""}
|
||||
Show key
|
||||
{/if}
|
||||
</button>
|
||||
<input bind:value={show_key} class="copy_textarea" type="text" placeholder="Your key will show up here" disabled={show_key === ""}/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<p>
|
||||
Paste the key in JDownloader to authenticate the app.
|
||||
</p>
|
||||
{:else if app_name === "sharex"}
|
||||
<h2>
|
||||
Connect
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon_small"/>
|
||||
ShareX to your pixeldrain account
|
||||
</h2>
|
||||
<p>
|
||||
ShareX is a Screen capture, file sharing and productivity tool.
|
||||
Pixeldrain is supported as a custom uploader. You can <a
|
||||
href="https://getsharex.com/" target="_blank">get ShareX
|
||||
here</a>.
|
||||
</p>
|
||||
<p>
|
||||
Here you can download our custom ShareX uploader which uses
|
||||
pixeldrain to upload your files. This uploader is configured to
|
||||
upload files to your personal pixeldrain account. <strong>Do not
|
||||
share the configuration file with anyone</strong>, it contains
|
||||
your account credentials.
|
||||
</p>
|
||||
|
||||
<div class="center">
|
||||
<a href="/misc/sharex/pixeldrain.com.sxcu" class="button button_highlight">
|
||||
<i class="icon small">save</i>
|
||||
Download ShareX Uploader
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3>Setting pixeldrain as default uploader</h3>
|
||||
<p>
|
||||
Download the uploader config and choose 'Open file'
|
||||
<br/>
|
||||
<img src="/res/img/sharex_download.png" style="max-width: 100%;" alt=""/><br/>
|
||||
Set pixeldrain.com as active uploader. Choose Yes
|
||||
<br/>
|
||||
<img src="/res/img/sharex_default.png" style="max-width: 100%;" alt=""/><br/>
|
||||
</p>
|
||||
{:else}
|
||||
<h2>Connect an app to your pixeldrain account</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<button on:click={() => {app_name = "jdownloader"}}>
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
|
||||
Connect JDownloader
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button on:click={() => {app_name = "sharex"}}>
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
|
||||
Connect ShareX
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{/if}
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
{#if app_name === "jdownloader"}
|
||||
<h2>
|
||||
Connect
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon_small"/>
|
||||
JDownloader to your pixeldrain account
|
||||
</h2>
|
||||
<p>
|
||||
To connect JDownloader to pixeldrain you need to generate an API
|
||||
key and enter it in JDownloader's Account Manager.
|
||||
<br/>
|
||||
<strong>Do not show the generated key to anyone</strong>, it can
|
||||
be used to gain access to your pixeldrain account!
|
||||
</p>
|
||||
|
||||
{#if !api_key}
|
||||
<div class="center">
|
||||
<button class="button_highlight" on:click={create_key}>
|
||||
<i class="icon">add</i>
|
||||
Generate key
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<h3>Key created</h3>
|
||||
|
||||
<div class="copy_container">
|
||||
<button on:click={copy_key} class="copy_button" class:button_highlight={copied}>
|
||||
<i class="icon">content_copy</i>
|
||||
{#if copied}
|
||||
Copied!
|
||||
{:else}
|
||||
Copy key to clipboard
|
||||
{/if}
|
||||
</button>
|
||||
<button on:click={toggle_show_key} class="copy_button" class:button_highlight={show_key !== ""}>
|
||||
<i class="icon">visibility</i>
|
||||
{#if show_key === ""}
|
||||
Show key
|
||||
{/if}
|
||||
</button>
|
||||
<input bind:value={show_key} class="copy_textarea" type="text" placeholder="Your key will show up here" disabled={show_key === ""}/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<p>
|
||||
Paste the key in JDownloader to authenticate the app.
|
||||
</p>
|
||||
{:else if app_name === "sharex"}
|
||||
<h2>
|
||||
Connect
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon_small"/>
|
||||
ShareX to your pixeldrain account
|
||||
</h2>
|
||||
<p>
|
||||
ShareX is a Screen capture, file sharing and productivity tool.
|
||||
Pixeldrain is supported as a custom uploader. You can <a
|
||||
href="https://getsharex.com/" target="_blank">get ShareX
|
||||
here</a>.
|
||||
</p>
|
||||
<p>
|
||||
Here you can download our custom ShareX uploader which uses
|
||||
pixeldrain to upload your files. This uploader is configured to
|
||||
upload files to your personal pixeldrain account. <strong>Do not
|
||||
share the configuration file with anyone</strong>, it contains
|
||||
your account credentials.
|
||||
</p>
|
||||
|
||||
<div class="center">
|
||||
<a href="/misc/sharex/pixeldrain.com.sxcu" class="button button_highlight">
|
||||
<i class="icon small">save</i>
|
||||
Download ShareX Uploader
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3>Setting pixeldrain as default uploader</h3>
|
||||
<p>
|
||||
Download the uploader config and choose 'Open file'
|
||||
<br/>
|
||||
<img src="/res/img/sharex_download.png" style="max-width: 100%;" alt=""/><br/>
|
||||
Set pixeldrain.com as active uploader. Choose Yes
|
||||
<br/>
|
||||
<img src="/res/img/sharex_default.png" style="max-width: 100%;" alt=""/><br/>
|
||||
</p>
|
||||
{:else}
|
||||
<h2>Connect an app to your pixeldrain account</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<button on:click={() => {app_name = "jdownloader"}}>
|
||||
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon"/>
|
||||
Connect JDownloader
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button on:click={() => {app_name = "sharex"}}>
|
||||
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
|
||||
Connect ShareX
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -174,142 +174,142 @@ onDestroy(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="limit_width">
|
||||
<h2>Account information</h2>
|
||||
<ul>
|
||||
<li>Username: {window.user.username}</li>
|
||||
<li>E-mail address: {window.user.email}</li>
|
||||
<li>
|
||||
Supporter level: {window.user.subscription.name}
|
||||
{#if window.user.subscription.type === "patreon"}
|
||||
(<a href="https://www.patreon.com/join/pixeldrain/checkout?edit=1">Manage subscription</a>)
|
||||
{/if}
|
||||
<ul>
|
||||
<li>
|
||||
Max file size: {formatDataVolume(window.user.subscription.file_size_limit, 3)}
|
||||
</li>
|
||||
{#if window.user.subscription.file_expiry_days > 0}
|
||||
<li>Files expire after {window.user.subscription.file_expiry_days} days</li>
|
||||
{:else}
|
||||
<li>Files never expire</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</li>
|
||||
{#if window.user.balance_micro_eur !== 0}
|
||||
<li>
|
||||
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
|
||||
</li>
|
||||
<section>
|
||||
<h2>Account information</h2>
|
||||
<ul>
|
||||
<li>Username: {window.user.username}</li>
|
||||
<li>E-mail address: {window.user.email}</li>
|
||||
<li>
|
||||
Supporter level: {window.user.subscription.name}
|
||||
{#if window.user.subscription.type === "patreon"}
|
||||
(<a href="https://www.patreon.com/join/pixeldrain/checkout?edit=1">Manage subscription</a>)
|
||||
{/if}
|
||||
</ul>
|
||||
|
||||
{#if window.user.subscription.storage_space === -1}
|
||||
Storage space used: {formatDataVolume(storage_space_used, 3)}<br/>
|
||||
{:else}
|
||||
<StorageProgressBar used={storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
|
||||
<ul>
|
||||
<li>
|
||||
Max file size: {formatDataVolume(window.user.subscription.file_size_limit, 3)}
|
||||
</li>
|
||||
{#if window.user.subscription.file_expiry_days > 0}
|
||||
<li>Files expire after {window.user.subscription.file_expiry_days} days</li>
|
||||
{:else}
|
||||
<li>Files never expire</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</li>
|
||||
{#if window.user.balance_micro_eur !== 0}
|
||||
<li>
|
||||
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
|
||||
{#if transfer_cap === -1}
|
||||
Paid transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
|
||||
{:else}
|
||||
Paid transfers:
|
||||
{formatDataVolume(transfer_used, 3)}
|
||||
out of
|
||||
{formatDataVolume(transfer_cap, 3)}
|
||||
(<a href="/user/subscription">Set your transfer limit on the subscription page</a>)
|
||||
<HotlinkProgressBar used={transfer_used} total={transfer_cap}></HotlinkProgressBar>
|
||||
{/if}
|
||||
{#if window.user.subscription.storage_space === -1}
|
||||
Storage space used: {formatDataVolume(storage_space_used, 3)}<br/>
|
||||
{:else}
|
||||
<StorageProgressBar used={storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
|
||||
{/if}
|
||||
|
||||
<h3>Exports</h3>
|
||||
<div style="text-align: center;">
|
||||
<a href="/user/export/files" class="button">
|
||||
<i class="icon">list</i>
|
||||
Export uploaded files to CSV
|
||||
</a>
|
||||
<a href="/user/export/lists" class="button">
|
||||
<i class="icon">list</i>
|
||||
Export created lists to CSV
|
||||
</a>
|
||||
</div>
|
||||
{#if transfer_cap === -1}
|
||||
Paid transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
|
||||
{:else}
|
||||
Paid transfers:
|
||||
{formatDataVolume(transfer_used, 3)}
|
||||
out of
|
||||
{formatDataVolume(transfer_cap, 3)}
|
||||
(<a href="/user/subscription">Set your transfer limit on the subscription page</a>)
|
||||
<HotlinkProgressBar used={transfer_used} total={transfer_cap}></HotlinkProgressBar>
|
||||
{/if}
|
||||
|
||||
<h2>Statistics</h2>
|
||||
<p>
|
||||
Here you can see how often your files are viewed, downloaded
|
||||
and how much bandwidth they consume. The buttons at the top
|
||||
can be pressed to adjust the timeframe. If you choose 'Day'
|
||||
the statistics will be updated periodically. No need to
|
||||
refresh the page.
|
||||
</p>
|
||||
<h3>Exports</h3>
|
||||
<div style="text-align: center;">
|
||||
<a href="/user/export/files" class="button">
|
||||
<i class="icon">list</i>
|
||||
Export uploaded files to CSV
|
||||
</a>
|
||||
<a href="/user/export/lists" class="button">
|
||||
<i class="icon">list</i>
|
||||
Export created lists to CSV
|
||||
</a>
|
||||
</div>
|
||||
<div class="highlight_light">
|
||||
<button
|
||||
on:click={() => { update_graphs(1440, 1, true) }}
|
||||
class:button_highlight={graph_timespan == 1440}>
|
||||
Day (1m)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(10080, 10, false) }}
|
||||
class:button_highlight={graph_timespan == 10080}>
|
||||
Week (10m)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(20160, 60, false) }}
|
||||
class:button_highlight={graph_timespan == 20160}>
|
||||
Two Weeks (1h)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(43200, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 43200}>
|
||||
Month (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(131400, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 131400}>
|
||||
Quarter (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(525600, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 525600}>
|
||||
Year (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(1051200, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 1051200}>
|
||||
Two Years (1d)
|
||||
</button>
|
||||
<br/>
|
||||
Total usage from {time_start} to {time_end}<br/>
|
||||
{formatThousands(total_views)} views,
|
||||
{formatThousands(total_downloads)} downloads,
|
||||
{formatDataVolume(total_bandwidth, 3)} bandwidth and
|
||||
{formatDataVolume(total_transfer_paid, 3)} paid transfers
|
||||
</div>
|
||||
<div class="limit_width">
|
||||
<h3>Premium transfers and total bandwidth usage</h3>
|
||||
<p>
|
||||
A premium transfer is when a file is downloaded using the data cap
|
||||
on your subscription plan. These can be files you downloaded from
|
||||
other people, or other people downloading your files if you have
|
||||
bandwidth sharing enabled. Bandwidth sharing can be changed on
|
||||
<a href="/user/subscription">the subscription page</a>.
|
||||
</p>
|
||||
<p>
|
||||
Total bandwidth usage is the combined bandwidth usage of all the
|
||||
files on your account. This includes paid transfers.
|
||||
</p>
|
||||
</div>
|
||||
<Chart bind:this={graph_bandwidth} data_type="bytes"/>
|
||||
<div class="limit_width">
|
||||
<h3>Views and downloads</h3>
|
||||
<p>
|
||||
A view is counted when someone visits the download page of one of
|
||||
your files. Views are unique per user per file.
|
||||
</p>
|
||||
<p>
|
||||
Downloads are counted when a user clicks the download button on one
|
||||
of your files. It does not matter whether the download is completed
|
||||
or not, only the start of the download is counted.
|
||||
</p>
|
||||
</div>
|
||||
<Chart bind:this={graph_views_downloads} data_type="number"/>
|
||||
|
||||
<h2>Statistics</h2>
|
||||
<p>
|
||||
Here you can see how often your files are viewed, downloaded
|
||||
and how much bandwidth they consume. The buttons at the top
|
||||
can be pressed to adjust the timeframe. If you choose 'Day'
|
||||
the statistics will be updated periodically. No need to
|
||||
refresh the page.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="highlight_light">
|
||||
<button
|
||||
on:click={() => { update_graphs(1440, 1, true) }}
|
||||
class:button_highlight={graph_timespan == 1440}>
|
||||
Day (1m)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(10080, 10, false) }}
|
||||
class:button_highlight={graph_timespan == 10080}>
|
||||
Week (10m)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(20160, 60, false) }}
|
||||
class:button_highlight={graph_timespan == 20160}>
|
||||
Two Weeks (1h)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(43200, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 43200}>
|
||||
Month (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(131400, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 131400}>
|
||||
Quarter (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(525600, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 525600}>
|
||||
Year (1d)
|
||||
</button>
|
||||
<button
|
||||
on:click={() => { update_graphs(1051200, 1440, false) }}
|
||||
class:button_highlight={graph_timespan == 1051200}>
|
||||
Two Years (1d)
|
||||
</button>
|
||||
<br/>
|
||||
Total usage from {time_start} to {time_end}<br/>
|
||||
{formatThousands(total_views)} views,
|
||||
{formatThousands(total_downloads)} downloads,
|
||||
{formatDataVolume(total_bandwidth, 3)} bandwidth and
|
||||
{formatDataVolume(total_transfer_paid, 3)} paid transfers
|
||||
</div>
|
||||
<section>
|
||||
<h3>Premium transfers and total bandwidth usage</h3>
|
||||
<p>
|
||||
A premium transfer is when a file is downloaded using the data cap
|
||||
on your subscription plan. These can be files you downloaded from
|
||||
other people, or other people downloading your files if you have
|
||||
bandwidth sharing enabled. Bandwidth sharing can be changed on
|
||||
<a href="/user/subscription">the subscription page</a>.
|
||||
</p>
|
||||
<p>
|
||||
Total bandwidth usage is the combined bandwidth usage of all the
|
||||
files on your account. This includes paid transfers.
|
||||
</p>
|
||||
</section>
|
||||
<Chart bind:this={graph_bandwidth} data_type="bytes"/>
|
||||
|
||||
<section>
|
||||
<h3>Views and downloads</h3>
|
||||
<p>
|
||||
A view is counted when someone visits the download page of one of
|
||||
your files. Views are unique per user per file.
|
||||
</p>
|
||||
<p>
|
||||
Downloads are counted when a user clicks the download button on one
|
||||
of your files. It does not matter whether the download is completed
|
||||
or not, only the start of the download is counted.
|
||||
</p>
|
||||
</section>
|
||||
<Chart bind:this={graph_views_downloads} data_type="number"/>
|
||||
|
@@ -8,29 +8,27 @@ export let used = 0
|
||||
$: frac = used / total
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<ProgressBar total={total} used={used}></ProgressBar>
|
||||
<ProgressBar total={total} used={used}></ProgressBar>
|
||||
|
||||
{#if frac > 0.99}
|
||||
<div class="highlight_red">
|
||||
You have used all of your data cap. People can still download your
|
||||
files, but not directly from the API anymore. The file viewer shows
|
||||
ads on your files and download speeds are limited.
|
||||
<br/>
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</div>
|
||||
{:else if frac > 0.8}
|
||||
<div class="highlight_yellow">
|
||||
You have used {(frac*100).toFixed(0)}% of your data cap. If your
|
||||
data runs out people won't be able to download your files directly
|
||||
from the API anymore, ads will be shown on the file viewer and
|
||||
transfer rates will be limited.
|
||||
<br/>
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if frac > 0.99}
|
||||
<div class="highlight_red">
|
||||
You have used all of your data cap. People can still download your
|
||||
files, but not directly from the API anymore. The file viewer shows
|
||||
ads on your files and download speeds are limited.
|
||||
<br/>
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</div>
|
||||
{:else if frac > 0.8}
|
||||
<div class="highlight_yellow">
|
||||
You have used {(frac*100).toFixed(0)}% of your data cap. If your
|
||||
data runs out people won't be able to download your files directly
|
||||
from the API anymore, ads will be shown on the file viewer and
|
||||
transfer rates will be limited.
|
||||
<br/>
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
@@ -33,7 +33,7 @@ onMount(() => {
|
||||
|
||||
<svelte:window on:popstate={get_page} />
|
||||
|
||||
<div class="checkers inset">
|
||||
<header>
|
||||
<h1>Welcome home, {window.user.username}!</h1>
|
||||
|
||||
<div class="tab_bar">
|
||||
@@ -75,7 +75,7 @@ onMount(() => {
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<br/>
|
||||
|
||||
{#if page === "home"}
|
||||
|
@@ -7,56 +7,54 @@ export let used = 0
|
||||
$: frac = used / total
|
||||
</script>
|
||||
|
||||
<div>
|
||||
Storage:
|
||||
{formatDataVolume(used, 3)}
|
||||
out of
|
||||
{formatDataVolume(total, 3)}
|
||||
<br/>
|
||||
<ProgressBar total={total} used={used}></ProgressBar>
|
||||
Storage:
|
||||
{formatDataVolume(used, 3)}
|
||||
out of
|
||||
{formatDataVolume(total, 3)}
|
||||
<br/>
|
||||
<ProgressBar total={total} used={used}></ProgressBar>
|
||||
|
||||
{#if frac > 2.0}
|
||||
<div class="highlight_red">
|
||||
<span class="warn_text">You are using more than 200% of your allowed storage space!</span>
|
||||
<p>
|
||||
We have started deleting your files to free up space. If you do
|
||||
not want to lose any more files please upgrade to a storage plan
|
||||
which supports the volume of storage which you need:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{:else if frac > 0.99}
|
||||
<div class="highlight_red">
|
||||
<p>
|
||||
You have used all of your storage space. You won't be able to
|
||||
upload new files anymore. Please upgrade to a higher support
|
||||
tier to continue uploading files:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Your files will not be deleted any sooner than normal at this
|
||||
moment. When your storage usage is over 200% we will start
|
||||
deleting your files to free up the space.
|
||||
</p>
|
||||
</div>
|
||||
{:else if frac > 0.8}
|
||||
<div class="highlight_yellow">
|
||||
<p>
|
||||
You have used {(frac*100).toFixed(0)}% of your
|
||||
storage space. If your storage space runs out you won't be able
|
||||
to upload new files anymore. Please upgrade to a higher support
|
||||
tier to continue uploading files:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if frac > 2.0}
|
||||
<div class="highlight_red">
|
||||
<span class="warn_text">You are using more than 200% of your allowed storage space!</span>
|
||||
<p>
|
||||
We have started deleting your files to free up space. If you do
|
||||
not want to lose any more files please upgrade to a storage plan
|
||||
which supports the volume of storage which you need:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{:else if frac > 0.99}
|
||||
<div class="highlight_red">
|
||||
<p>
|
||||
You have used all of your storage space. You won't be able to
|
||||
upload new files anymore. Please upgrade to a higher support
|
||||
tier to continue uploading files:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Your files will not be deleted any sooner than normal at this
|
||||
moment. When your storage usage is over 200% we will start
|
||||
deleting your files to free up the space.
|
||||
</p>
|
||||
</div>
|
||||
{:else if frac > 0.8}
|
||||
<div class="highlight_yellow">
|
||||
<p>
|
||||
You have used {(frac*100).toFixed(0)}% of your
|
||||
storage space. If your storage space runs out you won't be able
|
||||
to upload new files anymore. Please upgrade to a higher support
|
||||
tier to continue uploading files:
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||
Upgrade options
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.warn_text {
|
||||
|
@@ -74,170 +74,169 @@ onMount(load_tranfer_used)
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="limit_width">
|
||||
<h2>Manage subscription</h2>
|
||||
{#if window.user.subscription.type !== "patreon"}
|
||||
<p>
|
||||
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
|
||||
</p>
|
||||
<p>
|
||||
When your prepaid subscription is active you will be charged daily
|
||||
based on usage. Hotlink bandwidth is charged per TB based on the
|
||||
usage of the previous day. The amount charged for storage each day
|
||||
is your storage usage at the end of the day multiplied by the
|
||||
storage price (€4 / TB) and divided by the average number of days in
|
||||
a month (30.4375). So if you have exactly 1 TB on your account you
|
||||
will be charged €0.131416838 per day.
|
||||
</p>
|
||||
<p>
|
||||
The prepaid subscription will stay active for as long as you have
|
||||
credit on your account. When you reach negative balance the
|
||||
subscription will automatically end. You will need a positive
|
||||
balance to activate the subscription again.
|
||||
</p>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h3>Prepaid plans</h3>
|
||||
{#if result !== ""}
|
||||
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
|
||||
{result}
|
||||
</div>
|
||||
{/if}
|
||||
<section>
|
||||
<h2>Manage subscription</h2>
|
||||
{#if window.user.subscription.type !== "patreon"}
|
||||
<p>
|
||||
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
|
||||
</p>
|
||||
<p>
|
||||
When your prepaid subscription is active you will be charged daily
|
||||
based on usage. Hotlink bandwidth is charged per TB based on the
|
||||
usage of the previous day. The amount charged for storage each day
|
||||
is your storage usage at the end of the day multiplied by the
|
||||
storage price (€4 / TB) and divided by the average number of days in
|
||||
a month (30.4375). So if you have exactly 1 TB on your account you
|
||||
will be charged €0.131416838 per day.
|
||||
</p>
|
||||
<p>
|
||||
The prepaid subscription will stay active for as long as you have
|
||||
credit on your account. When you reach negative balance the
|
||||
subscription will automatically end. You will need a positive
|
||||
balance to activate the subscription again.
|
||||
</p>
|
||||
|
||||
<div class="feat_table">
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid"}>
|
||||
Prepaid<br/>
|
||||
{#if subscription === "prepaid"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal round_tr">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€4 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files never expire as long as subscription is active</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_120d"}>
|
||||
120 days storage<br/>
|
||||
{#if subscription === "prepaid_temp_storage_120d"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid_temp_storage_120d"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€2 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files expire 120 days after the last time they're viewed</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_60d"}>
|
||||
60 days storage<br/>
|
||||
{#if subscription === "prepaid_temp_storage_60d"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid_temp_storage_60d"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€1 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files expire 60 days after the last time they're viewed</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === ""}>
|
||||
Free<br/>
|
||||
{#if subscription === ""}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = ""; update("subscription")}}>
|
||||
<i class="icon">money_off</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal round_br">
|
||||
<ul>
|
||||
<li>Standard free plan, files expire after 30 days.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Prepaid plans</h3>
|
||||
{#if result !== ""}
|
||||
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
|
||||
{result}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h3>Bandwidth sharing</h3>
|
||||
{#if hotlinking}
|
||||
<button on:click={() => { hotlinking = false; update("limits") }}>
|
||||
<i class="icon green">check</i> ON (click to turn off)
|
||||
</button>
|
||||
{:else}
|
||||
<button on:click={() => { hotlinking = true; update("limits") }}>
|
||||
<i class="icon red">close</i> OFF (click to turn on)
|
||||
</button>
|
||||
{/if}
|
||||
<p>
|
||||
When bandwidth sharing is enabled all the bandwidth that your files
|
||||
use will be subtracted from your data cap. Advertisements will be
|
||||
disabled on the download pages for your files and download speed
|
||||
will be unlimited. The rate limiting captcha for files is also
|
||||
disabled when bandwidth sharing is on. You can directly embed your
|
||||
file's download link anywhere, you don't need to use the file viewer
|
||||
page.
|
||||
</p>
|
||||
<div class="feat_table">
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid"}>
|
||||
Prepaid<br/>
|
||||
{#if subscription === "prepaid"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal round_tr">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€4 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files never expire as long as subscription is active</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_120d"}>
|
||||
120 days storage<br/>
|
||||
{#if subscription === "prepaid_temp_storage_120d"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid_temp_storage_120d"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€2 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files expire 120 days after the last time they're viewed</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_60d"}>
|
||||
60 days storage<br/>
|
||||
{#if subscription === "prepaid_temp_storage_60d"}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = "prepaid_temp_storage_60d"; update("subscription")}}>
|
||||
<i class="icon">attach_money</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal">
|
||||
<ul>
|
||||
<li>Base price of €1 per month</li>
|
||||
<li>€1 per TB per month for storage</li>
|
||||
<li>€2 per TB for data transfer</li>
|
||||
<li>Files expire 60 days after the last time they're viewed</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feat_label" class:feat_highlight={subscription === ""}>
|
||||
Free<br/>
|
||||
{#if subscription === ""}
|
||||
Currently active
|
||||
{:else}
|
||||
<button on:click={() => {subscription = ""; update("subscription")}}>
|
||||
<i class="icon">money_off</i>
|
||||
Activate
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="feat_normal round_br">
|
||||
<ul>
|
||||
<li>Standard free plan, files expire after 30 days.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h3>Bill shock limit</h3>
|
||||
<p>
|
||||
Billshock limit in gigabytes per month (1 TB = 1000 GB). Set to 0 to disable.
|
||||
</p>
|
||||
<form on:submit|preventDefault={() => {update("limits")}} class="billshock_container">
|
||||
<input type="number" bind:value={transfer_cap} step="100" min="0"/>
|
||||
<div style="margin: 0.5em;">GB</div>
|
||||
<button type="submit">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</form>
|
||||
<h3>Bandwidth sharing</h3>
|
||||
{#if hotlinking}
|
||||
<button on:click={() => { hotlinking = false; update("limits") }}>
|
||||
<i class="icon green">check</i> ON (click to turn off)
|
||||
</button>
|
||||
{:else}
|
||||
<button on:click={() => { hotlinking = true; update("limits") }}>
|
||||
<i class="icon red">close</i> OFF (click to turn on)
|
||||
</button>
|
||||
{/if}
|
||||
<p>
|
||||
When bandwidth sharing is enabled all the bandwidth that your files
|
||||
use will be subtracted from your data cap. Advertisements will be
|
||||
disabled on the download pages for your files and download speed
|
||||
will be unlimited. The rate limiting captcha for files is also
|
||||
disabled when bandwidth sharing is on. You can directly embed your
|
||||
file's download link anywhere, you don't need to use the file viewer
|
||||
page.
|
||||
</p>
|
||||
|
||||
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
||||
new limit: {formatDataVolume(transfer_cap*1e9, 3)}
|
||||
<ProgressBar used={transfer_used} total={transfer_cap*1e9}></ProgressBar>
|
||||
<p>
|
||||
The billshock limit limits how much bandwidth your account can use
|
||||
in a 30 day window. When this limit is reached files will show ads
|
||||
again and can only be downloaded from the file viewer page. This is
|
||||
mostly useful for prepaid plans, but it works for patreon plans too.
|
||||
Set to 0 to disable the limit.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Bill shock limit</h3>
|
||||
<p>
|
||||
Billshock limit in gigabytes per month (1 TB = 1000 GB). Set to 0 to disable.
|
||||
</p>
|
||||
<form on:submit|preventDefault={() => {update("limits")}} class="billshock_container">
|
||||
<input type="number" bind:value={transfer_cap} step="100" min="0"/>
|
||||
<div style="margin: 0.5em;">GB</div>
|
||||
<button type="submit">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</form>
|
||||
|
||||
Bandwidth used in the last 30 days: {formatDataVolume(transfer_used, 3)},
|
||||
new limit: {formatDataVolume(transfer_cap*1e9, 3)}
|
||||
<ProgressBar used={transfer_used} total={transfer_cap*1e9}></ProgressBar>
|
||||
<p>
|
||||
The billshock limit limits how much bandwidth your account can use
|
||||
in a 30 day window. When this limit is reached files will show ads
|
||||
again and can only be downloaded from the file viewer page. This is
|
||||
mostly useful for prepaid plans, but it works for patreon plans too.
|
||||
Set to 0 to disable the limit.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -120,157 +120,156 @@ onMount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="limit_width">
|
||||
<h2>Deposit credits</h2>
|
||||
<p>
|
||||
You can deposit credit on your pixeldrain account with Bitcoin,
|
||||
Lightning network (<a
|
||||
href="https://btcpay.pixeldrain.com/embed/uS2mbWjXUuaAqMh8XLjkjwi8oehFuxeBZxekMxv68LN/BTC/ln"
|
||||
target="_blank">node info</a>) and Dogecoin. You must pay the full
|
||||
amount as stated on the invoice, else your payment will fail.
|
||||
</p>
|
||||
<p>
|
||||
Do note that it is not possible to withdraw coins from your
|
||||
pixeldrain account. It's not a wallet. Any amount of money you
|
||||
deposit has to be used up.
|
||||
</p>
|
||||
<div style="text-align: center;">
|
||||
Deposit amount €
|
||||
<input type="number" bind:value={credit_amount} min="1"/>
|
||||
<br/>
|
||||
Pay with:<br/>
|
||||
<button on:click={() => {checkout("btc")}}>
|
||||
<span class="icon_unicode">₿</span> Bitcoin
|
||||
</button>
|
||||
<button on:click={() => {checkout("btc_lightning")}}>
|
||||
<i class="icon">bolt</i> Lightning network
|
||||
</button>
|
||||
<button on:click={() => {checkout("doge")}}>
|
||||
<span class="icon_unicode">Ð</span> Dogecoin
|
||||
</button>
|
||||
</div>
|
||||
{#if loading}
|
||||
<div class="spinner_container">
|
||||
<Spinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<h2>Deposit credits</h2>
|
||||
<p>
|
||||
You can deposit credit on your pixeldrain account with Bitcoin,
|
||||
Lightning network (<a
|
||||
href="https://btcpay.pixeldrain.com/embed/uS2mbWjXUuaAqMh8XLjkjwi8oehFuxeBZxekMxv68LN/BTC/ln"
|
||||
target="_blank">node info</a>) and Dogecoin. You must pay the full
|
||||
amount as stated on the invoice, else your payment will fail.
|
||||
</p>
|
||||
<p>
|
||||
Do note that it is not possible to withdraw coins from your
|
||||
pixeldrain account. It's not a wallet. Any amount of money you
|
||||
deposit has to be used up.
|
||||
</p>
|
||||
<div style="text-align: center;">
|
||||
Deposit amount €
|
||||
<input type="number" bind:value={credit_amount} min="1"/>
|
||||
<br/>
|
||||
Pay with:<br/>
|
||||
<button on:click={() => {checkout("btc")}}>
|
||||
<span class="icon_unicode">₿</span> Bitcoin
|
||||
</button>
|
||||
<button on:click={() => {checkout("btc_lightning")}}>
|
||||
<i class="icon">bolt</i> Lightning network
|
||||
</button>
|
||||
<button on:click={() => {checkout("doge")}}>
|
||||
<span class="icon_unicode">Ð</span> Dogecoin
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h3>Open invoices</h3>
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Created</td>
|
||||
<td>Amount</td>
|
||||
<td>Status</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each invoices as row (row.id)}
|
||||
{#if row.status === "New" ||
|
||||
row.status === "InvoiceCreated" ||
|
||||
row.status === "InvoiceProcessing" ||
|
||||
show_expired
|
||||
}
|
||||
<tr>
|
||||
<td>{formatDate(row.time, true, true, false)}</td>
|
||||
<td><Euro amount={row.amount}></Euro></td>
|
||||
<td>
|
||||
{#if row.status === "InvoiceCreated"}
|
||||
New (waiting for payment)
|
||||
{:else if row.status === "InvoiceProcessing"}
|
||||
Payment received, waiting for confirmations
|
||||
{:else if row.status === "InvoiceSettled"}
|
||||
Paid
|
||||
{:else if row.status === "InvoiceExpired"}
|
||||
Expired
|
||||
{:else}
|
||||
{row.status}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if row.status === "New" || row.status === "InvoiceCreated"}
|
||||
<a href={row.checkout_url} class="button button_highlight">
|
||||
<i class="icon">paid</i> Pay
|
||||
</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: center;">
|
||||
<button on:click={() => {show_expired = !show_expired}}>
|
||||
{#if show_expired}
|
||||
Hide
|
||||
{:else}
|
||||
Show
|
||||
{/if}
|
||||
expired and settled invoices
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Transaction log</h2>
|
||||
<p>
|
||||
Here is a log of all transactions on your account balance.
|
||||
</p>
|
||||
|
||||
{#each months as month}
|
||||
<h3>{month.month}</h3>
|
||||
<ul>
|
||||
<li>Subscription charge: <Euro amount={month.total_subscription_charge}></Euro></li>
|
||||
<li>Storage charge: <Euro amount={month.total_storage_charge}></Euro></li>
|
||||
<li>Bandwidth charge: <Euro amount={month.total_bandwidth_charge}></Euro></li>
|
||||
<li>Total charge: <Euro amount={month.total_deducted}></Euro></li>
|
||||
<li>Deposited: <Euro amount={month.total_deposited}></Euro></li>
|
||||
</ul>
|
||||
|
||||
<h3>Open invoices</h3>
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Created</td>
|
||||
<td>Amount</td>
|
||||
<td>Status</td>
|
||||
<td>Time</td>
|
||||
<td>Balance</td>
|
||||
<td>Subscription</td>
|
||||
<td colspan="2">Storage</td>
|
||||
<td colspan="2">Bandwidth</td>
|
||||
<td>Deposited</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Charged</td>
|
||||
<td>Charged</td>
|
||||
<td>Used</td>
|
||||
<td>Charged</td>
|
||||
<td>Used</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each invoices as row (row.id)}
|
||||
{#if row.status === "New" ||
|
||||
row.status === "InvoiceCreated" ||
|
||||
row.status === "InvoiceProcessing" ||
|
||||
show_expired
|
||||
}
|
||||
<tr>
|
||||
<td>{formatDate(row.time, true, true, false)}</td>
|
||||
<td><Euro amount={row.amount}></Euro></td>
|
||||
<td>
|
||||
{#if row.status === "InvoiceCreated"}
|
||||
New (waiting for payment)
|
||||
{:else if row.status === "InvoiceProcessing"}
|
||||
Payment received, waiting for confirmations
|
||||
{:else if row.status === "InvoiceSettled"}
|
||||
Paid
|
||||
{:else if row.status === "InvoiceExpired"}
|
||||
Expired
|
||||
{:else}
|
||||
{row.status}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if row.status === "New" || row.status === "InvoiceCreated"}
|
||||
<a href={row.checkout_url} class="button button_highlight">
|
||||
<i class="icon">paid</i> Pay
|
||||
</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{#each month.rows as row}
|
||||
<tr>
|
||||
<td>{formatDate(row.time, true, true, false)}</td>
|
||||
<td><Euro amount={row.new_balance}></Euro></td>
|
||||
<td><Euro amount={row.subscription_charge} precision="4"></Euro></td>
|
||||
<td><Euro amount={row.storage_charge} precision="4"></Euro></td>
|
||||
<td>{formatDataVolume(row.storage_used, 3)}</td>
|
||||
<td><Euro amount={row.bandwidth_charge} precision="4"></Euro></td>
|
||||
<td>{formatDataVolume(row.bandwidth_used, 3)}</td>
|
||||
<td><Euro amount={row.deposit_amount}></Euro></td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: center;">
|
||||
<button on:click={() => {show_expired = !show_expired}}>
|
||||
{#if show_expired}
|
||||
Hide
|
||||
{:else}
|
||||
Show
|
||||
{/if}
|
||||
expired and settled invoices
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Transaction log</h2>
|
||||
<p>
|
||||
Here is a log of all transactions on your account balance.
|
||||
</p>
|
||||
|
||||
{#each months as month}
|
||||
<h3>{month.month}</h3>
|
||||
<ul>
|
||||
<li>Subscription charge: <Euro amount={month.total_subscription_charge}></Euro></li>
|
||||
<li>Storage charge: <Euro amount={month.total_storage_charge}></Euro></li>
|
||||
<li>Bandwidth charge: <Euro amount={month.total_bandwidth_charge}></Euro></li>
|
||||
<li>Total charge: <Euro amount={month.total_deducted}></Euro></li>
|
||||
<li>Deposited: <Euro amount={month.total_deposited}></Euro></li>
|
||||
</ul>
|
||||
|
||||
<div class="table_scroll">
|
||||
<table style="text-align: left;">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>Balance</td>
|
||||
<td>Subscription</td>
|
||||
<td colspan="2">Storage</td>
|
||||
<td colspan="2">Bandwidth</td>
|
||||
<td>Deposited</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Charged</td>
|
||||
<td>Charged</td>
|
||||
<td>Used</td>
|
||||
<td>Charged</td>
|
||||
<td>Used</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each month.rows as row}
|
||||
<tr>
|
||||
<td>{formatDate(row.time, true, true, false)}</td>
|
||||
<td><Euro amount={row.new_balance}></Euro></td>
|
||||
<td><Euro amount={row.subscription_charge} precision="4"></Euro></td>
|
||||
<td><Euro amount={row.storage_charge} precision="4"></Euro></td>
|
||||
<td>{formatDataVolume(row.storage_used, 3)}</td>
|
||||
<td><Euro amount={row.bandwidth_charge} precision="4"></Euro></td>
|
||||
<td>{formatDataVolume(row.bandwidth_used, 3)}</td>
|
||||
<td><Euro amount={row.deposit_amount}></Euro></td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.spinner_container {
|
||||
|
@@ -28,10 +28,8 @@ export const toggle = () => {
|
||||
.expandable {
|
||||
text-decoration: none;
|
||||
background-color: var(--layer_3_color);
|
||||
transition: box-shadow 0.5s;
|
||||
box-shadow: 1px 1px 6px -2px var(--shadow_color);
|
||||
margin: 1em 0;
|
||||
border-radius: 8px;
|
||||
margin: 0.8em 0;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
|
Reference in New Issue
Block a user