forked from psi-4ward/psitransfer
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
300 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
<template lang="pug"> | ||
.download-app | ||
.alert.alert-danger(v-show="error") | ||
strong | ||
i.fa.fa-exclamation-triangle | ||
| {{ error }} | ||
form.well(v-if='!loggedIn', @submit.stop.prevent="login") | ||
h3 Password | ||
.form-group | ||
input.form-control(type='password', v-model='password', autofocus="") | ||
p.text-danger(v-show='passwordWrong') | ||
strong Access denied! | ||
| | ||
button.btn.btn-primary(type="submit") | ||
i.fa.fa-sign-in | ||
| login | ||
|
||
div(v-if="loggedIn") | ||
table.table.table-hover | ||
thead | ||
tr | ||
th SID | ||
th Created | ||
th Downloaded | ||
th Expire | ||
th Size | ||
template(v-for="(bucket, sid) in db") | ||
tbody(:class="{expanded: expand===sid}") | ||
tr.bucket(@click="expandView(sid)") | ||
td | ||
| {{ sid }} | ||
i.fa.fa-key.pull-right(v-if="sum[sid].password", title="Password protected") | ||
td {{ sum[sid].created | date }} | ||
td | ||
template(v-if="sum[sid].lastDownload") {{ sum[sid].lastDownload | date}} | ||
template(v-else="") - | ||
td | ||
template(v-if="typeof sum[sid].firstExpire === 'number'") {{ sum[sid].firstExpire | date }} | ||
template(v-else) {{ sum[sid].firstExpire }} | ||
td.text-right {{ humanFileSize(sum[sid].size) }} | ||
tbody.expanded(v-if="expand === sid") | ||
template(v-for="file in bucket") | ||
tr.file | ||
td {{ file.metadata.name }} | ||
td {{+file.metadata.createdAt | date}} | ||
td | ||
template(v-if="file.metadata.lastDownload") {{ +file.metadata.lastDownload | date}} | ||
template(v-else="") - | ||
td | ||
template(v-if="typeof file.expireDate === 'number'") {{ file.expireDate | date }} | ||
template(v-else) {{ file.expireDate }} | ||
td.text-right {{ humanFileSize(file.size) }} | ||
tfoot | ||
tr | ||
td(colspan="3") | ||
td.text-right(colspan="2") Sum: {{ humanFileSize(sizeSum) }} | ||
|
||
</template> | ||
|
||
|
||
<script> | ||
"use strict"; | ||
export default { | ||
name: 'app', | ||
data () { | ||
return { | ||
db: {}, | ||
sum: {}, | ||
loggedIn: false, | ||
password: '', | ||
error: '', | ||
passwordWrong: false, | ||
expand: false, | ||
sizeSum: 0 | ||
} | ||
}, | ||
methods: { | ||
expandView(sid) { | ||
if(this.expand === sid) return this.expand = false; | ||
this.expand = sid; | ||
}, | ||
login() { | ||
const xhr = new XMLHttpRequest(); | ||
xhr.open('GET', '/admin/data.json'); | ||
xhr.setRequestHeader("x-passwd", this.password); | ||
xhr.onload = () => { | ||
if(xhr.status === 200) { | ||
try { | ||
this.db = JSON.parse(xhr.responseText); | ||
this.expandDb(); | ||
this.loggedIn = true; | ||
} | ||
catch(e) { | ||
this.error = e.toString(); | ||
} | ||
} else { | ||
if(xhr.status === 403) this.passwordWrong = true; | ||
else this.error = `${xhr.status} ${xhr.statusText}: ${xhr.responseText}`; | ||
} | ||
}; | ||
xhr.send(); | ||
}, | ||
expandDb() { | ||
Object.keys(this.db).forEach(sid => { | ||
const sum = { | ||
firstExpire: Number.MAX_SAFE_INTEGER, | ||
lastDownload: 0, | ||
created: Number.MAX_SAFE_INTEGER, | ||
password: false, | ||
size: 0 | ||
}; | ||
this.db[sid].forEach(file => { | ||
sum.size += file.size; | ||
if(file.metadata._password) { | ||
sum.password = true; | ||
} | ||
if(+file.metadata.createdAt < sum.created) { | ||
sum.created = +file.metadata.createdAt; | ||
} | ||
if(file.metadata.lastDownload && +file.metadata.lastDownload > sum.lastDownload) { | ||
sum.lastDownload = +file.metadata.lastDownload; | ||
} | ||
if(file.metadata.retention === 'one-time') { | ||
sum.firstExpire = 'one-time'; | ||
file.expireDate = file.metadata.retention; | ||
} | ||
else { | ||
file.expireDate = +file.metadata.createdAt + (+file.metadata.retention * 1000); | ||
if(sum.firstExpire > file.expireDate) sum.firstExpire = file.expireDate; | ||
} | ||
}); | ||
this.sizeSum += sum.size; | ||
this.$set(this.sum, sid, sum); | ||
}); | ||
}, | ||
humanFileSize(fileSizeInBytes) { | ||
let i = -1; | ||
const byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB']; | ||
do { | ||
fileSizeInBytes = fileSizeInBytes / 1024; | ||
i++; | ||
} while(fileSizeInBytes > 1024); | ||
return Math.max(fileSizeInBytes, 0.00).toFixed(2) + byteUnits[i]; | ||
}, | ||
}, | ||
} | ||
</script> | ||
|
||
<style> | ||
.bucket { | ||
cursor: pointer; | ||
} | ||
.expanded { | ||
background: #fafafa; | ||
} | ||
.expanded .bucket td { | ||
font-weight: bold; | ||
} | ||
tfoot { | ||
font-weight: bold; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import 'babel-polyfill'; | ||
import Vue from 'vue'; | ||
import Admin from './Admin.vue'; | ||
|
||
function parseDate(str) { | ||
if(!str) return str; | ||
return new Date(str); | ||
} | ||
|
||
function formatDate(dt) { | ||
if(dt === null) return ""; | ||
const f = function(d) { | ||
return d < 10 ? '0' + d : d; | ||
}; | ||
return dt.getFullYear() + '-' + f(dt.getMonth() + 1) + '-' + f(dt.getDate()) + ' ' + f(dt.getHours()) + ':' + f(dt.getMinutes()); | ||
} | ||
function isDate(d) { | ||
return Object.prototype.toString.call(d) === '[object Date]'; | ||
} | ||
|
||
Vue.filter('date', function(val, format) { | ||
if(!isDate(val)) { | ||
val = parseDate(val); | ||
} | ||
return isDate(val) ? formatDate(val, format) : val; | ||
}); | ||
|
||
|
||
new Vue({ | ||
el: '#admin', | ||
render: h => h(Admin) | ||
}); | ||
|
||
window.PSITRANSFER_VERSION = PSITRANSFER_VERSION; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>PsiTransfer Admin</title> | ||
<link href="/assets/favicon.ico" rel="icon" type="image/x-icon"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<meta name="robots" content="noindex,nofollow"> | ||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> | ||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"> | ||
<link href="/assets/styles.css" rel="stylesheet"> | ||
</head> | ||
|
||
<body> | ||
|
||
<div class="container"> | ||
<h1> | ||
<i class="fa fa-fw fa-gears" style="color: #0275D8"></i> | ||
PsiTransfer Admin | ||
</h1> | ||
<hr> | ||
<div id="admin"></div> | ||
</div> | ||
|
||
<footer class="footer"> | ||
<div class="container text-right"> | ||
<span class="text-muted"><a href="https://github.com/psi-4ward/psitransfer" target="_blank">Powered by PsiTransfer</a></span> | ||
</div> | ||
</footer> | ||
|
||
<script src="/app/common.js"></script> | ||
<script src="/app/admin.js"></script> | ||
|
||
</body> | ||
|
||
</html> |