Project

General

Profile

Feature #12005 » workflow_hidden_fields_redmine2.4_v1.0.patch

Gurvan Le Dromaguet, 2014-03-06 15:37

View differences:

app/helpers/issues_helper.rb (working copy)
160 160
  end
161 161

  
162 162
  def render_custom_fields_rows(issue)
163
    values = issue.visible_custom_field_values
163
    values = issue.viewable_custom_field_values
164 164
    return if values.empty?
165 165
    ordered_values = []
166 166
    half = (values.size / 2.0).ceil
......
260 260
    strings = []
261 261
    values_by_field = {}
262 262
    details.each do |detail|
263
      unless detail.journal.issue.hidden_attribute?(detail.prop_key, options[:user])
263 264
      if detail.property == 'cf'
264 265
        field = detail.custom_field
265 266
        if field && field.multiple?
......
274 275
        end
275 276
      end
276 277
      strings << show_detail(detail, no_html, options)
278
      end
277 279
    end
278 280
    values_by_field.each do |field, changes|
279 281
      detail = JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s)
280
      detail.instance_variable_set "@custom_field", field
281
      if changes[:added].any?
282
        detail.value = changes[:added]
283
        strings << show_detail(detail, no_html, options)
284
      elsif changes[:deleted].any?
285
        detail.old_value = changes[:deleted]
286
        strings << show_detail(detail, no_html, options)
282
      unless ( detail.journal != nil && detail.journal.issue.hidden_attribute?(detail.prop_key, options[:user]))
283
        detail.instance_variable_set "@custom_field", field
284
        if changes[:added].any?
285
          detail.value = changes[:added]
286
          strings << show_detail(detail, no_html, options)
287
        elsif changes[:deleted].any?
288
          detail.old_value = changes[:deleted]
289
          strings << show_detail(detail, no_html, options)
290
        end
287 291
      end
288 292
    end
289 293
    strings
app/helpers/workflows_helper.rb (working copy)
25 25
  def field_permission_tag(permissions, status, field, role)
26 26
    name = field.is_a?(CustomField) ? field.id.to_s : field
27 27
    options = [["", ""], [l(:label_readonly), "readonly"]]
28
    options << [l(:label_hidden), "hidden"] unless field_required?(field)
28 29
    options << [l(:label_required), "required"] unless field_required?(field)
29 30
    html_options = {}
30 31
    selected = permissions[status.id][name]
app/models/project.rb (working copy)
152 152
    user.allowed_to?(:view_project, self)
153 153
  end
154 154

  
155
  # Returns list of attributes that are hidden on all statuses of all trackers for +user+ or the current user.
156
  def completely_hidden_attribute_names(user=nil)
157
    user_real = user || User.current
158
    roles = user_real.admin ? Role.all : user_real.roles_for_project(self)
159
    return {} if roles.empty?
160

  
161
    result = {}
162
    workflow_permissions = WorkflowPermission.where(:tracker_id => trackers.map(&:id), :old_status_id => IssueStatus.all.map(&:id), :role_id => roles.map(&:id), :rule => 'hidden').all
163

  
164
    if workflow_permissions.any?
165
      workflow_rules = workflow_permissions.inject({}) do |h, wp|
166
        h[wp.field_name] ||= []
167
        h[wp.field_name] << wp.rule
168
        h
169
      end
170
      workflow_rules.each do |attr, rules|
171
        next if rules.size < (roles.size * trackers.size * IssueStatus.all.size)
172
        uniq_rules = rules.uniq
173
        if uniq_rules.size == 1
174
          result[attr] = uniq_rules.first
175
        else
176
          result[attr] = 'required'
177
        end
178
      end
179
    end
180

  
181
    result.keys    
182
  end
183

  
184

  
155 185
  # Returns a SQL conditions string used to find all projects visible by the specified user.
156 186
  #
157 187
  # Examples:
app/models/workflow_permission.rb (working copy)
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18 18
class WorkflowPermission < WorkflowRule
19
  validates_inclusion_of :rule, :in => %w(readonly required)
19
  validates_inclusion_of :rule, :in => %w(readonly required hidden)
20 20
  validate :validate_field_name
21 21

  
22 22
  # Replaces the workflow permissions for the given tracker and role
23 23
  #
24 24
  # Example:
25
  #   WorkflowPermission.replace_permissions role, tracker, {'due_date' => {'1' => 'readonly', '2' => 'required'}}
25
  #   WorkflowPermission.replace_permissions role, tracker, {'due_date' => {'1' => 'readonly', '2' => 'required', '3' => 'hidden'}}
26 26
  def self.replace_permissions(tracker, role, permissions)
27 27
    destroy_all(:tracker_id => tracker.id, :role_id => role.id)
28 28

  
app/models/issue.rb (working copy)
483 483
    end
484 484
  end
485 485

  
486
  # Returns the custom_field_values that can be viewed by the given user, also always excludes Fix Info, RNs and TAT, as it is printed separately below description.
487
  def viewable_custom_field_values(user=nil)
488
    custom_field_values.reject do |value|
489
      hidden_attribute_names(user).include?(value.custom_field_id.to_s)
490
    end
491
  end
492

  
486 493
  # Returns the names of attributes that are read-only for user or the current user
487 494
  # For users with multiple roles, the read-only fields are the intersection of
488 495
  # read-only fields of each role
489
  # The result is an array of strings where sustom fields are represented with their ids
496
  # The result is an array of strings where custom fields are represented with their ids
490 497
  #
491 498
  # Examples:
492 499
  #   issue.read_only_attribute_names # => ['due_date', '2']
493 500
  #   issue.read_only_attribute_names(user) # => []
494 501
  def read_only_attribute_names(user=nil)
495
    workflow_rule_by_attribute(user).reject {|attr, rule| rule != 'readonly'}.keys
502
    workflow_rule_by_attribute(user).reject {|attr, rule| rule != 'readonly' && rule != 'hidden' }.keys
496 503
  end
497 504

  
505
  # Same as above, return the names of attributes that are hidden for user or the current user
506
  def hidden_attribute_names(user=nil)
507
    workflow_rule_by_attribute(user).reject {|attr, rule| rule != 'hidden'}.keys
508
  end
509

  
498 510
  # Returns the names of required attributes for user or the current user
499 511
  # For users with multiple roles, the required fields are the intersection of
500 512
  # required fields of each role
......
512 524
    required_attribute_names(user).include?(name.to_s)
513 525
  end
514 526

  
527
  # Returns true if the attribute should be hidden for user
528
  def hidden_attribute?(name, user=nil)
529
    hidden_attribute_names(user).include?(name.to_s)
530
  end
531

  
532

  
515 533
  # Returns a hash of the workflow rule by attribute for the given user
516 534
  #
517 535
  # Examples:
app/views/mailer/_issue.text.erb (working copy)
1 1
<%= "#{issue.tracker.name} ##{issue.id}: #{issue.subject}" %>
2 2
<%= issue_url %>
3 3

  
4
<%= render_email_issue_attributes(issue, users.first) %>
4
* <%=l(:field_author)%>: <%= issue.author %>
5
<% unless issue.hidden_attribute?('status', user) %>
6
* <%=l(:field_status)%>: <%= issue.status %>
7
<% end %>
8
<% unless issue.hidden_attribute?('priority', user) %>
9
* <%=l(:field_priority)%>: <%= issue.priority %>
10
<% end %>
11
<% unless issue.disabled_core_fields.include?('assigned_to_id') || issue.hidden_attribute?('assigned_to_id', user) %>
12
* <%=l(:field_assigned_to)%>: <%= issue.assigned_to %>
13
<% end %>
14
<% unless issue.disabled_core_fields.include?('category_id') || issue.hidden_attribute?('category_id', user) %>
15
* <%=l(:field_category)%>: <%= issue.category %>
16
<% end %>
17
<% unless issue.disabled_core_fields.include?('fixed_version_id') || issue.hidden_attribute?('fixed_version_id', user) %>
18
* <%=l(:field_fixed_version)%>: <%= issue.fixed_version %>
19
<% end %>
20
<% issue.custom_field_values.each do |c| %>
21
<% unless issue.hidden_attribute?(c.custom_field.id, user) %>
22
* <%= c.custom_field.name %>: <%= show_value(c) %>
23
<% end %>
24
<% end -%>
5 25
----------------------------------------
6 26
<%= issue.description %>
7 27

  
app/views/mailer/_issue.html.erb (working copy)
1 1
<h1><%= link_to(h("#{issue.tracker.name} ##{issue.id}: #{issue.subject}"), issue_url) %></h1>
2 2

  
3
<%= render_email_issue_attributes(issue, users.first, true) %>
3
<ul>
4
<li><%=l(:field_author)%>: <%=h issue.author %></li>
5
<% unless issue.hidden_attribute?('status', user) %>
6
  <li><%=l(:field_status)%>: <%=h issue.status %></li>
7
<% end %>
8
<% unless issue.hidden_attribute?('priority', user) %>
9
  <li><%=l(:field_priority)%>: <%=h issue.priority %></li>
10
<% end %>
11
<% unless issue.disabled_core_fields.include?('assigned_to_id') || issue.hidden_attribute?('assigned_to_id', user) %>
12
  <li><%=l(:field_assigned_to)%>: <%=h issue.assigned_to %></li>
13
<% end %>
14
<% unless issue.disabled_core_fields.include?('category_id') || issue.hidden_attribute?('category_id', user) %>
15
  <li><%=l(:field_category)%>: <%=h issue.category %></li>
16
<% end %>
17
<% unless issue.disabled_core_fields.include?('fixed_version_id') || issue.hidden_attribute?('fixed_version_id', user) %>
18
  <li><%=l(:field_fixed_version)%>: <%=h issue.fixed_version %></li>
19
<% end %>
20
<% issue.custom_field_values.each do |c| %>
21
  <% unless issue.hidden_attribute?(c.custom_field.id, user) %>
22
    <li><%=h c.custom_field.name %>: <%=h show_value(c) %></li>
23
  <% end %>
24
<% end %>
25
</ul>
4 26

  
5 27
<%= textilizable(issue, :description, :only_path => false) %>
6 28

  
app/views/issues/show.html.erb (working copy)
33 33

  
34 34
<table class="attributes">
35 35
<%= issue_fields_rows do |rows|
36
  unless @issue.hidden_attribute?('status')
36 37
  rows.left l(:field_status), h(@issue.status.name), :class => 'status'
38
  end
39
  unless @issue.hidden_attribute?('priority_id')
37 40
  rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority'
38 41

  
39
  unless @issue.disabled_core_fields.include?('assigned_to_id')
42
  unless @issue.disabled_core_fields.include?('assigned_to_id') || @issue.hidden_attribute?('assigned_to_id')
40 43
    rows.left l(:field_assigned_to), avatar(@issue.assigned_to, :size => "14").to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to'
41 44
  end
42
  unless @issue.disabled_core_fields.include?('category_id')
45
  unless @issue.disabled_core_fields.include?('category_id') || @issue.hidden_attribute?('category_id')
43 46
    rows.left l(:field_category), h(@issue.category ? @issue.category.name : "-"), :class => 'category'
44 47
  end
45
  unless @issue.disabled_core_fields.include?('fixed_version_id')
48
  unless @issue.disabled_core_fields.include?('fixed_version_id') || @issue.hidden_attribute?('fixed_version_id')
46 49
    rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version'
47 50
  end
48 51

  
49
  unless @issue.disabled_core_fields.include?('start_date')
52
  unless @issue.disabled_core_fields.include?('start_date') || @issue.hidden_attribute?('start_date')
50 53
    rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
51 54
  end
52
  unless @issue.disabled_core_fields.include?('due_date')
55
  unless @issue.disabled_core_fields.include?('due_date') || @issue.hidden_attribute?('due_date')
53 56
    rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
54 57
  end
55
  unless @issue.disabled_core_fields.include?('done_ratio')
58
  unless @issue.disabled_core_fields.include?('done_ratio') || @issue.hidden_attribute?('done_ratio')
56 59
    rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress'
57 60
  end
58
  unless @issue.disabled_core_fields.include?('estimated_hours')
61
  unless @issue.disabled_core_fields.include?('estimated_hours') || @issue.hidden_attribute?('estimated_hours')
59 62
    unless @issue.estimated_hours.nil?
60 63
      rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours'
61 64
    end
config/locales/en.yml (working copy)
888 888
  label_fields_permissions: Fields permissions
889 889
  label_readonly: Read-only
890 890
  label_required: Required
891
  label_hidden: Hidden
891
  label_hidden: " Hidden "
892 892
  label_attribute_of_project: "Project's %{name}"
893 893
  label_attribute_of_issue: "Issue's %{name}"
894 894
  label_attribute_of_author: "Author's %{name}"
lib/redmine/export/pdf.rb (working copy)
550 550
        pdf.Ln
551 551

  
552 552
        left = []
553
        left << [l(:field_status), issue.status]
554
        left << [l(:field_priority), issue.priority]
555
        left << [l(:field_assigned_to), issue.assigned_to] unless issue.disabled_core_fields.include?('assigned_to_id')
556
        left << [l(:field_category), issue.category] unless issue.disabled_core_fields.include?('category_id')
557
        left << [l(:field_fixed_version), issue.fixed_version] unless issue.disabled_core_fields.include?('fixed_version_id')
553
        left << [l(:field_status), issue.status] unless issue.hidden_attribute?('status')
554
        left << [l(:field_priority), issue.priority] unless issue.hidden_attribute?('priority_id')
555
        left << [l(:field_assigned_to), issue.assigned_to] unless issue.disabled_core_fields.include?('assigned_to_id') or issue.hidden_attribute?('assigned_to_id')
556
        left << [l(:field_category), issue.category] unless issue.disabled_core_fields.include?('category_id') or issue.hidden_attribute?('category_id')
557
        left << [l(:field_fixed_version), issue.fixed_version] unless issue.disabled_core_fields.include?('fixed_version_id') or issue.hidden_attribute?('fixed_version_id')
558 558

  
559 559
        right = []
560
        right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date')
561
        right << [l(:field_due_date), format_date(issue.due_date)] unless issue.disabled_core_fields.include?('due_date')
562
        right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio')
563
        right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours')
560
        right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date') or issue.hidden_attribute?('start_date')
561
        right << [l(:field_due_date), format_date(issue.due_date)] unless issue.disabled_core_fields.include?('due_date') or issue.hidden_attribute?('due_date')
562
        right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio') or issue.hidden_attribute?('done_ratio')
563
        right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours') or issue.hidden_attribute?('estimated_hours')
564 564
        right << [l(:label_spent_time), l_hours(issue.total_spent_hours)] if User.current.allowed_to?(:view_time_entries, issue.project)
565 565

  
566 566
        rows = left.size > right.size ? left.size : right.size
(12-12/13)