diff --git a/frontend/src/utils/exam-correct/exam-correct.js b/frontend/src/utils/exam-correct/exam-correct.js index f9ab25fa7..aa76ea9ad 100644 --- a/frontend/src/utils/exam-correct/exam-correct.js +++ b/frontend/src/utils/exam-correct/exam-correct.js @@ -1,7 +1,7 @@ import { Utility } from '../../core/utility'; import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; -// import './exam-correct.sass'; +import './exam-correct.sass'; import moment from 'moment'; @@ -12,6 +12,8 @@ const EXAM_CORRECT_SEND_BTN_ID = 'exam-correct__send-btn'; const EXAM_CORRECT_PARTICIPANT_INPUT_ID = 'exam-correct__participant'; const EXAM_CORRECT_INPUT_BODY_ID = 'exam-correct__new'; +const INPUT_EMPTY_CLASS = 'input--invalid'; + @Utility({ selector: `table[${EXAM_CORRECT_IDENT}]`, @@ -51,9 +53,9 @@ export class ExamCorrect { } destroy() { - // TODO work in progress this._sendBtn.removeEventListener('click', this._sendCorrectionHandler); this._participantInput.removeEventListener('change', this._validateParticipantInput); + this._participantInput.removeEventListener('input', this._removeInputEmptyClassHandler); } _validateParticipantInput(event) { @@ -63,18 +65,36 @@ export class ExamCorrect { _sendCorrectionHandler(event) { console.log('WIP _sendCorrectionHandler', event); + // refocus participant input element for convenience + this._participantInput.focus(); + const participant = this._participantInput.value; + + // abort send if the participant input is empty + if (!participant) { + this._participantInput.classList.add(INPUT_EMPTY_CLASS); + this._participantInput.addEventListener('input', this._removeInputEmptyClassHandler.bind(this), { once: true }); + return; + } + const results = {}; this._partInputs.forEach((input) => { if (input.value && !isNaN(input.value)) { + // TODO instead of ignoring NaN values, abort send and add error class to corresponding input + // (latter is optional) const partKey = input.getAttribute(EXAM_CORRECT_PART_INPUT_ATTR); if (!partKey) throw new Error('Exam part input without part attribute!'); - results[partKey] = input.value; + results[partKey] = parseFloat(input.value); } }); + // abort send if there are no results (after validation) + if (results === {}) return; + console.log(participant, results); + // TODO apply row and data classes + // (maybe create some sort of template for this instead) const correctionRow = document.createElement('TR'); const dateTD = document.createElement('TD'); dateTD.appendChild(document.createTextNode(moment().format())); @@ -91,11 +111,8 @@ export class ExamCorrect { const tableBody = this._element.querySelector(`tbody:not(#${EXAM_CORRECT_INPUT_BODY_ID})`); tableBody.insertBefore(correctionRow, tableBody.firstChild); - this._participantInput.value = null; - console.log(this._partInputs); - this._partInputs.forEach((input) => { - input.value = null; - }); + // clear input values on validation success + [this._participantInput, ...this._partInputs].forEach(clearInput); const url = 'TODO'; const headers = {}; @@ -103,6 +120,7 @@ export class ExamCorrect { participant: participant, results: results, }; + this._app.httpClient.post({ url: url, headers: headers, @@ -110,13 +128,37 @@ export class ExamCorrect { }).then( (response) => response.json() ).then( - (response) => this._processResponse(response) + (response) => this._processResponse(response, participant) ).catch((error) => { - // TODO - console.error('Error while processing response', error, body); + console.error('Error while processing response', error); }); // TODO wait for response and replace status icon accordingly (add edit button to paste content in current input) } + _processResponse(response, participant) { + console.log('WIP ExamCorrect._processResponse', response, participant); + + // TODO find the first corresponding row (participant matches cell entry in second column) top-down + // if found: + // if the response status is 'success' (i.e. the results have been upserted into the DB), + // replace loading spinner in this row with tick mark icon + // otherwise, + // replace loading spinner with error icon (error message as tooltip if present?) + } + + _removeInputEmptyClassHandler() { + console.log('removeclass'); + if (this._participantInput.value) { + this._participantInput.classList.remove(INPUT_EMPTY_CLASS); + } else { + this._participantInput.addEventListener('input', this._removeInputEmptyClassHandler, { once: true }); + } + } + +} + +// TODO move to general util section? +function clearInput(inputElement) { + inputElement.value = null; } diff --git a/frontend/src/utils/exam-correct/exam-correct.sass b/frontend/src/utils/exam-correct/exam-correct.sass new file mode 100644 index 000000000..a6a646bed --- /dev/null +++ b/frontend/src/utils/exam-correct/exam-correct.sass @@ -0,0 +1,2 @@ +#exam-correct__participant.input--invalid + border: 2px solid var(--color-error)