Custom fields support added (Github request #19)
This commit is contained in:
parent
bab8cf362c
commit
5174466a05
@ -1,8 +1,9 @@
|
|||||||
# redmine_issue_dynamic_edit
|
# redmine_issue_dynamic_edit
|
||||||
|
|
||||||
Add new elements on detailed issue page to dynamically update issue's title, status, assignee, priority, start and due dates, ratio and estimated time fields, directly in the details block of the issue without any page refresh (JIRA style).
|
Add new elements on detailed issue page to **dynamically update issue's attributes and custom fields**, directly in the details block of the issue **without any page refresh** (*JIRA style*).
|
||||||
|
|
||||||
### 🔴 What info should you provide when opening an issue
|
|
||||||
|
### 🔴 What info you should provide when opening an issue
|
||||||
>This plugin use JS a lot. Could you then please check your JS console from your web browser ( [HowTo](https://webmasters.stackexchange.com/a/77337) ) and try again your issue. You'll see some information about what goes wrong.
|
>This plugin use JS a lot. Could you then please check your JS console from your web browser ( [HowTo](https://webmasters.stackexchange.com/a/77337) ) and try again your issue. You'll see some information about what goes wrong.
|
||||||
>
|
>
|
||||||
>Could you copy / paste it in your issue and expand all possible object (error data for example) so we can look if there's a problem with the ajax call the plugin performs to update the issue or if there's any JS error.
|
>Could you copy / paste it in your issue and expand all possible object (error data for example) so we can look if there's a problem with the ajax call the plugin performs to update the issue or if there's any JS error.
|
||||||
@ -24,6 +25,7 @@ This plugin uses [FontAwesome icons](http://fontawesome.io/)
|
|||||||
|
|
||||||
### Changelog
|
### Changelog
|
||||||
|
|
||||||
|
* **v 0.6.0** : NOW WITH CUSTOM FIELDS SUPPORT ! (Github #19)
|
||||||
* **v 0.5.0** : fixed Github issue #18 : textarea fixed (jstoolbar or ckeditor)
|
* **v 0.5.0** : fixed Github issue #18 : textarea fixed (jstoolbar or ckeditor)
|
||||||
* **v 0.4.9** : fixed Github issue #17 : Datepicker fallback added for date fields
|
* **v 0.4.9** : fixed Github issue #17 : Datepicker fallback added for date fields
|
||||||
* **v 0.4.8** : fixed Github issues #15 and #16
|
* **v 0.4.8** : fixed Github issues #15 and #16
|
||||||
|
|||||||
@ -91,6 +91,37 @@ function initEditFields()
|
|||||||
$('div.description .wiki').html(' <i class="fa fa-pencil fa-fw" aria-hidden="true" style="float:right;"></i><span class="showValue">' + $('div.description .wiki').html() + '</span>' +
|
$('div.description .wiki').html(' <i class="fa fa-pencil fa-fw" aria-hidden="true" style="float:right;"></i><span class="showValue">' + $('div.description .wiki').html() + '</span>' +
|
||||||
htmlCopy).addClass('value');
|
htmlCopy).addClass('value');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if($('.details .attributes .cf_' + info.id + '.attribute .value').length)
|
||||||
|
{
|
||||||
|
var htmlCopy = $('#issue_custom_field_values_' + info.id).get(0).outerHTML;
|
||||||
|
// 2 technics with simple or double quote (safety first)
|
||||||
|
htmlCopy = htmlCopy.replace('id="', 'id="dynamic_').replace("id='", "id='dynamic_");
|
||||||
|
htmlCopy = htmlCopy.replace('class="', 'class="cf_' + info.id + ' ').replace("class='", "class='cf_" + info.id + " ");
|
||||||
|
|
||||||
|
var editHTML = "<span class='dynamicEdit' id='dynamic_edit_cf_" + info.id + "'>";
|
||||||
|
editHTML += htmlCopy;
|
||||||
|
editHTML += " <a href='#' class='btn btn-primary validate' aria-label='" + _TXT_VALIDATION_BTN + "'><i class='fa fa-check fa-fw' aria-hidden='true'></i></a>";
|
||||||
|
editHTML += " <a href='#' class='btn btn-primary close' aria-label='" + _TXT_CANCEL_BTN + "'><i class='fa fa-times fa-fw' aria-hidden='true'></i></a>";
|
||||||
|
editHTML += "</span>";
|
||||||
|
|
||||||
|
$('.details .attributes .cf_' + info.id + '.attribute .value').html('<span class="showValue">' +
|
||||||
|
$('.details .attributes .cf_' + info.id + '.attribute .value').html() + '</span> <i class="fa fa-pencil fa-fw" aria-hidden="true"></i>' +
|
||||||
|
editHTML);
|
||||||
|
|
||||||
|
if(info.field_format == "date")
|
||||||
|
{
|
||||||
|
$('body').find('#dynamic_issue_custom_field_values_' + info.id).datepickerFallback(datepickerOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initEditFields();
|
initEditFields();
|
||||||
@ -152,7 +183,6 @@ function issueDynamicUpdate(field_name, field_value, type, cssClass){
|
|||||||
url: _BASE_REDMINE_PATH + '/issues/bulk_update?back_url=' + prepareReturnUrl + '&ids%5B%5D=' + _ISSUE_ID + '&issue%5B' + field_name + '%5D=' + field_value,
|
url: _BASE_REDMINE_PATH + '/issues/bulk_update?back_url=' + prepareReturnUrl + '&ids%5B%5D=' + _ISSUE_ID + '&issue%5B' + field_name + '%5D=' + field_value,
|
||||||
data: { "authenticity_token" : token },
|
data: { "authenticity_token" : token },
|
||||||
crossDomain: true,
|
crossDomain: true,
|
||||||
async: false,
|
|
||||||
beforeSend: function(xhr) {
|
beforeSend: function(xhr) {
|
||||||
xhr.setRequestHeader("authenticity_token", token);
|
xhr.setRequestHeader("authenticity_token", token);
|
||||||
},
|
},
|
||||||
@ -205,14 +235,14 @@ function issueDynamicUpdate(field_name, field_value, type, cssClass){
|
|||||||
$('div.issue.details').html($(parsed).find('div.issue.details').html());
|
$('div.issue.details').html($(parsed).find('div.issue.details').html());
|
||||||
$('body').find('.details .' + cssClass + ' .value').append(' <i class="fa fa-refresh fa-spin fa-fw"></i>');
|
$('body').find('.details .' + cssClass + ' .value').append(' <i class="fa fa-refresh fa-spin fa-fw"></i>');
|
||||||
|
|
||||||
|
/* we update issue properties edit block */
|
||||||
|
$('#all_attributes').html($(parsed).find('#all_attributes').html());
|
||||||
|
|
||||||
/* we init edit fields */
|
/* we init edit fields */
|
||||||
initEditFields();
|
initEditFields();
|
||||||
initEditFieldListeners();
|
initEditFieldListeners();
|
||||||
|
|
||||||
updateRequiredFields(JSON.parse($(parsed).find('#required_field_array').html()));
|
updateRequiredFields(JSON.parse($(parsed).find('#required_field_array').html()));
|
||||||
|
|
||||||
/* we update issue properties edit block */
|
|
||||||
$('#all_attributes').html($(parsed).find('#all_attributes').html());
|
|
||||||
|
|
||||||
/* we update the history list */
|
/* we update the history list */
|
||||||
$('#history').append($(parsed).find('#history .journal.has-details:last-child'));
|
$('#history').append($(parsed).find('#history .journal.has-details:last-child'));
|
||||||
@ -387,6 +417,59 @@ function initEditFieldListeners()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* end Description */
|
/* 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
issueDynamicUpdate('custom_field_values%5D%5B' + info.id , domInputField.val(), 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(inputType == "textarea")
|
||||||
|
{
|
||||||
|
if(typeof(jsToolBar) === typeof(Function))
|
||||||
|
{
|
||||||
|
var wikiToolbar = new jsToolBar(domInputField); wikiToolbar.setHelpLink('/help/fr/wiki_syntax_textile.html'); wikiToolbar.draw();
|
||||||
|
} else if(typeof(CKEDITOR) === "object" && typeof(CKEDITOR.replace) === typeof(Function)) {
|
||||||
|
CKEDITOR.replace('dynamic_issue_custom_field_values_' + info.id, { height: 100 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}()); // closure FTW
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initEditFieldListeners();
|
initEditFieldListeners();
|
||||||
@ -101,4 +101,8 @@ body.controller-issues.action-show div.issue.details .splitcontent {
|
|||||||
div.issue div.subject h3 {
|
div.issue div.subject h3 {
|
||||||
position:relative;
|
position:relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.controller-issues.action-show .dynamicEdit input[type="text"] {
|
||||||
|
width: auto !important;
|
||||||
}
|
}
|
||||||
2
init.rb
2
init.rb
@ -6,7 +6,7 @@ Redmine::Plugin.register :redmine_issue_dynamic_edit do
|
|||||||
name 'Redmine Dynamic edit Issue plugin'
|
name 'Redmine Dynamic edit Issue plugin'
|
||||||
author 'Hugo Zilliox'
|
author 'Hugo Zilliox'
|
||||||
description 'Allows users to dynamically update issue attributes in detailed view without refreshing the page (JIRA style)'
|
description 'Allows users to dynamically update issue attributes in detailed view without refreshing the page (JIRA style)'
|
||||||
version '0.5.0'
|
version '0.6.0'
|
||||||
url 'https://github.com/ilogeek/redmine_issue_dynamic_edit'
|
url 'https://github.com/ilogeek/redmine_issue_dynamic_edit'
|
||||||
author_url 'https://hzilliox.fr'
|
author_url 'https://hzilliox.fr'
|
||||||
end
|
end
|
||||||
|
|||||||
@ -159,12 +159,16 @@ class DetailsIssueHooks < Redmine::Hook::ViewListener
|
|||||||
end
|
end
|
||||||
|
|
||||||
o << "<script>"
|
o << "<script>"
|
||||||
|
|
||||||
|
o << " var CF_VALUE_JSON = " + issue.editable_custom_field_values(User.current).to_json + ";\n"
|
||||||
|
|
||||||
o << " var _ISSUE_ID = \"#{issue_id}\";\n"
|
o << " var _ISSUE_ID = \"#{issue_id}\";\n"
|
||||||
o << " var _USER_API_KEY = \"#{User.current.api_key}\";\n"
|
o << " var _USER_API_KEY = \"#{User.current.api_key}\";\n"
|
||||||
o << " var _BASE_REDMINE_PATH = \"#{Redmine::Utils.relative_url_root}\";\n"
|
o << " var _BASE_REDMINE_PATH = \"#{Redmine::Utils.relative_url_root}\";\n"
|
||||||
|
|
||||||
# Translations text
|
# Translations text
|
||||||
|
o << " var _TXT_VALIDATION_BTN = \"" + l(:ide_txt_validation_btn) + "\";\n"
|
||||||
|
o << " var _TXT_CANCEL_BTN = \"" + l(:ide_txt_cancel_btn) + "\";\n"
|
||||||
o << " var _TXT_ERROR_POSITIVE_NUMBER = \"" + l(:ide_txt_error_positive_number) + "\";\n"
|
o << " var _TXT_ERROR_POSITIVE_NUMBER = \"" + l(:ide_txt_error_positive_number) + "\";\n"
|
||||||
o << " var _TXT_ERROR_START_DATE = \"" + l(:ide_txt_error_start_date) + "\";\n"
|
o << " var _TXT_ERROR_START_DATE = \"" + l(:ide_txt_error_start_date) + "\";\n"
|
||||||
o << " var _TXT_ERROR_DUE_DATE = \"" + l(:ide_txt_error_due_date) + "\";\n"
|
o << " var _TXT_ERROR_DUE_DATE = \"" + l(:ide_txt_error_due_date) + "\";\n"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user