From 07c2af98413475307b59ab6cd0e9e056412bb60c Mon Sep 17 00:00:00 2001 From: Hugo Zilliox Date: Tue, 27 Dec 2022 18:20:10 +0100 Subject: [PATCH] Trying to remove jQuery code as much as possible --- assets/javascripts/issue_dynamic_edit.js | 447 ++++++++++++---------- assets/stylesheets/issue_dynamic_edit.css | 3 + lib/details_issue_hooks.rb | 2 +- 3 files changed, 250 insertions(+), 202 deletions(-) diff --git a/assets/javascripts/issue_dynamic_edit.js b/assets/javascripts/issue_dynamic_edit.js index 1fa6d16..18fd8ec 100644 --- a/assets/javascripts/issue_dynamic_edit.js +++ b/assets/javascripts/issue_dynamic_edit.js @@ -16,36 +16,36 @@ _CONF_LISTENER_TARGET = _CONF_LISTENER_TARGET === "all" ? "*" : _CONF_LISTENER_T * Source : https://www.iconfinder.com/iconsets/glyphs */ -var SVG_EDIT = ''; -var SVG_VALID = ''; -var SVG_CANCEL = ''; +const SVG_EDIT = ''; +const SVG_VALID = ''; +const SVG_CANCEL = ''; /* * Allow inclusion from other page * See https://github.com/Ilogeek/redmine_issue_dynamic_edit/commit/26684a2dd9b12dcc7377afd79e9fe5c142d26ebd for more info */ -var LOCATION_HREF = typeof custom_location_href !== 'undefined' ? custom_location_href : window.location.href; +let LOCATION_HREF = typeof custom_location_href !== 'undefined' ? custom_location_href : window.location.href; if (_CONF_FORCE_HTTPS) { LOCATION_HREF = LOCATION_HREF.replace(/^http:\/\//i, 'https://'); } -/* Check if admin want to display all editable fields when hovering the whole details block +/* Check if admin want to display all editable fields when hovering the whole details block * or if user has to hover every element to discover if (s)he can edit it */ if (_CONF_DISPLAY_EDIT_ICON === "block"){ - $('body.controller-issues.action-show .issue.details').addClass('showPencils'); + document.querySelectorAll('body.controller-issues.action-show .issue.details').forEach((elt) => elt.classList.add('showPencils')); } -let updateCSRFToken = function(token){ - document.querySelectorAll('input[name="authenticity_token"]').forEach(elt => elt.value = token); +const updateCSRFToken = function(token){ + document.querySelectorAll('input[name="authenticity_token"]').forEach((elt) => elt.value = token); document.querySelector('meta[name="csrf-token"]').setAttribute("content", token); } -let setCSRFTokenInput = function(token){ - document.querySelectorAll('form[method="post"]').forEach(elt => { +const setCSRFTokenInput = function(token){ + document.querySelectorAll('form[method="post"]').forEach((elt) => { if(!elt.querySelectorAll('input[name="authenticity_token"]').length){ - let input = document.createElement("input"); + const input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "authenticity_token"); input.value = token; @@ -55,50 +55,63 @@ let setCSRFTokenInput = function(token){ } /* Generate edit block */ -var getEditFormHTML = function(attribute){ - var formElement = $('#issue_' + attribute + "_id"); - formElement = formElement.length ? formElement : $('#issue_' + attribute); - formElement = formElement.length ? formElement : $('#' + attribute); +const getEditFormHTML = function(attribute){ + let formElement = document.querySelector('#issue_' + attribute + "_id"); + formElement = formElement ? formElement : document.querySelector('#issue_' + attribute); + formElement = formElement ? formElement : document.querySelector('#' + attribute); // Checkbox specific case - var is_checkboxes = false; + let is_checkboxes = false; let is_file = false; let is_list = false; let CF_ID = false; - if(!formElement.length && attribute.startsWith("custom_field_values_")){ + if(!formElement && attribute.startsWith("custom_field_values_")){ CF_ID = attribute.split("custom_field_values_")[1]; /* Is it a checkbox block ? */ - formElement = $('#issue_custom_field_values_' + CF_ID); - if(formElement.length){ - formElement = formElement.parents('.check_box_group'); + formElement = document.querySelector('#issue_custom_field_values_' + CF_ID); + if(formElement){ + formElement = formElement.closest('.check_box_group'); is_checkboxes = CF_ID; } else { /* Is it a file block ? */ - formElement = $('#issue_custom_field_values_' + CF_ID + '_blank'); - if(formElement.length){ - formElement = formElement.parents('p'); - formElement.find('label').remove(); + formElement = document.querySelector('#issue_custom_field_values_' + CF_ID + '_blank'); + if(formElement){ + formElement = formElement.closest('p'); + formElement.removeChild(formElement.querySelector('label')); is_file = CF_ID; } else { /* Is it a checkbox/radio group ? */ - formElement = $('#issue-form .cf_' + CF_ID + '.check_box_group'); + formElement = document.querySelector('#issue-form .cf_' + CF_ID + '.check_box_group'); is_list = CF_ID; } } } - - if(formElement.length){ - var clone = formElement.clone(); - if(clone.is('select') && !clone.prop('multiple')) clone.on('change', function(e){sendData($(this).serializeArray());}); - if(is_checkboxes || is_file || is_list) { - clone.prop('id', "issue_custom_field_values_" + CF_ID + "_dynamic"); - } else { - clone.prop('id', formElement.prop('id') + "_dynamic"); + + if(formElement){ + const clone = formElement.cloneNode(true); + if(clone.matches('select') && !clone.hasAttribute('multiple')) { + clone.addEventListener('change', function(e){ + sendData([{"name" : clone.getAttribute('name'), "value" : clone.value}]); + }); } - var wrapper = $("
").addClass('dynamicEditField'); - wrapper.append(clone); - if(!clone.is('select') || clone.prop('multiple')) wrapper.append(""); - wrapper.append(""); + if(is_checkboxes || is_file || is_list) { + clone.setAttribute('id', "issue_custom_field_values_" + CF_ID + "_dynamic"); + } else { + clone.setAttribute('id', formElement.getAttribute('id') + "_dynamic"); + } + const wrapper = document.createElement('div'); + wrapper.classList.add('dynamicEditField'); + wrapper.insertBefore(clone, null); + if(!clone.matches('select') || clone.hasAttribute('multiple')) { + let btn_valid = document.createElement('button'); + btn_valid.classList.add('action', 'valid'); + btn_valid.innerHTML = SVG_VALID; + wrapper.insertBefore(btn_valid, null); + } + const btn_refuse = document.createElement('button'); + btn_refuse.classList.add('action', 'refuse'); + btn_refuse.innerHTML = SVG_CANCEL; + wrapper.insertBefore(btn_refuse, null); return wrapper; } @@ -106,17 +119,24 @@ var getEditFormHTML = function(attribute){ } /* Loop over all form attribute and clone them into details part */ -var cloneEditForm = function(){ - $('.issue.details div.subject').append(''); - $(".issue.details ").wrap("
"); +const cloneEditForm = function(){ + const btn_refresh = document.createElement('button'); + btn_refresh.classList.add('refreshData'); + btn_refresh.innerHTML = "⟳"; + document.querySelector('.issue.details div.subject').insertBefore(btn_refresh, null); - $('div.issue.details .attribute').each(function(){ - var classList = $(this).attr('class').split(/\s+/); - - var attributes = classList.filter(function(elem) { return elem != "attribute"; }); + const wrapper = document.createElement('form'); + wrapper.setAttribute('id', 'fakeDynamicForm'); + document.querySelector('.issue.details').parentNode.insertBefore(wrapper, document.querySelector('.issue.details')); + wrapper.appendChild(document.querySelector('.issue.details')); + + document.querySelectorAll('div.issue.details .attribute').forEach(function(elt){ + const classList = elt.classList.value.split(/\s+/); + + let attributes = classList.filter(function(elem) { return elem != "attribute"; }); // Specific case : all "-" are replaced by "_" into form id - attributes = attributes.map(attr => attr.replaceAll('-', '_')); - + attributes = attributes.map((attr) => attr.replaceAll('-', '_')); + let custom_field = false; attributes.forEach(function(part, index, arr) { if(arr[index] === "progress") arr[index] = "done_ratio"; @@ -125,136 +145,176 @@ var cloneEditForm = function(){ custom_field = arr[index]; } }); - + attributes = attributes.join(" "); let selected_elt = custom_field ? custom_field : attributes; if(attributes && !_CONF_EXCLUDED_FIELD_ID.includes(selected_elt)){ let dynamicEditField = getEditFormHTML(selected_elt); - if(dynamicEditField) $(this).find('.value').append(" " + SVG_EDIT + "").append(dynamicEditField); + if(dynamicEditField){ + let btn_edit = document.createElement('span'); + btn_edit.classList.add('iconEdit'); + btn_edit.innerHTML = SVG_EDIT; + elt.querySelector('.value').insertBefore(btn_edit, null); + elt.querySelector('.value').insertBefore(dynamicEditField, null); + } } }); // Specific Case : Description field if(!_CONF_EXCLUDED_FIELD_ID.includes("description") && document.querySelectorAll('div.issue.details .description').length){ - $('div.issue.details .description > p').first().find('strong').after(" " + SVG_EDIT + ""); - var formDescription = getEditFormHTML("description"); - formDescription.find("#issue_description_dynamic").removeAttr('data-tribute'); - $('div.issue.details .description').append(formDescription); + const btn_edit = document.createElement('span'); + btn_edit.classList.add('iconEdit'); + btn_edit.innerHTML = SVG_EDIT; + document.querySelector('div.issue.details .description > p strong').insertAdjacentElement("afterend", btn_edit); + const formDescription = getEditFormHTML("description"); + formDescription.querySelector("#issue_description_dynamic").removeAttribute('data-tribute'); + document.querySelector('div.issue.details .description').insertBefore(formDescription, null); if ( typeof(CKEDITOR) === "object" && typeof(CKEDITOR.instances['issue_description'] !== "undefined") && typeof(CKEDITOR.instances['issue_description'].getData) === typeof(Function) ) { - var cfg = CKEDITOR.instances['issue_description'].config; + const cfg = CKEDITOR.instances['issue_description'].config; cfg.height = 100; CKEDITOR.replace("issue_description_dynamic", cfg) }else if (typeof(jsToolBar) === typeof(Function)) { - var wikiToolbar = new jsToolBar(document.getElementById('issue_description_dynamic')); wikiToolbar.draw(); + const wikiToolbar = new jsToolBar(document.querySelector('#issue_description_dynamic')); wikiToolbar.draw(); } } // Specific Case : Title field if(!_CONF_EXCLUDED_FIELD_ID.includes("subject")){ - $('div.issue.details div.subject h3').append(" " + SVG_EDIT + ""); - var formTitle = getEditFormHTML("issue_subject"); - $('div.issue.details div.subject').append(formTitle); + const btn_edit = document.createElement('span'); + btn_edit.classList.add('iconEdit'); + btn_edit.innerHTML = SVG_EDIT; + document.querySelector('div.issue.details div.subject h3').insertBefore(btn_edit, null); + const formTitle = getEditFormHTML("issue_subject"); + document.querySelector('div.issue.details div.subject').insertBefore(formTitle, null); } } -/* Perform action on .value (display edit form) */ -$('body').on(_CONF_LISTENER_TYPE_VALUE, - 'div.issue.details .attributes .attribute .' + _CONF_LISTENER_TARGET + ', div.issue.details div.description > p, div.issue.details div.subject', +/* Perform action on .value (display edit form) */ +document.querySelector('body').addEventListener(_CONF_LISTENER_TYPE_VALUE, function(e){ - if($(e.target).closest('.dynamicEditField').length) return; /* We're already into a dynamic field, ignore */ - $('.dynamicEditField').each(function(e){ $(this).removeClass('open'); }); - if(!$(e.target).closest('a').length && !$(e.target).closest('button').length){ - if($(this).parent().hasClass('description')){ - $(this).parent().find('.dynamicEditField').addClass('open'); - } else { - $(this).find('.dynamicEditField').addClass('open'); + let is_attribute = e.target.matches('div.issue.details .attributes .attribute .' + _CONF_LISTENER_TARGET) || e.target.closest('div.issue.details .attributes .attribute .' + _CONF_LISTENER_TARGET); + let is_description = e.target.matches('div.issue.details div.description > p') || e.target.closest('div.issue.details div.description > p'); + let is_subject = e.target.matches('div.issue.details div.subject') || e.target.closest('div.issue.details div.subject'); + if(is_attribute || is_description || is_subject ){ + if(e.target.closest('.dynamicEditField')) return; /* We're already into a dynamic field, ignore */ + document.querySelectorAll('.dynamicEditField').forEach(function(elt){ elt.classList.remove('open'); }); + if(!e.target.closest('a') && !e.target.closest('button')){ + let selector = e.target.closest('.value'); + if(is_description) selector = e.target.closest('.description'); + if(is_subject) selector = e.target.closest('.subject'); + selector.querySelector('.dynamicEditField').classList.add('open'); } } }); /* Perform action on .iconEdit (display edit form) */ -$('body').on(_CONF_LISTENER_TYPE_ICON, - 'div.issue.details .iconEdit', function(e){ - $('.dynamicEditField').each(function(e){ $(this).removeClass('open'); }); - $(this).parent().find('.dynamicEditField').addClass('open'); +document.querySelector('body').addEventListener(_CONF_LISTENER_TYPE_ICON, function(e){ + let is_attribute = e.target.matches('div.issue.details .attributes .attribute .' + _CONF_LISTENER_TARGET) || e.target.closest('div.issue.details .attributes .attribute .' + _CONF_LISTENER_TARGET); + let is_description = e.target.matches('div.issue.details div.description > p') || e.target.closest('div.issue.details div.description > p'); + let is_subject = e.target.matches('div.issue.details div.subject') || e.target.closest('div.issue.details div.subject'); + if(e.target.matches('.iconEdit') || e.target.closest('.iconEdit')){ + document.querySelectorAll('.dynamicEditField').forEach(function(elt){ elt.classList.remove('open'); }); + let selector = e.target.closest('.value'); + if(is_description) selector = e.target.closest('.description'); + if(is_subject) selector = e.target.closest('.subject'); + selector.querySelector('.dynamicEditField').classList.add('open'); + } }); /* Perform data update when clicking on valid button from edit form */ -$('body').on('click', '.dynamicEditField .action.valid', function(e){ - e.preventDefault(); - var input = $(this).parents('.dynamicEditField').find(':input'); - sendData(input.serializeArray()); - $(this).parents('.dynamicEditField').removeClass('open'); +document.querySelector('body').addEventListener('click', function(e){ + if(e.target.matches('.dynamicEditField .action.valid') || e.target.closest('.dynamicEditField .action.valid')){ + e.preventDefault(); + let inputs = e.target.closest('.dynamicEditField').querySelectorAll('*[name]'); + let formData = []; + let existingIndex = []; + inputs.forEach(elt => { + let not_multiple = !elt.matches('input[type="radio"]') && !elt.matches('input[type="checkbox"]'); + if(elt.matches('input[type="radio"]:checked') || elt.matches('input[type="checkbox"]:checked') || not_multiple){ + if(!existingIndex.includes(elt.getAttribute('name'))){ + existingIndex.push(elt.getAttribute('name')); + formData.push({"name" : elt.getAttribute('name'), "value" : elt.value}) + } + } + }); + sendData(formData); + e.target.closest('.dynamicEditField').classList.remove('open'); + } }); /* Hide edit form when clicking on cancel button */ -$('body').on('click', '.dynamicEditField .action.refuse', function(e){ - e.preventDefault(); - $(this).parents('.dynamicEditField').removeClass('open'); +document.querySelector('body').addEventListener('click', function(e){ + if(e.target.matches('.dynamicEditField .action.refuse') || e.target.closest('.dynamicEditField .action.refuse')){ + e.preventDefault(); + e.target.closest('.dynamicEditField').classList.remove('open'); + } }); /* Update whole .details block + history + form with global refresh button */ -$('body').on('click', '.refreshData', function(e){ - e.preventDefault(); - sendData(); +document.querySelector('body').addEventListener('click', function(e){ + if(e.target.matches('.refreshData') || e.target.closest('.refreshData')){ + e.preventDefault(); + sendData(); + } }); /* Listen on esc key press to close opened dialog box */ document.onkeydown = function(evt) { evt = evt || window.event; - var isEscape = false; + let isEscape = false; if ("key" in evt) { isEscape = (evt.key === "Escape" || evt.key === "Esc"); } else { isEscape = (evt.keyCode === 27); } if (isEscape) { - $('.dynamicEditField').each(function(e){ $(this).removeClass('open'); }); + document.querySelectorAll('.dynamicEditField').forEach(function(elt){ elt.classList.remove('open'); }); } }; -let checkVersion = function(callback){ - jQuery.ajax({ - type: 'GET', - url: LOCATION_HREF, - crossDomain: true, - global: false, - success: function(msg) { - let parsed = $.parseHTML(msg); - let current_version = $(parsed).find('#issue_lock_version').val(); - - if(current_version !== $('#issue_lock_version').val()){ - if(!$('#content .conflict').length){ - $('#content').prepend(` -
- ${_TXT_CONFLICT_TITLE} -
-
-

${_TXT_CONFLICT_LINK} ${_TXT_CONFLICT_TXT}

-
-
-
`); - } - } else { - $('#content .conflict').remove(); - } - - if(callback) callback(current_version); - } - }); +const checkVersion = function(callback){ + fetch(LOCATION_HREF, { + method: 'GET', + crossDomain: true, + }).then(res => res.text()).then(data => { + const parser = new DOMParser(); + const doc = parser.parseFromString(data, 'text/html'); + const distant_version = doc.querySelector('#issue_lock_version').value; + if(distant_version !== document.querySelector('#issue_lock_version').value){ + if(!document.querySelector('#content . conflict')){ + const msg = document.createElement('div'); + msg.classList.add('conflict'); + msg.innerHTML = `${_TXT_CONFLICT_TITLE} +
+
+

${_TXT_CONFLICT_LINK} ${_TXT_CONFLICT_TXT}

+
+
` + document.querySelector('#content').insertBefore(msg, document.querySelector('#content').firstChild); + } + } else { + if(document.querySelector('#content .conflict')) document.querySelector('#content .conflict').remove(); + } + if(callback) callback(distant_version); + }).catch(err => { + console.warn('Issue while trying to get version (avoiding conflict)'); + console.log(err); + }); } let checkVersionInterval = false; let setCheckVersionInterval = function(activate){ if(!_CONF_CHECK_ISSUE_UPDATE_CONFLICT) return false; if(activate && !checkVersionInterval){ - checkVersionInterval = window.setInterval(function(){ checkVersion(); }, 5000); + checkVersionInterval = window.setInterval(function(){ + if(Document.visibilityState === "visible") checkVersion(); + }, 5000); } else { clearInterval(checkVersionInterval); checkVersionInterval = false; @@ -264,111 +324,96 @@ let setCheckVersionInterval = function(activate){ setCheckVersionInterval(true); /* Global function to perform AJAX call */ -var sendData = function(serialized_data){ - +let sendData = function(serialized_data){ let updateIssue = function(serialized_data){ setCheckVersionInterval(false); - var token = $("meta[name=csrf-token]").attr('content'); - var params = serialized_data || []; + const token = document.querySelector("meta[name=csrf-token]").getAttribute('content'); + let params = serialized_data || []; params.push({name: '_method', value: "patch"}); - params.push({name: 'authenticity_token', value: token}) + params.push({name: 'authenticity_token', value: token}); - jQuery.ajax({ - type: 'POST', - url: LOCATION_HREF, - data: $.param(params), - success: function(msg) { - /* get result page content (updated issue detail page with new status) */ - $('#ajax-indicator').css('display', 'none'); + let request = new XMLHttpRequest(); + request.open('POST', LOCATION_HREF, true); + let formData = new FormData(); + params.forEach(data => formData.append(data.name, data.value)); - var parsed = $.parseHTML(msg); + let callError = function(msg){ + setCheckVersionInterval(true); + document.querySelector('#ajax-indicator').style.display = 'none'; - var error = $(parsed).find("#errorExplanation"); - if (error.length) { + /* error and no update, info logged into console */ + console.groupCollapsed('%c -------- Error while updating the issue attribute dynamically -------- ', 'background: #ff0000; color: white; font-weight:900'); + console.log("POST " + LOCATION_HREF); + console.log(msg); + console.groupEnd(); + } - if ($('html').find("#errorExplanation").length == 0) { - $('.issue.details').before("
" + error.html() + "
"); + request.onreadystatechange = function() { + if (this.readyState == 4) { + if(this.status == 200) { + const parser = new DOMParser(); + const doc = parser.parseFromString(this.responseText, 'text/html'); - $([document.documentElement, document.body]).animate({ - scrollTop: $("#errorExplanation").offset().top - }, 500); + let error = doc.querySelector("#errorExplanation"); + + if(error){ + if (!document.querySelector("#errorExplanation")) { + let err_div = document.createElement('div'); + err_div.setAttribute("id", "errorExplanation"); + err_div.innerHTML = error.innerHTML; + document.querySelector('.issue.details').insertAdjacentElement("beforebegin", err_div); + + location.href = "#"; + location.href = "#errorExplanation"; + } else { + document.querySelector("#errorExplanation").innerHTML = error.innerHTML; + } + + doc = fetch(LOCATION_HREF, { + method: 'GET', + crossDomain: true, + }).then(res => res.text()).then(data => { + const parser = new DOMParser(); + return parser.parseFromString(data, 'text/html'); + }); } else { - $('html').find("#errorExplanation").html(error.html()); + if(document.querySelector("#errorExplanation")) document.querySelector("#errorExplanation").remove(); } - jQuery.ajax({ - type: 'GET', - url: LOCATION_HREF, - data: { "authenticity_token" : token }, - crossDomain: true, - async: false, - success: function(msg) { - parsed = $.parseHTML(msg); - } - }); + document.querySelector('form#issue-form').innerHTML = doc.querySelector('form#issue-form').innerHTML; + document.querySelector('#all_attributes').innerHTML = doc.querySelector('#all_attributes').innerHTML; + document.querySelector('div.issue.details').innerHTML = doc.querySelector('div.issue.details').innerHTML; + document.querySelector('#tab-content-history').appendChild(doc.querySelector('#history .journal.has-details:last-child')); + document.querySelector('#issue_lock_version').value = doc.querySelector("#issue_lock_version").value; + + cloneEditForm(); + + //set datepicker fallback for input type date + if ( + document.querySelector('input[type=date]') && + $('body').find('input[type=date]').datepickerFallback instanceof Function && + typeof datepickerOptions !== 'undefined' + ) { + $('body').find('input[type=date]').datepickerFallback(datepickerOptions); + } + + setCSRFTokenInput(doc.querySelector('input[name="authenticity_token"]').value); + updateCSRFToken(doc.querySelector('input[name="authenticity_token"]').value); + setCheckVersionInterval(true); } else { - /* removing error div if exists */ - $('html').find("#errorExplanation").remove(); + callError(this.status); } - - /* we update form*/ - $('form#issue-form').html( $(parsed).find('form#issue-form').html() ); - - /* we update issue properties edit block */ - $('#all_attributes').html( $(parsed).find('#all_attributes').html() ); - - /* we update the details block */ - $('div.issue.details').html( $(parsed).find('div.issue.details').html() ); - - /* we update the history list */ - $('#tab-content-history').append($(parsed).find('#history .journal.has-details:last-child')); - - /* Update lock version with last one */ - $('#issue_lock_version').val($(parsed).find("#issue_lock_version").val()); - - /* we init edit fields */ - cloneEditForm(); - - //set datepicker fallback for input type date - if ( - $('body').find('input[type=date]').length && - $('body').find('input[type=date]').datepickerFallback instanceof Function && - typeof datepickerOptions !== 'undefined' - ) { - $('body').find('input[type=date]').datepickerFallback(datepickerOptions); - } - - setCSRFTokenInput($(parsed).find('input[name="authenticity_token"]').val()); - updateCSRFToken($(parsed).find('input[name="authenticity_token"]').val()); - setCheckVersionInterval(true); - }, - error: function(xhr, msg, error) { - setCheckVersionInterval(true); - $('#ajax-indicator').css('display', 'none'); - - /* error and no update, info logged into console */ - console.groupCollapsed('%c -------- Error while updating the issue attribute dynamically -------- ', 'background: #ff0000; color: white; font-weight:900'); - console.log("POST " + LOCATION_HREF); - console.table(params); - console.log('%c xhr data: ', 'background: black; color: white;'); - console.log(xhr); - console.log('%c msg data: ', 'background: black; color: white;'); - console.log(msg); - console.log('%c error data: ', 'background: black; color: white;');; - console.log(error); - console.groupEnd(); } - }); - }; + }; + request.send(formData); + } if(_CONF_CHECK_ISSUE_UPDATE_CONFLICT){ - checkVersion(function(current_version){ - if(current_version == $('#issue_lock_version').val()){ + checkVersion(function(distant_version){ + if(distant_version == document.querySelector('#issue_lock_version').value){ updateIssue(serialized_data); } else { - $([document.documentElement, document.body]).animate({ - scrollTop: $("#content .conflict").offset().top - }, 500); + } }); } else { diff --git a/assets/stylesheets/issue_dynamic_edit.css b/assets/stylesheets/issue_dynamic_edit.css index 6fd9584..f4573af 100644 --- a/assets/stylesheets/issue_dynamic_edit.css +++ b/assets/stylesheets/issue_dynamic_edit.css @@ -41,6 +41,7 @@ body.controller-issues.action-show div.issue.details .iconEdit { display: inline-block; transition: opacity .3s ease-in; font-weight: 700; + margin-left: 1ch; } body.controller-issues.action-show div.issue.details.showPencil .iconEdit, @@ -108,6 +109,7 @@ body.controller-issues.action-show .dynamicEditField select { font-family: inherit; border: 1px solid #ccc; border-radius: 3px; + width: auto; } body.controller-issues.action-show .dynamicEditField select[multiple="multiple"] { @@ -143,6 +145,7 @@ body.controller-issues.action-show .dynamicEditField select { body.controller-issues.action-show .dynamicEditField .check_box_group { border: 0px !important; margin-bottom: 10px; + width:100%; } /* MOBILE MEDIAQUERY */ diff --git a/lib/details_issue_hooks.rb b/lib/details_issue_hooks.rb index b555845..91a7566 100644 --- a/lib/details_issue_hooks.rb +++ b/lib/details_issue_hooks.rb @@ -31,7 +31,7 @@ class DetailsIssueHooks < Redmine::Hook::ViewListener content << " var _TXT_CONFLICT_LINK = \"" + l(:ide_txt_notice_conflict_link) + "\";\n" content << "\n" content << "