Add prototype

This commit is contained in:
Patrick Jentsch
2019-06-03 14:57:09 +02:00
parent b8fa8f47ab
commit 86557443a2
43 changed files with 24638 additions and 53 deletions

View File

@ -0,0 +1,110 @@
function setUserCallback() {
userFormEMailElement.value = user["e-mail"];
userFormFirstNameElement.value = user["firstName"];
userFormLastNameElement.value = user["lastName"];
userFormNotificationsElement.checked = user["notifications"];
userFormPhoneElement.value = user["phone"];
M.updateTextFields();
userFormEMailElement.addEventListener("input", event => {
eMailChanged = (user["e-mail"] != userFormEMailElement.value) ? true : false;
evaluateUserForm();
});
userFormFirstNameElement.addEventListener("input", event => {
firstNameChanged = (user["firstName"] != userFormFirstNameElement.value) ? true : false;
evaluateUserForm();
});
userFormLastNameElement.addEventListener("input", event => {
lastNameChanged = (user["lastName"] != userFormLastNameElement.value) ? true : false;
evaluateUserForm();
});
userFormNotificationsElement.addEventListener("change", event => {
notificationsChanged = (user["notifications"] != userFormNotificationsElement.checked) ? true : false;
evaluateUserForm();
});
userFormPhoneElement.addEventListener("input", event => {
phoneChanged = (user["phone"] != userFormPhoneElement.value) ? true : false;
evaluateUserForm();
});
userFormResetElement.addEventListener("click", event => {
eMailChanged = false;
firstNameChanged = false;
lastNameChanged = false;
notificationsChanged = false;
phoneChanged = false;
userFormEMailElement.value = user["e-mail"];
userFormFirstNameElement.value = user["firstName"];
userFormLastNameElement.value = user["lastName"];
userFormNotificationsElement.checked = user["notifications"];
userFormPhoneElement.value = user["phone"];
evaluateUserForm();
});
userFormSubmitElement.addEventListener("click", event => {
if (eMailChanged) {
user["e-mail"] = userFormEMailElement.value;
eMailChanged = false;
}
if (firstNameChanged) {
user["firstName"] = userFormFirstNameElement.value;
firstNameChanged = false;
}
if (lastNameChanged) {
user["lastName"] = userFormLastNameElement.value;
lastNameChanged = false;
}
if (notificationsChanged) {
user["notifications"] = userFormNotificationsElement.checked;
notificationsChanged = false;
}
if (phoneChanged) {
user["phone"] = userFormPhoneElement.value;
phoneChanged = false;
}
localStorage.setItem("user", JSON.stringify(user));
M.toast({html: "Benutzerdaten wurden aktualisiert."});
evaluateUserForm();
});
}
function evaluateUserForm() {
var somethingChanged;
somethingChanged = eMailChanged || firstNameChanged || lastNameChanged || notificationsChanged || phoneChanged;
if (somethingChanged) {
userFormResetElement.classList.remove("disabled");
userFormSubmitElement.classList.remove("disabled");
} else {
userFormResetElement.classList.add("disabled");
userFormSubmitElement.classList.add("disabled");
}
}
var eMailChanged;
var firstNameChanged;
var lastNameChanged;
var notificationsChanged;
var phoneChanged;
var userFormEMailElement;
var userFormFirstNameElement;
var userFormLastNameElement;
var userFormNotificationsElement;
var userFormPhoneElement;
var userFormResetElement;
var userFormSubmitElement;
eMailChanged = false;
firstNameChanged = false;
lastNameChanged = false;
notificationsChanged = false;
phoneChanged = false;
userFormFirstNameElement = document.getElementById("user-form-first-name");
userFormLastNameElement = document.getElementById("user-form-last-name");
userFormEMailElement = document.getElementById("user-form-e-mail");
userFormNotificationsElement = document.getElementById("user-form-notifications");
userFormPhoneElement = document.getElementById("user-form-phone");
userFormResetElement = document.getElementById("user-form-reset");
userFormSubmitElement = document.getElementById("user-form-submit");

View File

@ -0,0 +1,17 @@
/**
* Process the submit event from the login form.
*/
function LoginFormSubmitHandler() {
var loginFormPasswordElement;
var loginFormUserElement;
loginFormPasswordElement = document.getElementById("login-form-password");
loginFormUserElement = document.getElementById("login-form-user");
try {
login(loginFormPasswordElement.value, loginFormUserElement.value);
} catch(e) {
loginFormPasswordElement.classList.add("invalid");
loginFormUserElement.classList.add("invalid");
}
}

View File

@ -0,0 +1,43 @@
function jobFormChangeHandler() {
if (jobFormFileElement.files.length === 0 || jobFormLanguageElement.value === "" || jobFormNameElement.value === "") {
jobFormSubmitElement.classList.add("disabled");
} else {
jobFormSubmitElement.classList.remove("disabled");
}
}
function jobFormSubmitHandler() {
createJob(jobFormFileElement.files[0], jobFormLanguageElement.value, jobFormNameElement.value, jobFormServiceElement.value, user["id"]);
}
var jobFormElement;
var jobFormFileElement;
var jobFormLanguageElement;
var jobFormNameElement;
var jobFormServiceElement;
var jobFormSubmitElement;
jobFormElement = document.getElementById("job_form");
jobFormFileElement = document.getElementById("job_form_file");
jobFormLanguageElement = document.getElementById("job_form_language");
jobFormNameElement = document.getElementById("job_form_name");
jobFormServiceElement = document.getElementById("job_form_service");
jobFormSubmitElement = document.getElementById("job_form_submit");
jobFormFileElement.addEventListener("change", jobFormChangeHandler);
jobFormLanguageElement.addEventListener("change", jobFormChangeHandler);
jobFormNameElement.addEventListener("input", jobFormChangeHandler);
M.Modal.init(
document.getElementById("create_job"),
{
"onCloseEnd": modal => {
jobFormElement.reset();
M.updateTextFields();
}
}
);

View File

@ -0,0 +1,172 @@
var JOBLANGUAGES = {
"nlp": {
"de": "Deutsch",
"en": "Englisch",
"fr": "Französisch",
"pt": "Portugisisch",
"es": "Spanisch"
},
"ocr": {
"deu": "Deutsch",
"deu_frak": "Deutsch (Fraktur)",
"eng": "Englisch",
"fra": "Französisch",
"por": "Portugisisch",
"spa": "Spanisch"
}
};
var JOBSERVICEICONS = {
"nlp": "format_textdirection_l_to_r",
"ocr": "find_in_page"
};
var JOBSTATUSCOLORS = {
"failed": "pink",
"finished": "teal",
"queued": "amber",
"running": "indigo"
};
var JOBSTATUSNAMES = {
"failed": 'Fehlgeschlagen',
"finished": 'Abgeschlossen',
"queued": 'Wartend',
"running": 'Laufend'
}
var JOBSTATUSTEXTS = {
'failed': 'Es ist ein Fehler bei der Bearbeitung des Auftrages aufgetreten. \
Für weitere Informationen wenden Sie sich mit dem \
Auftragskennzeichen an den Seitenbetreiber.',
'finished': 'Der Auftrag ist abgeschlossen, die Ergebnisse können nun \
heruntergeladen werden. Die Quelldatei bleibt verfügbar und \
kann jederzeit abgerufen werden.',
'queued': 'Der Auftrag befindet sich in der Warteschlange und wird vom \
System bearbeitet, sobald Rechenkapazität verfügbar ist.',
'running': 'Dieser Auftrag wird gerade bearbeitet, sobald der Vorgang \
abgeschlossen wurde, können die Ergebnisse hier heruntergeladen \
werden.'
}
var jobsCollapsibleElement;
var jobStatusFilter;
jobsCollapsibleElement = document.getElementById("jobs-collapsible");
jobStatusFilter = '';
M.Collapsible.init(
jobsCollapsibleElement,
{accordion: false}
);
document.querySelectorAll('[data-job-filter]').forEach(jobFilterElement => {
jobFilterElement.addEventListener("click", event => {
jobStatusFilter = event.currentTarget.getAttribute("data-job-filter");
jobListManager();
});
});
function jobListManager() {
jobs.forEach(job => {
var jobElement;
jobElement = document.getElementById(job["id"]);
// Check whether an element with id = job['id'] is found
if (jobElement) {
var jobResultElement;
var jobStatusElement;
var jobStatusTextElement;
jobResultElement = jobElement.querySelector('.job-result');
jobStatusElement = jobElement.querySelector('.job-status');
jobStatusTextElement = jobElement.querySelector('.job-status-text');
// Check whether the job status changed since it got printed
if (jobStatusElement.innerHTML != JOBSTATUSNAMES[job["status"]]) {
// Update the job status element (label and color)
jobStatusElement.innerHTML = JOBSTATUSNAMES[job["status"]];
jobStatusElement.classList.remove("pink", "teal", "amber", "indigo");
jobStatusElement.classList.add(JOBSTATUSCOLORS[job["status"]]);
// Update the job status text element
jobStatusTextElement.innerHTML = JOBSTATUSTEXTS[job["status"]];
// Check whether the new job status is 'finished'
if (job["status"] === "finished") {
// Unhide the jobs result element
jobResultElement.classList.remove("hide");
}
}
// If the job status doesn't match the current filter, remove it
//if (jobStatusFilter != "" && job["status"] != jobStatusFilter) jobElement.remove();
// If the job status doesn't match the current filter, hide it
if (jobStatusFilter != "" && job["status"] != jobStatusFilter) {
jobElement.classList.add('hide');
} else {
jobElement.classList.remove('hide');
}
} else {
// If the job status doesn't match the current filter, skip it
//if (jobStatusFilter != "" && job["status"] != jobStatusFilter) return;
jobElement = document.createElement("li");
jobElement.setAttribute("id", job["id"]);
// If the job status doesn't match the current filter, skip it
if (jobStatusFilter != "" && job["status"] != jobStatusFilter) {
jobElement.classList.add('hide');
} else {
jobElement.classList.remove('hide');
}
jobElement.innerHTML =
'<div class="collapsible-header">'
+ '<i class="material-icons dropdown-indicator">arrow_drop_down</i>'
+ '<i class="material-icons">'
+ JOBSERVICEICONS[job["service"]]
+ '</i>'
+ job["name"]
+ '<span class="job-status new badge ' + JOBSTATUSCOLORS[job["status"]] + '" data-badge-caption="">'
+ JOBSTATUSNAMES[job["status"]]
+ '</span>'
+ '</div>'
+ '<div class="collapsible-body">'
+ '<p class="job-status-text">' + JOBSTATUSTEXTS[job["status"]] + '</p>'
+ '<p>&nbsp;</p>'
+ '<p class="overflow-hidden">'
+ '<i class="material-icons blue-grey-text text-darken-2 left">bookmark</i>'
+ 'Auftragskennzeichen: '
+ job["id"]
+ '</p>'
+ '<p class="overflow-hidden">'
+ '<i class="material-icons blue-grey-text text-darken-2 left">insert_drive_file</i>'
+ 'Datei: '
+ '<a href="../vre_files/jobs/' + job["id"] + '/' + job["file"] + '">'
+ job["file"]
+ '</a>'
+ '</p>'
+ '<p class="overflow-hidden">'
+ '<i class="material-icons blue-grey-text text-darken-2 left">language</i>'
+ 'Sprache: '
+ JOBLANGUAGES[job["service"]][job["language"]]
+ '</p>'
+ '<p class="job-result' + (job['status'] != 'finished' ? ' hide' : '') + ' overflow-hidden">'
+ '<i class="material-icons blue-grey-text text-darken-2 left">archive</i>'
+ 'Ergebnisse: '
+ '<a href="../vre_files/jobs/' + job["id"] + '/' + job["file"].split(".").slice(0, -1).join(".") + '_-_' + job["service"] + '.zip">'
+ 'Download'
+ '</a>'
+ '</p>'
+ '</div>';
jobElement.querySelector('.collapsible-header').addEventListener("click", event => {
var dropdownIndicatorElement;
dropdownIndicatorElement = event.currentTarget.querySelector('.dropdown-indicator');
if (dropdownIndicatorElement.innerHTML === "arrow_drop_down") {
dropdownIndicatorElement.innerHTML = "arrow_drop_up";
} else {
dropdownIndicatorElement.innerHTML = "arrow_drop_down";
}
});
jobsCollapsibleElement.appendChild(jobElement);
}
});
}
setJobsCallback = jobListManager;

12374
vre_www/website/js/materialize.js vendored Normal file

File diff suppressed because it is too large Load Diff

6
vre_www/website/js/materialize.min.js vendored Normal file

File diff suppressed because one or more lines are too long

154
vre_www/website/js/vre.js Normal file
View File

@ -0,0 +1,154 @@
var JOBSPOLLINTERVALL = 1000;
var USERS = {
"testbenutzer": {
"e-mail": "t.benutzer@uni-bielefeld.de",
"firstName": "Test",
"id": "testbenutzer",
"lastName": "Benutzer",
"notifications": true,
"password": "passwort",
"phone": "+49 521 106-XXXXX"
}
};
// The job list of the current user
var jobs;
// The current user
var user;
/**
* Login a user and redirect the visitor to the portal page.
* @param {string} password - The password to use for login.
* @param {string} user - The user to use for login.
*/
function login(password, user) {
// Check if the user exists
if (USERS[user]) {
// Check if the password is correct
if (USERS[user]["password"] === password) {
// Save the user data to the local storage
localStorage.setItem("user", JSON.stringify(USERS[user]));
// Redirect the visitor to the portal page
window.location = "/vre/portal.html";
return;
}
}
// The function only ends here, when the user doesn't exists or when the
// password was wrong, in both cases it should throw an exception
throw "User doesn't exist or password was wrong!";
}
/**
* Logout the current user and redirect the visitor to the login page.
*/
function logout() {
// delete all data from the local storage
localStorage.clear();
// redirect to the login page
window.location = "/vre/";
}
/**
* The main function, which is executed on each page after it's completly
* loaded.
*/
function main() {
M.Dropdown.init(
document.getElementById("main-nav-account"),
{"constrainWidth": false, "coverTrigger": false}
);
// Indicates whether the current page is the login page
var isLoginPage;
// Indicates whether the current page is a service page (like ocr or nlp)
var isServicePage;
isLoginPage = window.location.pathname === "/vre/" || window.location.pathname === "/vre/index.html";
isServicePage = window.location.pathname === "/vre/nlp.html" || window.location.pathname === "/vre/ocr.html";
// Check if the visitor is logged in, by checking if the local storage
// contains a user
if (localStorage.getItem("user")) {
// Redirect to the portal page if the current page is the login page
if (isLoginPage) window.location = "portal.html";
// Load user from the local storage
user = JSON.parse(localStorage.getItem("user"));
// If a function named setUserCallback exists, call it
if (typeof(setUserCallback) === "function") setUserCallback();
} else {
// Redirect to the login page if the current page isn't the login page
if (!isLoginPage) window.location = "index.html";
return;
}
// Check if the local storage contains a copy of the users job list
if (localStorage.getItem("jobs")) {
// Load the job list from the local storage
jobs = JSON.parse(localStorage.getItem("jobs"));
// If a function named setJobsCallback exists, call it
if (typeof(setJobsCallback) === "function") setJobsCallback();
} else {
// Load the job list from the vre server
getJobs({"user": user["id"]}, function(newJobs) {
jobs = newJobs;
// If a function named setJobsCallback exists, call it
if (typeof(setJobsCallback) === "function") setJobsCallback();
});
}
// Set a continous poll for the job list
setInterval(getJobs, JOBSPOLLINTERVALL, {"user": user["id"]}, updateJobs);
}
/**
* Updates the job list in the local storage and the contents of the global
* job list variable. It also informs the visitor about job status changes.
* @param {Object[]} newJobs - The new job list.
*/
function updateJobs(newJobs) {
var i;
// Indicates whether the new job list differs from the old one
var hasJobsChanged;
// The new job list as JSON string
var newJobsAsJSONString;
newJobsAsJSONString = JSON.stringify(newJobs);
hasJobsChanged = localStorage.getItem("jobs") != newJobsAsJSONString;
if (hasJobsChanged) {
// Iterate over the old job list
for (i = 0; i < jobs.length; i++) {
// Check whether the status of the currently iterated job changed
if (jobs[i]["status"] != newJobs[i]["status"]) {
// Inform the visitor with a toast message about the new status
switch (newJobs[i]["status"]) {
case "failed":
M.toast({html: "Auftrag '" + jobs[i]["name"] + "' is fehlgeschlagen."});
break;
case "finished":
M.toast({html: "Auftrag '" + jobs[i]["name"] + "' wurde abgeschlossen."});
break;
case "running":
M.toast({html: "Auftrag '" + jobs[i]["name"] + "' wird bearbeitet."});
break;
default:
}
}
}
// Save the new job list to the local storage
localStorage.setItem("jobs", newJobsAsJSONString);
// Replace the global job list variable with the new job list
jobs = newJobs;
// If a function named setJobsCallback exists, call it
if (typeof(setJobsCallback) === "function") setJobsCallback();
}
}
window.onload = main;

View File

@ -0,0 +1,180 @@
var VREMANAGER = "http://" + window.location.hostname + ":5000";
/**
* Sends an asynchronous HTTP request to the vre manager in order to create a
* new job.
* @param {File} file - The file to process with the job.
* @param {string} language - The language of the file contents.
* @param {string} name - A name for the job, this doesn't have to be unique.
* @param {string} service - The service this job belongs to.
* @param {string} user - The user this job belongs to.
* @param {function} [callback] - A function, that is called after the HTTP
* request finished.
*/
function createJob(file, language, name, service, user, callback = console.log) {
var formData;
var oReq;
var query;
formData = new FormData();
formData.append("file", file);
oReq = new XMLHttpRequest();
oReq.addEventListener("loadend", function(oEvent) {
if (this.status === 201) {
M.toast({html: "Auftrag '" + name + "' wurde erstellt."});
callback(JSON.parse(this.responseText));
} else {
if (this.status === 415) {
M.toast({html: "Auftrag '" + name + "' konnte nicht erstellt werden.<br>(Unerwarteter Dateityp)"});
} else {
M.toast({html: "Auftrag '" + name + "' konnte nicht erstellt werden.<br>(Fehlercode: " + this.status + ")"});
}
}
});
query = "?language=" + language + "&name=" + name + "&service=" + service + "&user=" + user;
oReq.open("POST", VREMANAGER + "/vre/jobs" + query);
oReq.send(formData);
}
/**
* Sends an asynchronous HTTP request to the vre manager in order to delete an
* existing job.
* @param {string} id - The id of the job to be deleted.
* @param {function} [callback] - A function, that is called after the HTTP
* request finished.
*/
function deleteJob(id, callback = console.log) {
var oReq;
oReq = new XMLHttpRequest();
oReq.addEventListener("loadend", function(oEvent) {
if (this.status === 204) {
M.toast({html: "Auftrag '" + id + "' wurde gelöscht."});
callback();
} else {
M.toast({html: "Auftrag '" + id + "' konnte nicht gelöscht werden.<br>(Fehlercode: " + this.status + ")"});
}
});
oReq.open("DELETE", VREMANAGER + "/vre/jobs/" + id);
oReq.send();
}
/**
* Sends an asynchronous HTTP request to the vre manager in order to get all
* informations about a specific and existing job.
* @param {string} id - The id of the job to get the information from.
* @param {function} [callback] - A function, that is called after the HTTP
* request finished.
*/
function getJob(id, callback = console.log) {
var oReq;
oReq = new XMLHttpRequest();
oReq.addEventListener("loadend", function(oEvent) {
if (this.status === 200) {
callback(JSON.parse(this.responseText));
}
});
oReq.open("GET", VREMANAGER + "/vre/jobs/" + id);
oReq.send();
}
/**
* Sends an asynchronous HTTP request to the vre manager in order to get a
* (filtered) list of all jobs.
* @param {object} [filters=null] - An object containing filters. E.g.
* {'service': 'nlp', 'status': 'finished'}
* @param {function} [callback] - A function, that is called after the HTTP
* request finished.
*/
function getJobs(filters = null, callback = console.log) {
var oReq;
var query;
oReq = new XMLHttpRequest();
oReq.addEventListener("loadend", function(oEvent) {
if (this.status === 200) {
callback(JSON.parse(this.responseText));
}
});
query = ""
if (filters) {
if (filters["name"]) {
query += (query === "") ? "?" : "&";
query += "name=" + filters["name"];
}
if (filters["service"]) {
query += (query === "") ? "?" : "&";
query += "service=" + filters["service"];
}
if (filters["status"]) {
query += (query === "") ? "?" : "&";
query += "status=" + filters["status"];
}
if (filters["user"]) {
query += (query === "") ? "?" : "&";
query += "user=" + filters["user"];
}
}
oReq.open("GET", VREMANAGER + "/vre/jobs" + query);
oReq.send();
}
/**
* Sends an asynchronous HTTP request to the vre manager in order to update the
* values of a specific and existing job.
* @param {string} id - The id of the job to update.
* @param {object} [newValues=null] - An object containing the new values. E.g.
* {'status': 'finished'}
* @param {function} [callback] - A function, that is called after the HTTP
* request finished.
*/
function updateJob(id, newValues = null, callback = console.log) {
var oReq;
var query;
oReq = new XMLHttpRequest();
oReq.addEventListener("loadend", function(oEvent) {
if (this.status === 200) {
M.toast({html: "Auftrag '" + id + "' wurde aktualisiert."});
callback(JSON.parse(this.responseText));
} else {
M.toast({html: "Auftrag '" + id + "' konnte nicht aktualisiert werden.<br>(Fehlercode: " + this.status + ")"});
}
});
query = ""
if (newValues) {
if (newValues["name"]) {
query += (query === "") ? "?" : "&";
query += "name=" + newValues["name"];
}
if (newValues["language"]) {
query += (query === "") ? "?" : "&";
query += "language=" + newValues["language"];
}
if (newValues["report"]) {
query += (query === "") ? "?" : "&";
query += "report=" + newValues["report"];
}
if (newValues["status"]) {
query += (query === "") ? "?" : "&";
query += "status=" + newValues["status"];
}
}
oReq.open("PUT", VREMANAGER + "/vre/jobs/" + id + query);
oReq.send();
}