mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
Create a proper class for the upload form
This commit is contained in:
parent
d8f11a9759
commit
03a57fd7ee
@ -1,4 +1,22 @@
|
||||
class CorpusFileList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="filename"></span></td>
|
||||
<td><span class="author"></span></td>
|
||||
<td><span class="title"></span></td>
|
||||
<td><span class="publishing_year"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'author', 'filename', 'publishing_year', 'title']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...CorpusFileList.options, ...options});
|
||||
this.corpusId = listElement.dataset.corpusId;
|
||||
@ -109,19 +127,3 @@ class CorpusFileList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
CorpusFileList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="filename"></span></td>
|
||||
<td><span class="author"></span></td>
|
||||
<td><span class="title"></span></td>
|
||||
<td><span class="publishing_year"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'author', 'filename', 'publishing_year', 'title']
|
||||
};
|
||||
|
@ -1,4 +1,20 @@
|
||||
class CorpusList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
|
||||
<td><b class="title"></b><br><i class="description"></i></td>
|
||||
<td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, {name: 'status', attr: 'data-status'}, 'description', 'title']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...CorpusList.options, ...options});
|
||||
}
|
||||
@ -102,17 +118,3 @@ class CorpusList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
CorpusList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
|
||||
<td><b class="title"></b><br><i class="description"></i></td>
|
||||
<td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, {name: 'status', attr: 'data-status'}, 'description', 'title']
|
||||
};
|
||||
|
@ -1,4 +1,17 @@
|
||||
class JobInputList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="filename"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'filename']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...JobInputList.options, ...options});
|
||||
this.jobId = listElement.dataset.jobId;
|
||||
@ -39,14 +52,3 @@ class JobInputList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
JobInputList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="filename"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'filename']
|
||||
};
|
||||
|
@ -1,4 +1,20 @@
|
||||
class JobList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><a class="btn-floating disabled"><i class="nopaque-icons service service-color darken service-icon"></i></a></td>
|
||||
<td><b class="title"></b><br><i class="description"></i></td>
|
||||
<td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, {name: 'status', attr: 'data-status'}, 'description', 'title']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...JobList.options, ...options});
|
||||
}
|
||||
@ -105,17 +121,3 @@ class JobList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
JobList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><a class="btn-floating disabled"><i class="nopaque-icons service service-color darken service-icon"></i></a></td>
|
||||
<td><b class="title"></b><br><i class="description"></i></td>
|
||||
<td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, {name: 'status', attr: 'data-status'}, 'description', 'title']
|
||||
};
|
||||
|
@ -1,4 +1,18 @@
|
||||
class JobResultList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="description"></span></td>
|
||||
<td><span class="filename"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'description', 'filename']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...JobResultList.options, ...options});
|
||||
this.jobId = listElement.dataset.jobId;
|
||||
@ -74,15 +88,3 @@ class JobResultList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
JobResultList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="description"></span></td>
|
||||
<td><span class="filename"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'description', 'filename']
|
||||
};
|
||||
|
@ -1,4 +1,19 @@
|
||||
class QueryResultList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><b class="title"></b><br><i class="description"></i><br></td>
|
||||
<td><span class="corpus_title"></span><br><span class="query"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
|
||||
};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...QueryResultList.options, ...options});
|
||||
}
|
||||
@ -105,16 +120,3 @@ class QueryResultList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
QueryResultList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><b class="title"></b><br><i class="description"></i><br></td>
|
||||
<td><span class="corpus_title"></span><br><span class="query"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
|
||||
};
|
||||
|
@ -3,6 +3,41 @@ class RessourceList {
|
||||
* This class is not meant to be used directly, instead it should be used as
|
||||
* a base class for concrete ressource list implementations.
|
||||
*/
|
||||
static autoInit() {
|
||||
const nopaqueRessourceListElements = document.querySelectorAll('.nopaque-ressource-list[data-ressource-type]:not(.no-autoinit)');
|
||||
let nopaqueRessourceListElement;
|
||||
|
||||
for (nopaqueRessourceListElement of nopaqueRessourceListElements) {
|
||||
switch (nopaqueRessourceListElement.dataset.ressourceType) {
|
||||
case 'Corpus':
|
||||
new CorpusList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'CorpusFile':
|
||||
new CorpusFileList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'Job':
|
||||
new JobList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'JobInput':
|
||||
new JobInputList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'JobResult':
|
||||
new JobResultList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'QueryResult':
|
||||
new QueryResultList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'User':
|
||||
new UserList(nopaqueRessourceListElement);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
let i;
|
||||
|
||||
@ -88,4 +123,3 @@ class RessourceList {
|
||||
this.listjs.get('id', id)[0].values({[valueName]: newValue});
|
||||
}
|
||||
}
|
||||
RessourceList.options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
|
||||
|
@ -1,4 +1,24 @@
|
||||
class UserList extends RessourceList {
|
||||
static options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="id_"></span></td>
|
||||
<td><span class="username"></span></td>
|
||||
<td><span class="email"></span></td>
|
||||
<td><span class="last_seen"></span></td>
|
||||
<td><span class="role"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="edit" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'id_', 'username', 'email', 'last_seen', 'role']
|
||||
};
|
||||
|
||||
|
||||
|
||||
constructor(listElement, options = {}) {
|
||||
super(listElement, {...UserList.options, ...options});
|
||||
}
|
||||
@ -70,20 +90,3 @@ class UserList extends RessourceList {
|
||||
};
|
||||
}
|
||||
}
|
||||
UserList.options = {
|
||||
item: `
|
||||
<tr>
|
||||
<td><span class="id_"></span></td>
|
||||
<td><span class="username"></span></td>
|
||||
<td><span class="email"></span></td>
|
||||
<td><span class="last_seen"></span></td>
|
||||
<td><span class="role"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="edit" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
valueNames: [{data: ['id']}, 'id_', 'username', 'email', 'last_seen', 'role']
|
||||
};
|
||||
|
125
app/static/js/nopaque/UploadForm.js
Normal file
125
app/static/js/nopaque/UploadForm.js
Normal file
@ -0,0 +1,125 @@
|
||||
class UploadForm {
|
||||
static autoInit() {
|
||||
const nopaqueSubmitForms = document.querySelectorAll('.nopaque-upload-form');
|
||||
let nopaqueSubmitForm;
|
||||
|
||||
for (nopaqueSubmitForm of nopaqueSubmitForms) {
|
||||
new UploadForm(nopaqueSubmitForm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
constructor(formElement) {
|
||||
this.formElement = formElement;
|
||||
this.request = new XMLHttpRequest();
|
||||
|
||||
this.formElement.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
this.submit();
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
const selectElements = this.formElement.querySelectorAll('select');
|
||||
let abortElement;
|
||||
let helperTextElement;
|
||||
let helperTextElements;
|
||||
let inputFieldElement;
|
||||
let modal;
|
||||
let modalElement;
|
||||
let progressElement;
|
||||
let selectElement;
|
||||
let tmp;
|
||||
|
||||
// Check if select elements are filled out properly
|
||||
for (selectElement of selectElements) {
|
||||
if (selectElement.value === '') {
|
||||
inputFieldElement = selectElement.closest('.input-field');
|
||||
inputFieldElement.querySelector('.select-dropdown').classList.add('invalid');
|
||||
helperTextElements = inputFieldElement.querySelectorAll('.helper-text');
|
||||
for (helperTextElement of helperTextElements) {
|
||||
helperTextElement.remove();
|
||||
}
|
||||
inputFieldElement.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
'<span class="helper-text error-color-text">Please select an option.</span>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup modal
|
||||
tmp = document.createElement('div');
|
||||
tmp.innerHTML = `
|
||||
<div class="modal">
|
||||
<div class="modal-content">
|
||||
<h4><i class="material-icons left">file_upload</i>Uploading files...</h4>
|
||||
<div class="progress">
|
||||
<div class="determinate" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="btn red waves-effect waves-light abort">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
`.trim();
|
||||
modalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
|
||||
modal = M.Modal.init(
|
||||
modalElement,
|
||||
{
|
||||
dismissible: false,
|
||||
onCloseEnd: () => {
|
||||
modal.destroy();
|
||||
modalElement.remove();
|
||||
}
|
||||
}
|
||||
);
|
||||
modal.open();
|
||||
|
||||
// Setup abort handling
|
||||
abortElement = modalElement.querySelector('.abort');
|
||||
abortElement.addEventListener('click', event => {this.request.abort();});
|
||||
this.request.addEventListener('abort', event => {
|
||||
this.request.abort();
|
||||
modal.close();
|
||||
});
|
||||
|
||||
// Setup load handling (after the request completed)
|
||||
this.request.addEventListener('load', event => {
|
||||
const response = JSON.parse(this.request.responseText);
|
||||
let inputError;
|
||||
let inputErrors;
|
||||
let inputFieldElement;
|
||||
let inputName;
|
||||
|
||||
if (this.request.status === 201) {
|
||||
window.location.href = response.redirect_url;
|
||||
}
|
||||
if (this.request.status === 400) {
|
||||
for ([inputName, inputErrors] of Object.entries(response)) {
|
||||
inputFieldElement = this.formElement.querySelector(`input[name="${inputName}"], select[name="${inputName}"]`).closest('.input-field');
|
||||
for (inputError of inputErrors) {
|
||||
inputFieldElement.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
`<span class="helper-text red-text">${inputError}</span>`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.request.status === 500) {
|
||||
location.reload();
|
||||
}
|
||||
modal.close();
|
||||
});
|
||||
|
||||
// Setup progress handling
|
||||
progressElement = modalElement.querySelector('.progress > .determinate');
|
||||
this.request.upload.addEventListener('progress', event => {
|
||||
const progress = Math.floor(100 * event.loaded / event.total);
|
||||
progressElement.style.width = `${progress}%`;
|
||||
});
|
||||
|
||||
this.request.open('POST', window.location.href);
|
||||
this.request.send(new FormData(this.formElement));
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* The nopaque object is used as a namespace for nopaque specific functions and
|
||||
* variables.
|
||||
*/
|
||||
var nopaque = {};
|
||||
|
||||
nopaque.Forms = {};
|
||||
nopaque.Forms.autoInit = () => {
|
||||
const nopaqueSubmitForms = document.querySelectorAll('.nopaque-submit-form');
|
||||
let nopaqueSubmitForm;
|
||||
|
||||
for (nopaqueSubmitForm of nopaqueSubmitForms) {
|
||||
nopaqueSubmitForm.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const request = new XMLHttpRequest();
|
||||
const selectElements = nopaqueSubmitForm.querySelectorAll('select');
|
||||
let abortElement;
|
||||
let helperTextElement;
|
||||
let helperTextElements;
|
||||
let inputFieldElement;
|
||||
let modal;
|
||||
let modalElement;
|
||||
let progressElement;
|
||||
let selectElement;
|
||||
let tmp;
|
||||
|
||||
// Check if select elements are filled out properly
|
||||
for (selectElement of selectElements) {
|
||||
if (selectElement.value === '') {
|
||||
inputFieldElement = selectElement.closest('.input-field');
|
||||
inputFieldElement.querySelector('.select-dropdown').classList.add('invalid');
|
||||
helperTextElements = inputFieldElement.querySelectorAll('.helper-text');
|
||||
for (helperTextElement of helperTextElements) {
|
||||
helperTextElement.remove();
|
||||
}
|
||||
inputFieldElement.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
'<span class="helper-text error-color-text">Please select an option.</span>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup modal
|
||||
tmp = document.createElement('div');
|
||||
tmp.innerHTML = `
|
||||
<div class="modal">
|
||||
<div class="modal-content">
|
||||
<h4><i class="material-icons left">file_upload</i>Uploading files...</h4>
|
||||
<div class="progress">
|
||||
<div class="determinate" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="btn red waves-effect waves-light abort">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
`.trim();
|
||||
modalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
|
||||
modal = M.Modal.init(
|
||||
modalElement,
|
||||
{
|
||||
dismissible: false,
|
||||
onCloseEnd: () => {
|
||||
modal.destroy();
|
||||
modalElement.remove();
|
||||
}
|
||||
}
|
||||
);
|
||||
modal.open();
|
||||
|
||||
// Setup abort handling
|
||||
abortElement = modalElement.querySelector('.abort');
|
||||
abortElement.addEventListener('click', event => {request.abort();});
|
||||
request.addEventListener('abort', event => {
|
||||
request.abort();
|
||||
modal.close();
|
||||
});
|
||||
|
||||
// Setup load handling (after the request completed)
|
||||
request.addEventListener('load', event => {
|
||||
const response = JSON.parse(request.responseText);
|
||||
let inputError;
|
||||
let inputErrors;
|
||||
let inputFieldElement;
|
||||
let inputName;
|
||||
|
||||
if (request.status === 201) {
|
||||
window.location.href = response.redirect_url;
|
||||
}
|
||||
if (request.status === 400) {
|
||||
for ([inputName, inputErrors] of Object.entries(response)) {
|
||||
inputFieldElement = nopaqueSubmitForm.querySelector(`input[name="${inputName}"], select[name="${inputName}"]`).closest('.input-field');
|
||||
for (inputError of inputErrors) {
|
||||
inputFieldElement.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
`<span class="helper-text red-text">${inputError}</span>`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (request.status === 500) {
|
||||
location.reload();
|
||||
}
|
||||
modal.close();
|
||||
});
|
||||
|
||||
// Setup progress handling
|
||||
progressElement = modalElement.querySelector('.progress > .determinate');
|
||||
request.upload.addEventListener('progress', event => {
|
||||
const progress = Math.floor(100 * event.loaded / event.total);
|
||||
progressElement.style.width = `${progress}%`;
|
||||
});
|
||||
|
||||
request.open('POST', window.location.href);
|
||||
request.send(new FormData(nopaqueSubmitForm));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nopaque.RessourceList = {};
|
||||
nopaque.RessourceList.autoInit = () => {
|
||||
const nopaqueRessourceListElements = document.querySelectorAll('.nopaque-ressource-list[data-ressource-type]:not(.no-autoinit)');
|
||||
let nopaqueRessourceListElement;
|
||||
|
||||
for (nopaqueRessourceListElement of nopaqueRessourceListElements) {
|
||||
switch (nopaqueRessourceListElement.dataset.ressourceType) {
|
||||
case 'Corpus':
|
||||
new CorpusList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'CorpusFile':
|
||||
new CorpusFileList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'Job':
|
||||
new JobList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'JobInput':
|
||||
new JobInputList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'JobResult':
|
||||
new JobResultList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'QueryResult':
|
||||
new QueryResultList(nopaqueRessourceListElement);
|
||||
break;
|
||||
case 'User':
|
||||
new UserList(nopaqueRessourceListElement);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
<script src="{{ url_for('static', filename='js/socket.io.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/nopaque/App.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/nopaque/JobStatusNotifier.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/nopaque/main.js') }}"></script>
|
||||
{% assets filters='rjsmin', output="js/nopaque/RessourceDisplays.min.bundle.js",
|
||||
"js/nopaque/RessourceDisplays/RessourceDisplay.js",
|
||||
"js/nopaque/RessourceDisplays/CorpusDisplay.js",
|
||||
@ -27,6 +26,7 @@
|
||||
"js/nopaque/RessourceLists/UserList.js" %}
|
||||
<script src="{{ ASSET_URL }}"></script>
|
||||
{% endassets %}
|
||||
<script src="{{ url_for('static', filename='js/nopaque/UploadForm.js') }}"></script>
|
||||
<script>
|
||||
// Disable all option elements with no value
|
||||
for (let optionElement of document.querySelectorAll('option[value=""]')) {optionElement.disabled = true;}
|
||||
@ -40,7 +40,7 @@
|
||||
app.addEventListener('users.patch', patch => jobStatusNotifier.usersPatchHandler(patch));
|
||||
app.getUserById(currentUserId).then(user => {}, error => {throw JSON.stringify(error)});
|
||||
{% endif %}
|
||||
nopaque.Forms.autoInit();
|
||||
nopaque.RessourceList.autoInit();
|
||||
UploadForm.autoInit();
|
||||
RessourceList.autoInit();
|
||||
for (let flashedMessage of {{ get_flashed_messages(with_categories=True)|tojson }}) {app.flash(flashedMessage[1], flashedMessage[0]);}
|
||||
</script>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col s12 m8">
|
||||
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
|
||||
<form class="nopaque-upload-form" data-progress-modal="progress-modal">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
{{ form.hidden_tag() }}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col s12 m8">
|
||||
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
|
||||
<form class="nopaque-upload-form" data-progress-modal="progress-modal">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
{{ form.hidden_tag() }}
|
||||
|
@ -39,7 +39,7 @@
|
||||
<div class="col s12">
|
||||
<h2>Submit a job</h2>
|
||||
<div class="card">
|
||||
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
|
||||
<form class="nopaque-upload-form" data-progress-modal="progress-modal">
|
||||
<div class="card-content">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="row">
|
||||
@ -66,18 +66,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock page_content %}
|
||||
|
||||
{% block modals %}
|
||||
{{ super() }}
|
||||
<div id="progress-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4><i class="material-icons prefix">file_upload</i> Uploading files...</h4>
|
||||
<div class="progress">
|
||||
<div class="determinate" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock modals %}
|
||||
|
@ -57,7 +57,7 @@
|
||||
<div class="col s12">
|
||||
<h2>Submit a job</h2>
|
||||
<div class="card">
|
||||
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
|
||||
<form class="nopaque-upload-form" data-progress-modal="progress-modal">
|
||||
<div class="card-content">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="row">
|
||||
|
@ -39,7 +39,7 @@
|
||||
<div class="col s12">
|
||||
<h2>Submit a job</h2>
|
||||
<div class="card">
|
||||
<form class="nopaque-submit-form" data-progress-modal="progress-modal">
|
||||
<form class="nopaque-upload-form" data-progress-modal="progress-modal">
|
||||
<div class="card-content">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="row">
|
||||
|
Loading…
Reference in New Issue
Block a user