Skip to content

Commit

Permalink
version with view_options.
Browse files Browse the repository at this point in the history
  • Loading branch information
hron committed May 26, 2009
1 parent deee106 commit 83d6d6a
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 122 deletions.
99 changes: 12 additions & 87 deletions app/controllers/issues_controller.rb
Expand Up @@ -4,24 +4,19 @@

class IssuesController < ApplicationController

unloadable
skip_before_filter :authorize, :only => [ :add_subissue,
:auto_complete_for_issue_parent]

skip_before_filter :authorize,
:only => [ :auto_complete_for_issue_parent ]

before_filter :find_parent_issue,
:only => [:add_subissue]
before_filter :find_parent_issue, :only => [:add_subissue]
before_filter :find_optional_parent_issue, :only => [:new]
before_filter :find_project, :only => [ :new,
:update_form,
:preview,
:auto_complete_for_issue_parent,
:add_subissue]
before_filter :find_project, :only => [ :add_subissue,
:auto_complete_for_issue_parent ]

include ActionView::Helpers::PrototypeHelper

def add_subissue
redirect_to :action => 'new', :issue => { :parent_id => @parent_issue.id }
redirect_to :action => 'new',
:issue => { :parent_id => @parent_issue.id }
end

def auto_complete_for_issue_parent
Expand Down Expand Up @@ -63,49 +58,6 @@ def auto_complete_for_issue_parent
end


def index_with_subtasks
retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update({'id' => "#{Issue.table_name}.id"}.merge(@query.available_columns.inject({}) {|h, c| h[c.name.to_s] = c.sortable; h}))

if @query.valid?
limit = per_page_option
respond_to do |format|
format.html { }
format.atom { }
format.csv { limit = Setting.issues_export_limit.to_i }
format.pdf { limit = Setting.issues_export_limit.to_i }
end
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
@issue_pages = ActionController::Pagination::Paginator.new self, @issue_count, limit, params['page']
@issues = Issue.find( :all, :order => sort_clause,
:include => [ :assigned_to,
:status,
:tracker,
:project,
:priority,
:category,
:fixed_version ],
:conditions => @query.statement,
:limit => limit,
:offset => @issue_pages.current.offset)

respond_to do |format|
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(issues_to_csv(@issues, @project).read, :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project), :type => 'application/pdf', :filename => 'export.pdf') }
end
else
# Send html if the query is not valid
render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
end
rescue ActiveRecord::RecordNotFound
render_404
end
alias_method_chain :index, :subtasks


# Add a new issue
# The new issue will be created from an existing one if copy_from parameter is given
def new_with_subtasks
Expand Down Expand Up @@ -153,7 +105,6 @@ def new_with_subtasks
end
alias_method_chain :new, :subtasks


private

def find_parent_issue
Expand All @@ -172,44 +123,18 @@ def find_optional_parent_issue

# Retrieve query from session or build a new query
def retrieve_query_with_subtasks
if !params[:query_id].blank?
cond = "project_id IS NULL"
cond << " OR project_id = #{@project.id}" if @project
@query = Query.find(params[:query_id], :conditions => cond)
@query.project = @project
session[:query] = {:id => @query.id, :project_id => @query.project_id}
sort_clear
else
RAILS_DEFAULT_LOGGER.info "retrieve_query_with_subtasks execution."
retrieve_query_without_subtasks
if params[:query_id].blank?
if params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
# Give it a name, required to be valid
@query = Query.new(:name => "_")
@query.project = @project
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end
else
@query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field]
end
end
if params[:view_options] and params[:view_options].is_a? Hash
params[:view_options].each_pair do |name, value|
@query.set_view_option( name, value)
end
end
session[:query] = {
:project_id => @query.project_id,
:filters => @query.filters,
:view_options => @query.view_options
}
session[:query][:view_options] = @query.view_options
else
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
@query ||= Query.new(:name => "_",
:project => @project,
:filters => session[:query][:filters],
:view_options => session[:query][:view_options])
@query.project = @project
@query.set_view_option :view_options, session[:query][:view_options]
end
end
end
Expand Down
75 changes: 75 additions & 0 deletions app/helpers/queries_helper.rb
@@ -0,0 +1,75 @@
require_dependency 'queries_helper'

module QueriesHelper

def column_content_with_subtasks(column, issue, query)
if column.is_a?(QueryCustomFieldColumn)
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
show_value(cv)
else
value = issue.send(column.name)
if value.is_a?(Date)
format_date(value)
elsif value.is_a?(Time)
format_time(value)
else
case column.name
when :subject
subject_in_tree(issue, value, query)
when :done_ratio
progress_bar(value, :width => '80px')
when :fixed_version
link_to(h(value), { :controller => 'versions', :action => 'show', :id => issue.fixed_version_id })
else
h(value)
end
end
end
end
alias_method_chain :column_content, :subtasks

def subject_in_tree(issue, value, query)
RAILS_DEFAULT_LOGGER.info "QUERY: #{query.view_options}"
case query.view_options['show_parents']
when Query::VIEW_OPTIONS_SHOW_PARENTS_NEVER
content_tag('div', subject_text(issue, value), :class=>'issue-subject')
else
content_tag('span', content_tag('div', subject_text(issue, value), :class=>'issue-subject'), :class=>"issue-subject-level-#{issue.hierarchical_level}")
end
end

def subject_text(issue, value)
subject_text = link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
h((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') + subject_text
end

def issue_content(issue, query, options = { })
html = ""
html << "<tr id=\"issue-#{issue.id}\" class=\"issue hascontextmenu " +
( options[:unfiltered] ? 'issue-unfiltered ' : '') +
"status-#{issue.status.position} priority-#{issue.priority.position} " +
cycle('odd', 'even') + '">'
html << '<td class="checkbox">' + check_box_tag( "ids[]", issue.id, false, :id => nil) + '</td>'
html << '<td>' + link_to( issue.id, :controller => 'issues', :action => 'show', :id => issue) + '</td>'
query.columns.each do |column|
html << content_tag( 'td', column_content(column, issue, query), :class => column.name)
end
html << "</tr>"
html
end

def issues_family_content( parent, issues_to_show, query)
html = ""
html << issue_content( parent, query, :unfiltered => !( issues_to_show.include? parent))
unless parent.children.empty?
parent.children.each do |child|
if issues_to_show.include?( child) || issues_to_show.detect { |i| i.ancestors.include? child }
html << issues_family_content( child, issues_to_show, query)
end
end
end
html
end

end

40 changes: 40 additions & 0 deletions app/views/issues/_list.rhtml
@@ -0,0 +1,40 @@
<% form_tag({}) do -%>
<table class="list issues">
<thead><tr>
<th><%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;',
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %>
</th>
<%= sort_header_tag('id', :caption => '#', :default_order => 'desc') %>
<% query.columns.each do |column| %>
<%= column_header(column) %>
<% end %>
</tr></thead>
<tbody>
<% if query.view_options['show_parents'] == Query::VIEW_OPTIONS_SHOW_PARENTS_NEVER -%>
<% issues.each do |issue| -%>
<%= issue_content( issue, query) %>
<% end -%>
<% elsif query.view_options['show_parents'] == Query::VIEW_OPTIONS_SHOW_PARENTS_ALWAYS -%>
<% issues.each do |issue| -%>
<% issue.ancestors.reverse.each do |parent_issue| -%>
<%= issue_content( parent_issue, query, :unfiltered => true) %>
<% end -%>
<%= issue_content( issue, query) %>
<% end -%>
<% elsif query.view_options['show_parents'] == Query::VIEW_OPTIONS_SHOW_PARENTS_ORGANIZE_BY_PARENT -%>
<% parents_on_first_lvl = []
issues.each do |i|
if i.parent
first_parent = i.root
else
first_parent = i
end
parents_on_first_lvl += [ first_parent ] unless parents_on_first_lvl.include?( first_parent)
end -%>
<% parents_on_first_lvl.each do |parent| -%>
<%= issues_family_content( parent, issues, query) %>
<% end -%>
<% end -%>
</tbody>
</table>
<% end -%>
71 changes: 71 additions & 0 deletions app/views/issues/index.rhtml
@@ -0,0 +1,71 @@
<% if @query.new_record? %>
<h2><%=l(:label_issue_plural)%></h2>
<% html_title(l(:label_issue_plural)) %>
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
<%= hidden_field_tag('project_id', @project.to_param) if @project %>
<fieldset id="view"><legend><%= l(:label_view) %></legend>
<%= render :partial => 'queries/view_options', :locals => {:query => @query } %>
</fieldset>
<fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
</fieldset>
<p class="buttons">
<%= link_to_remote l(:button_apply),
{ :url => { :set_filter => 1 },
:update => "content",
:with => "Form.serialize('query_form')"
}, :class => 'icon icon-checked' %>
<%= link_to_remote l(:button_clear),
{ :url => { :set_filter => 1, :project_id => @project },
:method => :get,
:update => "content",
}, :class => 'icon icon-reload' %>
<% if User.current.allowed_to?(:save_queries, @project, :global => true) %>
<%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
<% end %>
</p>
<% end %>
<% else %>
<div class="contextual">
<% if @query.editable_by?(User.current) %>
<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
<% end %>
</div>
<h2><%=h @query.name %></h2>
<div id="query_form"></div>
<% html_title @query.name %>
<% end %>
<%= error_messages_for 'query' %>
<% if @query.valid? %>
<% if @issues.empty? %>
<p class="nodata"><%= l(:label_no_data) %></p>
<% else %>
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
<p class="pagination"><%= pagination_links_full @issue_pages, @issue_count %></p>
<% end %>
<% other_formats_links do |f| %>
<%= f.link_to 'Atom', :url => { :project_id => @project, :query_id => (@query.new_record? ? nil : @query), :key => User.current.rss_key } %>
<%= f.link_to 'CSV', :url => { :project_id => @project } %>
<%= f.link_to 'PDF', :url => { :project_id => @project } %>
<% end %>
<% end %>
<% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %>
<% end %>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_issue_plural)) %>
<%= auto_discovery_link_tag(:atom, {:action => 'changes', :query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_changes_details)) %>
<%= javascript_include_tag 'context_menu' %>
<%= stylesheet_link_tag 'context_menu' %>
<% end %>

<div id="context-menu" style="display: none;"></div>
<%= javascript_tag "new ContextMenu('#{url_for(:controller => 'issues', :action => 'context_menu')}')" %>
6 changes: 6 additions & 0 deletions app/views/queries/_view_options.rhtml
@@ -0,0 +1,6 @@
<% query.view_options.each_key do |voption| -%>
<%= query.caption_for_view_option( voption) %>:
<%= select_tag( "view_options[#{voption}]",
options_for_select( query.values_for_view_option( voption),
query.view_options[voption])) %>
<% end %>
9 changes: 0 additions & 9 deletions init.rb
Expand Up @@ -8,14 +8,5 @@
author 'Aleksei Gusev'
description 'This is plugin for Redmine for adding subtasks functionality.'
version '0.0.1'

# remapping permissions
[ :edit_issues, :manage_issue_relations ].each do |pname|
Redmine::AccessControl.permissions.delete_if { |p| p.name == pname }
end
project_module :issue_tracking do |map|
map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :update_subject]}
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy], :issues => [:add_subissue]}
end
end

0 comments on commit 83d6d6a

Please sign in to comment.