update graphs and add new tier
This commit is contained in:
@@ -39,6 +39,10 @@ account. {{if .Authenticated}}(Your e-mail address: {{.User.Email}}){{end}}
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427">
|
||||
Order plan 'I'm doing my part!'
|
||||
</a>
|
||||
{{else if eq $plan "t5"}}
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5736701">
|
||||
Order plan 'Resolve'
|
||||
</a>
|
||||
{{else if eq $plan "t2"}}
|
||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291482">
|
||||
Order plan 'Persistence'
|
||||
|
@@ -1,102 +1,10 @@
|
||||
// Draw usage graph
|
||||
let graphViews = drawGraph(document.getElementById("views_chart"), "Views", "number");
|
||||
let graphBandwidth = drawGraph(document.getElementById("bandwidth_chart"), "Bandwidth", "bytes");
|
||||
|
||||
Chart.defaults.global.defaultFontColor = "#b3b3b3";
|
||||
Chart.defaults.global.defaultFontSize = 15;
|
||||
Chart.defaults.global.defaultFontFamily = "Ubuntu";
|
||||
Chart.defaults.global.maintainAspectRatio = false;
|
||||
Chart.defaults.global.elements.point.radius = 0;
|
||||
Chart.defaults.global.tooltips.mode = "index";
|
||||
Chart.defaults.global.tooltips.axis = "x";
|
||||
Chart.defaults.global.tooltips.intersect = false;
|
||||
Chart.defaults.global.animation.duration = 1000;
|
||||
Chart.defaults.global.animation.easing = "linear";
|
||||
|
||||
var graph = new Chart(
|
||||
document.getElementById('bandwidth_chart'),
|
||||
{
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: "Bandwidth",
|
||||
backgroundColor: "rgba(64, 255, 64, .01)",
|
||||
borderColor: "rgba(96, 255, 96, 1)",
|
||||
borderWidth: 1.5,
|
||||
lineTension: 0.2,
|
||||
fill: true,
|
||||
yAxisID: "y_bandwidth"
|
||||
}, {
|
||||
label: "Views",
|
||||
backgroundColor: "rgba(64, 64, 255, .01)",
|
||||
borderColor: "rgba(96, 96, 255, 1)",
|
||||
borderWidth: 1.5,
|
||||
lineTension: 0.2,
|
||||
fill: true,
|
||||
yAxisID: "y_views"
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [
|
||||
{
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y_bandwidth",
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Bandwidth"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, values) {
|
||||
return formatDataVolume(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(100, 255, 100, .05)"
|
||||
}
|
||||
}, {
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y_views",
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Views"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, values) {
|
||||
return formatNumber(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(128, 128, 255, .05)"
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
ticks: {
|
||||
maxRotation: 16
|
||||
},
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let graphTimeout = null;
|
||||
function loadGraph(minutes, interval, live){
|
||||
if (graphTimeout !== null) { clearTimeout(graphTimeout) }
|
||||
if (live) {
|
||||
graphTimeout = setTimeout(() => {loadGraph(minutes, interval, true)}, 2000)
|
||||
graphTimeout = setTimeout(() => {updateGraphs(minutes, interval, true)}, 10000)
|
||||
}
|
||||
|
||||
let today = new Date()
|
||||
@@ -112,26 +20,41 @@ function loadGraph(minutes, interval, live){
|
||||
if (!resp.ok) { return Promise.reject("Error: "+resp.status);}
|
||||
return resp.json();
|
||||
}).then(resp => {
|
||||
if (resp.success) {
|
||||
window.graph.data.labels = resp.labels;
|
||||
window.graph.data.datasets[0].data = resp.downloads;
|
||||
window.graph.data.datasets[1].data = resp.views;
|
||||
window.graph.update();
|
||||
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);
|
||||
dateStr += ":"+("00"+date.getMinutes()).slice(-2);
|
||||
resp.views.timestamps[idx] = " "+dateStr+" "; // Poor man's padding
|
||||
});
|
||||
graphViews.data.labels = resp.views.timestamps;
|
||||
graphViews.data.datasets[0].data = resp.views.amounts;
|
||||
graphBandwidth.data.labels = resp.views.timestamps;
|
||||
graphBandwidth.data.datasets[0].data = resp.bandwidth.amounts;
|
||||
graphViews.update()
|
||||
graphBandwidth.update();
|
||||
|
||||
document.getElementById("time_start").innerText = resp.labels[0];
|
||||
document.getElementById("time_end").innerText = resp.labels.slice(-1)[0];
|
||||
let total = 0
|
||||
resp.downloads.forEach(e => { total += e; });
|
||||
document.getElementById("total_bandwidth").innerText = formatDataVolume(total, 3);
|
||||
total = 0
|
||||
resp.views.forEach(e => { total += e; });
|
||||
document.getElementById("total_views").innerText = formatThousands(total);
|
||||
}
|
||||
document.getElementById("time_start").innerText = resp.views.timestamps[0];
|
||||
document.getElementById("time_end").innerText = resp.views.timestamps.slice(-1)[0];
|
||||
let total = 0
|
||||
resp.bandwidth.amounts.forEach(e => { total += e; });
|
||||
document.getElementById("total_bandwidth").innerText = formatDataVolume(total, 3);
|
||||
total = 0
|
||||
resp.views.amounts.forEach(e => { total += e; });
|
||||
document.getElementById("total_views").innerText = formatThousands(total);
|
||||
}).catch(e => {
|
||||
alert("Error requesting time series: "+e);
|
||||
})
|
||||
}
|
||||
|
||||
let graphTimeout = null;
|
||||
function updateGraphs(minutes, interval, live) {
|
||||
|
||||
loadGraph(graphViews, "views", minutes, interval);
|
||||
loadGraph(graphBandwidth, "bandwidth", minutes, interval);
|
||||
}
|
||||
|
||||
loadGraph(1440, 10, true);
|
||||
|
||||
// Load performance statistics
|
||||
|
@@ -55,6 +55,10 @@ Modal.prototype.setBody = function(element) {
|
||||
this.body.append(element)
|
||||
}
|
||||
|
||||
Modal.prototype.cloneTemplate = function(templateID) {
|
||||
this.setBody(document.getElementById(templateID).content.cloneNode(true))
|
||||
}
|
||||
|
||||
Modal.prototype.open = function() {
|
||||
if (this.visible) { return }
|
||||
this.visible = true
|
||||
|
65
res/include/script/dependencies/drawGraph.js
Normal file
65
res/include/script/dependencies/drawGraph.js
Normal file
@@ -0,0 +1,65 @@
|
||||
Chart.defaults.global.defaultFontColor = "#b3b3b3";
|
||||
Chart.defaults.global.defaultFontSize = 15;
|
||||
Chart.defaults.global.defaultFontFamily = "system-ui, sans-serif";
|
||||
Chart.defaults.global.maintainAspectRatio = false;
|
||||
Chart.defaults.global.elements.point.radius = 0;
|
||||
Chart.defaults.global.tooltips.mode = "index";
|
||||
Chart.defaults.global.tooltips.axis = "x";
|
||||
Chart.defaults.global.tooltips.intersect = false;
|
||||
Chart.defaults.global.animation.duration = 500;
|
||||
Chart.defaults.global.animation.easing = "linear";
|
||||
|
||||
function drawGraph(element, label, dataType) {
|
||||
return new Chart(
|
||||
element,
|
||||
{
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: label,
|
||||
backgroundColor: highlightColor,
|
||||
borderWidth: 0,
|
||||
lineTension: 0,
|
||||
fill: true,
|
||||
yAxisID: "ax_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
legend: { display: false },
|
||||
scales: {
|
||||
yAxes: [
|
||||
{
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "ax_1",
|
||||
ticks: {
|
||||
callback: function(value, index, values) {
|
||||
if (dataType == "bytes") {
|
||||
return formatDataVolume(value, 3);
|
||||
}
|
||||
return formatNumber(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: { display: false },
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
ticks: {
|
||||
sampleSize: 1,
|
||||
padding: 4,
|
||||
minRotation: 0,
|
||||
maxRotation: 0
|
||||
},
|
||||
gridLines: { display: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
@@ -2,7 +2,9 @@ function DetailsWindow(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.file = null
|
||||
this.graph = 0
|
||||
this.graphsInitialized = false
|
||||
this.graphViews = 0
|
||||
this.graphDownloads = 0
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
@@ -27,8 +29,9 @@ DetailsWindow.prototype.toggle = function() {
|
||||
this.btnDetails.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
|
||||
if (this.graph === 0) {
|
||||
this.renderGraph()
|
||||
if (!this.graphsInitialized) {
|
||||
this.renderGraphs()
|
||||
this.graphsInitialized = true
|
||||
}
|
||||
this.updateGraph(this.file)
|
||||
}
|
||||
@@ -54,12 +57,22 @@ DetailsWindow.prototype.setFile = function(file) {
|
||||
}
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.renderGraphs = function() {
|
||||
console.log("rendering graphs")
|
||||
this.graphDownloads = drawGraph(
|
||||
document.getElementById("downloads_chart"), "Downloads", "number",
|
||||
);
|
||||
this.graphViews = drawGraph(
|
||||
document.getElementById("views_chart"), "Views", "number",
|
||||
);
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.updateGraph = function(file) {
|
||||
console.log("updating graph")
|
||||
|
||||
let today = new Date()
|
||||
let start = new Date()
|
||||
start.setDate(start.getDate()-30)
|
||||
start.setDate(start.getDate()-90)
|
||||
|
||||
fetch(
|
||||
file.timeseries_href+
|
||||
@@ -70,101 +83,21 @@ DetailsWindow.prototype.updateGraph = function(file) {
|
||||
if (!resp.ok) {return null}
|
||||
return resp.json()
|
||||
}).then(resp => {
|
||||
this.graph.data.labels = resp.labels
|
||||
this.graph.data.datasets[0].data = resp.downloads
|
||||
this.graph.data.datasets[1].data = resp.views
|
||||
this.graph.update()
|
||||
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
|
||||
});
|
||||
resp.bandwidth.amounts.forEach((val, idx) => {
|
||||
resp.bandwidth.amounts[idx] = Math.round(val/file.size);
|
||||
});
|
||||
this.graphDownloads.data.labels = resp.views.timestamps
|
||||
this.graphViews.data.labels = resp.views.timestamps
|
||||
this.graphDownloads.data.datasets[0].data = resp.bandwidth.amounts
|
||||
this.graphViews.data.datasets[0].data = resp.views.amounts
|
||||
this.graphDownloads.update()
|
||||
this.graphViews.update()
|
||||
})
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.renderGraph = function() {
|
||||
console.log("rendering graph")
|
||||
Chart.defaults.global.defaultFontColor = "#b3b3b3"
|
||||
Chart.defaults.global.defaultFontSize = 15
|
||||
Chart.defaults.global.defaultFontFamily = "Ubuntu"
|
||||
Chart.defaults.global.maintainAspectRatio = false;
|
||||
Chart.defaults.global.elements.point.radius = 0
|
||||
Chart.defaults.global.tooltips.mode = "index"
|
||||
Chart.defaults.global.tooltips.axis = "x"
|
||||
Chart.defaults.global.tooltips.intersect = false
|
||||
this.graph = new Chart(
|
||||
document.getElementById('bandwidth_chart'),
|
||||
{
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: "Downloads",
|
||||
backgroundColor: "rgba(64, 255, 64, .01)",
|
||||
borderColor: "rgba(96, 255, 96, 1)",
|
||||
borderWidth: 1.5,
|
||||
lineTension: 0.2,
|
||||
fill: true,
|
||||
yAxisID: "y_bandwidth"
|
||||
}, {
|
||||
label: "Views",
|
||||
backgroundColor: "rgba(64, 64, 255, .01)",
|
||||
borderColor: "rgba(96, 96, 255, 1)",
|
||||
borderWidth: 1.5,
|
||||
lineTension: 0.2,
|
||||
fill: true,
|
||||
yAxisID: "y_views"
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [
|
||||
{
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y_bandwidth",
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Downloads"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, values) {
|
||||
return formatNumber(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(100, 255, 100, .05)"
|
||||
}
|
||||
}, {
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y_views",
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: "Views"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, values) {
|
||||
return formatNumber(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(128, 128, 255, .05)"
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
ticks: {
|
||||
maxRotation: 16
|
||||
},
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
61
res/include/script/user_home.js
Normal file
61
res/include/script/user_home.js
Normal file
@@ -0,0 +1,61 @@
|
||||
function loadGraph(graph, stat, minutes, interval){
|
||||
let today = new Date()
|
||||
let start = new Date()
|
||||
start.setMinutes(start.getMinutes()-minutes)
|
||||
|
||||
fetch(
|
||||
apiEndpoint+"/user/time_series/" + stat +
|
||||
"?start="+start.toISOString() +
|
||||
"&end="+today.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.data.labels = resp.timestamps;
|
||||
graph.data.datasets[0].data = resp.amounts;
|
||||
graph.update();
|
||||
|
||||
document.getElementById("time_start").innerText = resp.timestamps[0];
|
||||
document.getElementById("time_end").innerText = resp.timestamps.slice(-1)[0];
|
||||
let total = 0
|
||||
resp.amounts.forEach(e => { total += e; });
|
||||
|
||||
if (stat == "views") {
|
||||
document.getElementById("total_views").innerText = formatThousands(total);
|
||||
} else if (stat == "downloads") {
|
||||
document.getElementById("total_downloads").innerText = formatThousands(total);
|
||||
} else if (stat == "bandwidth") {
|
||||
document.getElementById("total_bandwidth").innerText = formatDataVolume(total, 3);
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error("Error requesting time series: "+e);
|
||||
})
|
||||
}
|
||||
|
||||
let graphViews = drawGraph(document.getElementById("views_chart"), "Views", "number");
|
||||
let graphDownloads = drawGraph(document.getElementById("downloads_chart"), "Downloads", "number");
|
||||
let graphBandwidth = drawGraph(document.getElementById("bandwidth_chart"), "Bandwidth", "bytes");
|
||||
let graphTimeout = null;
|
||||
|
||||
function updateGraphs(minutes, interval, live) {
|
||||
if (graphTimeout !== null) { clearTimeout(graphTimeout) }
|
||||
if (live) {
|
||||
graphTimeout = setTimeout(() => {updateGraphs(minutes, interval, true)}, 10000)
|
||||
}
|
||||
|
||||
loadGraph(graphViews, "views", minutes, interval);
|
||||
loadGraph(graphDownloads, "downloads", minutes, interval);
|
||||
loadGraph(graphBandwidth, "bandwidth", minutes, interval);
|
||||
}
|
||||
|
||||
// Default
|
||||
updateGraphs(10080, 60, false);
|
@@ -104,6 +104,7 @@ is collapsed */
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
color: var(--text_color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.node:hover:not(.node_selected) {
|
||||
background-color: var(--input_color_dark);
|
||||
|
@@ -96,7 +96,7 @@ body{
|
||||
.page_navigation {
|
||||
position: fixed;
|
||||
backface-visibility: hidden;
|
||||
z-index: 100;
|
||||
z-index: 99;
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
@@ -125,7 +125,7 @@ body{
|
||||
overflow-x: hidden;
|
||||
z-index: 50;
|
||||
transition: left 0.5s;
|
||||
padding: 50px 0 50px 0;
|
||||
padding: 70px 0 100px 0;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.page_navigation {
|
||||
@@ -183,6 +183,7 @@ body{
|
||||
text-overflow: ellipsis;
|
||||
transition: background-color 0.5s;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.page_navigation a:hover {
|
||||
background-color: #3f3f3f;
|
||||
@@ -285,10 +286,11 @@ hr{
|
||||
|
||||
a {
|
||||
color: #74ad38;
|
||||
color: var(--highlight_color);
|
||||
text-decoration: none;
|
||||
color: var(--highlight_color_dark);
|
||||
}
|
||||
a:hover {
|
||||
color: var(--highlight_color);
|
||||
}
|
||||
a:hover {text-decoration: underline;}
|
||||
|
||||
.form{
|
||||
margin-left: auto;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
.modal_background {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
BIN
res/static/img/benefit_5.png
Normal file
BIN
res/static/img/benefit_5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 145 KiB |
@@ -18,52 +18,77 @@
|
||||
<li>Username: {{.User.Username}}</li>
|
||||
<li>E-mail address: {{.User.Email}}</li>
|
||||
<li>
|
||||
Supporter status:
|
||||
{{if eq .User.Subscription ""}}
|
||||
Not a pixeldrain supporter<br/>
|
||||
{{if eq .User.Subscription.Name ""}}
|
||||
Supporter status: Not a pixeldrain supporter<br/>
|
||||
<a href="https://www.patreon.com/pixeldrain">Learn how to support pixeldrain</a>.
|
||||
{{else}}
|
||||
{{if eq .User.Subscription "patreon_1"}}
|
||||
Level 1 Patreon supporter. Benefits:
|
||||
<ul>
|
||||
<li>No ads when viewing files</li>
|
||||
</ul>
|
||||
{{else if eq .User.Subscription "patreon_2"}}
|
||||
Level 2 Patreon supporter. Benefits:
|
||||
<ul>
|
||||
<li>No ads when viewing files</li>
|
||||
<li>No ads on uploaded files</li>
|
||||
<li>2-month file expiry</li>
|
||||
</ul>
|
||||
{{else if eq .User.Subscription "patreon_3"}}
|
||||
Level 3 Patreon supporter. Benefits:
|
||||
<ul>
|
||||
<li>No ads when viewing files</li>
|
||||
<li>No ads on uploaded files</li>
|
||||
<li>6-month file expiry</li>
|
||||
</ul>
|
||||
{{else if eq .User.Subscription "patreon_4"}}
|
||||
Level 4 Patreon supporter. Benefits:
|
||||
<ul>
|
||||
<li>No ads when viewing files</li>
|
||||
<li>No ads on uploaded files</li>
|
||||
<li>No file expiry</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
Supporter level {{.User.Subscription.Name}}
|
||||
<ul>
|
||||
<li>Ads when viewing files: {{if .User.Subscription.DisableAdDisplay}}No{{else}}Yes{{end}}</li>
|
||||
<li>Ads on uploaded files: {{if .User.Subscription.DisableAdsOnFiles}}No{{else}}Yes{{end}}</li>
|
||||
{{if gt .User.Subscription.FileExpiryDays 0}}
|
||||
<li>Files expire after {{.User.Subscription.FileExpiryDays}} days</li>
|
||||
{{else}}
|
||||
<li>Files never expire</li>
|
||||
{{end}}
|
||||
<li>Direct linking bandwidth: {{formatData .User.Subscription.DirectLinkingBandwidth}}</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
</li>
|
||||
</ul>
|
||||
<a href="/user/settings" class="button button_highlight">Change account settings</a>
|
||||
<h2>Navigation</h2>
|
||||
<a href="/" class="button">Upload files</a>
|
||||
<a href="/user/filemanager#files" class="button">My files</a>
|
||||
<a href="/user/filemanager#lists" class="button">My lists</a>
|
||||
|
||||
<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 'Live'
|
||||
or 'Day' the statistics will be updated periodically. No
|
||||
need to refresh the page.
|
||||
</p>
|
||||
</div>
|
||||
<div class="highlight_dark">
|
||||
<button onclick="updateGraphs(360, 1, true);">Live</button>
|
||||
<button onclick="updateGraphs(1440, 10, true);">Day</button>
|
||||
<button onclick="updateGraphs(10080, 60, false);">Week</button>
|
||||
<button onclick="updateGraphs(20160, 60, false);">Two Weeks</button>
|
||||
<button onclick="updateGraphs(43200, 1440, false);">Month</button>
|
||||
<button onclick="updateGraphs(131400, 1440, false);">Quarter</button>
|
||||
<button onclick="updateGraphs(262800, 1440, false);">Half-year</button>
|
||||
<button onclick="updateGraphs(525600, 1440, false);">Year</button>
|
||||
</div>
|
||||
<h3>Views</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 120px;">
|
||||
<canvas id="views_chart"></canvas>
|
||||
</div>
|
||||
<h3>Downloads</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 120px;">
|
||||
<canvas id="downloads_chart"></canvas>
|
||||
</div>
|
||||
<h3>Bandwidth</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 120px;">
|
||||
<canvas id="bandwidth_chart"></canvas>
|
||||
</div>
|
||||
<div class="highlight_dark">
|
||||
Total usage from <span id="time_start"></span> to <span id="time_end"></span><br/>
|
||||
<span id="total_views"></span> views,
|
||||
<span id="total_downloads"></span> downloads and
|
||||
<span id="total_bandwidth"></span> bandwidth
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "page_bottom" .}}
|
||||
|
||||
{{template "analytics"}}
|
||||
|
||||
<script src="/res/script/Chart.min.js"></script>
|
||||
<script>
|
||||
var apiEndpoint = '{{.APIEndpoint}}';
|
||||
var highlightColor = '#{{.Style.HighlightColor.RGB}}';
|
||||
{{template `util.js`}}
|
||||
{{template `drawGraph.js`}}
|
||||
{{template `user_home.js`}}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
|
@@ -24,9 +24,13 @@
|
||||
<button onclick="loadGraph(262800, 1440, false);">Half-year</button>
|
||||
<button onclick="loadGraph(525600, 1440, false);">Year</button>
|
||||
</div>
|
||||
<div id="chart_container" class="chart-container" style="position: relative; width: 100%; height: 300px;">
|
||||
<div id="chart_container" class="chart-container" style="position: relative; width: 100%; height: 160px; padding-top: 6px;">
|
||||
<canvas id="bandwidth_chart"></canvas>
|
||||
</div>
|
||||
<hr>
|
||||
<div id="chart_container" class="chart-container" style="position: relative; width: 100%; height: 160px;">
|
||||
<canvas id="views_chart"></canvas>
|
||||
</div>
|
||||
<div class="highlight_dark">
|
||||
Total usage from <span id="time_start"></span> to <span id="time_end"></span><br/>
|
||||
<span id="total_bandwidth"></span> bandwidth and <span id="total_views"></span> views
|
||||
@@ -63,7 +67,9 @@
|
||||
<script src="/res/script/Chart.min.js"></script>
|
||||
<script>
|
||||
var apiEndpoint = '{{.APIEndpoint}}';
|
||||
var highlightColor = '#{{.Style.HighlightColor.RGB}}';
|
||||
{{template `util.js`}}
|
||||
{{template `drawGraph.js`}}
|
||||
{{template `admin.js`}}
|
||||
</script>
|
||||
{{else}}
|
||||
|
@@ -156,12 +156,16 @@
|
||||
<table class="info_file_details" style="min-width: 100%;"></table>
|
||||
|
||||
<div class="info_about">
|
||||
<h3>Downloads and views</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 250px;">
|
||||
<canvas id="bandwidth_chart"></canvas>
|
||||
<h3>Downloads</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 120px;">
|
||||
<canvas id="downloads_chart"></canvas>
|
||||
</div>
|
||||
<h3>Views</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 120px;">
|
||||
<canvas id="views_chart"></canvas>
|
||||
</div>
|
||||
<p style="text-align: center">
|
||||
Chart rendered by the amazing <a href="https://www.chartjs.org/" target="_blank">Chart.js</a>.
|
||||
Charts rendered by the amazing <a href="https://www.chartjs.org/" target="_blank">Chart.js</a>.
|
||||
</p>
|
||||
|
||||
<h3>About</h3>
|
||||
@@ -210,8 +214,9 @@
|
||||
'use strict';
|
||||
let apiEndpoint = '{{.APIEndpoint}}';
|
||||
let captchaKey = '{{.Other.CaptchaKey}}';
|
||||
|
||||
let highlightColor = '#{{.Style.HighlightColor.RGB}}';
|
||||
{{template `util.js`}}
|
||||
{{template `drawGraph.js`}}
|
||||
{{template `Modal.js`}}
|
||||
{{template `Toolbar.js`}}
|
||||
{{template `EditWindow.js`}}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
.header_image{
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 20px auto 50px auto;
|
||||
margin: 0 auto 50px auto;
|
||||
}
|
||||
|
||||
.instruction_highlight {
|
||||
@@ -75,6 +75,7 @@
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.features > div > .feature {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 6px;
|
||||
border-bottom: 1px solid var(--layer_3_color_border);
|
||||
@@ -86,6 +87,8 @@
|
||||
margin: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
{{template `modal.css`}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -195,6 +198,11 @@
|
||||
<a href="/about">about</a> page.
|
||||
</p>
|
||||
<h2>Features</h2>
|
||||
<p>
|
||||
By purchasing a subscription you support pixeldrain on its
|
||||
mission to make content sharing easier, safer and faster for
|
||||
everyone.
|
||||
</p>
|
||||
</div>
|
||||
<div class="features">
|
||||
<div>
|
||||
@@ -203,7 +211,9 @@
|
||||
<img src="/res/img/benefit_0.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No account required</div>
|
||||
<div class="feature">Files expire 30 days after last view</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files expire 30 days after last view
|
||||
</a>
|
||||
<div class="feature">Max file size 10 GB</div>
|
||||
<div class="feature">Access your files anywhere with a pixeldrain account</div>
|
||||
<div class="feature">Group multiple files together in a single link with lists</div>
|
||||
@@ -213,11 +223,16 @@
|
||||
<div class="price">€2 per month + tax</div>
|
||||
<img src="/res/img/benefit_1.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No ads when viewing and downloading files</div>
|
||||
<div class="feature">Support pixeldrain's development</div>
|
||||
<div class="feature">No ads when viewing files</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files expire 2 months after last view
|
||||
</a>
|
||||
<!--<a href="#" onclick="return explainDirectLinking()" class="feature">
|
||||
3 TB of direct linking bandwidth
|
||||
</a>-->
|
||||
|
||||
<div style="text-align: center; padding: 8px;">
|
||||
{{if eq .User.Subscription "patreon_1"}}
|
||||
{{if eq .User.Subscription.ID "patreon_1"}}
|
||||
<strong>You have this plan. Thank you for supporting pixeldrain!</strong>
|
||||
{{else}}
|
||||
<a href="/subscribe?plan=t1" class="button button_highlight" style="width: 90%;">
|
||||
@@ -226,17 +241,46 @@
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Resolve</h3>
|
||||
<div class="price">€4 per month + tax</div>
|
||||
<img src="/res/img/benefit_5.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No ads when viewing files</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files expire 3 months after last view
|
||||
</a>
|
||||
<!--<a href="#" onclick="return explainDirectLinking()" class="feature">
|
||||
6 TB of direct linking bandwidth
|
||||
</a>-->
|
||||
<div class="feature">No ads on files you uploaded</div>
|
||||
|
||||
<div style="text-align: center; padding: 8px;">
|
||||
{{if eq .User.Subscription.ID "patreon_5"}}
|
||||
<strong>You have this plan. Thank you for supporting pixeldrain!</strong>
|
||||
{{else}}
|
||||
<a href="/subscribe?plan=t5" class="button button_highlight" style="width: 90%;">
|
||||
Get Started
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Persistence</h3>
|
||||
<div class="price">€8 per month + tax</div>
|
||||
<img src="/res/img/benefit_2.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No ads when viewing and downloading files</div>
|
||||
<div class="feature">No ads when viewing files</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files expire 4 months after last view
|
||||
</a>
|
||||
<!--<a href="#" onclick="return explainDirectLinking()" class="feature">
|
||||
12 TB of direct linking bandwidth
|
||||
</a>-->
|
||||
<div class="feature">No ads on files you uploaded</div>
|
||||
<div class="feature">Files expire two months after last view</div>
|
||||
|
||||
<div style="text-align: center; padding: 8px;">
|
||||
{{if eq .User.Subscription "patreon_2"}}
|
||||
{{if eq .User.Subscription.ID "patreon_2"}}
|
||||
<strong>You have this plan. Thank you for supporting pixeldrain!</strong>
|
||||
{{else}}
|
||||
<a href="/subscribe?plan=t2" class="button button_highlight" style="width: 90%;">
|
||||
@@ -250,12 +294,17 @@
|
||||
<div class="price">€16 per month + tax</div>
|
||||
<img src="/res/img/benefit_3.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No ads when viewing and downloading files</div>
|
||||
<div class="feature">No ads when viewing files</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files expire 8 months after last view
|
||||
</a>
|
||||
<!--<a href="#" onclick="return explainDirectLinking()" class="feature">
|
||||
24 TB of direct linking bandwidth
|
||||
</a>-->
|
||||
<div class="feature">No ads on files you uploaded</div>
|
||||
<div class="feature">Files expire six months after last view</div>
|
||||
|
||||
<div style="text-align: center; padding: 8px;">
|
||||
{{if eq .User.Subscription "patreon_3"}}
|
||||
{{if eq .User.Subscription.ID "patreon_3"}}
|
||||
<strong>You have this plan. Thank you for supporting pixeldrain!</strong>
|
||||
{{else}}
|
||||
<a href="/subscribe?plan=t3" class="button button_highlight" style="width: 90%;">
|
||||
@@ -269,12 +318,17 @@
|
||||
<div class="price">€32 per month + tax</div>
|
||||
<img src="/res/img/benefit_4.png" style="width: 100%;">
|
||||
|
||||
<div class="feature">No ads when viewing and downloading files</div>
|
||||
<div class="feature">No ads when viewing files</div>
|
||||
<a href="#" onclick="return explainFileExpiry()" class="feature">
|
||||
Files you upload never expire
|
||||
</a>
|
||||
<!--<a href="#" onclick="return explainDirectLinking()" class="feature">
|
||||
48 TB of direct linking bandwidth
|
||||
</a>-->
|
||||
<div class="feature">No ads on files you uploaded</div>
|
||||
<div class="feature">Files you upload never expire</div>
|
||||
|
||||
<div style="text-align: center; padding: 8px;">
|
||||
{{if eq .User.Subscription "patreon_4"}}
|
||||
{{if eq .User.Subscription.ID "patreon_4"}}
|
||||
<strong>You have this plan. Thank you for supporting pixeldrain!</strong>
|
||||
{{else}}
|
||||
<a href="/subscribe?plan=t4" class="button button_highlight" style="width: 90%;">
|
||||
@@ -286,14 +340,77 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="tpl_file_expiry">
|
||||
<p>
|
||||
Files on pixeldrain have to expire eventually. If we didn't do
|
||||
this the website would keep growing forever and we would run out
|
||||
of money pretty quickly.
|
||||
</p>
|
||||
<p>
|
||||
Unlike most other sharing sites pixeldrain uses a postponing
|
||||
system for expiring files. When a file is freshly uploaded it
|
||||
gets 30 days by default (this can be extended by supporting the
|
||||
site on patreon). After these 30 days we will check when the
|
||||
file was last viewed. Files which are regularly viewed could
|
||||
still bring new users to the platform, it would be rude to show
|
||||
these people a 404 Not Found page. So if the file was viewed in
|
||||
the last 30 days we will simply postpone the next check a month.
|
||||
If the file was not viewed however it will immediately be
|
||||
removed.
|
||||
</p>
|
||||
<p>
|
||||
This way we can minimize dead links, and you won't have to tell
|
||||
your friends to 'hurry and download this before it expires'.
|
||||
</p>
|
||||
</template>
|
||||
<template id="tpl_direct_linking">
|
||||
<p>
|
||||
Normally when viewing a file on pixeldrain it has to go through
|
||||
the file viewer. Files which are directly downloaded without
|
||||
visiting the file viewer are blocked after a while.
|
||||
</p>
|
||||
<p>
|
||||
Direct linking allows you to share files without going through
|
||||
the file viewer. You can use this to embed videos / images in
|
||||
your own webpages. Files which are direct linked won't count any
|
||||
views but we will keep track of the downloads and used
|
||||
bandwidth.
|
||||
</p>
|
||||
<p>
|
||||
When you use up your direct linking bandwidth your direct links
|
||||
will stop working for the rest of the month. You can always
|
||||
upgrade to get more bandwidth. The amount of bandwidth used in
|
||||
the month can be seen on your <a href="/user">user page</a> when
|
||||
logged in.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
{{template "page_bottom" .}}
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
let apiEndpoint = '{{.APIEndpoint}}';
|
||||
{{template "util.js"}}
|
||||
{{template "Modal.js"}}
|
||||
{{template "UploadManager.js"}}
|
||||
{{template "homepage.js"}}
|
||||
|
||||
function explainFileExpiry() {
|
||||
let m = new Modal(
|
||||
document.body, null, "File Expiry Postponing", "600px", "auto"
|
||||
)
|
||||
m.cloneTemplate("tpl_file_expiry")
|
||||
m.open()
|
||||
return false
|
||||
}
|
||||
function explainDirectLinking() {
|
||||
let m = new Modal(
|
||||
document.body, null, "Direct Linking Bandwidth", "600px", "auto"
|
||||
)
|
||||
m.cloneTemplate("tpl_direct_linking")
|
||||
m.open()
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
|
||||
{{template "analytics"}}
|
||||
|
@@ -93,7 +93,7 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
|
||||
showAds := true
|
||||
if (templateData.Authenticated && templateData.User.DisableAdDisplay) || finfo[0].ShowAds == false {
|
||||
if (templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay) || finfo[0].ShowAds == false {
|
||||
showAds = false
|
||||
}
|
||||
|
||||
@@ -188,7 +188,8 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
|
||||
showAds := true
|
||||
if (templateData.Authenticated && templateData.User.DisableAdDisplay) || list.Files[0].ShowAds == false {
|
||||
if (templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay) ||
|
||||
list.Files[0].ShowAds == false {
|
||||
showAds = false
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user