Feature #7360 » default_custom_trunk_r19977.patch
| 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 | |