Project

General

Profile

Feature #22802 » 0001-Add-the-posibility-to-set-change-the-position-of-an-.patch

Codruț Gușoi, 2022-06-27 18:27

View differences:

app/controllers/enumerations_controller.rb
25 25
  before_action :require_admin_or_api_request, :only => :index
26 26
  before_action :build_new_enumeration, :only => [:new, :create]
27 27
  before_action :find_enumeration, :only => [:edit, :update, :destroy]
28
  accept_api_auth :index
28
  accept_api_auth :index, :update
29 29

  
30 30
  helper :custom_fields
31 31

  
app/controllers/issues_controller.rb
209 209
            issue_path(@issue, previous_and_next_issue_ids_params)
210 210
          )
211 211
        end
212
        format.js { head 200 }
212 213
        format.api  {render_api_ok}
213 214
      end
214 215
    else
215 216
      respond_to do |format|
216 217
        format.html {render :action => 'edit'}
218
        format.js { head 422 }
217 219
        format.api  {render_validation_errors(@issue)}
218 220
      end
219 221
    end
app/controllers/versions_controller.rb
52 52
            includes(:project, :tracker).
53 53
            preload(:status, :priority, :fixed_version).
54 54
            where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)).
55
            order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
55
            #order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
56
            order(order_issues_by)
56 57
          @issues_by_version = issues.group_by(&:fixed_version)
57 58
        end
58 59
        @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
......
69 70
        @issues = @version.fixed_issues.visible.
70 71
          includes(:status, :tracker, :priority).
71 72
          preload(:project).
72
          reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
73
          #reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
74
          reorder(order_issues_by).
73 75
          to_a
74 76
      end
75 77
      format.api
......
173 175
    end
174 176
  end
175 177

  
178
  def order_issues_by
179
    if Setting.manual_issue_position_in_versions == '1'
180
      return "COALESCE(#{Issue.table_name}.position, 999999), #{Issue.table_name}.id"
181
    else
182
      return "#{Tracker.table_name}.position, #{Issue.table_name}.id"
183
    end
184
  end
185

  
176 186
  private
177 187

  
178 188
  def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
app/models/issue.rb
54 54
  acts_as_activity_provider :scope => proc {preload(:project, :author, :tracker, :status)},
55 55
                            :author_key => :author_id
56 56

  
57
  acts_as_positioned :scope => [:fixed_version_id]
58

  
57 59
  DONE_RATIO_OPTIONS = %w(issue_field issue_status)
58 60

  
59 61
  attr_reader :transition_warning
......
510 512
      (issue.new_record? || issue.attributes_editable?(user)) &&
511 513
        user.allowed_to?(:manage_subtasks, issue.project)
512 514
    end)
515
  safe_attributes(
516
    'position',
517
    :if => lambda {|issue, user| user.allowed_to?(:change_issue_position_in_version, issue.project)}
518
  )
513 519
  safe_attributes(
514 520
    'deleted_attachment_ids',
515 521
    :if => lambda {|issue, user| issue.attachments_deletable?(user)})
......
861 867

  
862 868
  # Returns the names of attributes that are journalized when updating the issue
863 869
  def journalized_attribute_names
864
    names = Issue.column_names - %w(id root_id lft rgt lock_version created_on updated_on closed_on)
870
    names = Issue.column_names - %w(id root_id lft rgt lock_version position created_on updated_on closed_on)
865 871
    if tracker
866 872
      names -= tracker.disabled_core_fields
867 873
    end
app/models/issue_query.rb
49 49
    QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date", :groupable => true),
50 50
    QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours",
51 51
                    :totalable => true),
52
    QueryColumn.new(:position, :sortable => "#{Issue.table_name}.position"),
52 53
    QueryColumn.new(
53 54
      :total_estimated_hours,
54 55
      :sortable =>
......
182 183
    add_available_filter "start_date", :type => :date
183 184
    add_available_filter "due_date", :type => :date
184 185
    add_available_filter "estimated_hours", :type => :float
186
    add_available_filter "position", :type => :integer
185 187

  
186 188
    if User.current.allowed_to?(:view_time_entries, project, :global => true)
187 189
      add_available_filter "spent_time", :type => :float, :label => :label_spent_time
app/views/settings/_issues.html.erb
15 15

  
16 16
<p><%= setting_check_box :display_subprojects_issues %></p>
17 17

  
18
<p><%= setting_check_box :manual_issue_position_in_versions %></p>
19

  
18 20
<p><%= setting_select :issue_done_ratio, Issue::DONE_RATIO_OPTIONS.collect {|i| [l("setting_issue_done_ratio_#{i}"), i]} %></p>
19 21

  
20 22
<p><%= setting_multiselect :non_working_week_days, (1..7).map {|d| [day_name(d), d.to_s]}, :inline => true %></p>
app/views/versions/index.html.erb
32 32
      <%= form_tag({}, :data => {:cm_url => issues_context_menu_path}) do -%>
33 33
        <table class="list related-issues">
34 34
        <caption><%= l(:label_related_issues) %></caption>
35
        <% issues.each do |issue| -%>
36
          <tr class="hascontextmenu <%= issue.css_classes %>">
37
            <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
38
            <td class="assigned_to"><%= assignee_avatar(issue.assigned_to, :size => 16) %></td>
39
            <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
40
            <td class="buttons"><%= link_to_context_menu %></td>
41
          </tr>
42
        <% end -%>
35
          <tbody>
36
            <% issues.each do |issue| -%>
37
              <tr class="hascontextmenu <%= issue.css_classes %>">
38
                <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
39
                <td class="assigned_to"><%= assignee_avatar(issue.assigned_to, :size => 16) %></td>
40
                <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
41
                <td class="buttons"><%= link_to_context_menu %></td>
42
                <% if Setting.manual_issue_position_in_versions == '1' && User.current.allowed_to?(:change_issue_position_in_version, version.project) %>
43
                  <td class="sortable"><%= reorder_handle(issue) %></td>
44
                <% end%>
45
              </tr>
46
            <% end -%>
47
          </tbody>
43 48
        </table>
44 49
      <% end %>
45 50
    <% end %>
......
108 113
<% html_title(l(:label_roadmap)) %>
109 114

  
110 115
<%= context_menu %>
116

  
117
<% if Setting.manual_issue_position_in_versions == '1' && User.current.allowed_to?(:change_issue_position_in_version, @project) %>
118
  <%= javascript_tag do %>
119
   $(function() { $("table.related-issues tbody").positionedItems(); });
120
  <% end %>
121
<% end %>
app/views/versions/show.html.erb
41 41
<% if @issues.present? %>
42 42
<%= form_tag({}, :data => {:cm_url => issues_context_menu_path}) do -%>
43 43
  <table class="list related-issues">
44
  <caption><%= l(:label_related_issues) %></caption>
45
  <%- @issues.each do |issue| -%>
46
    <tr class="hascontextmenu <%= issue.css_classes %>">
47
      <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
48
      <td class="assigned_to"><%= assignee_avatar(issue.assigned_to, :size => 16) %></td>
49
      <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
50
      <td class="buttons"><%= link_to_context_menu %></td>
51
    </tr>
52
  <% end %>
44
    <caption><%= l(:label_related_issues) %></caption>
45
    <tbody>
46
      <%- @issues.each do |issue| -%>
47
        <tr class="hascontextmenu <%= issue.css_classes %>">
48
          <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
49
          <td class="assigned_to"><%= assignee_avatar(issue.assigned_to, :size => 16) %></td>
50
          <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
51
          <td class="buttons"><%= link_to_context_menu %></td>
52
          <% if Setting.manual_issue_position_in_versions == '1' && !@version.closed? && User.current.allowed_to?(:change_issue_position_in_version, @version.project) %>
53
            <td class="sortable"><%= reorder_handle(issue) %></td>
54
          <% end%>
55
        </tr>
56
      <% end %>
57
    </tbody>
53 58
  </table>
54 59
<% end %>
55 60
<%= context_menu %>
......
59 64
<%= call_hook :view_versions_show_bottom, :version => @version %>
60 65

  
61 66
<% html_title @version.name %>
67

  
68
<% if Setting.manual_issue_position_in_versions == '1' && !@version.closed? && User.current.allowed_to?(:change_issue_position_in_version, @version.project) %>
69
  <%= javascript_tag do %>
70
   $(function() { $("table.related-issues tbody").positionedItems(); });
71
  <% end %>
72
<% end %>
config/locales/en.yml
506 506
  setting_timelog_accept_future_dates: Accept time logs on future dates
507 507
  setting_show_status_changes_in_mail_subject: Show status changes in issue mail notifications subject
508 508
  setting_project_list_defaults: Projects list defaults
509
  setting_manual_issue_position_in_versions: Enable manually set issue position in versions
509 510
  setting_twofa: Two-factor authentication
510 511

  
511 512
  permission_add_project: Create project
......
579 580
  permission_manage_related_issues: Manage related issues
580 581
  permission_import_issues: Import issues
581 582
  permission_log_time_for_other_users: Log spent time for other users
583
  permission_change_issue_position_in_version: Change issue position in version
582 584

  
583 585
  project_module_issue_tracking: Issue tracking
584 586
  project_module_time_tracking: Time tracking
config/locales/fr.yml
481 481
  setting_time_entry_list_defaults: Affichage par défaut de la liste des temps passés
482 482
  setting_timelog_accept_0_hours: Autoriser la saisie de temps avec 0 heure
483 483
  setting_timelog_max_hours_per_day: Maximum d'heures pouvant être saisies par un utilisateur sur un jour
484
  setting_manual_issue_position_in_versions: Activer le positionnement manuel des tickets dans les versions
484 485

  
485 486
  permission_add_project: Créer un projet
486 487
  permission_add_subprojects: Créer des sous-projets
......
547 548
  permission_manage_subtasks: Gérer les sous-tâches
548 549
  permission_manage_related_issues: Gérer les demandes associées
549 550
  permission_import_issues: Importer des demandes
551
  permission_change_issue_position_in_version: Changer la position d'un ticket dans une version
550 552

  
551 553
  project_module_issue_tracking: Suivi des demandes
552 554
  project_module_time_tracking: Suivi du temps passé
config/settings.yml
187 187
  default: 'derived'
188 188
link_copied_issue:
189 189
  default: 'ask'
190
manual_issue_position_in_versions:
191
  default: 1
190 192
close_duplicate_issues:
191 193
  default: 1
192 194
issue_group_assignment:
db/migrate/20200315154300_add_issue_position.rb
1
class AddIssuePosition < ActiveRecord::Migration[5.2]
2
  def self.up
3
    add_column :issues, :position, :integer
4
  end
5

  
6
  def self.down
7
    remove_column :issues, :position
8
  end
9
end
lib/redmine.rb
118 118
    map.permission :view_private_notes, {}, :read => true, :require => :member
119 119
    map.permission :set_notes_private, {}, :require => :member
120 120
    map.permission :delete_issues, {:issues => :destroy}, :require => :member
121
    map.permission :change_issue_position_in_version, {}
121 122
    # Watchers
122 123
    map.permission :view_issue_watchers, {}, :read => true
123 124
    map.permission :add_issue_watchers, {:watchers => [:new, :create, :append, :autocomplete_for_user]}
public/stylesheets/application.css
633 633
div#roadmap .related-issues td.checkbox { display: none; }
634 634
div#roadmap .related-issues td.assigned_to { width:1px; white-space:nowrap; padding: 0; }
635 635
div#roadmap .related-issues td.assigned_to img { padding-left: 4px; padding-right: 4px;}
636
div#roadmap .related-issues td.sortable { text-align: right; }
636 637
div#roadmap .wiki h1:first-child { display: none; }
637 638
div#roadmap .wiki h1 { font-size: 120%; }
638 639
div#roadmap .wiki h2 { font-size: 110%; }
(9-9/9)