Files
fnx_web/svelte/src/user_home/Home.svelte
2022-10-11 14:21:06 +02:00

365 lines
11 KiB
Svelte

<script>
import { onDestroy, onMount } from "svelte";
import { formatDataVolume, formatThousands } from "../util/Formatting.svelte";
import Chart from "../util/Chart.svelte";
import StorageProgressBar from "./StorageProgressBar.svelte";
import HotlinkProgressBar from "./HotlinkProgressBar.svelte";
import Euro from "../util/Euro.svelte"
import { color_by_name } from "../util/Util.svelte";
let graph_views_downloads = null
let graph_bandwidth = null
let time_start = ""
let time_end = ""
let load_graphs = async (minutes, interval) => {
let end = new Date()
let start = new Date()
start.setMinutes(start.getMinutes() - minutes)
try {
let views = get_graph_data("views", start, end, interval);
let downloads = get_graph_data("downloads", start, end, interval);
let bandwidth = get_graph_data("bandwidth", start, end, interval);
let transfer_paid = get_graph_data("transfer_paid", start, end, interval);
views = await views
downloads = await downloads
bandwidth = await bandwidth
transfer_paid = await transfer_paid
graph_views_downloads.data().labels = views.timestamps;
graph_views_downloads.data().datasets[0].data = views.amounts
graph_views_downloads.data().datasets[1].data = downloads.amounts
graph_bandwidth.data().labels = bandwidth.timestamps;
graph_bandwidth.data().datasets[0].data = bandwidth.amounts
graph_bandwidth.data().datasets[1].data = transfer_paid.amounts
graph_views_downloads.update()
graph_bandwidth.update()
time_start = views.timestamps[0];
time_end = views.timestamps.slice(-1)[0];
} catch (err) {
console.error("Failed to update graphs", err)
return
}
}
let total_views = 0
let total_downloads = 0
let total_bandwidth = 0
let total_transfer_paid = 0
let get_graph_data = async (stat, start, end, interval) => {
let resp = await fetch(
window.api_endpoint + "/user/time_series/" + stat +
"?start=" + start.toISOString() +
"&end=" + end.toISOString() +
"&interval=" + interval
)
resp = await resp.json()
// Convert the timestamps to a human-friendly format
resp.timestamps.forEach((val, idx) => {
let date = new Date(val);
let str = date.getFullYear();
str += "-" + ("00" + (date.getMonth() + 1)).slice(-2);
str += "-" + ("00" + date.getDate()).slice(-2);
str += " " + ("00" + date.getHours()).slice(-2);
str += ":" + ("00" + date.getMinutes()).slice(-2);
resp.timestamps[idx] = " " + str + " "; // Poor man's padding
});
// Add up the total amount and save it in the correct place
let total = resp.amounts.reduce((acc, cur) => { return acc + cur }, 0)
if (stat == "views") {
total_views = total;
} else if (stat == "downloads") {
total_downloads = total;
graph_views_downloads.update()
} else if (stat == "bandwidth") {
total_bandwidth = total;
} else if (stat == "transfer_paid") {
total_transfer_paid = total;
}
return resp
}
let graph_timeout = null
let graph_timespan = 0
let update_graphs = (minutes, interval, live) => {
if (graph_timeout !== null) { clearTimeout(graph_timeout) }
if (live) {
graph_timeout = setTimeout(() => { update_graphs(minutes, interval, true) }, 6000)
}
graph_timespan = minutes
load_graphs(minutes, interval)
load_direct_bw()
}
let transfer_cap = 0
let transfer_used = 0
let storage_space_used = 0
let load_direct_bw = () => {
let today = new Date()
let start = new Date()
start.setDate(start.getDate() - 30)
fetch(
window.api_endpoint + "/user/time_series/transfer_paid" +
"?start=" + start.toISOString() +
"&end=" + today.toISOString() +
"&interval=60"
).then(resp => {
if (!resp.ok) { return Promise.reject("Error: " + resp.status); }
return resp.json();
}).then(resp => {
let total = resp.amounts.reduce((accum, val) => accum += val, 0);
transfer_used = total
storage_space_used = window.user.storage_space_used
}).catch(e => {
console.error("Error requesting time series: " + e);
})
}
let patreon_response = ""
onMount(() => {
if (window.location.hash.startsWith("#patreon_")) {
patreon_response = window.location.hash.replace("#patreon_", "")
window.location.hash = ""
}
if (window.user.monthly_transfer_cap > 0) {
transfer_cap = window.user.monthly_transfer_cap
} else if (window.user.subscription.monthly_transfer_cap > 0) {
transfer_cap = window.user.subscription.monthly_transfer_cap
} else {
transfer_cap = -1
}
graph_views_downloads.data().datasets = [
{
label: "Views",
borderWidth: 2,
pointRadius: 0,
borderColor: color_by_name("highlight_color"),
backgroundColor: color_by_name("highlight_color"),
},
{
label: "Downloads",
borderWidth: 2,
pointRadius: 0,
borderColor: color_by_name("danger_color"),
backgroundColor: color_by_name("danger_color"),
},
];
graph_bandwidth.data().datasets = [
{
label: "Total bandwidth",
borderWidth: 2,
pointRadius: 0,
borderColor: color_by_name("highlight_color"),
backgroundColor: color_by_name("highlight_color"),
},
{
label: "Premium bandwidth",
borderWidth: 2,
pointRadius: 0,
borderColor: color_by_name("danger_color"),
backgroundColor: color_by_name("danger_color"),
}
];
update_graphs(10080, 60, true);
})
onDestroy(() => {
if (graph_timeout !== null) {
clearTimeout(graph_timeout)
}
})
</script>
<section>
{#if patreon_response !== ""}
{#if patreon_response === "error"}
<div class="highlight_red">
An error occurred while linking Patreon subscription. Please try
again later.
</div>
{:else if patreon_response === "pledge_not_found"}
<div class="highlight_yellow">
<p>
We were not able to find your payment on Patreon. Please
wait until the payment is confirmed and try again. You can
see the status of your payment <a
href="https://www.patreon.com/pledges?ty=h"
target="_blank">on Patreon itself</a>.
</p>
<p>
If your payment is complete and your account is still not
upgraded please contact me at support@pixeldrain.com, or
send me a message on Patreon.
<p/>
</div>
{:else if patreon_response === "success"}
<div class="highlight_green">
Success! Your Patreon pledge has been linked to your pixeldrain
account. You are now able to use Pro features.
</div>
{/if}
<br/>
{/if}
<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>)
{:else if window.user.subscription.id === ""}
(<a href="/api/patreon_auth/start" class="button">Link Patreon 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>
{/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>
{/if}
{#if transfer_cap === -1}
Premium transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
{:else}
Premium 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}
<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>
<h2>Statistics</h2>
<p>
Here you can see how often your files are viewed, downloaded and how
much bandwidth they consume. The buttons below can be pressed to adjust
the timeframe.
</p>
<div class="highlight_border">
<button
on:click={() => update_graphs(1440, 1, true)}
class:button_highlight={graph_timespan == 1440}>
Day (1m)
</button>
<button
on:click={() => update_graphs(10080, 60, true)}
class:button_highlight={graph_timespan == 10080}>
Week (1h)
</button>
<button
on:click={() => update_graphs(20160, 60, true)}
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>
</div>
<h3>Premium transfers and total bandwidth usage</h3>
<p>
Total bandwidth usage is the combined bandwidth usage of all the files
on your account. This includes paid transfers.
</p>
<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>
</section>
<Chart bind:this={graph_bandwidth} data_type="bytes"/>
<section>
<div class="highlight_border">
Total usage from {time_start} to {time_end}<br/>
{formatDataVolume(total_bandwidth, 3)} bandwidth,
{formatDataVolume(total_transfer_paid, 3)} paid transfers
</div>
<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"/>
<section>
<div class="highlight_border">
Total usage from {time_start} to {time_end}<br/>
{formatThousands(total_views)} views and
{formatThousands(total_downloads)} downloads
</div>
</section>