pull/190/head
commit
96dd9c77ca
After Width: | Height: | Size: 160 B |
@ -0,0 +1,67 @@ |
||||
/* |
||||
The action menu is a menu that usually belongs to an OpenProject entity (like an Issue, WikiPage, Meeting, ..). |
||||
Most likely it looks like this: |
||||
<ul class="action_menu_main"> |
||||
<li><a>Menu item text</a></li> |
||||
<li><a>Menu item text</a></li> |
||||
<li class="drop-down"> |
||||
<a class="icon icon-more" href="javascript:">More functions</a> |
||||
<ul style="display:none;" class="action_menu_more"> |
||||
<li><a>Menu item text</a></li> |
||||
</ul> |
||||
</li> |
||||
</ul> |
||||
The following code is responsible to open and close the "more functions" submenu. |
||||
*/ |
||||
|
||||
jQuery(function ($) { |
||||
var animationSpeed = 100; // ms
|
||||
|
||||
function menu_top_position(menu) { |
||||
// if an h2 tag follows the submenu should unfold out at the border
|
||||
var menu_start_position; |
||||
if (menu.next().get(0) != undefined && (menu.next().get(0).tagName == 'H2')){ |
||||
menu_start_position = menu.next().innerHeight() + menu.next().position().top; |
||||
} |
||||
else if(menu.next().hasClass("wiki-content") && menu.next().children().next().first().get(0) != undefined && menu.next().children().next().first().get(0).tagName == 'H1'){ |
||||
var wiki_heading = menu.next().children().next().first(); |
||||
menu_start_position = wiki_heading.innerHeight() + wiki_heading.position().top; |
||||
} |
||||
return menu_start_position; |
||||
}; |
||||
|
||||
function close_menu(event) { |
||||
var menu = $(event.data.menu); |
||||
// do not close the menu, if the user accidentally clicked next to a menu item (but still within the menu)
|
||||
if ( event.target !== menu.find(" > li.drop-down.open > ul").get(0)) { |
||||
menu.find(" > li.drop-down.open").removeClass("open").find("> ul").slideUp(animationSpeed); |
||||
// no need to watch for clicks, when the menu is already closed
|
||||
$('html').off('click', close_menu); |
||||
}; |
||||
}; |
||||
|
||||
function open_menu(menu) { |
||||
var drop_down = menu.find(" > li.drop-down") |
||||
// do not open a menu, which is already open
|
||||
if ( !drop_down.hasClass('open') ) { |
||||
drop_down.find('> ul').slideDown(animationSpeed, function(){ |
||||
drop_down.find('li > a:first').focus(); |
||||
// when clicking on something, which is not the menu, close the menu
|
||||
$('html').on('click', {menu: menu.get(0)}, close_menu); |
||||
}); |
||||
drop_down.addClass('open'); |
||||
}; |
||||
}; |
||||
|
||||
// open the given submenu when clicking on it
|
||||
function install_menu_logic(menu) { |
||||
menu.find(" > li.drop-down").click(function(event) { |
||||
$(this).find("ul.action_menu_more").css({ top: menu_top_position(menu) }); |
||||
open_menu(menu); |
||||
}); |
||||
}; |
||||
|
||||
$('.action_menu_main').each(function(idx, menu){ |
||||
install_menu_logic($(menu)); |
||||
}); |
||||
}); |
@ -0,0 +1,166 @@ |
||||
(function ($) { |
||||
var AjaxAppender = function (options) { |
||||
var append_href, |
||||
close, |
||||
target_container, |
||||
is_inplace, |
||||
is_loaded, |
||||
state_loading, |
||||
state_loaded, |
||||
replace_with_close, |
||||
replace_with_open, |
||||
slideIn, |
||||
init; |
||||
|
||||
options = $.extend(true, |
||||
{}, |
||||
{ loading_class: 'loading', |
||||
loading: null, |
||||
loaded: null, |
||||
load_target: null, |
||||
trigger: '.ajax_append', |
||||
container_class: 'ajax_appended_information', |
||||
indicator_class: 'ajax_indicator', |
||||
hide_text: 'Hide', |
||||
loading_text: null |
||||
}, |
||||
options); |
||||
|
||||
close = function () { |
||||
var close_link = $(this), |
||||
information_window = close_link.siblings('.' + options.container_class); |
||||
|
||||
replace_with_open(close_link); |
||||
|
||||
information_window.slideUp(); |
||||
}; |
||||
|
||||
append_href = function (link) { |
||||
var target = target_container(link), |
||||
loading_div, |
||||
url = link.attr('href'); |
||||
|
||||
if (is_loaded(link)) { |
||||
state_loaded(target, link); |
||||
} |
||||
else { |
||||
state_loading(target); |
||||
|
||||
$.ajax({ url: url, |
||||
headers: { Accept: 'text/javascript' }, |
||||
complete: function (jqXHR) { |
||||
target.html(jqXHR.responseText); |
||||
|
||||
state_loaded(target, link); |
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
is_inplace = function() { |
||||
return options.load_target === null; |
||||
}; |
||||
|
||||
is_loaded = function(link) { |
||||
var container = target_container(link); |
||||
|
||||
return container.children().not('.' + options.indicator_class).size() > 0; |
||||
}; |
||||
|
||||
target_container = function(link) { |
||||
var target, |
||||
container_string = '<div class="' + options.container_class + '"></div>', |
||||
container; |
||||
|
||||
if (is_inplace()) { |
||||
target = link.parent(); |
||||
} |
||||
else { |
||||
target = $(options.load_target); |
||||
} |
||||
|
||||
container = target.find('.' + options.container_class); |
||||
|
||||
if (container.size() === 0) { |
||||
container = $(container_string); |
||||
|
||||
target.append(container); |
||||
} |
||||
|
||||
return container; |
||||
}; |
||||
|
||||
state_loading = function (target) { |
||||
var loading = $('<span class="' + options.indicator_class + '"></span>'); |
||||
|
||||
if (options.loading_text !== null) { |
||||
loading.html(options.loading_text); |
||||
} |
||||
|
||||
target.addClass(options.loading_class); |
||||
target.append(loading); |
||||
|
||||
if (options.loading !== null) { |
||||
options.loading.call(this, target); |
||||
} |
||||
}; |
||||
|
||||
state_loaded = function (target, link) { |
||||
target.removeClass(options.loading_class); |
||||
|
||||
if (is_inplace()) { |
||||
replace_with_close(link, true); |
||||
} |
||||
|
||||
if (options.loaded !== null) { |
||||
target.slideDown(function() { |
||||
options.loaded.call(this, target, link); |
||||
}); |
||||
} |
||||
else{ |
||||
target.slideDown(); |
||||
} |
||||
}; |
||||
|
||||
replace_with_close = function (to_replace, hide) { |
||||
var close_link = $('<a href="javascript:void(0)">' + options.hide_text + '</a>'); |
||||
|
||||
to_replace.after(close_link); |
||||
|
||||
if (hide) { |
||||
to_replace.hide(); |
||||
} |
||||
else { |
||||
to_replace.remove(); |
||||
} |
||||
|
||||
close_link.click(close); |
||||
}; |
||||
|
||||
replace_with_open = function(to_replace) { |
||||
var load_link = to_replace.siblings(options.trigger); |
||||
|
||||
to_replace.remove(); |
||||
|
||||
/* this link is never removed, only hidden */ |
||||
load_link.show(); |
||||
}; |
||||
|
||||
$(options.trigger).click(function(link) { |
||||
append_href($(this)); |
||||
|
||||
return false; |
||||
}); |
||||
|
||||
return this; |
||||
}; |
||||
|
||||
if ($.ajaxAppend) { |
||||
return; |
||||
} |
||||
|
||||
$.ajaxAppend = function (options) { |
||||
AjaxAppender(options); |
||||
return this; |
||||
}; |
||||
}(jQuery)); |
@ -0,0 +1,71 @@ |
||||
var Issue = Issue || {}; |
||||
|
||||
Issue.Show = (function($) { |
||||
var init; |
||||
|
||||
init = function () { |
||||
$.ajaxAppend({ |
||||
trigger: '.action_menu_main .edit', |
||||
indicator_class: 'ajax-indicator', |
||||
load_target: '#update', |
||||
loading_text: I18n.t("js.ajax.loading"), |
||||
loading_class: 'box loading', |
||||
loading: function(update) { |
||||
$('html, body').animate({ |
||||
scrollTop: $(update).offset().top |
||||
}, 200); |
||||
}, |
||||
loaded: function(update) { |
||||
$('html, body').animate({ |
||||
scrollTop: $(update).offset().top |
||||
}, 200); |
||||
$("#notes").focus(); |
||||
} |
||||
}); |
||||
|
||||
$.ajaxAppend({ |
||||
trigger: '.quote-link', |
||||
indicator_class: 'ajax-indicator', |
||||
load_target: '#update', |
||||
loading_text: I18n.t("js.ajax.loading"), |
||||
loading_class: 'box loading', |
||||
loading: function(update) { |
||||
$('html, body').animate({ |
||||
scrollTop: $(update).offset().top |
||||
}, 200); |
||||
}, |
||||
loaded: function(update, target) { |
||||
var content = $(target.context).parent().siblings('.wikicontent'); |
||||
var text = content.text(); |
||||
var user = content.attr('data-user'); |
||||
|
||||
text = text.trim().replace(/<pre>((.|\s)*?)<\/pre>/g, '[...]'); |
||||
// remove blank lines generated by redmine textilizable |
||||
text = text.replace(/^\s*$[\n\r]{1,}/gm, ''); |
||||
|
||||
var quotedText = "<%= ::I18n.t(:text_user_wrote, :value => "{{{user}}}", :locale => Setting.default_language.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" }) %>\n> "; |
||||
quotedText = quotedText.replace("{{{user}}}", user); |
||||
quotedText += text.replace(/(\r?\n|\r\n?)/g, "\n> ") + "\n\n"; |
||||
|
||||
$('#notes').text(quotedText); |
||||
$('html, body').animate({ |
||||
scrollTop: $(update).offset().top |
||||
}, 200); |
||||
$("#notes").focus(); |
||||
} |
||||
}); |
||||
|
||||
$.ajaxAppend({ |
||||
trigger: '.description-details', |
||||
indicator_class: 'ajax-indicator', |
||||
loading_class: 'text-diff', |
||||
hide_text: I18n.t("js.ajax.hide") |
||||
} ); |
||||
}; |
||||
|
||||
$('document').ready(function () { |
||||
if ($('body.controller-issues.action-show').size() > 0) { |
||||
init(); |
||||
} |
||||
}); |
||||
})(jQuery); |
@ -0,0 +1,33 @@ |
||||
class PermittedParams < Struct.new(:params, :user) |
||||
# This class intends to provide a method for all params hashes comming from the |
||||
# client and that are used for mass assignment. |
||||
# |
||||
# As such, please make it a deliberate decission to whitelist attributes. |
||||
# |
||||
# This implementation depends on the strong_parameters gem. For further |
||||
# information see here: https://github.com/rails/strong_parameters |
||||
# |
||||
# |
||||
# A method should look like the following: |
||||
# |
||||
# def name_of_the_params_key_referenced |
||||
# params.require(:name_of_the_params_key_referenced).permit(list_of_whitelisted_params) |
||||
# end |
||||
# |
||||
# |
||||
# A controller could use a permitted_params method like this |
||||
# |
||||
# model_instance.attributes = permitted_params.name_of_the_params_key_referenced |
||||
# |
||||
# instead of doing something like this which will not work anymore once the |
||||
# model is protected: |
||||
# |
||||
# model_instance.attributes = params[:name_of_the_params_key_referenced] |
||||
# |
||||
# |
||||
# A model will need the following module included in order to be protected by |
||||
# strong_params |
||||
# |
||||
# include ActiveModel::ForbiddenAttributesProtection |
||||
end |
||||
|
@ -1,19 +1,19 @@ |
||||
<%= error_messages_for 'enumeration' %> |
||||
<div class="box"> |
||||
<!--[form:optvalue]--> |
||||
<%= hidden_field 'enumeration', 'type' %> |
||||
<%= hidden_field 'enumeration', 'type' %> |
||||
|
||||
<p><label for="enumeration_name"><%=l(:field_name)%></label> |
||||
<%= text_field 'enumeration', 'name' %></p> |
||||
<p><label for="enumeration_name"><%= Enumeration.human_attribute_name(:name) %></label> |
||||
<%= text_field 'enumeration', 'name' %></p> |
||||
|
||||
<p><label for="enumeration_active"><%=l(:field_active)%></label> |
||||
<%= check_box 'enumeration', 'active' %></p> |
||||
<p><label for="enumeration_active"><%= Enumeration.human_attribute_name(:active) %></label> |
||||
<%= check_box 'enumeration', 'active' %></p> |
||||
|
||||
<p><label for="enumeration_is_default"><%=l(:field_is_default)%></label> |
||||
<%= check_box 'enumeration', 'is_default' %></p> |
||||
<p><label for="enumeration_is_default"><%= Enumeration.human_attribute_name(:is_default) %></label> |
||||
<%= check_box 'enumeration', 'is_default' %></p> |
||||
<!--[eoform:optvalue]--> |
||||
|
||||
<% @enumeration.custom_field_values.each do |value| %> |
||||
<p><%= custom_field_tag_with_label :enumeration, value %></p> |
||||
<p><%= custom_field_tag_with_label :enumeration, value %></p> |
||||
<% end %> |
||||
</div> |
||||
|
@ -1,8 +1,8 @@ |
||||
<%= error_messages_for :group %> |
||||
|
||||
<div class="box tabular"> |
||||
<p><%= f.text_field :lastname, :label => :field_name %></p> |
||||
<% @group.custom_field_values.each do |value| %> |
||||
<p><%= custom_field_tag_with_label :group, value %></p> |
||||
<p><%= f.text_field :lastname, :label => Group.human_attribute_name(:name) %></p> |
||||
<% @group.custom_field_values.each do |value| %> |
||||
<p><%= custom_field_tag_with_label :group, value %></p> |
||||
<% end %> |
||||
</div> |
||||
|
@ -1,12 +1,12 @@ |
||||
<div class="splitcontentleft"> |
||||
<% i = 0 %> |
||||
<% split_on = (@issue.custom_field_values.size / 2.0).ceil - 1 %> |
||||
<% @issue.custom_field_values.each do |value| %> |
||||
<p><%= custom_field_tag_with_label :issue, value %></p> |
||||
<% if i == split_on -%> |
||||
</div><div class="splitcontentright"> |
||||
<% end -%> |
||||
<% i += 1 -%> |
||||
<% end -%> |
||||
<% i = 0 %> |
||||
<% split_on = (@issue.custom_field_values.size / 2.0).ceil - 1 %> |
||||
<% @issue.custom_field_values.each do |value| %> |
||||
<p><%= custom_field_tag_with_label :issue, value %></p> |
||||
<% if i == split_on -%> |
||||
</div><div class="splitcontentright"> |
||||
<% end -%> |
||||
<% i += 1 -%> |
||||
<% end -%> |
||||
</div> |
||||
<div style="clear:both;"> </div> |
||||
|
@ -1,29 +1,29 @@ |
||||
<% if issues && issues.any? %> |
||||
<%= form_tag({}) do %> |
||||
<table class="list issues"> |
||||
<thead><tr> |
||||
<th>#</th> |
||||
<th><%=l(:field_project)%></th> |
||||
<th><%=l(:field_tracker)%></th> |
||||
<th><%=l(:field_subject)%></th> |
||||
</tr></thead> |
||||
<tbody> |
||||
<% for issue in issues %> |
||||
<tr id="issue-<%= h(issue.id) %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>"> |
||||
<td class="id"> |
||||
<%= check_box_tag("ids[]", issue.id, false, :style => 'display:none;') %> |
||||
<%= link_to(h(issue.id), :controller => '/issues', :action => 'show', :id => issue) %> |
||||
</td> |
||||
<td class="project"><%= link_to_project(issue.project) %></td> |
||||
<td class="tracker"><%=h issue.tracker %></td> |
||||
<td class="subject"> |
||||
<table class="list issues"> |
||||
<thead><tr> |
||||
<th>#</th> |
||||
<th><%= Issue.human_attribute_name(:project)%></th> |
||||
<th><%= Issue.human_attribute_name(:tracker)%></th> |
||||
<th><%= Issue.human_attribute_name(:subject)%></th> |
||||
</tr></thead> |
||||
<tbody> |
||||
<% for issue in issues %> |
||||
<tr id="issue-<%= h(issue.id) %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>"> |
||||
<td class="id"> |
||||
<%= check_box_tag("ids[]", issue.id, false, :style => 'display:none;') %> |
||||
<%= link_to(h(issue.id), :controller => '/issues', :action => 'show', :id => issue) %> |
||||
</td> |
||||
<td class="project"><%= link_to_project(issue.project) %></td> |
||||
<td class="tracker"><%=h issue.tracker %></td> |
||||
<td class="subject"> |
||||
<%= link_to h(truncate(issue.subject, :length => 60)), :controller => '/issues', :action => 'show', :id => issue %> (<%=h issue.status %>) |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
<% end %> |
||||
<% else %> |
||||
<p class="nodata"><%= l(:label_no_data) %></p> |
||||
<p class="nodata"><%= l(:label_no_data) %></p> |
||||
<% end %> |
||||
|
@ -1,11 +1,11 @@ |
||||
<% if @notes %> |
||||
<fieldset class="preview"><legend><%= l(:field_notes) %></legend> |
||||
<fieldset class="preview"><legend><%= Journal.human_attribute_name(:notes) %></legend> |
||||
<%= textilizable @notes, :attachments => @attachements, :object => @issue %> |
||||
</fieldset> |
||||
<% end %> |
||||
|
||||
<% if @description %> |
||||
<fieldset class="preview"><legend><%= l(:field_description) %></legend> |
||||
<fieldset class="preview"><legend><%= Issue.human_attribute_name(:description) %></legend> |
||||
<%= textilizable @description, :attachments => @attachements, :object => @issue %> |
||||
</fieldset> |
||||
<% end %> |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue