Combine view and download graphs

This commit is contained in:
2021-12-16 21:20:05 +01:00
parent c5c8d6f8d5
commit 81c8baf639
4 changed files with 223 additions and 116 deletions

View File

@@ -39,11 +39,12 @@ const loadGraph = (minutes, interval, live) => {
dateStr += ":" + ("00" + date.getMinutes()).slice(-2);
resp.views.timestamps[idx] = " " + dateStr + " "; // Poor man's padding
});
graphViews.chart().data.labels = resp.views.timestamps;
graphViews.chart().data.datasets[0].data = resp.views.amounts;
graphBandwidth.chart().data.labels = resp.views.timestamps;
graphBandwidth.chart().data.datasets[0].data = resp.bandwidth.amounts
graphBandwidth.chart().data.datasets[1].data = resp.bandwidth_paid.amounts
graphViews.data().labels = resp.views.timestamps;
graphViews.data().datasets[0].data = resp.views.amounts;
graphViews.data().datasets[1].data = resp.downloads.amounts;
graphBandwidth.data().labels = resp.views.timestamps;
graphBandwidth.data().datasets[0].data = resp.bandwidth.amounts
graphBandwidth.data().datasets[1].data = resp.bandwidth_paid.amounts
graphViews.update()
graphBandwidth.update()
@@ -107,7 +108,7 @@ function getStats(order) {
let statsInterval = null
onMount(() => {
// Prepare chart datasets
graphBandwidth.chart().data.datasets = [
graphBandwidth.data().datasets = [
{
label: "Bandwidth (free)",
borderWidth: 2,
@@ -123,7 +124,7 @@ onMount(() => {
backgroundColor: "#"+window.style.dangerColor,
},
];
graphViews.chart().data.datasets = [
graphViews.data().datasets = [
{
label: "Views",
borderWidth: 2,
@@ -131,6 +132,13 @@ onMount(() => {
borderColor: "#"+window.style.highlightColor,
backgroundColor: "#"+window.style.highlightColor,
},
{
label: "Downloads",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.dangerColor,
backgroundColor: "#"+window.style.dangerColor,
},
];
loadGraph(10080, 10, false);
@@ -163,8 +171,8 @@ onDestroy(() => {
<button on:click={() => { loadGraph(525600, 1440, false) }}>Year</button>
<button on:click={() => { loadGraph(1051200, 1440, false) }}>Two Years</button>
</div>
<Chart bind:this={graphBandwidth} dataType="bytes" label="Bandwidth" />
<Chart bind:this={graphViews} dataType="number" label="Views" />
<Chart bind:this={graphBandwidth} data_type="bytes" />
<Chart bind:this={graphViews} data_type="number" />
<div class="highlight_dark">
Total usage from {start_time} to {end_time}<br/>
{formatDataVolume(total_bandwidth, 3)} bandwidth,

View File

@@ -1,7 +1,8 @@
<script>
import Chart from "../util/Chart.svelte";
import { onMount } from "svelte";
import { formatDataVolume, formatDate, formatThousands } from "../util/Formatting.svelte"
import { domain_url } from "../util/Util.svelte";
import Chart from "../util/Chart.svelte";
export let file = {
id: "",
@@ -16,24 +17,31 @@ export let file = {
timeseries_href: "",
}
let download_chart
let view_chart
let chart
let chart_timespan = 43200
let chart_interval = 60
$: update_charts(file.id)
let update_charts = () => {
if (file.id === "") {
return
$: update_file(file.id)
let update_file = id => {
if (id) {
update_chart(chart_timespan, chart_interval)
}
}
let update_chart = (timespan, interval) => {
chart_timespan = timespan
chart_interval = interval
console.log("updating graph")
let today = new Date()
let start = new Date()
start.setDate(start.getDate() - 90)
start.setMinutes(start.getMinutes() - timespan)
let end = new Date()
fetch(
file.timeseries_href +
"?start=" + start.toISOString() +
"&end=" + today.toISOString() +
"&end=" + end.toISOString() +
"&interval=" + 60
).then(resp => {
if (!resp.ok) { return null }
@@ -41,10 +49,10 @@ let update_charts = () => {
}).then(resp => {
resp.views.timestamps.forEach((val, idx) => {
let date = new Date(val);
let dateStr = ("00" + (date.getMonth() + 1)).slice(-2);
dateStr += "-" + ("00" + date.getDate()).slice(-2);
dateStr += " " + ("00" + date.getHours()).slice(-2) + "h";
resp.views.timestamps[idx] = " " + dateStr + " "; // Poor man's padding
let str = ("00" + (date.getMonth() + 1)).slice(-2);
str += "-" + ("00" + date.getDate()).slice(-2);
str += " " + ("00" + date.getHours()).slice(-2) + "h";
resp.views.timestamps[idx] = " " + str + " "; // Poor man's padding
});
resp.bandwidth.amounts.forEach((val, idx) => {
resp.bandwidth.amounts[idx] = Math.round(val / file.size);
@@ -52,14 +60,31 @@ let update_charts = () => {
resp.bandwidth_paid.amounts.forEach((val, idx) => {
resp.bandwidth.amounts[idx] += Math.round(val / file.size);
});
download_chart.chart().data.labels = resp.views.timestamps
view_chart.chart().data.labels = resp.views.timestamps
download_chart.chart().data.datasets[0].data = resp.bandwidth.amounts
view_chart.chart().data.datasets[0].data = resp.views.amounts
download_chart.update()
view_chart.update()
chart.data().labels = resp.views.timestamps
chart.data().datasets[0].data = resp.views.amounts
chart.data().datasets[1].data = resp.bandwidth.amounts
chart.update()
})
}
onMount(() => {
chart.data().datasets = [
{
label: "Views",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.highlightColor,
backgroundColor: "#"+window.style.highlightColor,
},
{
label: "Downloads",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.dangerColor,
backgroundColor: "#"+window.style.dangerColor,
},
];
})
</script>
<div>
@@ -126,10 +151,42 @@ let update_charts = () => {
{/if}
</table>
<h2>Downloads</h2>
<Chart bind:this={download_chart} label="Downloads"></Chart>
<h2>Views</h2>
<Chart bind:this={view_chart} label="Views"></Chart>
<h2>Views and downloads</h2>
<div class="button_bar">
<button
on:click={() => { update_chart(1440, 1) }}
class:button_highlight={chart_timespan == 1440}>
Day (1m)
</button>
<button
on:click={() => { update_chart(10080, 60) }}
class:button_highlight={chart_timespan == 10080}>
Week (1h)
</button>
<button
on:click={() => { update_chart(43200, 1440) }}
class:button_highlight={chart_timespan == 43200}>
Month (1d)
</button>
<button
on:click={() => { update_chart(131400, 1440) }}
class:button_highlight={chart_timespan == 131400}>
Quarter (1d)
</button>
<button
on:click={() => { update_chart(525600, 1440) }}
class:button_highlight={chart_timespan == 525600}>
Year (1d)
</button>
<button
on:click={() => { update_chart(1051200, 1440) }}
class:button_highlight={chart_timespan == 1051200}>
Two Years (1d)
</button>
</div>
<Chart bind:this={chart} />
<p style="text-align: center">
Charts rendered by the amazing <a href="https://www.chartjs.org/" target="_blank">Chart.js</a>.
@@ -155,3 +212,11 @@ let update_charts = () => {
<tr><td>SHIFT + s</td><td> = Download all the files in the list as a zip archive</td></tr>
</table>
</div>
<style>
.button_bar {
display: block;
width: 100%;
text-align: center;
}
</style>

View File

@@ -6,10 +6,8 @@ import StorageProgressBar from "./StorageProgressBar.svelte";
import HotlinkProgressBar from "./HotlinkProgressBar.svelte";
import Euro from "../util/Euro.svelte"
let graph_view = null
let graph_download = null
let graph_views_downloads = null
let graph_bandwidth = null
let graph_transfer_paid = null
let time_start = ""
let time_end = ""
let total_views = 0
@@ -17,49 +15,73 @@ let total_downloads = 0
let total_bandwidth = 0
let total_transfer_paid = 0
let load_graph = (graph, stat, minutes, interval) => {
let today = new Date()
let load_graphs = async (minutes, interval) => {
let end = new Date()
let start = new Date()
start.setMinutes(start.getMinutes() - minutes)
fetch(
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 get_graph_data = async (stat, start, end, interval) => {
let resp = await fetch(
window.api_endpoint + "/user/time_series/" + stat +
"?start=" + start.toISOString() +
"&end=" + today.toISOString() +
"&end=" + end.toISOString() +
"&interval=" + interval
).then(resp => {
if (!resp.ok) { return Promise.reject("Error: " + resp.status); }
return resp.json();
}).then(resp => {
resp.timestamps.forEach((val, idx) => {
let date = new Date(val);
let dateStr = ("00" + (date.getMonth() + 1)).slice(-2);
dateStr += "-" + ("00" + date.getDate()).slice(-2);
dateStr += " " + ("00" + date.getHours()).slice(-2);
dateStr += ":" + ("00" + date.getMinutes()).slice(-2);
resp.timestamps[idx] = " " + dateStr + " "; // Poor man's padding
});
graph.chart().data.labels = resp.timestamps;
graph.chart().data.datasets[0].data = resp.amounts;
graph.chart().update();
)
resp = await resp.json()
time_start = resp.timestamps[0];
time_end = resp.timestamps.slice(-1)[0];
// Convert the timestamps to a human-friendly format
resp.timestamps.forEach((val, idx) => {
let date = new Date(val);
let 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
});
let total = resp.amounts.reduce((acc, cur) => { return acc + cur }, 0)
// 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;
} else if (stat == "bandwidth") {
total_bandwidth = total;
} else if (stat == "transfer_paid") {
total_transfer_paid = total;
}
}).catch(e => {
console.error("Error requesting time series: " + e);
})
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
@@ -72,10 +94,7 @@ let update_graphs = (minutes, interval, live) => {
graph_timespan = minutes
load_graph(graph_view, "views", minutes, interval)
load_graph(graph_download, "downloads", minutes, interval)
load_graph(graph_bandwidth, "bandwidth", minutes, interval)
load_graph(graph_transfer_paid, "transfer_paid", minutes, interval)
load_graphs(minutes, interval)
load_direct_bw()
}
@@ -113,6 +132,39 @@ onMount(() => {
transfer_cap = -1
}
graph_views_downloads.data().datasets = [
{
label: "Views",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.highlightColor,
backgroundColor: "#"+window.style.highlightColor,
},
{
label: "Downloads",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.dangerColor,
backgroundColor: "#"+window.style.dangerColor,
},
];
graph_bandwidth.data().datasets = [
{
label: "Bandwidth (total)",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.highlightColor,
backgroundColor: "#"+window.style.highlightColor,
},
{
label: "Bandwidth (premium)",
borderWidth: 2,
pointRadius: 0,
borderColor: "#"+window.style.dangerColor,
backgroundColor: "#"+window.style.dangerColor,
},
];
update_graphs(1440, 1, true);
})
onDestroy(() => {
@@ -235,43 +287,31 @@ onDestroy(() => {
{formatDataVolume(total_transfer_paid, 3)} paid transfers
</div>
<div class="limit_width">
<h3>Paid transfers</h3>
<h3>Premium transfers and total bandwidth usage</h3>
<p>
A paid 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 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>
</div>
<Chart bind:this={graph_transfer_paid} dataType="bytes" label="Paid transfers" />
<div class="limit_width">
<h3>Views</h3>
<p>
A view is counted when someone visits the download page of one
of your files. Views are unique per user per file.
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_view} dataType="number" label="Views" />
<Chart bind:this={graph_bandwidth} data_type="bytes"/>
<div class="limit_width">
<h3>Downloads</h3>
<h3>Views and downloads</h3>
<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.
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_download} dataType="number" label="Downloads" />
<div class="limit_width">
<h3>Bandwidth</h3>
<p>
This is how much bandwidth your files are using in total.
Bandwidth is used when a file is tranferred from a
pixeldrain server to a user who is downloading the file.
When a 5 MB file is downloaded 8 times it has used 40 MB of
bandwidth.
</p>
</div>
<Chart bind:this={graph_bandwidth} dataType="bytes" label="Bandwidth" />
<Chart bind:this={graph_views_downloads} data_type="number"/>
</div>

View File

@@ -5,12 +5,14 @@ import { Chart, PointElement, LineElement, LinearScale, CategoryScale, LineContr
let chart_element
let chart_object
export let label = "label"
export let dataType = ""
export let data_type = ""
export const chart = () => {
return chart_object
}
export const data = () => {
return chart_object.data
}
export const update = () => {
return chart_object.update()
}
@@ -32,15 +34,8 @@ onMount(() => {
{
type: 'line',
data: {
datasets: [
{
label: label,
borderWidth: 0,
pointRadius: 0,
fill: 'origin',
backgroundColor: "#"+window.style.highlightColor,
}
]
labels: [],
datasets: [],
},
options: {
legend: { display: false },
@@ -57,7 +52,7 @@ onMount(() => {
position: "left",
ticks: {
callback: function (value, index, values) {
if (dataType == "bytes") {
if (data_type == "bytes") {
return formatDataVolume(value, 3);
}
return formatNumber(value, 3);
@@ -88,7 +83,6 @@ onMount(() => {
}
);
})
</script>
<div class="chart-container">