mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
New logic for forms including file upload.
This commit is contained in:
parent
7acb3b40c2
commit
131afd6419
18
app/static/js/Forms/CreateCorpusFileForm.js
Normal file
18
app/static/js/Forms/CreateCorpusFileForm.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
class CreateCorpusFileForm extends Form {
|
||||||
|
static autoInit() {
|
||||||
|
let createCorpusFileFormElements = document.querySelectorAll('.create-corpus-file-form');
|
||||||
|
for (let createCorpusFileFormElement of createCorpusFileFormElements) {
|
||||||
|
new CreateCorpusFileForm(createCorpusFileFormElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(formElement) {
|
||||||
|
super(formElement);
|
||||||
|
|
||||||
|
this.addEventListener('requestLoad', (event) => {
|
||||||
|
if (event.target.status === 201) {
|
||||||
|
window.location.href = event.target.getResponseHeader('Location');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
25
app/static/js/Forms/CreateJobForm.js
Normal file
25
app/static/js/Forms/CreateJobForm.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
class CreateJobForm extends Form {
|
||||||
|
static autoInit() {
|
||||||
|
let createJobFormElements = document.querySelectorAll('.create-job-form');
|
||||||
|
for (let createJobFormElement of createJobFormElements) {
|
||||||
|
new CreateJobForm(createJobFormElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(formElement) {
|
||||||
|
super(formElement);
|
||||||
|
|
||||||
|
let versionField = this.formElement.querySelector('#create-job-form-version');
|
||||||
|
versionField.addEventListener('change', (event) => {
|
||||||
|
let url = new URL(window.location.href);
|
||||||
|
url.search = `?version=${event.target.value}`;
|
||||||
|
window.location.href = url.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addEventListener('requestLoad', (event) => {
|
||||||
|
if (event.target.status === 201) {
|
||||||
|
window.location.href = event.target.getResponseHeader('Location');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
141
app/static/js/Forms/Form.js
Normal file
141
app/static/js/Forms/Form.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
class Form {
|
||||||
|
static autoInit() {
|
||||||
|
CreateCorpusFileForm.autoInit();
|
||||||
|
CreateJobForm.autoInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(formElement) {
|
||||||
|
this.formElement = formElement;
|
||||||
|
this.eventListeners = {
|
||||||
|
'requestLoad': []
|
||||||
|
};
|
||||||
|
this.afterRequestListeners = [];
|
||||||
|
|
||||||
|
for (let selectElement of this.formElement.querySelectorAll('select')) {
|
||||||
|
selectElement.removeAttribute('required');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.formElement.addEventListener('submit', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this.submit(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener(eventType, listener) {
|
||||||
|
if (eventType in this.eventListeners) {
|
||||||
|
this.eventListeners[eventType].push(listener);
|
||||||
|
} else {
|
||||||
|
throw `Unknown event type ${eventType}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submit(event) {
|
||||||
|
let request = new XMLHttpRequest();
|
||||||
|
let modalElement = Utils.elementFromString(
|
||||||
|
`
|
||||||
|
<div class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h4><i class="material-icons left">file_upload</i>Submitting...</h4>
|
||||||
|
<div class="progress">
|
||||||
|
<div class="determinate" style="width: 0%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="action-button btn red waves-effect waves-light modal-close" data-action="cancel">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
document.querySelector('#modals').appendChild(modalElement);
|
||||||
|
let modal = M.Modal.init(
|
||||||
|
modalElement,
|
||||||
|
{
|
||||||
|
dismissible: false,
|
||||||
|
onCloseEnd: () => {
|
||||||
|
modal.destroy();
|
||||||
|
modalElement.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
modal.open();
|
||||||
|
|
||||||
|
// Remove all previous helper text elements that indicate errors
|
||||||
|
let errorHelperTextElements = this.formElement
|
||||||
|
.querySelectorAll('.helper-text[data-helper-text-type="error"]');
|
||||||
|
for (let errorHelperTextElement of errorHelperTextElements) {
|
||||||
|
errorHelperTextElement.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if select elements are filled out properly
|
||||||
|
for (let selectElement of this.formElement.querySelectorAll('select')) {
|
||||||
|
if (selectElement.value === '') {
|
||||||
|
let inputFieldElement = selectElement.closest('.input-field');
|
||||||
|
let errorHelperTextElement = Utils.elementFromString(
|
||||||
|
'<span class="helper-text error-color-text" data-helper-text-type="error">Please select an option.</span>'
|
||||||
|
);
|
||||||
|
inputFieldElement.appendChild(errorHelperTextElement);
|
||||||
|
inputFieldElement.querySelector('.select-dropdown').classList.add('invalid');
|
||||||
|
modal.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup abort handling
|
||||||
|
let cancelElement = modalElement.querySelector('.action-button[data-action="cancel"]');
|
||||||
|
cancelElement.addEventListener('click', (event) => {request.abort();});
|
||||||
|
|
||||||
|
// Setup load handling (after the request completed)
|
||||||
|
request.addEventListener('load', (event) => {
|
||||||
|
for (let listener of this.eventListeners['requestLoad']) {
|
||||||
|
listener(event);
|
||||||
|
}
|
||||||
|
if (request.status === 400) {
|
||||||
|
let responseJson = JSON.parse(request.responseText);
|
||||||
|
console.log(responseJson);
|
||||||
|
for (let [inputName, inputErrors] of Object.entries(responseJson.errors)) {
|
||||||
|
let inputFieldElement = this.formElement
|
||||||
|
.querySelector(`input[name$="${inputName}"], select[name$="${inputName}"]`)
|
||||||
|
.closest('.input-field');
|
||||||
|
for (let inputError of inputErrors) {
|
||||||
|
let errorHelperTextElement = Utils.elementFromString(
|
||||||
|
`<span class="helper-text error-color-text" data-helper-type="error">${inputError}</span>`
|
||||||
|
);
|
||||||
|
inputFieldElement.appendChild(errorHelperTextElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request.status === 500) {
|
||||||
|
app.flash('Internal Server Error', 'error');
|
||||||
|
}
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup progress handling
|
||||||
|
let progressBarElement = modalElement.querySelector('.progress > .determinate');
|
||||||
|
request.upload.addEventListener('progress', (event) => {
|
||||||
|
let progress = Math.floor(100 * event.loaded / event.total);
|
||||||
|
progressBarElement.style.width = `${progress}%`;
|
||||||
|
});
|
||||||
|
|
||||||
|
request.open(this.formElement.method, this.formElement.action);
|
||||||
|
request.setRequestHeader('Accept', 'application/json');
|
||||||
|
let formData = new FormData(this.formElement);
|
||||||
|
switch (this.formElement.enctype) {
|
||||||
|
case 'application/x-www-form-urlencoded':
|
||||||
|
let urlSearchParams = new URLSearchParams(formData);
|
||||||
|
request.send(urlSearchParams);
|
||||||
|
break;
|
||||||
|
case 'multipart/form-data': {
|
||||||
|
request.send(formData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'text/plain': {
|
||||||
|
throw 'enctype "text/plain" is not supported';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user