Making giant leaps with typescript

This commit is contained in:
2018-01-17 01:16:06 +01:00
parent b45ceb85d0
commit c26d35282c
14 changed files with 187 additions and 610 deletions

4
.gitignore vendored
View File

@@ -1,5 +1,5 @@
.vscode
main
pdwebconfig.toml
res/script/pixellib.js
res/script/home.js
res/static/res/script/pixellib.js
res/static/res/script/home.js

View File

@@ -12,6 +12,4 @@ deps:
backgroundrun:
go run main.go
backgroundts:
tsc --watch res/static/res/typescript/lib/*.ts --outFile res/static/res/script/pixellib.js \
res/static/res/typescript/home/*.ts \
res/static/res/typescript/lib/*.ts --outFile res/static/res/script/home.js
tsc --watch --project res/static/res/typescript/home

View File

@@ -0,0 +1,4 @@
All files in this directory are compiled typescript files. You can find the
sources in /res/typescript.
Have fun typing!

View File

@@ -1,159 +0,0 @@
"use strict";
var uploader = null;
/*
* Form upload handlers
*/
$("#selectFileButton").click(function (event) {
$("#fileInputField").click();
});
function fileInputChange(dom, files) {
if (uploader === null) {
uploader = new UploadManager();
}
uploader.uploadFileList(files);
// This resets the file input field
// http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
$('#fileName').html("");
$("#fileUploadButton").css("visibility", "hidden");
$("#fileInputField").wrap("<form>").closest("form").get(0).reset();
$("#fileInputField").unwrap();
}
/*
* Drag 'n Drop upload handlers
*/
$(document).on('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on('dragenter', function (e) {
e.preventDefault();
e.stopPropagation();
});
document.addEventListener('drop', function (e) {
if (e.dataTransfer && e.dataTransfer.files.length > 0) {
e.preventDefault();
e.stopPropagation();
if (uploader === null) {
uploader = new UploadManager();
}
uploader.uploadFileList(e.dataTransfer.files);
}
});
/*
* Upload functions
*/
// function pushUploads(array){
// var len = array.length;
// for(i = 0; i < len; i++){
// uploadQueue.push(array[i]);
// }
// startFileUpload();
// }
var Cookie;
(function (Cookie) {
function read(name) {
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie);
return result ? result[1] : null;
}
Cookie.read = read;
function write(name, value, days) {
if (!days) {
days = 365 * 20;
}
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + value + expires + "; path=/";
}
Cookie.write = write;
function remove(name) {
write(name, "", -1);
}
Cookie.remove = remove;
})(Cookie || (Cookie = {}));
var UploadManager = /** @class */ (function () {
function UploadManager() {
this.uploadQueue = new Array();
this.uploadThreads = new Array();
}
UploadManager.prototype.uploadFile = function (file) {
console.debug("Adding upload to queue");
this.uploadQueue.push(file);
if (this.uploadThreads.length < 4) {
console.debug("Starting upload thread");
setTimeout(new UploadWorker(this).start(), 0); // Start a new upload thread
}
};
UploadManager.prototype.uploadFileList = function (files) {
for (var i = 0; i < files.length; i++) {
this.uploadFile(files.item(i));
}
};
UploadManager.prototype.grabFile = function () {
if (this.uploadQueue.length > 0) {
return this.uploadQueue.pop();
}
else {
return undefined;
}
};
return UploadManager;
}());
var UploadWorker = /** @class */ (function () {
function UploadWorker(manager) {
this.manager = manager;
}
UploadWorker.prototype.start = function () {
var file = this.manager.grabFile();
if (file === null) {
console.debug("No file");
return; // Stop the thread
}
this.tries = 0;
this.upload(file);
};
UploadWorker.prototype.upload = function (file) {
console.debug("Starting upload of " + file.name);
var formData = new FormData();
formData.append('file', file);
formData.append("name", file.name);
$.ajax({
url: "/api/file",
data: formData,
cache: false,
crossDomain: false,
contentType: false,
processData: false,
type: 'POST',
success: function (data) {
console.log("Done: " + data.id);
this.setHistoryCookie(data.id);
},
error: function (xhr, status, error) {
console.log(status);
console.log(error);
if (this.tries === 3) {
alert("Upload failed: " + status);
return; // Upload failed
}
// Try again
this.tries++;
this.upload(file);
}
});
};
UploadWorker.prototype.setHistoryCookie = function (id) {
var uc = Cookie.read("pduploads");
// First upload in this browser
if (uc === null) {
Cookie.write("pduploads", id + ".", undefined);
return;
}
if (uc.length > 2000) {
// Cookie is becoming too long, drop the oldest two files
uc = uc.substring(uc.indexOf(".") + 1).substring(uc.indexOf(".") + 1);
}
Cookie.write("pduploads", uc + id + ".", undefined);
};
return UploadWorker;
}());

View File

@@ -1,194 +0,0 @@
/*
* Made by Fornax for PixelDrain
* Use if you want
*
* I'll clean up this baby some time in the future too
*/
/*
* Form upload handlers
*/
/* global API_URL */
$("#selectFileButton").click(function(event){
$("#fileInputField").click();
});
$("#fileInputField").change(function(){
pushUploads($("#fileInputField")[0].files);
// This resets the file input field
// http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
$('#fileName').html("");
$("#fileUploadButton").css("visibility", "hidden");
$("#fileInputField").wrap("<form>").closest("form").get(0).reset();
$("#fileInputField").unwrap();
});
/*
* Drag 'n Drop upload handlers
*/
$(document).on('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on('dragenter', function (e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on('drop', function (e) {
if (e.originalEvent.dataTransfer) {
var len = e.originalEvent.dataTransfer.files.length;
if (len) {
e.preventDefault();
e.stopPropagation();
pushUploads(e.originalEvent.dataTransfer.files);
}
}
});
/*
* Upload functions
*/
function pushUploads(array){
var len = array.length;
for(i = 0; i < len; i++){
uploadQueue.push(array[i]);
}
startFileUpload();
}
var isFirstUpload = true;
var uploadQueue = new Array();
var isUploading = false;
function startFileUpload() {
if(isUploading){
return;
}
var file = uploadQueue.shift();
if(file === null){
return;
}
if(isFirstUpload){
isFirstUpload = false;
$("#uploads-completed").animate(
{"height": "340px"},
{"duration": 2000, queue: false}
);
$("#progress-bar").animate(
{"height": "20px"},
{"duration": 1000, queue: false}
);
}
isUploading = true;
formData = new FormData();
formData.append('file', file);
formData.append("name", file.name);
jQuery.ajax({
url: API_URL + "/file",
data: formData,
cache: false,
crossDomain: false,
contentType: false,
processData: false,
type: 'POST',
xhr: function () {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
percentComplete = (evt.loaded / evt.total) * 100;
$("#upload-progress").animate(
{"width": percentComplete + "%"},
{"duration": 200, queue: false}
);
$(".progress-text").html("Uploading... "
+ evt.loaded + " / " + evt.total + " Bytes "
+ "(" + uploadQueue.length + " files in queue)"
);
}
}, false);
return xhr;
},
success: function (data) {
isUploading = false;
if(uploadQueue.length > 0){
startFileUpload();
}else{
$(".progress-text").html("Done! File link is available below");
}
fileUploadComplete(data);
},
error: function (xhr, status, error){
console.log(status);
console.log(error);
}
});
}
function fileUploadComplete(json) {
if (json.success) {
setHistoryCookie(json.id)
resultString = "<div class=\"uploadItem\">Upload successful!<br/>"
+ "Your file URL:<br/>"
+ "<a href=\"/u/"+json.id+"\" target=\"_blank\">"+window.location.hostname+"/u/"+json.id+"</a>"
+ "</div>";
$('#uploads-completed').prepend(
$(resultString).hide().fadeIn('slow')
);
addToList(json.id, "");
} else {
resultString = "<div class=\"uploadItem\">Something went wrong! "
+ "The server responded with this:<br/>\"" + json.message
+ "\"</div>";
$('#uploads-completed').prepend(
$(resultString).hide().fadeIn('slow')
);
$(".progressText").html(json.message);
}
}
function setHistoryCookie(id){
uc = Cookie.get("pduploads");
// First upload in this browser
if (uc === null) {
Cookie.set("pduploads", id + ".");
return;
}
if (uc.length > 2000){
// Cookie is becoming too long, drop the oldest two files
uc = uc.substring(
uc.indexOf(".") + 1
).substring(
uc.indexOf(".") + 1
);
}
Cookie.set("pduploads", uc + id + ".");
}
$("#btnClearHistory").click(function(){
$('#uploads-container').html("");
listItems = new Array();
});

View File

@@ -1,23 +1,22 @@
var listItems = new Array();
$("#btnCreateList").click(function (evt) {
$("#btn_create_list").click(function (evt) {
createList();
});
function addToList(id, desc){
var listEntry = {id: id, desc: desc};
listItems.push(listEntry);
function createList(){
let listfiles = new Array()
for (var i = 0; i < finishedUploads.length; i++) {
if (finishedUploads[i] === undefined) {
continue;
}
listfiles.push(finishedUploads[i]);
}
function createList(){
var url = "/api/list";
var postData = {};
var title = prompt(
"You are creating a list containing " + listItems.length + " files.\n"
"You are creating a list containing " + listfiles.length + " files.\n"
+ "What do you want to call it?", "My New Album"
);
@@ -31,12 +30,10 @@ function createList(){
"files": new Array()
};
var arrayLength = listItems.length;
for (var i = 0; i < arrayLength; i++) {
postData.files[i] = {
"id": listItems[i]["id"],
"description": listItems[i]["desc"]
};
for (var i = 0; i < listfiles.length; i++) {
postData.files.push({
"id": listfiles[i]
});
}
$.ajax({
@@ -57,7 +54,7 @@ function listCreated(response){
+ "<a href=\"/l/" + response.id + "\" target=\"_blank\" style=\"font-weight: bold;\">"+window.location.hostname+"/l/" + response.id + "</a>"
+ "</div>";
$('#uploads-completed').prepend(
$('#uploads_completed').prepend(
$(resultString).hide().fadeIn('slow')
);
}else{

View File

@@ -1,109 +0,0 @@
"use strict";
var Cookie;
(function (Cookie) {
function read(name) {
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie);
return result ? result[1] : null;
}
Cookie.read = read;
function write(name, value, days) {
if (!days) {
days = 365 * 20;
}
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + value + expires + "; path=/";
}
Cookie.write = write;
function remove(name) {
write(name, "", -1);
}
Cookie.remove = remove;
})(Cookie || (Cookie = {}));
var UploadManager = /** @class */ (function () {
function UploadManager() {
this.uploadQueue = new Array();
this.uploadThreads = new Array();
}
UploadManager.prototype.uploadFile = function (file) {
console.debug("Adding upload to queue");
this.uploadQueue.push(file);
if (this.uploadThreads.length < 4) {
console.debug("Starting upload thread");
setTimeout(new UploadWorker(this).start(), 0); // Start a new upload thread
}
};
UploadManager.prototype.uploadFileList = function (files) {
for (var i = 0; i < files.length; i++) {
this.uploadFile(files.item(i));
}
};
UploadManager.prototype.grabFile = function () {
if (this.uploadQueue.length > 0) {
return this.uploadQueue.pop();
}
else {
return undefined;
}
};
return UploadManager;
}());
var UploadWorker = /** @class */ (function () {
function UploadWorker(manager) {
this.manager = manager;
}
UploadWorker.prototype.start = function () {
var file = this.manager.grabFile();
if (file === null) {
console.debug("No file");
return; // Stop the thread
}
this.tries = 0;
this.upload(file);
};
UploadWorker.prototype.upload = function (file) {
console.debug("Starting upload of " + file.name);
var formData = new FormData();
formData.append('file', file);
formData.append("name", file.name);
$.ajax({
url: "/api/file",
data: formData,
cache: false,
crossDomain: false,
contentType: false,
processData: false,
type: 'POST',
success: function (data) {
console.log("Done: " + data.id);
this.setHistoryCookie(data.id);
},
error: function (xhr, status, error) {
console.log(status);
console.log(error);
if (this.tries === 3) {
alert("Upload failed: " + status);
return; // Upload failed
}
// Try again
this.tries++;
this.upload(file);
}
});
};
UploadWorker.prototype.setHistoryCookie = function (id) {
var uc = Cookie.read("pduploads");
// First upload in this browser
if (uc === null) {
Cookie.write("pduploads", id + ".", undefined);
return;
}
if (uc.length > 2000) {
// Cookie is becoming too long, drop the oldest two files
uc = uc.substring(uc.indexOf(".") + 1).substring(uc.indexOf(".") + 1);
}
Cookie.write("pduploads", uc + id + ".", undefined);
};
return UploadWorker;
}());

View File

@@ -1,36 +0,0 @@
/*
Created on : Dec 1, 2015, 9:54:01 PM
Author : Fornax
*/
.progress-bar{
position: relative;
margin: 3px;
height: 20px;
background-color: #555;
border: #999 groove 2px;
overflow: hidden;
color: #eeeeee;
z-index: 100;
text-align: left;
white-space: nowrap;
}
.progress-bar div{
position: absolute;
top: 0;
width: 0%;
left: 0;
height: 100%;
background-color: #9FCF6C;
overflow: hidden;
color: #000;
white-space: nowrap;
}
.progress-bar span,
.progress-bar div span {
overflow: hidden;
width: 100%;
white-space: nowrap;
}

View File

@@ -6,9 +6,10 @@
display: inline-block;
}
.uploadItem{
.uploadItem, .uploadItem:hover{
position: relative;
width: 238px;
box-sizing: border-box;
width: 322px;
max-width: 90%;
height: 60px;
float: left;
@@ -17,6 +18,7 @@
border: 1px #555 solid;
overflow: hidden;
background-color: #111;
color: var(--text_color);
word-break: break-all;
text-align: left;
line-height: 120%;

View File

@@ -35,13 +35,13 @@ html{
border-bottom: #606060 solid 1px;
}
#header-image{
#header_image{
width: 100%;
max-width: 1000px;
margin-top: 15px;
}
#uploads-completed{
#uploads_queue{
position: relative;
width: 100%;
height: 0;
@@ -178,7 +178,7 @@ a:hover{
line-height: 8px;
}
.progress-bar{
.progress_bar{
position: relative;
width: 100%;
height: 0;
@@ -188,7 +188,7 @@ a:hover{
text-align: left;
white-space: nowrap;
}
.progressbar-inner{
.progressbar_inner{
position: absolute;
top: 0;
width: 0%;
@@ -199,7 +199,7 @@ a:hover{
color: #000;
white-space: nowrap;
}
.progress-text{
.progress_text{
overflow: hidden;
width: 100%;
white-space: nowrap;

View File

@@ -1,62 +1,103 @@
var uploader: UploadManager|null = null;
var finishedUploads: Array<string> = new Array()
var totalUploads: number = 0
class UploadProgressBar implements FileUpload {
private uploadDiv: HTMLAnchorElement
private uploadDivJQ: JQuery<HTMLElement>
private queueNum: number
constructor(file: File){
this.file = file
this.queueNum = totalUploads
totalUploads++
this.uploadDiv = document.createElement("a");
this.uploadDiv.setAttribute("class", "uploadItem");
this.uploadDiv.innerText = "Queued\n" + this.file.name
this.uploadDivJQ = $(this.uploadDiv)
$("#uploads_queue").append(
this.uploadDivJQ.hide().fadeIn('slow')
)
}
// Interface stuff
public file: File;
public onProgress(progress: number){
this.uploadDiv.innerText = "Uploading... " + Math.round(progress*1000)/10 + "%\n" + this.file.name
this.uploadDiv.setAttribute(
'style',
'background: linear-gradient('
+'to right, '
+'#111 0%, '
+'var(--highlight_color) '+ ((progress*100)) +'%, '
+'#111 '+ ((progress*100)+1) +'%)'
)
}
public onFinished(id: string){
finishedUploads[this.queueNum] = id
this.uploadDiv.setAttribute('style', 'background: #111')
this.uploadDiv.setAttribute('href', '/u/'+id)
this.uploadDiv.setAttribute("target", "_blank");
this.uploadDivJQ.html(
'<img src="/api/file/'+id+'/thumbnail" alt="'+this.file.name+'" class="uploadItemImage"/>'
+ this.file.name+'<br/>'
+ '<span style="color: var(--highlight_color);">'+window.location.hostname+'/u/'+id+'</span>'
)
}
}
function handleUploads(files: FileList) {
if (uploader === null){
uploader = new UploadManager()
$("#uploads_queue").animate(
{"height": "340px"},
{"duration": 2000, queue: false}
);
}
for (var i = 0; i < files.length; i++) {
uploader.uploadFile(new UploadProgressBar(files.item(i)))
}
}
/*
* Form upload handlers
*/
$("#selectFileButton").click(function(event){
$("#fileInputField").click();
});
// Relay click event to hidden file field
$("#select_file_button").click(function(){$("#file_input_field").click()})
function fileInputChange(dom: HTMLInputElement, files: FileList) {
if (uploader === null){
uploader = new UploadManager()
}
uploader.uploadFileList(files);
$("#file_input_field").change(function(evt){
handleUploads((<HTMLInputElement>evt.target).files)
// This resets the file input field
// http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
$('#fileName').html("");
$("#fileUploadButton").css("visibility", "hidden");
(<HTMLFormElement>$("#fileInputField").wrap("<form>").closest("form").get(0)).reset();
$("#fileInputField").unwrap();
}
$('#file_name').html("")
$("#file_upload_button").css("visibility", "hidden");
(<HTMLFormElement>$("#file_input_field").wrap("<form>").closest("form").get(0)).reset()
$("#file_input_field").unwrap()
})
/*
* Drag 'n Drop upload handlers
*/
$(document).on('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
e.preventDefault()
e.stopPropagation()
})
$(document).on('dragenter', function (e) {
e.preventDefault();
e.stopPropagation();
});
e.preventDefault()
e.stopPropagation()
})
document.addEventListener('drop', function(e: DragEvent){
if (e.dataTransfer && e.dataTransfer.files.length > 0) {
e.preventDefault();
e.stopPropagation();
e.preventDefault()
e.stopPropagation()
if (uploader === null){
uploader = new UploadManager()
}
uploader.uploadFileList(e.dataTransfer.files);
handleUploads(e.dataTransfer.files)
}
})
/*
* Upload functions
*/
// function pushUploads(array){
// var len = array.length;
// for(i = 0; i < len; i++){
// uploadQueue.push(array[i]);
// }
// startFileUpload();
// }

View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"outFile": "../../script/compiled/home.js"
},
"files": [
"home.ts",
"../lib/cookie.ts",
"../lib/jquery.d.ts",
"../lib/uploader.ts"
]
}

View File

@@ -1,26 +1,32 @@
interface FileUpload {
file: File
onProgress(progress: number)
onFinished(id: string)
}
class UploadManager {
private uploadQueue: Array<File> = new Array();
private uploadQueue: Array<FileUpload> = new Array();
private uploadThreads: Array<UploadWorker> = new Array();
private maxThreads: 4;
private maxThreads: number = 2;
public uploadFile(file: File) {
public uploadFile(file: FileUpload) {
console.debug("Adding upload to queue")
this.uploadQueue.push(file);
if (this.uploadThreads.length < 4) {
if (this.uploadThreads.length < this.maxThreads) {
console.debug("Starting upload thread")
setTimeout(new UploadWorker(this).start(), 0) // Start a new upload thread
let thread = new UploadWorker(this)
this.uploadThreads.push(thread)
setTimeout(thread.start(), 0) // Start a new upload thread
} else {
for (var i = 0; i < this.uploadThreads.length; i++) {
this.uploadThreads[i].startIfInactive()
}
}
public uploadFileList(files: FileList) {
for (var i = 0; i < files.length; i++) {
this.uploadFile(files.item(i))
}
}
public grabFile(): File | undefined {
public grabFile(): FileUpload | undefined {
if (this.uploadQueue.length > 0) {
return this.uploadQueue.pop()
return this.uploadQueue.shift()
} else {
return undefined
}
@@ -29,7 +35,8 @@ class UploadManager {
class UploadWorker {
private manager: UploadManager
private tries: number
private tries: number = 0
private uploading: boolean = false
constructor(manager: UploadManager) {
this.manager = manager
@@ -37,21 +44,30 @@ class UploadWorker {
public start() {
var file = this.manager.grabFile()
if (file === null) {
console.debug("No file")
if (file === undefined) {
this.uploading = false
console.debug("No files left in queue")
return // Stop the thread
}
this.uploading = true
this.tries = 0
this.upload(<File>file)
this.upload(<FileUpload>file)
}
public startIfInactive(){
if (!this.uploading) {
this.start()
}
}
private upload(file: File){
console.debug("Starting upload of " + file.name)
private upload(file: FileUpload){
console.debug("Starting upload of " + file.file.name)
var formData = new FormData()
formData.append('file', file)
formData.append("name", file.name)
formData.append('file', file.file)
formData.append("name", file.file.name)
var that = this // jquery changes the definiton of "this"
$.ajax({
url: "/api/file",
@@ -61,22 +77,35 @@ class UploadWorker {
contentType: false,
processData: false,
type: 'POST',
xhr: function () {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
file.onProgress(evt.loaded / evt.total)
}
}, false);
return xhr;
},
success: function (data) {
file.onFinished(data.id)
console.log("Done: " + data.id)
this.setHistoryCookie(data.id)
that.setHistoryCookie(data.id)
that.start() // Continue uploading on this thread
},
error: function (xhr, status, error){
console.log(status)
console.log(error)
if (this.tries === 3) {
if (that.tries === 3) {
alert("Upload failed: " + status);
that.uploading = false
return; // Upload failed
}
// Try again
this.tries++
this.upload(file)
that.tries++
that.upload(file)
}
});
}

View File

@@ -34,25 +34,18 @@
</head>
<body>
<img id="header-image" src="/res/img/header_neuropol.png" alt="Header image"/>
<img id="header_image" src="/res/img/header_neuropol.png" alt="Header image"/>
<div id="body" class="body">
{{template "menu"}}
<div class="highlight_middle border-bottom">
<input id="fileInputField" type="file" name="file" multiple="multiple" onchange="fileInputChange(this, event);"/>
<button id="selectFileButton" class="big_button button_highlight">Upload Files</button>
<button id="textButton" class="big_button button_highlight" onClick="window.location.href = '/t/'">Upload Text</button><br/>
<input id="file_input_field" type="file" name="file" multiple="multiple"/>
<button id="select_file_button" class="big_button button_highlight">Upload Files</button>
<button id="text_button" class="big_button button_highlight" onClick="window.location.href = '/t/'">Upload Text</button><br/>
<div id="progress-bar" class="progress-bar">
<span class="progress-text"></span>
<div id="upload-progress" class="progressbar-inner">
<span class="progress-text"></span>
</div>
</div>
<div id="uploads-completed"></div>
<div id="uploads_queue"></div>
</div>
<div class="highlight_dark border-bottom">
<button id="btnCreateList">Create list with uploaded files</button>
<button id="btn_create_list">Create list with uploaded files</button>
</div>
<h1>Pixeldrain Public Beta<img src="/res/img/sia.png" style="height: 40px;"/></h1>
@@ -144,7 +137,7 @@
<script type="text/javascript">var API_URL = "/api";</script>
<script src="/res/script/listmaker.js"></script>
<script src="/res/script/home.js"></script>
<script src="/res/script/compiled/home.js"></script>
{{template "analytics"}}
</body>
</html>