Project

General

Profile

Feature #7360 » default_custom_trunk_r19977.patch

Olivier Chabert, 2020-08-13 18:09

View differences:

app/controllers/issues_controller.rb
25 25
  before_action :authorize, :except => [:index, :new, :create]
26 26
  before_action :find_optional_project, :only => [:index, :new, :create]
27 27
  before_action :build_new_issue_from_params, :only => [:new, :create]
28
  before_action :with_default_query, only: [:index]
28 29
  accept_rss_auth :index, :show
29 30
  accept_api_auth :index, :show, :create, :update, :destroy
30 31

  
......
468 469

  
469 470
  private
470 471

  
472
  def with_default_query
473
    return if params[:query_id].present?
474
    return if api_request?
475
    return if params[:set_filter] && params.key?(:op) && params.key?(:f)
476
    params[:set_filter] = 1 and return if params[:without_default].present?
477
    apply_default_query! and return if params[:set_filter] && [:op, :f].all? { |k| !params.key?(k) }
478
    if session[:issue_query]
479
      query_id, project_id = session[:issue_query].values_at(:id, :project_id)
480
      unless query_id && (@project.is_a?(Project) && project_id == @project.id) && IssueQuery.available_query?(@project.id, query_id, User.current.id)
481
        apply_default_query!
482
      end
483
    else
484
      apply_default_query!
485
    end
486
  end
487

  
488
  def apply_default_query!
489
    if default_query = find_default_query
490
      params[:query_id] = default_query.id
491
    end
492
  end
493

  
471 494
  def retrieve_previous_and_next_issue_ids
472 495
    if params[:prev_issue_id].present? || params[:next_issue_id].present?
473 496
      @prev_issue_id = params[:prev_issue_id].presence.try(:to_i)
app/helpers/projects_helper.rb
110 110
    principals_options_for_select(assignable_users, project.default_assigned_to)
111 111
  end
112 112

  
113
  def project_default_query_options(project)
114
    grouped = Hash.new {|h,k| h[k] = []}
115
    IssueQuery.only_public.where(project_id: nil).each do |query|
116
      grouped[l('label_default_queries.for_all_projects')] << [query.name, query.id]
117
    end
118
    IssueQuery.only_public.where(project: project).each do |query|
119
      grouped[l('label_default_queries.for_current_project')] << [query.name, query.id]
120
    end
121
    grouped_options_for_select(grouped, project.default_query_id)
122
  end
123

  
113 124
  def format_version_sharing(sharing)
114 125
    sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
115 126
    l("label_version_sharing_#{sharing}")
app/helpers/queries_helper.rb
347 347
        @query.project = @project
348 348
      end
349 349
      @query
350
    else
351
      @query = find_default_query
350 352
    end
351 353
  end
352 354

  
355
  private
356

  
357
  def find_default_query
358
    query = nil
359
    if User.current.pref.default_user_project_query != nil
360
      query = IssueQuery.find_by_id(User.current.pref.default_user_project_query)
361
    end
362

  
363
    unless query.is_a?(IssueQuery)
364
      if @project.is_a?(Project) and @project.default_query.is_a?(IssueQuery)
365
        query = @project.default_query
366
      elsif Setting.default_project_query != nil
367
        query = IssueQuery.find_by_id(Setting.default_project_query)
368
      end
369
    end
370
    query
371
  end
372

  
353 373
  # Returns the query definition as hidden field tags
354 374
  def query_as_hidden_field_tags(query)
355 375
    tags = hidden_field_tag("set_filter", "1", :id => nil)
......
408 428
        queries.collect {|query|
409 429
          css = +'query'
410 430
          clear_link = +''
431
          clear_link_param = {:set_filter => 1, :sort => '', :project_id => @project}
432

  
433
          if query == find_default_query
434
            css << ' default'
435
            clear_link_param[:without_default] = 1
436
          end
437

  
411 438
          if query == @query
412 439
            css << ' selected'
413
            clear_link += link_to_clear_query
440
            clear_link += link_to_clear_query(clear_link_param)
414 441
          end
415 442
          content_tag('li',
416 443
                      link_to(query.name,
......
422 449
      ) + "\n"
423 450
  end
424 451

  
425
  def link_to_clear_query
452
  def link_to_clear_query(params = {:set_filter => 1, :sort => '', :project_id => @project})
426 453
    link_to(
427 454
      l(:button_clear),
428
      {:set_filter => 1, :sort => '', :project_id => @project},
455
      params,
429 456
      :class => 'icon-only icon-clear-query',
430 457
      :title => l(:button_clear)
431 458
    )
app/helpers/settings_helper.rb
165 165
    options.map {|label, value| [l(label), value.to_s]}
166 166
  end
167 167

  
168
  def default_global_project_query_options
169
    options = [
170
        [l(:label_none), '']
171
    ]
172
    IssueQuery.only_public.where(project_id: nil).each do |query|
173
      options.push([query.name, query.id])
174
    end
175
    options
176
  end
177

  
168 178
  def cross_project_subtasks_options
169 179
    options = [
170 180
      [:label_disabled, ''],
app/helpers/users_helper.rb
29 29
    user.valid_notification_options.collect {|o| [l(o.last), o.first]}
30 30
  end
31 31

  
32
  def default_user_project_query_options(user)
33
    grouped = Hash.new {|h,k| h[k] = []}
34
    IssueQuery.only_public.for_all_projects.each do |query|
35
      grouped[l('label_default_queries.for_all_users')] << [query.name, query.id]
36
    end
37
    IssueQuery.for_all_projects.where(user_id: user.id).each do |query|
38
      grouped[l('label_default_queries.for_current_user')] << [query.name, query.id]
39
    end
40
    grouped_options_for_select(grouped, user.pref.default_user_project_query)
41
  end
42

  
32 43
  def textarea_font_options
33 44
    [[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]}
34 45
  end
app/models/issue_query.rb
55 55
    QueryColumn.new(:last_notes, :caption => :label_last_notes, :inline => false)
56 56
  ]
57 57

  
58
  has_many :projects, :foreign_key => 'default_query_id'
59
  after_update { self.projects.clear unless self.public_visibility? }
60
  after_destroy { self.projects.clear }
61
  scope :only_public, -> {
62
    where(:visibility => VISIBILITY_PUBLIC)
63
  }
64
  scope :for_all_projects, -> {
65
    where(project_id: nil)
66
  }
67

  
68
  def self.available_query?(project_id, query_id, user_id)
69
    self.where('project_id is null or project_id = ?', project_id)
70
        .where('user_id = ? or visibility = ?', user_id, VISIBILITY_PUBLIC)
71
        .where(id: query_id).exists?
72
  end
73

  
58 74
  def initialize(attributes=nil, *args)
59 75
    super attributes
60 76
    self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
61 77
  end
62 78

  
79
  def public_visibility?
80
    visibility == VISIBILITY_PUBLIC
81
  end
82

  
63 83
  def draw_relations
64 84
    r = options[:draw_relations]
65 85
    r.nil? || r == '1'
app/models/project.rb
58 58
                          :class_name => 'IssueCustomField',
59 59
                          :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
60 60
                          :association_foreign_key => 'custom_field_id'
61
  # Default Custom Query
62
  belongs_to :default_query, :class_name => 'IssueQuery'
61 63

  
62 64
  acts_as_attachable :view_permission => :view_files,
63 65
                     :edit_permission => :manage_files,
......
767 769
    'issue_custom_field_ids',
768 770
    'parent_id',
769 771
    'default_version_id',
770
    'default_assigned_to_id')
772
    'default_assigned_to_id',
773
    'default_query_id')
771 774

  
772 775
  safe_attributes(
773 776
    'enabled_module_names',
app/models/user_preference.rb
37 37
    'textarea_font',
38 38
    'recently_used_projects',
39 39
    'history_default_tab',
40
    'default_user_project_query',
40 41
    'toolbar_language_options')
41 42

  
42 43
  TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
......
113 114
    self[:toolbar_language_options] = languages.join(',')
114 115
  end
115 116

  
117
  def default_user_project_query; self[:default_user_project_query] end
118
  def default_user_project_query=(value); self[:default_user_project_query]=value; end
119

  
116 120
  # Returns the names of groups that are displayed on user's page
117 121
  # Example:
118 122
  #   preferences.my_page_groups
app/views/projects/copy.html.erb
28 28

  
29 29
<%= submit_tag l(:button_copy) %>
30 30
<% end %>
31

  
32
<%= javascript_tag do %>
33
  $('input[value="queries"]').change(function() {
34
    if ($(this).prop('checked')){
35
      $('select#project_default_query_id optgroup[label="For current project"] option').prop("disabled", false);
36
    }else{
37
      $('select#project_default_query_id optgroup[label="For current project"] option').prop("disabled", true);
38
    }
39
  });
40
<% end %>
app/views/projects/settings/_issues.html.erb
41 41
  <% if @project.safe_attribute?('default_assigned_to_id') %>
42 42
    <p><%= f.select :default_assigned_to_id, project_default_assigned_to_options(@project), include_blank: l(:label_none) %></p>
43 43
  <% end %>
44

  
45
  <% if @project.safe_attribute?('default_query_id') && project_default_query_options(@project).present? %>
46
    <p>
47
      <%= f.select :default_query_id, project_default_query_options(@project), include_blank: l(:label_none) %>
48
      <em class="info"><%=l 'text_allowed_queries_to_select' %></em>
49
    </p>
50
  <% end %>
44 51
  </div>
45 52

  
46 53
  <p><%= submit_tag l(:button_save) %></p>
app/views/settings/_issues.html.erb
24 24
<p><%= setting_text_field :gantt_items_limit, :size => 6 %></p>
25 25

  
26 26
<p><%= setting_text_field :gantt_months_limit, :size => 6 %></p>
27

  
28
<p><%= setting_select :default_project_query, default_global_project_query_options %></p>
27 29
</div>
28 30

  
29 31
<fieldset class="box">
app/views/users/_preferences.html.erb
7 7
<p><%= pref_fields.text_field :recently_used_projects, :size => 2 %></p>
8 8
<p><%= pref_fields.select :history_default_tab, history_default_tab_options %></p>
9 9
<p><%= pref_fields.text_area :toolbar_language_options, :rows => 4 %></p>
10
<p><%= pref_fields.select :default_user_project_query, default_user_project_query_options(@user), include_blank: l(:label_none) %></p>
10 11
<% end %>
config/locales/en.yml
384 384
  field_time_entries_visibility: Time logs visibility
385 385
  field_total_estimated_hours: Total estimated time
386 386
  field_default_version: Default version
387
  field_default_query: Default Query
387 388
  field_remote_ip: IP address
388 389
  field_textarea_font: Font used for text areas
389 390
  field_updated_by: Updated by
......
494 495
  setting_timelog_accept_future_dates: Accept time logs on future dates
495 496
  setting_show_status_changes_in_mail_subject: Show status changes in issue mail notifications subject
496 497
  setting_project_list_defaults: Projects list defaults
498
  setting_default_project_query: Default Query
497 499

  
498 500
  permission_add_project: Create project
499 501
  permission_add_subprojects: Create subprojects
......
1070 1072
  label_optgroup_others: Other projects
1071 1073
  label_optgroup_recents: Recently used
1072 1074
  label_last_notes: Last notes
1075
  label_default_queries:
1076
    for_all_projects: For all projects
1077
    for_current_project: For current project
1078
    for_all_users: For all users
1079
    for_current_user: For current user
1073 1080
  label_nothing_to_preview: Nothing to preview
1074 1081
  label_inherited_from_parent_project: "Inherited from parent project"
1075 1082
  label_inherited_from_group: "Inherited from group %{name}"
......
1290 1297
  description_issue_category_reassign: Choose issue category
1291 1298
  description_wiki_subpages_reassign: Choose new parent page
1292 1299
  text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.'
1300
  text_allowed_queries_to_select: Public (to any users) queries only selectable
1293 1301
  text_login_required_html: When not requiring authentication, public projects and their contents are openly available on the network. You can <a href="%{anonymous_role_path}">edit the applicable permissions</a>.
1294 1302
  label_login_required_yes: "Yes"
1295 1303
  label_login_required_no: "No, allow anonymous access to public projects"
config/locales/fr.yml
385 385
  field_time_entries_visibility: Visibilité du temps passé
386 386
  field_total_estimated_hours: Temps estimé total
387 387
  field_default_version: Version par défaut
388
  field_default_query: Rapport par défaut
388 389
  field_textarea_font: Police utilisée pour les champs texte
389 390
  field_updated_by: Mise à jour par
390 391
  field_last_updated_by: Dernière mise à jour par
......
481 482
  setting_time_entry_list_defaults: Affichage par défaut de la liste des temps passés
482 483
  setting_timelog_accept_0_hours: Autoriser la saisie de temps avec 0 heure
483 484
  setting_timelog_max_hours_per_day: Maximum d'heures pouvant être saisies par un utilisateur sur un jour
485
  setting_default_project_query: Rapport par défaut
484 486

  
485 487
  permission_add_project: Créer un projet
486 488
  permission_add_subprojects: Créer des sous-projets
......
1026 1028
  label_font_monospace: Police non proportionnelle
1027 1029
  label_font_proportional: Police proportionnelle
1028 1030
  label_last_notes: Dernières notes
1031
  label_default_queries:
1032
    for_all_projects: Pour tous les projets
1033
    for_current_project: Pour le projet en cours
1034
    for_all_users: Pour tous les utilisateurs
1035
    for_current_user: Pour l'utilisateur courrant
1029 1036
  label_trackers_description: Description des trackers
1030 1037
  label_open_trackers_description: Afficher la description des trackers
1031 1038

  
......
1218 1225
  description_issue_category_reassign: Choisir une catégorie
1219 1226
  description_wiki_subpages_reassign: Choisir une nouvelle page parent
1220 1227
  text_repository_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisés.<br />Un fois sauvegardé, l''identifiant ne pourra plus être modifié.'
1228
  text_allowed_queries_to_select: Seuls les rapports publics (pour tous les utilisateurs) sont sélectionnables
1221 1229
  label_parent_task_attributes_derived: Calculé à partir des sous-tâches
1222 1230
  label_parent_task_attributes_independent: Indépendent des sous-tâches
1223 1231
  mail_subject_security_notification: Notification de sécurité
config/settings.yml
119 119
gantt_months_limit:
120 120
  format: int
121 121
  default: 24
122
default_project_query:
123
  default: ''
122 124
# Maximum size of files that can be displayed
123 125
# inline through the file viewer (in KB)
124 126
file_max_size_displayed:
db/migrate/20200806105730_add_projects_default_query_id.rb
1
class AddProjectsDefaultQueryId < ActiveRecord::Migration[4.2]
2
  def self.up
3
    unless column_exists?(:projects, :default_query_id, :integer)
4
      add_column :projects, :default_query_id, :integer, :default => nil
5
    end
6
  end
7
  def self.down
8
    remove_column :projects, :default_query_id
9
  end
10
end
public/stylesheets/application.css
145 145

  
146 146
#sidebar a.selected {line-height:1.7em; padding:1px 3px 2px 2px; margin-left:-2px; background-color:#9DB9D5; color:#fff; border-radius:2px;}
147 147
#sidebar a.selected:hover {text-decoration:none;}
148
#sidebar .query.default {font-weight: bold;}
148 149
#admin-menu a {line-height:1.7em;}
149 150
#admin-menu a.selected {padding-left: 20px !important; background-position: 2px 40%;}
150 151

  
(6-6/14)