diff --git a/assets/javascripts/issue_dynamic_edit.js b/assets/javascripts/issue_dynamic_edit.js index 57a1576..8ed5002 100644 --- a/assets/javascripts/issue_dynamic_edit.js +++ b/assets/javascripts/issue_dynamic_edit.js @@ -6,119 +6,141 @@ var _CONF_LISTENER_TYPE = _CONF_LISTENER_TYPE || "click"; var _CONF_LISTENER_TARGET = _CONF_LISTENER_TARGET || "value"; var _CONF_EXCLUDED_FIELD_ID = _CONF_EXCLUDED_FIELD_ID || []; -/* - * Allow inclusion from other page +/* + * 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; -if(_CONF_FORCE_HTTPS) { LOCATION_HREF = LOCATION_HREF.replace(/^http:\/\//i, 'https://'); } +var 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://'); +} + /* FontAwesome inclusion */ var cssId = 'fontAwesome'; - if (!document.getElementById(cssId)) - { - var head = document.getElementsByTagName('head')[0]; - var link = document.createElement('link'); - link.id = cssId; - link.rel = 'stylesheet'; - link.type = 'text/css'; - link.href = 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'; - link.media = 'all'; - head.appendChild(link); - } -$(document).on(_CONF_LISTENER_TYPE, function(e){ +if (!document.getElementById(cssId)) { + var head = document.getElementsByTagName('head')[0]; + var link = document.createElement('link'); + link.id = cssId; + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'; + link.media = 'all'; + head.appendChild(link); +} + +$(document).on(_CONF_LISTENER_TYPE, function(e) { $('.issue .attributes .attribute .value').removeClass('edited'); - if($(e.target).closest('a').length){ return; } - if($(e.target).closest('.' + _CONF_LISTENER_TARGET).length) { + + if ($(e.target).closest('a').length) { return; } + if ($(e.target).closest('.' + _CONF_LISTENER_TARGET).length) { // avoid text selection if dblclick var sel = window.getSelection ? window.getSelection() : document.selection; var activeElement = document.activeElement; var inputs = ['input', 'select', 'button', 'textarea']; if (sel && inputs.indexOf(activeElement.tagName.toLowerCase()) === -1) { - if (sel.removeAllRanges) { - sel.removeAllRanges(); - } else if (sel.empty) { - sel.empty(); - } + if (sel.removeAllRanges) { + sel.removeAllRanges(); + } else if (sel.empty) { + sel.empty(); + } } + // we show the edit box - $(e.target).closest('.value').addClass('edited'); - } + $(e.target).closest('.value').addClass('edited'); + } }); function isExcluded(elmt_id) { - return _CONF_EXCLUDED_FIELD_ID.indexOf(elmt_id) > -1; + return _CONF_EXCLUDED_FIELD_ID.indexOf(elmt_id) > -1; } -function initEditFields() -{ - /* Put new dropdown lists in the detailed info block */ - if($('#statusListDropdown').length > 0 && !isExcluded('statusListDropdown')) { +function initEditFields() { + /* Put new dropdown lists in the detailed info block */ + if ($('#statusListDropdown').length > 0 && !isExcluded('statusListDropdown')) { var htmlCopy = $('#statusListDropdown').get(0).outerHTML; $('#statusListDropdown').remove(); - $('.details .attributes .status.attribute .value').html( '' + - $('.details .attributes .status.attribute .value').html() + ' ' + - htmlCopy); - } - - if($('#prioritiesListDropdown').length > 0 && !isExcluded('prioritiesListDropdown')) { - var htmlCopy = $('#prioritiesListDropdown').get(0).outerHTML; - $('#prioritiesListDropdown').remove(); - $('.details .attributes .priority.attribute .value').html( '' + - $('.details .attributes .priority.attribute .value').html() + ' ' + - htmlCopy); + $('.details .attributes .status.attribute .value').html( + '' + + $('.details .attributes .status.attribute .value').html() + + ' ' + + htmlCopy + ); } - if($('#doneRatioListDropdown').length > 0 && !isExcluded('doneRatioListDropdown')) { + if ($('#prioritiesListDropdown').length > 0 && !isExcluded('prioritiesListDropdown')) { + var htmlCopy = $('#prioritiesListDropdown').get(0).outerHTML; + $('#prioritiesListDropdown').remove(); + $('.details .attributes .priority.attribute .value').html( + '' + + $('.details .attributes .priority.attribute .value').html() + + ' ' + + htmlCopy + ); + } + + if ($('#doneRatioListDropdown').length > 0 && !isExcluded('doneRatioListDropdown')) { var htmlCopy = $('#doneRatioListDropdown').get(0).outerHTML; $('#doneRatioListDropdown').remove(); - $('.details .attributes .progress.attribute .value').html('' + + $('.details .attributes .progress.attribute .value').html('' + $('.details .attributes .progress.attribute .value').html() + ' ' + htmlCopy); } - if($('#EstimatedTimeInput').length > 0 && !isExcluded('EstimatedTimeInput')) { + if ($('#EstimatedTimeInput').length > 0 && !isExcluded('EstimatedTimeInput')) { var htmlCopy = $('#EstimatedTimeInput').get(0).outerHTML; $('#EstimatedTimeInput').remove(); - $('.details .attributes .estimated-hours.attribute .value').html('' + - $('.details .attributes .estimated-hours.attribute .value').html() + ' ' + - htmlCopy); + $('.details .attributes .estimated-hours.attribute .value').html( + '' + + $('.details .attributes .estimated-hours.attribute .value').html() + + ' ' + + htmlCopy + ); } - if($('#StartDateInput').length > 0 && !isExcluded('StartDateInput')) { + if ($('#StartDateInput').length > 0 && !isExcluded('StartDateInput')) { var htmlCopy = $('#StartDateInput').get(0).outerHTML; $('#StartDateInput').remove(); - $('.details .attributes .start-date.attribute .value').html('' + - $('.details .attributes .start-date.attribute .value').html() + ' ' + - htmlCopy); + $('.details .attributes .start-date.attribute .value').html( + '' + + $('.details .attributes .start-date.attribute .value').html() + + ' ' + + htmlCopy + ); } - if($('#DueDateInput').length > 0 && !isExcluded('DueDateInput')) { + if ($('#DueDateInput').length > 0 && !isExcluded('DueDateInput')) { var htmlCopy = $('#DueDateInput').get(0).outerHTML; $('#DueDateInput').remove(); - $('.details .attributes .due-date.attribute .value').html('' + - $('.details .attributes .due-date.attribute .value').html() + ' ' + - htmlCopy); + $('.details .attributes .due-date.attribute .value').html( + '' + + $('.details .attributes .due-date.attribute .value').html() + + ' ' + + htmlCopy + ); } - if($('#TitleInput').length > 0 && !isExcluded('TitleInput')) { + if ($('#TitleInput').length > 0 && !isExcluded('TitleInput')) { var htmlCopy = $('#TitleInput').get(0).outerHTML; $('#TitleInput').remove(); $('.subject h3').html('' + $('.subject h3').html() + ' ' + htmlCopy).addClass('value'); } - if($('#DescriptionInput').length > 0 && !isExcluded('DescriptionInput')) { + if ($('#DescriptionInput').length > 0 && !isExcluded('DescriptionInput')) { var htmlCopy = $('#DescriptionInput').get(0).outerHTML; $('#DescriptionInput').remove(); - $('div.description .wiki').html(' ' + $('div.description .wiki').html() + '' + - htmlCopy).addClass('value'); + $('div.description .wiki').html( + ' ' + + $('div.description .wiki').html() + '' + + htmlCopy + ).addClass('value'); } - if($('select#issue_assigned_to_id').length > 0 && !isExcluded('issue_assigned_to_id')) - { + if ($('select#issue_assigned_to_id').length > 0 && !isExcluded('issue_assigned_to_id')) { var htmlCopy = $('select#issue_assigned_to_id').get(0).outerHTML; // 2 technics with simple or double quote (safety first) htmlCopy = htmlCopy.replace(/id="/g, 'id="dynamic_').replace(/id='/g, "id='dynamic_"); @@ -127,14 +149,16 @@ function initEditFields() editHTML += htmlCopy; editHTML += " "; editHTML += ""; - - $('.details .attributes .assigned-to.attribute .value').html('' + - $('.details .attributes .assigned-to.attribute .value').html() + ' ' + - editHTML); + + $('.details .attributes .assigned-to.attribute .value').html( + '' + + $('.details .attributes .assigned-to.attribute .value').html() + + ' ' + + editHTML + ); } - if($('select#issue_fixed_version_id').length > 0 && !isExcluded('issue_fixed_version_id')) - { + if ($('select#issue_fixed_version_id').length > 0 && !isExcluded('issue_fixed_version_id')) { var htmlCopy = $('select#issue_fixed_version_id').get(0).outerHTML; // 2 technics with simple or double quote (safety first) htmlCopy = htmlCopy.replace(/id="/g, 'id="dynamic_').replace(/id='/g, "id='dynamic_"); @@ -143,49 +167,66 @@ function initEditFields() editHTML += htmlCopy; editHTML += " "; editHTML += ""; - - $('.details .attributes .fixed-version.attribute .value').html('' + - $('.details .attributes .fixed-version.attribute .value').html() + ' ' + - editHTML); + + $('.details .attributes .fixed-version.attribute .value').html( + '' + + $('.details .attributes .fixed-version.attribute .value').html() + + ' ' + + editHTML + ); } - for(var i = 0 ; i < CF_VALUE_JSON.length ; i++) - { + for (var i = 0 ; i < CF_VALUE_JSON.length ; i++) { var info = CF_VALUE_JSON[i].custom_field; var value = CF_VALUE_JSON[i].value; - if(info.visible && info.editable && !isExcluded("issue_custom_field_values_" + info.id)) - { - if($('.details .attributes .cf_' + info.id + '.attribute .value').length - && $('#issue_custom_field_values_' + info.id).length ) - { + + if (info.visible && info.editable && !isExcluded("issue_custom_field_values_" + info.id)) { + if ( + $('.details .attributes .cf_' + info.id + '.attribute .value').length && + $('#issue_custom_field_values_' + info.id).length + ) { var htmlCopy = $('#issue_custom_field_values_' + info.id).get(0).outerHTML; - if(info.field_format == "version" && info.format_store.edit_tag_style == "check_box") - { + if (info.field_format == "version" && info.format_store.edit_tag_style == "check_box") { htmlCopy = $('#issue_custom_field_values_' + info.id).parents('span').html(); } + // 2 technics with simple or double quote (safety first) htmlCopy = htmlCopy.replace(/id="/g, 'id="dynamic_').replace(/id='/g, "id='dynamic_"); htmlCopy = htmlCopy.replace(/class="/g, 'class="cf_' + info.id + ' ').replace(/class='/g, "class='cf_" + info.id + " "); - + var editHTML = ""; - editHTML += htmlCopy; - editHTML += " "; - editHTML += " "; - editHTML += ""; - $('.details .attributes .cf_' + info.id + '.attribute .value').html('' + - $('.details .attributes .cf_' + info.id + '.attribute .value').html() + ' ' + - editHTML); + editHTML += htmlCopy; + editHTML += " "; + editHTML += " "; + editHTML += ""; - if(info.field_format == "date") - { - if( $('body').find('#dynamic_issue_custom_field_values_' + info.id).length - && $('body').find('#dynamic_issue_custom_field_values_' + info.id).datepickerFallback instanceof Function - && typeof datepickerOptions !== 'undefined') - { + $('.details .attributes .cf_' + info.id + '.attribute .value').html( + '' + + $('.details .attributes .cf_' + info.id + '.attribute .value').html() + + ' ' + + editHTML + ); + + if (info.field_format == "date") { + if ( + $('body').find('#dynamic_issue_custom_field_values_' + info.id).length && + $('body').find('#dynamic_issue_custom_field_values_' + info.id).datepickerFallback instanceof Function && + typeof datepickerOptions !== 'undefined' + ) { $('body').find('#dynamic_issue_custom_field_values_' + info.id).datepickerFallback(datepickerOptions); } } + + cf_datetime = $('body').find('#dynamic_issue_custom_field_values_' + info.id); + if (info.field_format == "datetime") { + if ( + cf_datetime.length && + typeof datetimepickerOptions !== 'undefined' + ) { + cf_datetime.datetimepicker(datetimepickerOptions); + } + } } } } @@ -194,20 +235,22 @@ function initEditFields() initEditFields(); /* Add required style to attributes */ -function updateRequiredFields(reqFieldsArray) -{ +function updateRequiredFields(reqFieldsArray) { for (var i = 0; i < reqFieldsArray.length; i++) { - var htmlLabel = reqFieldsArray[i].replace(/_/g, '-'); - $('.issue.details .attribute.' + htmlLabel + ' .label').html('' + $('.issue.details .attribute.' + htmlLabel + ' .label').html() + ' *'); + var htmlLabel = reqFieldsArray[i].replace(/_/g, '-'); + $('.issue.details .attribute.' + htmlLabel + ' .label').html( + '' + + $('.issue.details .attribute.' + htmlLabel + ' .label').html() + + ' *' + ); } - } - -if($('#required_field_array').length) { - updateRequiredFields(JSON.parse($('#required_field_array').html())); } +if ($('#required_field_array').length) { + updateRequiredFields(JSON.parse($('#required_field_array').html())); +} -$('body.controller-issues.action-show').on('click', '.btn.close', function(e){ +$('body.controller-issues.action-show').on('click', '.btn.close', function(e) { e.preventDefault(); $(e.target).closest('.value').removeClass('edited'); return false; @@ -216,153 +259,146 @@ $('body.controller-issues.action-show').on('click', '.btn.close', function(e){ function getLastLockVersion() { var token = $("meta[name=csrf-token]").attr('content'); var lock_version = $('#issue_lock_version').val(); + + jQuery.ajax({ - type: 'GET', - url: LOCATION_HREF, - data: { "authenticity_token" : token }, + type: 'GET', + url: LOCATION_HREF, + data: { "authenticity_token" : token }, crossDomain: true, - async: false, - beforeSend: function(xhr) { - xhr.setRequestHeader("authenticity_token", token); - }, - success: function(msg) { - parsed = $.parseHTML(msg); - lock_version = $(parsed).find('#issue_lock_version').val(); - } + async: false, + beforeSend: function(xhr) { + xhr.setRequestHeader("authenticity_token", token); + }, + success: function(msg) { + parsed = $.parseHTML(msg); + lock_version = $(parsed).find('#issue_lock_version').val(); + } }); return lock_version; } -function issueDynamicUpdate(field_name, field_value, type, cssClass){ - +function issueDynamicUpdate(field_name, field_value, type, cssClass) { /* hide edit field */ $('.details .' + cssClass + ' .value').removeClass('edited'); /* add spin notification */ $('.details .' + cssClass + ' .value').append(' '); - + /* update value displayed */ - $('.details .' + cssClass + ' .showValue').html(function(){ - if(type == "select") - { + $('.details .' + cssClass + ' .showValue').html(function() { + if (type == "select") { return $('.details .' + cssClass + ' .value select option:selected').html() - } else if (type == "input") - { + } else if (type == "input") { return $('.details .' + cssClass + ' .value input').val() - } else if(type == "textarea") - { + } else if (type == "textarea") { return $('.details .' + cssClass + ' .value textarea').val() - } else if(type == "date") - { + } else if (type == "date") { return "XXXX/XX/XX"; } }); - + /* lost focus on element */ - if( type != "select") - { + if (type != "select") { $('.details .' + cssClass + ' .value input').blur(); } - + var token = $("meta[name=csrf-token]").attr('content'); - + $('#issue-form').find("#issue_" + field_name).val(field_value).css({"display": "inline-block"}); // avoid conflict revision var lastLockVersion = getLastLockVersion(); $('#issue_lock_version').val(lastLockVersion); var formData = $('#issue-form').serialize(); - + + jQuery.ajax({ - type: 'POST', - url: LOCATION_HREF, - data: formData, + type: 'POST', + url: LOCATION_HREF, + data: formData, beforeSend: function(xhr) { - xhr.setRequestHeader("authenticity_token", token); - }, - success: function(msg) { - /* get result page content (updated issue detail page with new status) */ - - var parsed = $.parseHTML(msg); - + xhr.setRequestHeader("authenticity_token", token); + }, + success: function(msg) { + /* get result page content (updated issue detail page with new status) */ + + var parsed = $.parseHTML(msg); + var error = $(parsed).find("#errorExplanation"); - - if(error.length) - { - if($('html').find("#errorExplanation").length == 0) - { + + if (error.length) { + if ($('html').find("#errorExplanation").length == 0) { $('.issue.details').before("
" + error.html() + "
"); - } else - { + } else { $('html').find("#errorExplanation").html(error.html()); } + /* data updated, remove spin and add success icon for 2sec */ - setTimeout(function(){ + setTimeout(function() { $('.details .' + cssClass + ' i.fa-spin').removeClass('fa-refresh fa-spin').addClass('fa-times statusKo'); - setTimeout(function(){ + setTimeout(function() { $('.details .' + cssClass + ' i.fa-times.statusKo').remove(); }, 2000); }, 500); - jQuery.ajax({ - type: 'GET', - url: LOCATION_HREF, - data: { "authenticity_token" : token }, - crossDomain: true, - async: false, - beforeSend: function(xhr) { - xhr.setRequestHeader("authenticity_token", token); - }, - success: function(msg) { - parsed = $.parseHTML(msg); - } - }); + jQuery.ajax({ + type: 'GET', + url: LOCATION_HREF, + data: { "authenticity_token" : token }, + crossDomain: true, + async: false, + beforeSend: function(xhr) { + xhr.setRequestHeader("authenticity_token", token); + }, + success: function(msg) { + parsed = $.parseHTML(msg); + } + }); } else { - /* removing error div if exists */ $('html').find("#errorExplanation").remove(); - } - - /* we update the details block */ - $('div.issue.details').html($(parsed).find('div.issue.details').html()); - $('body').find('.details .' + cssClass + ' .value').append(' '); - - /* 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() ); + $('body').find('.details .' + cssClass + ' .value').append(' '); - /* we init edit fields */ - initEditFields(); - initEditFieldListeners(); - - if($(parsed).find('#required_field_array').length) { - updateRequiredFields(JSON.parse($(parsed).find('#required_field_array').html())); - } - - /* we update the history list */ - $('#history').append($(parsed).find('#history .journal.has-details:last-child')); + /* we update form*/ + $('form#issue-form').html( $(parsed).find('form#issue-form').html() ); - /* data updated, remove spin and add success icon for 2sec */ + /* we update issue properties edit block */ + $('#all_attributes').html( $(parsed).find('#all_attributes').html() ); + + /* we init edit fields */ + initEditFields(); + initEditFieldListeners(); + + if ($(parsed).find('#required_field_array').length) { + updateRequiredFields(JSON.parse($(parsed).find('#required_field_array').html())); + } + + /* we update the history list */ + $('#history').append($(parsed).find('#history .journal.has-details:last-child')); + + /* data updated, remove spin and add success icon for 2sec */ + setTimeout(function(){ + $('.details .' + cssClass + ' i.fa-spin').removeClass('fa-refresh fa-spin').addClass('fa-check statusOk'); setTimeout(function(){ - $('.details .' + cssClass + ' i.fa-spin').removeClass('fa-refresh fa-spin').addClass('fa-check statusOk'); - setTimeout(function(){ - $('.details .' + cssClass + ' i.fa-check.statusOk').remove(); - }, 2000); - }, 500); + $('.details .' + cssClass + ' i.fa-check.statusOk').remove(); + }, 2000); + }, 500); - //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); - } - + //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); + } }, - error: function(xhr, msg, error) { + error: function(xhr, msg, error) { /* error and no update, info logged into console */ console.log('%c -------- Error while updating the issue attribute dynamically -------- ', 'background: #ff0000; color: white; font-weight:900'); console.log('%c xhr data: ', 'background: black; color: white;'); @@ -372,98 +408,99 @@ function issueDynamicUpdate(field_name, field_value, type, cssClass){ console.log('%c error data: ', 'background: black; color: white;');; console.log(error); console.log('%c ---------------------------------------------------------- ', 'background: #ff0000; color: white; font-weight:900'); + $('.details .' + cssClass + ' i.fa-spin').removeClass('fa-refresh fa-spin').addClass('fa-times').html(" " + _TXT_ERROR_AJAX_CALL); - setTimeout(function(){ - $('.details .' + cssClass + ' i.fa-times').remove(); - }, 2000); + setTimeout(function(){ + $('.details .' + cssClass + ' i.fa-times').remove(); + }, 2000); } - }); + }); }; /* Listeners foreach attribute */ -function initEditFieldListeners() -{ - var domSelectStatus = $('body').find('#statusListDropdown select'); - domSelectStatus.on('change', function(e){ +function initEditFieldListeners() { + var domSelectStatus = $('body').find('#statusListDropdown select'); + domSelectStatus.on('change', function(e) { issueDynamicUpdate('status_id', domSelectStatus.val(), 'select', 'status'); /* update the classes status from */ $("#content > div.issue").removeClass(function (index, className) { return (className.match (/(^|\s)status-\S+/g) || []).join(' '); }).addClass('status-' + domSelectStatus.val()); - }); /* end on change domSelectStatus */ - - var domSelectPriorities = $('body').find('#prioritiesListDropdown select'); - domSelectPriorities.on('change', function(e){ + }); /* end on change domSelectStatus */ + + var domSelectPriorities = $('body').find('#prioritiesListDropdown select'); + domSelectPriorities.on('change', function(e){ issueDynamicUpdate('priority_id', domSelectPriorities.val(), 'select', 'priority'); /* update the classes priority from */ $("#content > div.issue").removeClass(function (index, className) { return (className.match (/(^|\s)priority-\S+/g) || []).join(' '); }).addClass('priority-' + domSelectPriorities.val()); - }); /* end on change domSelectPriorities */ - - var domSelectUsers = $('body').find('#usersListDropdown select'); - domSelectUsers.on('change', function(e){ + }); /* end on change domSelectPriorities */ + + var domSelectUsers = $('body').find('#usersListDropdown select'); + domSelectUsers.on('change', function(e){ issueDynamicUpdate('assigned_to_id', domSelectUsers.val(), 'select', 'assigned-to'); - }); /* end on change domSelectUsers */ - - var domSelectRatio = $('body').find('#doneRatioListDropdown select'); - domSelectRatio.on('change', function(e){ + }); /* end on change domSelectUsers */ + + var domSelectRatio = $('body').find('#doneRatioListDropdown select'); + domSelectRatio.on('change', function(e){ issueDynamicUpdate('done_ratio', domSelectRatio.val(), 'progress', 'progress'); - }); /* end on change domSelectRatio */ - - var domInputEstimatedTime = $('body').find('#EstimatedTimeInput input'); - $('#EstimatedTimeInput a.btn.validate').on('click', function(e) - { + }); /* end on change domSelectRatio */ + + var domInputEstimatedTime = $('body').find('#EstimatedTimeInput input'); + $('#EstimatedTimeInput a.btn.validate').on('click', function(e) { e.preventDefault(); $('.estimated-hours .value .error').remove(); var estimatedTime = parseFloat(domInputEstimatedTime.val()); - if(estimatedTime >= 0) - { + + if (estimatedTime >= 0) { issueDynamicUpdate('estimated_hours', estimatedTime, 'input', 'estimated-hours'); } else { /* estimated time must be > 0 */ $('.estimated-hours .value').append(' ' + _TXT_ERROR_POSITIVE_NUMBER + ''); } + return false; - }); - - domInputEstimatedTime.on('keyup', function(e){ + }); + + domInputEstimatedTime.on('keyup', function(e){ $('.details .attributes .estimated-hours.attribute .selectedValue span').html( $('.details .attributes .estimated-hours.attribute .value input').val() ); + if (e.keyCode == 13) { $('#EstimatedTimeInput a.btn.validate').click(); } - });/* end EstimatedTime */ - - var domInputStartDate = $('body').find('#StartDateInput input'); - $('#StartDateInput a.btn.validate').on('click', function(e) - { + });/* end EstimatedTime */ + + var domInputStartDate = $('body').find('#StartDateInput input'); + $('#StartDateInput a.btn.validate').on('click', function(e) { e.preventDefault(); $('.start-date .value .error').remove(); - if(new Date(domInputStartDate.val()).getTime() <= new Date($('body').find('#DueDateInput input').val()).getTime() || $('body').find('#DueDateInput input').val() == "") + if (new Date(domInputStartDate.val()).getTime() <= new Date($('body').find('#DueDateInput input').val()).getTime() || $('body').find('#DueDateInput input').val() == "") { issueDynamicUpdate('start_date', domInputStartDate.val(), 'date', 'start-date'); } else { /* start date must be < due date */ $('.start-date .value').append(' ' + _TXT_ERROR_START_DATE + ''); } + return false; - }); - - domInputStartDate.on('keyup', function(e){ + }); + + domInputStartDate.on('keyup', function(e){ if (e.keyCode == 13) { $('#StartDateInput a.btn.validate').click(); } - });/* end StartDate */ - - var domInputDueDate = $('body').find('#DueDateInput input'); - $('#DueDateInput a.btn.validate').on('click', function(e) - { + });/* end StartDate */ + + var domInputDueDate = $('body').find('#DueDateInput input'); + $('#DueDateInput a.btn.validate').on('click', function(e) { e.preventDefault(); $('.due-date .value .error').remove(); + if(new Date($('body').find('#StartDateInput input').val()).getTime() <= new Date(domInputDueDate.val()).getTime() || $('body').find('#StartDateInput input').val() == "" ) { issueDynamicUpdate('due_date', domInputDueDate.val(), 'date', 'due-date'); @@ -472,129 +509,120 @@ function initEditFieldListeners() $('.due-date .value').append(' ' + _TXT_ERROR_DUE_DATE + ''); } return false; - }); - - domInputDueDate.on('keyup', function(e){ + }); + + domInputDueDate.on('keyup', function(e){ if (e.keyCode == 13) { $('#DueDateInput a.btn.validate').click(); } - });/* end StartDate */ + });/* end StartDate */ - var domInputTitle = $('body').find('#TitleInput input'); - $('#TitleInput a.btn.validate').on('click', function(e) - { + var domInputTitle = $('body').find('#TitleInput input'); + $('#TitleInput a.btn.validate').on('click', function(e) { e.preventDefault(); issueDynamicUpdate('subject', domInputTitle.val(), 'input', 'subject'); - + return false; - }); - - domInputTitle.on('keyup', function(e){ + }); + + domInputTitle.on('keyup', function(e){ if (e.keyCode == 13) { $('#TitleInput a.btn.validate').click(); } - });/* end Title */ + });/* end Title */ - var domInputDescription = $('body').find('#DescriptionInput textarea'); + var domInputDescription = $('body').find('#DescriptionInput textarea'); - if(domInputDescription.length) - { - $('#DescriptionInput a.btn.validate').on('click', function(e) - { + if(domInputDescription.length) { + $('#DescriptionInput a.btn.validate').on('click', function(e) { e.preventDefault(); var new_value = domInputDescription.val(); - - if(typeof(CKEDITOR) === "object" - && typeof(CKEDITOR.instances['description_textarea'].getData) === typeof(Function)){ + + if ( + typeof(CKEDITOR) === "object" && + typeof(CKEDITOR.instances['description_textarea'].getData) === typeof(Function) + ) { new_value = CKEDITOR.instances['description_textarea'].getData(); } - + issueDynamicUpdate('description', new_value, 'textarea', 'description'); return false; - }); - - if(typeof(jsToolBar) === typeof(Function)) - { + }); + + if (typeof(jsToolBar) === typeof(Function)) { var wikiToolbar = new jsToolBar(document.getElementById('description_textarea')); wikiToolbar.draw(); - } else if(typeof(CKEDITOR) === "object" && typeof(CKEDITOR.replace) === typeof(Function)) { + } else if (typeof(CKEDITOR) === "object" && typeof(CKEDITOR.replace) === typeof(Function)) { CKEDITOR.replace('description_textarea', { height: 100 }); } - } + } - var dynamic_edit_assigned_to_id = $('body').find('#dynamic_edit_assigned_to_id select'); + var dynamic_edit_assigned_to_id = $('body').find('#dynamic_edit_assigned_to_id select'); - if(dynamic_edit_assigned_to_id.length) - { + if (dynamic_edit_assigned_to_id.length) { dynamic_edit_assigned_to_id.on('change', function(e){ issueDynamicUpdate('assigned_to_id', dynamic_edit_assigned_to_id.val(), 'select', 'assigned-to'); - }); - } + }); + } - var dynamic_edit_fixed_version = $('body').find('#dynamic_edit_fixed_version select'); + var dynamic_edit_fixed_version = $('body').find('#dynamic_edit_fixed_version select'); - if(dynamic_edit_fixed_version.length) - { + if (dynamic_edit_fixed_version.length) { dynamic_edit_fixed_version.on('change', function(e){ issueDynamicUpdate('fixed_version_id', dynamic_edit_fixed_version.val(), 'select', 'fixed-version'); - }); - } - + }); + } + /* end Description */ /* Custom fields */ - for(var i = 0 ; i < CF_VALUE_JSON.length ; i++) - { - (function() { - var info = CF_VALUE_JSON[i].custom_field; - var value = CF_VALUE_JSON[i].value; - if(info.visible && info.editable) - { - var inputType = "input"; - switch (info.field_format) - { - case "bool": - case "user": - case "list": - case "enumeration": - case "version": - inputType = "select"; - break; - case "text": - inputType = "textarea"; - break; - - } + for (var i = 0 ; i < CF_VALUE_JSON.length ; i++) { + ( + function() { + var info = CF_VALUE_JSON[i].custom_field; + var value = CF_VALUE_JSON[i].value; - // Specific case : version field with checkboxes - if(info.field_format == "version" && info.format_store.edit_tag_style == "check_box") - { - inputType = "version"; - $('body').find('#dynamic_edit_cf_' + info.id + ' input').on('click', function(e){ - $('label[for=issue_custom_field_values_' + info.id + ']').next().find('input[value=' + $(this).val() + ']').click(); - }); - } - - var domInputField = $('body').find('#dynamic_issue_custom_field_values_' + info.id); - $('body').find('#dynamic_edit_cf_' + info.id + ' a.btn.validate').on('click', function(e) - { - var new_value = domInputField.val(); - - issueDynamicUpdate('custom_field_values_' + info.id , new_value, inputType, 'cf_' + info.id); - - return false; - }); - - domInputField.on('keyup', function(e){ - if (e.keyCode == 13 && inputType != "textarea") { - $('body').find('#dynamic_edit_cf_' + info.id + ' a.btn.validate').click(); + if (info.visible && info.editable) { + var inputType = "input"; + switch (info.field_format) { + case "bool": + case "user": + case "list": + case "enumeration": + case "version": + inputType = "select"; + break; + case "text": + inputType = "textarea"; + break; } - }); - } - }()); // closure FTW + // Specific case : version field with checkboxes + if (info.field_format == "version" && info.format_store.edit_tag_style == "check_box") { + inputType = "version"; + $('body').find('#dynamic_edit_cf_' + info.id + ' input').on('click', function(e) { + $('label[for=issue_custom_field_values_' + info.id + ']').next().find('input[value=' + $(this).val() + ']').click(); + }); + } + + var domInputField = $('body').find('#dynamic_issue_custom_field_values_' + info.id); + $('body').find('#dynamic_edit_cf_' + info.id + ' a.btn.validate').on('click', function(e) { + var new_value = domInputField.val(); + + issueDynamicUpdate('custom_field_values_' + info.id , new_value, inputType, 'cf_' + info.id); + + return false; + }); + + domInputField.on('keyup', function(e) { + if (e.keyCode == 13 && inputType != "textarea") { + $('body').find('#dynamic_edit_cf_' + info.id + ' a.btn.validate').click(); + } + }); + } + }() + ); // closure FTW } +} -} - -initEditFieldListeners(); \ No newline at end of file +initEditFieldListeners(); diff --git a/lib/details_issue_hooks.rb b/lib/details_issue_hooks.rb index ea9cae9..888869b 100644 --- a/lib/details_issue_hooks.rb +++ b/lib/details_issue_hooks.rb @@ -1,205 +1,213 @@ class DetailsIssueHooks < Redmine::Hook::ViewListener - def protect_against_forgery? false - end - - def current_is_detail_page(context) - # check if we see an issue but not creating a new one or on the specific edit page - ret = context[:controller] && context[:controller].is_a?(IssuesController) && context[:request].original_url.rindex(/\/issues\/\S+/) && !context[:request].original_url.rindex(/\/issues\/new/) && !context[:request].original_url.rindex(/\/issues\/\d+\/edit/) - end - - def view_layouts_base_html_head(context) - if current_is_detail_page(context) - stylesheet_link_tag('issue_dynamic_edit.css', :plugin => :redmine_issue_dynamic_edit) - end - end - - def view_layouts_base_body_bottom(context) - if current_is_detail_page(context) - javascript_include_tag('issue_dynamic_edit_configuration_file.js', 'issue_dynamic_edit.js', :plugin => :redmine_issue_dynamic_edit) - end end - def view_issues_show_details_bottom(context = { }) + def current_is_detail_page(context) + # check if we see an issue but not creating a new one or on the specific edit page + ret = context[:controller] && context[:controller].is_a?(IssuesController) && context[:request].original_url.rindex(/\/issues\/\S+/) && !context[:request].original_url.rindex(/\/issues\/new/) && !context[:request].original_url.rindex(/\/issues\/\d+\/edit/) + end + + def view_layouts_base_html_head(context) + return unless current_is_detail_page(context) + + stylesheet_link_tag('issue_dynamic_edit.css', :plugin => :redmine_issue_dynamic_edit) + end + + def view_layouts_base_body_bottom(context) + return unless current_is_detail_page(context) + + javascript_include_tag('issue_dynamic_edit_configuration_file.js', 'issue_dynamic_edit.js', :plugin => :redmine_issue_dynamic_edit) + end + + def view_issues_show_details_bottom(context = {}) project = context[:project] request = context[:request] issue_id = request.path_parameters[:id] - back = request.env['HTTP_REFERER'] + back = request.env['HTTP_REFERER'] - o = '' - - if (issue_id) + o = '' + + if issue_id issue = Issue.find(issue_id) - readOnlyAttributes = issue.read_only_attribute_names(User.current) - requiredAttributes = issue.required_attribute_names(User.current) - - # o << requiredAttributes.to_json - - allRequiredFieldsFilled = true - requiredAttributes.each do |attr| - if(issue.read_attribute(attr).to_s.empty?) - allRequiredFieldsFilled = false - end - end - - if (issue) - if (User.current.allowed_to?(:edit_issues, project)) - - # if there's a JS error, we hide the generated values - o << '
' - - # Status dropdown - statuses = issue.new_statuses_allowed_to(User.current) - if (!statuses.empty? && !(readOnlyAttributes.include? 'status_id') && allRequiredFieldsFilled) - o << "" - o << " " + readOnlyAttributes = issue.read_only_attribute_names(User.current) + requiredAttributes = issue.required_attribute_names(User.current) + + # o << requiredAttributes.to_json + + allRequiredFieldsFilled = true + requiredAttributes.each do |attr| + if issue.read_attribute(attr).to_s.empty? + allRequiredFieldsFilled = false + end + end + + if issue + if User.current.allowed_to?(:edit_issues, project) + # if there's a JS error, we hide the generated values + o << '
' + + # Status dropdown + statuses = issue.new_statuses_allowed_to(User.current) + if ( + !statuses.empty? && + !readOnlyAttributes.include?('status_id') && + allRequiredFieldsFilled + ) + o << "" + o << " " end - - # Users dropdown - assignables = project.assignable_users - if (!assignables.empty? && !(readOnlyAttributes.include? 'assigned_to_id')) - o << "" - o << " " + + # Users dropdown + assignables = project.assignable_users + if ( + !assignables.empty? && + !readOnlyAttributes.include?('assigned_to_id') + ) + o << "" + o << " " end - - # Priorities dropdown - priorities = IssuePriority.all - if(!priorities.empty? && !(readOnlyAttributes.include? 'priority_id')) - o << "" - o << " " - end - - # %done dropdown - if(!(readOnlyAttributes.include? 'done_ratio')) - percent = 0 - o << "" - o << " " - end - - # Estimated_time dropdown - if(!(readOnlyAttributes.include? 'estimated_hours')) - o << "" - o << " " - o << "" - o << " " - o << "" - end - - # Start date - if(!(readOnlyAttributes.include? 'start_date')) - o << "" - o << " " - o << " " - o << " " - o << "" - o << "" - end - - # Due date - if(!(readOnlyAttributes.include? 'due_date')) - o << "" - o << " " - o << " " - o << " " - o << "" - o << "" - end - # Title - # Make quotings in subject! (PP) - clonesubject = issue.subject.gsub('"','"') - o << "" - o << " " - o << " " - o << " " - o << "" + # Priorities dropdown + priorities = IssuePriority.all - # Description - o << "" - o << " " - o << "
" - o << "
" - o << "
" - - end - end - - o << "\n" - - - - o << "\n" - + o << " " + end - # closing the display none div parent - o << "
" - return o + # %done dropdown + if ! readOnlyAttributes.include?('done_ratio') + percent = 0 + o << "" + o << " " + end + + # Estimated_time dropdown + if ! readOnlyAttributes.include?('estimated_hours') + o << "" + o << " " + o << "" + o << " " + o << "" + end + + # Start date + if ! readOnlyAttributes.include?('start_date') + o << "" + o << " " + o << " " + o << " " + o << "" + o << "" + end + + # Due date + if ! readOnlyAttributes.include?('due_date') + o << "" + o << " " + o << " " + o << " " + o << "" + o << "" + end + + # Title + # Make quotings in subject! (PP) + clonesubject = issue.subject.gsub('"','"') + o << "" + o << " " + o << " " + o << " " + o << "" + + # Description + o << "" + o << " " + o << "
" + o << "
" + o << "
" + end + end + + o << "\n" + + o << "\n" + + # closing the display none div parent + o << "
" + + return o + end end - end