diff --git a/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css b/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css index b69d4dc4cf8a2fd900e7ad1debdf79650ce9f2d2..3019f60766ac4a5acd7bd342ea5a4ae57e0d6413 100644 --- a/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css +++ b/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css @@ -85,7 +85,7 @@ ol { color: #e6e6e6; text-decoration: none; } -.annotation-header-title { +.annotation-header-data { display: flex; flex-flow: column; width: calc(100% - 40px); @@ -123,7 +123,7 @@ ol { .annotation-footer span { margin-left: 5px; } -.annotation-footer-delete { +.annotation-footer-edit { margin-right: 5px; cursor: pointer; } diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js index 7ca850714f87359c130171de86eed305354b345e..5a18f3fde00b2d000e819670fc0f2fd0331a7245 100644 --- a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js +++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js @@ -44,8 +44,6 @@ $(document).ready(function() { location.href="givefeedback.jsp?token=" + getUserTokenFromUrl(); }); - - /** * validation of annotation create form inside the modal */ @@ -72,6 +70,32 @@ $(document).ready(function() { } }); + /** + * validation of annotation edit form inside the modal + */ + $('#annotation-edit-form').validate({ + rules: { + title: { + required: true, + maxlength: 120 + }, + comment: { + required: true, + maxlength: 400 + } + }, + messages: { + title: { + required: "Ein Titel wird benötigt", + maxlength: "Maximal 120 Zeichen erlaubt" + }, + comment: { + required: "Ein Kommentar wird benötigt", + maxlength: "Maximal 400 Zeichen erlaubt" + } + } + }); + /** * Save button of the annotation create modal * hide modal and build new annotation @@ -91,7 +115,66 @@ $(document).ready(function() { }); /** - * Clear the title and comment input field of the modal + * Edit button of the annotation edit modal + * hide modal and alter the annotation + */ + $('#btnEdit').click(function () { + if ($('#annotation-edit-form').valid()) { + // get title and comment from clicked annotation card + var id = $('#annotation-edit-modal').data('id'); + var card = $('#' + id); + var title = card.find('.annotation-header-data-title').text(); + var comment = card.find('.annotation-body-text').text(); + + // get title and comment from form + var newTitle = $('#annotation-edit-form-title').val(); + var newComment = $('#annotation-edit-form-comment').val(); + + // compare new and old card content + if (title !== newTitle || comment !== newComment) { + + // build patch request + var annotationPatchRequest = { + title: newTitle, + comment: newComment + }; + // send alter request to server + alterAnnotation(id, annotationPatchRequest, function (response) { + // alter the annotation card + card.find('.annotation-header-data-title').text(newTitle); + card.find('.annotation-body-text').text(newComment); + + // handle drop down button + showAndHideToggleButton(); + + // hide and clear the modal + $('#annotation-edit-modal').modal('hide'); + }) + } + } + }); + + /** + * Delete an annotation from list and server + */ + $('#btnDelete').click(function () { + // get id from edit modal + var id = $('#annotation-edit-modal').data('id'); + + // delte annotation from server and from list + deleteAnnotation(id, function () { + // remove annotation from list + $('#' + id).closest('.listelement').remove() + // remove highlighted text + deleteHighlightedText(); + + // hide and clear the modal + $('#annotation-edit-modal').modal('hide'); + }) + }); + + /** + * Clear the title and comment input field of the create modal */ $('#annotation-create-modal').on('hidden.bs.modal', function(){ // clear title @@ -100,6 +183,16 @@ $(document).ready(function() { $('#annotation-form-comment').val('') }); + /** + * Clear the title and comment input field of the edit modal + */ + $('#annotation-edit-modal').on('hidden.bs.modal', function(e){ + // clear title + $('#annotation-edit-form-title').val(''); + // clear comment + $('#annotation-edit-form-comment').val('') + }); + documentText = $('#documentText').html(); // fetch annotations from server on page start @@ -108,10 +201,20 @@ $(document).ready(function() { $.each(response, function (i, annotation) { displayAnnotation(annotation); }) + // handle drop down button + showAndHideToggleButton(); }); }); +/** + * This will be called on page resize + */ +$( window ).resize(function() { + // handle drop down button for every annotation + showAndHideToggleButton(); +}); + /** * POST: Save an annotation in the database * @@ -160,14 +263,14 @@ function alterAnnotation(id, annotationPatchRequest, responseHandler) { * * @param id The annotation id */ -function deleteAnnotation(id) { +function deleteAnnotation(id, responseHandler) { var url = "../rest/annotations/" + id; $.ajax({ url: url, type: "DELETE", dataType: "json", success: function (response) { - // Nothing to do + responseHandler(response) } }); } @@ -196,21 +299,6 @@ function getAnnotations(targetId, responseHandler) { }); } -/** - * Delete annotation from list - * - * @param elem The parent li element - * @param id The id of the annotation - */ -function deleteAnnotationHandler(elem, id) { - // remove annotation from list - elem.remove() - // remove highlighted text - deleteHighlightedText(); - // remove annotation from database - deleteAnnotation(id) -} - /** * Display annotation in the list * @@ -220,7 +308,7 @@ function displayAnnotation(annotation) { // fetch list of annotations var list = $('#annotations') - var deleteIcon = "fas fa-trash"; + var editIcon = "fas fa-edit"; var dateIcon = "fas fa-calendar"; if (isTimestampToday(annotation.timestamp)) { dateIcon = "fas fa-clock"; @@ -234,6 +322,7 @@ function displayAnnotation(annotation) { .append( // annotation card $('<div>').attr('class', 'annotation-card') + .attr('id', annotation.id) .mouseenter(function () { $(this).children('.annotation-header').css('background-color', getDarkUserColor(annotation.userToken)); }) @@ -246,7 +335,7 @@ function displayAnnotation(annotation) { .css('background-color', getUserColor(annotation.userToken)) .append( // header data - $('<div>').attr('class', 'annotation-header-title') + $('<div>').attr('class', 'annotation-header-data') .append( // user $('<div>').attr('class', 'overflow-hidden') @@ -264,7 +353,7 @@ function displayAnnotation(annotation) { $('<i>').attr('class', 'fas fa-bookmark') ) .append( - $('<span>').append(annotation.body.title) + $('<span>').attr('class', 'annotation-header-data-title').append(annotation.body.title) ) ) ) @@ -272,7 +361,7 @@ function displayAnnotation(annotation) { // unfold button $('<div>').attr('class', 'annotation-header-toggle') .click(function () { - toggleButtonHandler($(this)); + toggleButtonHandler(annotation.id); }) .append( $('<i>').attr('class', 'fas fa-chevron-down') @@ -283,22 +372,22 @@ function displayAnnotation(annotation) { // annotation body $('<div>').attr('class', 'annotation-body') .append( - $('<p>').attr('class', 'overflow-hidden').append(annotation.body.comment) + $('<p>').attr('class', 'overflow-hidden annotation-body-text').append(annotation.body.comment) ) ) .append( // annotation footer $('<div>').attr('class', 'annotation-footer') .append( - // delete + // edit function () { if (userToken == annotation.userToken) { - return $('<div>').attr('class', 'annotation-footer-delete') + return $('<div>').attr('class', 'annotation-footer-edit') .append( - $('<i>').attr('class', deleteIcon) + $('<i>').attr('class', editIcon) ) .click(function () { - deleteAnnotationHandler($(this).closest('li'), annotation.id) + editAnnotationHandler(annotation.id) }) } } @@ -439,29 +528,27 @@ function timestampToReadableTime(timestamp) { // declare response var responseTimestamp; + // get hours from date + var hours = "0" + annotationDate.getHours(); + // get minutes from date + var minutes = "0" + annotationDate.getMinutes(); + // if annotation is from today if (isTimestampToday(timestamp)) { - // get hours from date - var hours = annotationDate.getHours(); - // get minutes from date - var minutes = "0" + annotationDate.getMinutes(); - // get seconds from date - // var seconds = "0" + annotationDate.getSeconds(); - - // build readable timestamp - responseTimestamp = hours + ":" + minutes.substr(-2); + // build readable timestamp in format HH:mm + responseTimestamp = hours.substr(-2) + ":" + minutes.substr(-2); } // else annotation is not from today else { // get date - var date = annotationDate.getDate(); + var date = "0" + annotationDate.getDate(); // get month - var month = annotationDate.getMonth(); + var month = "0" + annotationDate.getMonth(); // get year - var year = annotationDate.getFullYear(); + var year = "" + annotationDate.getFullYear(); - // build readable timestamp - responseTimestamp = date + "." + month + "." + year; + // build readable timestamp dd.MM.yy HH:mm + responseTimestamp = date.substr(-2) + "." + month.substr(-2) + "." + year.substr(-2) + " " + hours.substr(-2) + ":" + minutes.substr(-2); } return responseTimestamp; @@ -491,13 +578,15 @@ function isTimestampToday(timestamp) { /** * Toggle between the toggle button status * - * @param element The given toggle button + * @param id The id of the clicked annotation */ -function toggleButtonHandler(element) { +function toggleButtonHandler(id) { + // the clicked annotation card + var card = $('#' + id); // open and close annotation text - element.parent().siblings(".annotation-body").children("p").toggleClass("overflow-hidden"); + card.find(".annotation-body").children("p").toggleClass("overflow-hidden"); // toggle between up and down button - element.children("i").toggleClass("fa-chevron-down fa-chevron-up") + card.find('.annotation-header-toggle').children("i").toggleClass("fa-chevron-down fa-chevron-up") } /** @@ -528,3 +617,52 @@ function saveNewAnnotation(title, comment, startCharacter, endCharacter) { }); } + +/** + * Open edit modal with title and comment from given card + * + * @param id The id of the clicked annotation + */ +function editAnnotationHandler(id) { + // the clicked annotation card + var card = $('#' + id); + // get title and comment + var title = card.find('.annotation-header-data-title').text(); + var comment = card.find('.annotation-body-text').text(); + + // set title and comment + $('#annotation-edit-form-title').val(title); + $('#annotation-edit-form-comment').val(comment); + + // display annotation edit modal and pass id + $('#annotation-edit-modal').data('id', id).modal("show"); +} + +/** + * Show or hide the drop down button for every annotation card. + * Call this on page resize and after annotations GET + */ +function showAndHideToggleButton() { + // iterate over each annotation card + $('#annotations').find('li').each(function () { + + // find the comment element, clone and hide it + var comment = $(this).find('.annotation-body').children('p'); + var clone = comment.clone() + .css({display: 'inline', width: 'auto', visibility: 'hidden'}) + .appendTo('body'); + var cloneWidth = clone.width(); + + // remove the element from the page + clone.remove(); + + // show drop down button only if text was truncated + if(cloneWidth > comment.width()) { + $(this).find('.annotation-header-toggle').show(); + } + else { + $(this).find('.annotation-header-toggle').hide(); + } + + }) +} diff --git a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp index 1b1515c1712672bbae51adc783f37c9800176678..36738f2a5114c65cbb42722c95910d842442156c 100644 --- a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp +++ b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp @@ -105,13 +105,45 @@ </form> <!-- modal footer --> <div class="modal-footer"> - <button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button> <button id="btnSave" type="button" class="btn btn-success">Speichern</button> </div> </div> </div> </div> </div> + + <!-- annotation edit modal --> + <div id="annotation-edit-modal" class="modal fade" role="dialog"> + <div class="modal-dialog modal-dialog-centered modal-sm"> + <div class="modal-content"> + + <!-- modal header --> + <div class="modal-header flex"> + <h4 class="modal-title flex-one">Annotation bearbeiten</h4> + <button type="button" class="close" data-dismiss="modal">×</button> + </div> + + <!-- modal body --> + <div class="modal-body"> + <form id="annotation-edit-form"> + <div class="form-group"> + <label for="annotation-form-title" class="col-form-label">Titel:</label> + <input type="text" class="form-control" id="annotation-edit-form-title" name="title"> + </div> + <div class="form-group"> + <label for="annotation-form-comment" class="col-form-label">Kommentar:</label> + <textarea class="form-control resize-vertical" id="annotation-edit-form-comment" name="comment"></textarea> + </div> + </form> + <!-- modal footer --> + <div class="modal-footer"> + <button id="btnDelete" type="button" class="btn btn-danger">Löschen</button> + <button id="btnEdit" type="button" class="btn btn-success">Bearbeiten</button> + </div> + </div> + </div> + </div> + </div> </div> </body>