@@ -0,0 +1,49 | |||||
|
1 | # redMine - project management software | |||
|
2 | # Copyright (C) 2006 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class QueriesController < ApplicationController | |||
|
19 | layout 'base' | |||
|
20 | before_filter :require_login, :find_query | |||
|
21 | ||||
|
22 | def edit | |||
|
23 | if request.post? | |||
|
24 | @query.filters = {} | |||
|
25 | params[:fields].each do |field| | |||
|
26 | @query.add_filter(field, params[:operators][field], params[:values][field]) | |||
|
27 | end if params[:fields] | |||
|
28 | @query.attributes = params[:query] | |||
|
29 | ||||
|
30 | if @query.save | |||
|
31 | flash[:notice] = l(:notice_successful_update) | |||
|
32 | redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query | |||
|
33 | end | |||
|
34 | end | |||
|
35 | end | |||
|
36 | ||||
|
37 | def destroy | |||
|
38 | @query.destroy if request.post? | |||
|
39 | redirect_to :controller => 'reports', :action => 'issue_report', :id => @project | |||
|
40 | end | |||
|
41 | ||||
|
42 | private | |||
|
43 | def find_query | |||
|
44 | @query = Query.find(params[:id]) | |||
|
45 | @project = @query.project | |||
|
46 | # check if user is allowed to manage queries (same permission as add_query) | |||
|
47 | authorize('projects', 'add_query') | |||
|
48 | end | |||
|
49 | end |
@@ -0,0 +1,6 | |||||
|
1 | module QueriesHelper | |||
|
2 | ||||
|
3 | def operators_for_select(filter_type) | |||
|
4 | Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]} | |||
|
5 | end | |||
|
6 | end |
@@ -0,0 +1,166 | |||||
|
1 | # redMine - project management software | |||
|
2 | # Copyright (C) 2006 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class Query < ActiveRecord::Base | |||
|
19 | belongs_to :project | |||
|
20 | belongs_to :user | |||
|
21 | serialize :filters | |||
|
22 | ||||
|
23 | attr_protected :project, :user | |||
|
24 | ||||
|
25 | validates_presence_of :name, :on => :save | |||
|
26 | ||||
|
27 | @@operators = { "=" => :label_equals, | |||
|
28 | "!" => :label_not_equals, | |||
|
29 | "o" => :label_open_issues, | |||
|
30 | "c" => :label_closed_issues, | |||
|
31 | "!*" => :label_none, | |||
|
32 | "*" => :label_all, | |||
|
33 | "<t+" => :label_in_less_than, | |||
|
34 | ">t+" => :label_in_more_than, | |||
|
35 | "t+" => :label_in, | |||
|
36 | "t" => :label_today, | |||
|
37 | ">t-" => :label_less_than_ago, | |||
|
38 | "<t-" => :label_more_than_ago, | |||
|
39 | "t-" => :label_ago, | |||
|
40 | "~" => :label_contains, | |||
|
41 | "!~" => :label_not_contains } | |||
|
42 | ||||
|
43 | cattr_reader :operators | |||
|
44 | ||||
|
45 | @@operators_by_filter_type = { :list => [ "=", "!" ], | |||
|
46 | :list_status => [ "o", "=", "!", "c", "*" ], | |||
|
47 | :list_optional => [ "=", "!", "!*", "*" ], | |||
|
48 | :date => [ "<t+", ">t+", "t+", "t", ">t-", "<t-", "t-" ], | |||
|
49 | :date_past => [ ">t-", "<t-", "t-", "t" ], | |||
|
50 | :text => [ "~", "!~" ] } | |||
|
51 | ||||
|
52 | cattr_reader :operators_by_filter_type | |||
|
53 | ||||
|
54 | def initialize(attributes = nil) | |||
|
55 | super attributes | |||
|
56 | self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } | |||
|
57 | self.is_public = true | |||
|
58 | end | |||
|
59 | ||||
|
60 | def validate | |||
|
61 | filters.each_key do |field| | |||
|
62 | errors.add field.gsub(/\_id$/, ""), :activerecord_error_blank unless | |||
|
63 | # filter requires one or more values | |||
|
64 | (values_for(field) and !values_for(field).first.empty?) or | |||
|
65 | # filter doesn't require any value | |||
|
66 | ["o", "c", "!*", "*", "t"].include? operator_for(field) | |||
|
67 | end if filters | |||
|
68 | end | |||
|
69 | ||||
|
70 | def available_filters | |||
|
71 | return @available_filters if @available_filters | |||
|
72 | @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all).collect{|s| [s.name, s.id.to_s] } }, | |||
|
73 | "tracker_id" => { :type => :list, :order => 2, :values => Tracker.find(:all).collect{|s| [s.name, s.id.to_s] } }, | |||
|
74 | "priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } }, | |||
|
75 | "subject" => { :type => :text, :order => 7 }, | |||
|
76 | "created_on" => { :type => :date_past, :order => 8 }, | |||
|
77 | "updated_on" => { :type => :date_past, :order => 9 }, | |||
|
78 | "start_date" => { :type => :date, :order => 10 }, | |||
|
79 | "due_date" => { :type => :date, :order => 11 } } | |||
|
80 | unless project.nil? | |||
|
81 | # project specific filters | |||
|
82 | @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => @project.users.collect{|s| [s.name, s.id.to_s] } } | |||
|
83 | @available_filters["author_id"] = { :type => :list, :order => 5, :values => @project.users.collect{|s| [s.name, s.id.to_s] } } | |||
|
84 | @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } } | |||
|
85 | # remove category filter if no category defined | |||
|
86 | @available_filters.delete "category_id" if @available_filters["category_id"][:values].empty? | |||
|
87 | end | |||
|
88 | @available_filters | |||
|
89 | end | |||
|
90 | ||||
|
91 | def add_filter(field, operator, values) | |||
|
92 | # values must be an array | |||
|
93 | return unless values and values.is_a? Array # and !values.first.empty? | |||
|
94 | # check if field is defined as an available filter | |||
|
95 | if available_filters.has_key? field | |||
|
96 | filter_options = available_filters[field] | |||
|
97 | # check if operator is allowed for that filter | |||
|
98 | #if @@operators_by_filter_type[filter_options[:type]].include? operator | |||
|
99 | # allowed_values = values & ([""] + (filter_options[:values] || []).collect {|val| val[1]}) | |||
|
100 | # filters[field] = {:operator => operator, :values => allowed_values } if (allowed_values.first and !allowed_values.first.empty?) or ["o", "c", "!*", "*", "t"].include? operator | |||
|
101 | #end | |||
|
102 | filters[field] = {:operator => operator, :values => values } | |||
|
103 | end | |||
|
104 | end | |||
|
105 | ||||
|
106 | def add_short_filter(field, expression) | |||
|
107 | return unless expression | |||
|
108 | parms = expression.scan(/^(o|c|\!|\*)?(.*)$/).first | |||
|
109 | add_filter field, (parms[0] || "="), [parms[1] || ""] | |||
|
110 | end | |||
|
111 | ||||
|
112 | def has_filter?(field) | |||
|
113 | filters and filters[field] | |||
|
114 | end | |||
|
115 | ||||
|
116 | def operator_for(field) | |||
|
117 | has_filter?(field) ? filters[field][:operator] : nil | |||
|
118 | end | |||
|
119 | ||||
|
120 | def values_for(field) | |||
|
121 | has_filter?(field) ? filters[field][:values] : nil | |||
|
122 | end | |||
|
123 | ||||
|
124 | def statement | |||
|
125 | sql = "1=1" | |||
|
126 | sql << " AND issues.project_id=%d" % project.id if project | |||
|
127 | filters.each_key do |field| | |||
|
128 | v = values_for field | |||
|
129 | next unless v and !v.empty? | |||
|
130 | sql = sql + " AND " unless sql.empty? | |||
|
131 | case operator_for field | |||
|
132 | when "=" | |||
|
133 | sql = sql + "issues.#{field} IN (" + v.each(&:to_i).join(",") + ")" | |||
|
134 | when "!" | |||
|
135 | sql = sql + "issues.#{field} NOT IN (" + v.each(&:to_i).join(",") + ")" | |||
|
136 | when "!*" | |||
|
137 | sql = sql + "issues.#{field} IS NULL" | |||
|
138 | when "*" | |||
|
139 | sql = sql + "issues.#{field} IS NOT NULL" | |||
|
140 | when "o" | |||
|
141 | sql = sql + "issue_statuses.is_closed=#{connection.quoted_false}" if field == "status_id" | |||
|
142 | when "c" | |||
|
143 | sql = sql + "issue_statuses.is_closed=#{connection.quoted_true}" if field == "status_id" | |||
|
144 | when ">t-" | |||
|
145 | sql = sql + "issues.#{field} >= '%s'" % connection.quoted_date(Date.today - v.first.to_i) | |||
|
146 | when "<t-" | |||
|
147 | sql = sql + "issues.#{field} <= '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'" | |||
|
148 | when "t-" | |||
|
149 | sql = sql + "issues.#{field} = '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'" | |||
|
150 | when ">t+" | |||
|
151 | sql = sql + "issues.#{field} >= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'" | |||
|
152 | when "<t+" | |||
|
153 | sql = sql + "issues.#{field} <= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'" | |||
|
154 | when "t+" | |||
|
155 | sql = sql + "issues.#{field} = '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'" | |||
|
156 | when "t" | |||
|
157 | sql = sql + "issues.#{field} = '%s'" % connection.quoted_date(Date.today) | |||
|
158 | when "~" | |||
|
159 | sql = sql + "issues.#{field} LIKE '%#{connection.quote_string(v.first)}%'" | |||
|
160 | when "!~" | |||
|
161 | sql = sql + "issues.#{field} NOT LIKE '%#{connection.quote_string(v.first)}%'" | |||
|
162 | end | |||
|
163 | end if filters and valid? | |||
|
164 | sql | |||
|
165 | end | |||
|
166 | end |
@@ -0,0 +1,6 | |||||
|
1 | <h2><%= l(:label_query_new) %></h2> | |||
|
2 | ||||
|
3 | <%= start_form_tag :action => 'add_query', :id => @project %> | |||
|
4 | <%= render :partial => 'queries/form', :locals => {:query => @query} %> | |||
|
5 | <%= submit_tag l(:button_create) %> | |||
|
6 | <%= end_form_tag %> No newline at end of file |
@@ -0,0 +1,100 | |||||
|
1 | <script> | |||
|
2 | ||||
|
3 | function add_filter() { | |||
|
4 | select = $('add_filter_select'); | |||
|
5 | field = select.value | |||
|
6 | Element.show('tr_' + field); | |||
|
7 | check_box = $('cb_' + field); | |||
|
8 | check_box.checked = true; | |||
|
9 | toggle_filter(field); | |||
|
10 | select.selectedIndex = 0; | |||
|
11 | ||||
|
12 | for (i=0; i<select.options.length; i++) { | |||
|
13 | if (select.options[i].value == field) { | |||
|
14 | select.options[i].disabled = true; | |||
|
15 | } | |||
|
16 | } | |||
|
17 | } | |||
|
18 | ||||
|
19 | function toggle_filter(field) { | |||
|
20 | check_box = $('cb_' + field); | |||
|
21 | ||||
|
22 | if (check_box.checked) { | |||
|
23 | Element.show("operators[" + field + "]"); | |||
|
24 | toggle_operator(field); | |||
|
25 | } else { | |||
|
26 | Element.hide("operators[" + field + "]"); | |||
|
27 | Element.hide("values_div[" + field + "]"); | |||
|
28 | } | |||
|
29 | } | |||
|
30 | ||||
|
31 | function toggle_operator(field) { | |||
|
32 | operator = $("operators[" + field + "]"); | |||
|
33 | switch (operator.value) { | |||
|
34 | case "!*": | |||
|
35 | case "*": | |||
|
36 | case "t": | |||
|
37 | case "o": | |||
|
38 | case "c": | |||
|
39 | Element.hide("values_div[" + field + "]"); | |||
|
40 | break; | |||
|
41 | default: | |||
|
42 | Element.show("values_div[" + field + "]"); | |||
|
43 | break; | |||
|
44 | } | |||
|
45 | } | |||
|
46 | ||||
|
47 | function toggle_multi_select(field) { | |||
|
48 | select = $('values[' + field + '][]'); | |||
|
49 | if (select.multiple == true) { | |||
|
50 | select.multiple = false; | |||
|
51 | } else { | |||
|
52 | select.multiple = true; | |||
|
53 | } | |||
|
54 | } | |||
|
55 | ||||
|
56 | </script> | |||
|
57 | ||||
|
58 | <fieldset style="margin:0;"><legend><%= l(:label_filter_plural) %></legend> | |||
|
59 | <table width="100%" cellpadding=0 cellspacing=0> | |||
|
60 | <tr> | |||
|
61 | <td> | |||
|
62 | <table> | |||
|
63 | <% query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %> | |||
|
64 | <% field = filter[0] | |||
|
65 | options = filter[1] %> | |||
|
66 | <tr <%= 'style="display:none;"' unless query.has_filter?(field) %> id="tr_<%= field %>"> | |||
|
67 | <td valign="top" width="200"> | |||
|
68 | <%= check_box_tag 'fields[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %> | |||
|
69 | <label for="cb_<%= field %>"><%= l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label> | |||
|
70 | </td> | |||
|
71 | <td valign="top" width="150"> | |||
|
72 | <%= select_tag "operators[#{field}]", options_for_select(operators_for_select(options[:type]), query.operator_for(field)), :onchange => "toggle_operator('#{field}');", :class => "select-small", :style => "vertical-align: top;" %> | |||
|
73 | </td> | |||
|
74 | <td valign="top"> | |||
|
75 | <div id="values_div[<%= field %>]"> | |||
|
76 | <% case options[:type] | |||
|
77 | when :list, :list_optional, :list_status %> | |||
|
78 | <select <%= "multiple=true" if query.values_for(field) and query.values_for(field).length > 1 %>" name="values[<%= field %>][]" id="values[<%= field %>][]" class="select-small" style="vertical-align: top;"> | |||
|
79 | <%= options_for_select options[:values], query.values_for(field) %> | |||
|
80 | </select> | |||
|
81 | <%= link_to_function image_tag('expand'), "toggle_multi_select('#{field}');" %> | |||
|
82 | <% when :date, :date_past %> | |||
|
83 | <%= text_field_tag "values[#{field}][]", query.values_for(field), :size => 3, :class => "select-small" %> <%= l(:label_day_plural) %> | |||
|
84 | <% when :text %> | |||
|
85 | <%= text_field_tag "values[#{field}][]", query.values_for(field), :size => 30, :class => "select-small" %> | |||
|
86 | <% end %> | |||
|
87 | </div> | |||
|
88 | </td> | |||
|
89 | </tr> | |||
|
90 | <script>toggle_filter('<%= field %>');</script> | |||
|
91 | <% end %> | |||
|
92 | </table> | |||
|
93 | </td> | |||
|
94 | <td align="right" valign="top"> | |||
|
95 | <%= l(:label_filter_add) %>: | |||
|
96 | <%= select_tag 'add_filter_select', options_for_select([["",""]] + query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.collect{|field| [l(("field_"+field[0].to_s.gsub(/\_id$/, "")).to_sym), field[0]] unless query.has_filter?(field[0])}.compact), :onchange => "add_filter();", :class => "select-small" %> | |||
|
97 | </td> | |||
|
98 | </tr> | |||
|
99 | </table> | |||
|
100 | </fieldset> No newline at end of file |
@@ -0,0 +1,12 | |||||
|
1 | <%= error_messages_for 'query' %> | |||
|
2 | ||||
|
3 | <!--[form:query]--> | |||
|
4 | <div class="box"> | |||
|
5 | <div class="tabular"> | |||
|
6 | <p><label for="query_name"><%=l(:field_name)%></label> | |||
|
7 | <%= text_field 'query', 'name', :size => 80 %></p> | |||
|
8 | </div> | |||
|
9 | ||||
|
10 | <%= render :partial => 'queries/filters', :locals => {:query => query}%> | |||
|
11 | </div> | |||
|
12 | <!--[eoform:query]--> No newline at end of file |
@@ -0,0 +1,6 | |||||
|
1 | <h2><%= l(:label_query) %></h2> | |||
|
2 | ||||
|
3 | <%= start_form_tag :action => 'edit', :id => @query %> | |||
|
4 | <%= render :partial => 'form', :locals => {:query => @query} %> | |||
|
5 | <%= submit_tag l(:button_save) %> | |||
|
6 | <%= end_form_tag %> No newline at end of file |
@@ -0,0 +1,15 | |||||
|
1 | class CreateQueries < ActiveRecord::Migration | |||
|
2 | def self.up | |||
|
3 | create_table :queries, :force => true do |t| | |||
|
4 | t.column "project_id", :integer | |||
|
5 | t.column "name", :string, :default => "", :null => false | |||
|
6 | t.column "filters", :text | |||
|
7 | t.column "user_id", :integer, :default => 0, :null => false | |||
|
8 | t.column "is_public", :boolean, :default => false, :null => false | |||
|
9 | end | |||
|
10 | end | |||
|
11 | ||||
|
12 | def self.down | |||
|
13 | drop_table :queries | |||
|
14 | end | |||
|
15 | end |
@@ -0,0 +1,9 | |||||
|
1 | class AddQueriesPermissions < ActiveRecord::Migration | |||
|
2 | def self.up | |||
|
3 | Permission.create :controller => "projects", :action => "add_query", :description => "button_create", :sort => 600, :is_public => false, :mail_option => 0, :mail_enabled => 0 | |||
|
4 | end | |||
|
5 | ||||
|
6 | def self.down | |||
|
7 | Permission.find(:first, :conditions => ["controller=? and action=?", 'projects', 'add_query']).destroy | |||
|
8 | end | |||
|
9 | end |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
@@ -71,9 +71,9 class ApplicationController < ActionController::Base | |||||
71 | end |
|
71 | end | |
72 |
|
72 | |||
73 | # authorizes the user for the requested action. |
|
73 | # authorizes the user for the requested action. | |
74 | def authorize |
|
74 | def authorize(ctrl = @params[:controller], action = @params[:action]) | |
75 | # check if action is allowed on public projects |
|
75 | # check if action is allowed on public projects | |
76 |
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ |
|
76 | if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ] | |
77 | return true |
|
77 | return true | |
78 | end |
|
78 | end | |
79 | # if action is not public, force login |
|
79 | # if action is not public, force login | |
@@ -82,7 +82,7 class ApplicationController < ActionController::Base | |||||
82 | return true if self.logged_in_user.admin? |
|
82 | return true if self.logged_in_user.admin? | |
83 | # if not admin, check membership permission |
|
83 | # if not admin, check membership permission | |
84 | @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id]) |
|
84 | @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id]) | |
85 |
if @user_membership and Permission.allowed_to_role( "%s/%s" % [ |
|
85 | if @user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], @user_membership.role_id ) | |
86 | return true |
|
86 | return true | |
87 | end |
|
87 | end | |
88 | render :nothing => true, :status => 403 |
|
88 | render :nothing => true, :status => 403 |
@@ -16,19 +16,19 | |||||
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
17 |
|
17 | |||
18 | class ProjectsController < ApplicationController |
|
18 | class ProjectsController < ApplicationController | |
19 | layout 'base', :except => :export_issues_pdf |
|
19 | layout 'base' | |
20 | before_filter :find_project, :authorize, :except => [ :index, :list, :add ] |
|
20 | before_filter :find_project, :authorize, :except => [ :index, :list, :add ] | |
21 | before_filter :require_admin, :only => [ :add, :destroy ] |
|
21 | before_filter :require_admin, :only => [ :add, :destroy ] | |
22 |
|
22 | |||
23 | helper :sort |
|
23 | helper :sort | |
24 |
include SortHelper |
|
24 | include SortHelper | |
25 | helper :search_filter |
|
|||
26 | include SearchFilterHelper |
|
|||
27 | helper :custom_fields |
|
25 | helper :custom_fields | |
28 | include CustomFieldsHelper |
|
26 | include CustomFieldsHelper | |
29 | helper :ifpdf |
|
27 | helper :ifpdf | |
30 | include IfpdfHelper |
|
28 | include IfpdfHelper | |
31 | helper IssuesHelper |
|
29 | helper IssuesHelper | |
|
30 | helper :queries | |||
|
31 | include QueriesHelper | |||
32 |
|
32 | |||
33 | def index |
|
33 | def index | |
34 | list |
|
34 | list | |
@@ -208,8 +208,7 class ProjectsController < ApplicationController | |||||
208 | sort_init 'issues.id', 'desc' |
|
208 | sort_init 'issues.id', 'desc' | |
209 | sort_update |
|
209 | sort_update | |
210 |
|
210 | |||
211 | search_filter_init_list_issues |
|
211 | retrieve_query | |
212 | search_filter_update if params[:set_filter] |
|
|||
213 |
|
212 | |||
214 | @results_per_page_options = [ 15, 25, 50, 100 ] |
|
213 | @results_per_page_options = [ 15, 25, 50, 100 ] | |
215 | if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i |
|
214 | if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i | |
@@ -219,14 +218,15 class ProjectsController < ApplicationController | |||||
219 | @results_per_page = session[:results_per_page] || 25 |
|
218 | @results_per_page = session[:results_per_page] || 25 | |
220 | end |
|
219 | end | |
221 |
|
220 | |||
222 | @issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause) |
|
221 | if @query.valid? | |
223 | @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page'] |
|
222 | @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement) | |
224 | @issues = Issue.find :all, :order => sort_clause, |
|
223 | @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page'] | |
225 | :include => [ :author, :status, :tracker, :project ], |
|
224 | @issues = Issue.find :all, :order => sort_clause, | |
226 | :conditions => search_filter_clause, |
|
225 | :include => [ :author, :status, :tracker, :project ], | |
227 | :limit => @issue_pages.items_per_page, |
|
226 | :conditions => @query.statement, | |
228 | :offset => @issue_pages.current.offset |
|
227 | :limit => @issue_pages.items_per_page, | |
229 |
|
228 | :offset => @issue_pages.current.offset | ||
|
229 | end | |||
230 | render :layout => false if request.xhr? |
|
230 | render :layout => false if request.xhr? | |
231 | end |
|
231 | end | |
232 |
|
232 | |||
@@ -235,11 +235,12 class ProjectsController < ApplicationController | |||||
235 | sort_init 'issues.id', 'desc' |
|
235 | sort_init 'issues.id', 'desc' | |
236 | sort_update |
|
236 | sort_update | |
237 |
|
237 | |||
238 | search_filter_init_list_issues |
|
238 | retrieve_query | |
|
239 | render :action => 'list_issues' and return unless @query.valid? | |||
239 |
|
240 | |||
240 | @issues = Issue.find :all, :order => sort_clause, |
|
241 | @issues = Issue.find :all, :order => sort_clause, | |
241 | :include => [ :author, :status, :tracker, :project, :custom_values ], |
|
242 | :include => [ :author, :status, :tracker, :project, :custom_values ], | |
242 |
:conditions => |
|
243 | :conditions => @query.statement | |
243 |
|
244 | |||
244 | ic = Iconv.new('ISO-8859-1', 'UTF-8') |
|
245 | ic = Iconv.new('ISO-8859-1', 'UTF-8') | |
245 | export = StringIO.new |
|
246 | export = StringIO.new | |
@@ -268,14 +269,16 class ProjectsController < ApplicationController | |||||
268 | sort_init 'issues.id', 'desc' |
|
269 | sort_init 'issues.id', 'desc' | |
269 | sort_update |
|
270 | sort_update | |
270 |
|
271 | |||
271 | search_filter_init_list_issues |
|
272 | retrieve_query | |
|
273 | render :action => 'list_issues' and return unless @query.valid? | |||
272 |
|
274 | |||
273 | @issues = Issue.find :all, :order => sort_clause, |
|
275 | @issues = Issue.find :all, :order => sort_clause, | |
274 | :include => [ :author, :status, :tracker, :project, :custom_values ], |
|
276 | :include => [ :author, :status, :tracker, :project, :custom_values ], | |
275 |
:conditions => |
|
277 | :conditions => @query.statement | |
276 |
|
278 | |||
277 | @options_for_rfpdf ||= {} |
|
279 | @options_for_rfpdf ||= {} | |
278 | @options_for_rfpdf[:file_name] = "export.pdf" |
|
280 | @options_for_rfpdf[:file_name] = "export.pdf" | |
|
281 | render :layout => false | |||
279 | end |
|
282 | end | |
280 |
|
283 | |||
281 | def move_issues |
|
284 | def move_issues | |
@@ -302,6 +305,22 class ProjectsController < ApplicationController | |||||
302 | end |
|
305 | end | |
303 | end |
|
306 | end | |
304 |
|
307 | |||
|
308 | def add_query | |||
|
309 | @query = Query.new(params[:query]) | |||
|
310 | @query.project = @project | |||
|
311 | @query.user = logged_in_user | |||
|
312 | ||||
|
313 | params[:fields].each do |field| | |||
|
314 | @query.add_filter(field, params[:operators][field], params[:values][field]) | |||
|
315 | end if params[:fields] | |||
|
316 | ||||
|
317 | if request.post? and @query.save | |||
|
318 | flash[:notice] = l(:notice_successful_create) | |||
|
319 | redirect_to :controller => 'reports', :action => 'issue_report', :id => @project | |||
|
320 | end | |||
|
321 | render :layout => false if request.xhr? | |||
|
322 | end | |||
|
323 | ||||
305 | # Add a news to @project |
|
324 | # Add a news to @project | |
306 | def add_news |
|
325 | def add_news | |
307 | @news = News.new(:project => @project) |
|
326 | @news = News.new(:project => @project) | |
@@ -471,4 +490,29 private | |||||
471 | rescue |
|
490 | rescue | |
472 | redirect_to :action => 'list' |
|
491 | redirect_to :action => 'list' | |
473 | end |
|
492 | end | |
|
493 | ||||
|
494 | # Retrieve query from session or build a new query | |||
|
495 | def retrieve_query | |||
|
496 | if params[:query_id] | |||
|
497 | @query = @project.queries.find(params[:query_id]) | |||
|
498 | else | |||
|
499 | if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id | |||
|
500 | # Give it a name, required to be valid | |||
|
501 | @query = Query.new(:name => "_") | |||
|
502 | @query.project = @project | |||
|
503 | if params[:fields] and params[:fields].is_a? Array | |||
|
504 | params[:fields].each do |field| | |||
|
505 | @query.add_filter(field, params[:operators][field], params[:values][field]) | |||
|
506 | end | |||
|
507 | else | |||
|
508 | @query.available_filters.keys.each do |field| | |||
|
509 | @query.add_short_filter(field, params[field]) if params[field] | |||
|
510 | end | |||
|
511 | end | |||
|
512 | session[:query] = @query | |||
|
513 | else | |||
|
514 | @query = session[:query] | |||
|
515 | end | |||
|
516 | end | |||
|
517 | end | |||
474 | end |
|
518 | end |
@@ -48,6 +48,7 class ReportsController < ApplicationController | |||||
48 | @report_title = l(:field_author) |
|
48 | @report_title = l(:field_author) | |
49 | render :template => "reports/issue_report_details" |
|
49 | render :template => "reports/issue_report_details" | |
50 | else |
|
50 | else | |
|
51 | @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)] | |||
51 | @trackers = Tracker.find(:all) |
|
52 | @trackers = Tracker.find(:all) | |
52 | @priorities = Enumeration::get_values('IPRI') |
|
53 | @priorities = Enumeration::get_values('IPRI') | |
53 | @categories = @project.issue_categories |
|
54 | @categories = @project.issue_categories |
@@ -25,6 +25,7 class Permission < ActiveRecord::Base | |||||
25 | 200 => :label_member_plural, |
|
25 | 200 => :label_member_plural, | |
26 | 300 => :label_version_plural, |
|
26 | 300 => :label_version_plural, | |
27 | 400 => :label_issue_category_plural, |
|
27 | 400 => :label_issue_category_plural, | |
|
28 | 600 => :label_query_plural, | |||
28 | 1000 => :label_issue_plural, |
|
29 | 1000 => :label_issue_plural, | |
29 | 1100 => :label_news_plural, |
|
30 | 1100 => :label_news_plural, | |
30 | 1200 => :label_document_plural, |
|
31 | 1200 => :label_document_plural, |
@@ -21,6 +21,7 class Project < ActiveRecord::Base | |||||
21 | has_many :users, :through => :members |
|
21 | has_many :users, :through => :members | |
22 | has_many :custom_values, :dependent => true, :as => :customized |
|
22 | has_many :custom_values, :dependent => true, :as => :customized | |
23 | has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status |
|
23 | has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status | |
|
24 | has_many :queries, :dependent => true | |||
24 | has_many :documents, :dependent => true |
|
25 | has_many :documents, :dependent => true | |
25 | has_many :news, :dependent => true, :include => :author |
|
26 | has_many :news, :dependent => true, :include => :author | |
26 | has_many :issue_categories, :dependent => true, :order => "issue_categories.name" |
|
27 | has_many :issue_categories, :dependent => true, :order => "issue_categories.name" |
@@ -1,34 +1,40 | |||||
1 | <div class="contextual"> |
|
1 | <% if @query.new_record? %> | |
2 | <%= l(:label_export_to) %> |
|
2 | <h2><%=l(:label_issue_plural)%></h2> | |
3 | <%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'pic picCsv' %>, |
|
3 | ||
4 | <%= link_to 'PDF', {:action => 'export_issues_pdf', :id => @project}, :class => 'pic picPdf' %> |
|
4 | <%= start_form_tag({:action => 'list_issues'}, :id => 'query_form') %> | |
5 | </div> |
|
5 | <%= render :partial => 'queries/filters', :locals => {:query => @query} %> | |
6 |
|
6 | <%= end_form_tag %> | ||
7 | <h2><%=l(:label_issue_plural)%></h2> |
|
7 | <div class="contextual"> | |
8 |
|
8 | <%= link_to_remote l(:button_apply), | ||
9 | <%= start_form_tag :action => 'list_issues' %> |
|
9 | { :url => { :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 }, | |
10 | <table cellpadding=2> |
|
10 | :update => "content", | |
11 | <tr> |
|
11 | :with => "Form.serialize('query_form')" | |
12 | <td valign="bottom"><small><%=l(:field_status)%>:</small><br /><%= search_filter_tag 'status_id', :class => 'select-small' %></td> |
|
12 | }, :class => 'pic picCheck' %> | |
13 | <td valign="bottom"><small><%=l(:field_tracker)%>:</small><br /><%= search_filter_tag 'tracker_id', :class => 'select-small' %></td> |
|
13 | ||
14 | <td valign="bottom"><small><%=l(:field_priority)%>:</small><br /><%= search_filter_tag 'priority_id', :class => 'select-small' %></td> |
|
14 | <%= link_to l(:button_clear), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1}, :class => 'pic picDelete' %> | |
15 | <td valign="bottom"><small><%=l(:field_category)%>:</small><br /><%= search_filter_tag 'category_id', :class => 'select-small' %></td> |
|
15 | <% if authorize_for('projects', 'add_query') %> | |
16 | <td valign="bottom"><small><%=l(:field_fixed_version)%>:</small><br /><%= search_filter_tag 'fixed_version_id', :class => 'select-small' %></td> |
|
16 | ||
17 | <td valign="bottom"><small><%=l(:field_author)%>:</small><br /><%= search_filter_tag 'author_id', :class => 'select-small' %></td> |
|
17 | <%= link_to_remote l(:button_save), | |
18 | <td valign="bottom"><small><%=l(:field_assigned_to)%>:</small><br /><%= search_filter_tag 'assigned_to_id', :class => 'select-small' %></td> |
|
18 | { :url => { :controller => 'projects', :action => "add_query", :id => @project }, | |
19 | <td valign="bottom"><small><%=l(:label_subproject_plural)%>:</small><br /><%= search_filter_tag 'subproject_id', :class => 'select-small' %></td> |
|
19 | :method => 'get', | |
20 | <td valign="bottom"> |
|
20 | :update => "content", | |
21 | <%= hidden_field_tag 'set_filter', 1 %> |
|
21 | :with => "Form.serialize('query_form')" | |
22 | <%= submit_tag l(:button_apply), :class => 'button-small' %> |
|
22 | }, :class => 'pic picEdit' %> | |
23 |
< |
|
23 | <% end %> | |
24 | <td valign="bottom"> |
|
24 | </div> | |
25 | <%= link_to l(:button_clear), :action => 'list_issues', :id => @project, :set_filter => 1 %> |
|
25 | <br /> | |
26 | </td> |
|
26 | <% else %> | |
27 | </tr> |
|
27 | <% if authorize_for('projects', 'add_query') %> | |
28 | </table> |
|
28 | <div class="contextual"> | |
29 | <%= end_form_tag %> |
|
29 | <%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'pic picEdit' %> | |
30 |
|
30 | <%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :post => true, :class => 'pic picDelete' %> | ||
31 | |
|
31 | </div> | |
|
32 | <% end %> | |||
|
33 | <h2><%= @query.name %></h2> | |||
|
34 | <% end %> | |||
|
35 | <%= error_messages_for 'query' %> | |||
|
36 | <% if @query.valid? %> | |||
|
37 | | |||
32 | <table class="listTableContent"> |
|
38 | <table class="listTableContent"> | |
33 | <tr> |
|
39 | <tr> | |
34 | <td colspan="6" align="left"><small><%= check_all_links 'issues_form' %></small></td> |
|
40 | <td colspan="6" align="left"><small><%= check_all_links 'issues_form' %></small></td> | |
@@ -67,9 +73,15 | |||||
67 | </tr> |
|
73 | </tr> | |
68 | <% end %> |
|
74 | <% end %> | |
69 | </table> |
|
75 | </table> | |
|
76 | <div class="contextual"> | |||
|
77 | <%= l(:label_export_to) %> | |||
|
78 | <%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'pic picCsv' %>, | |||
|
79 | <%= link_to 'PDF', {:action => 'export_issues_pdf', :id => @project}, :class => 'pic picPdf' %> | |||
|
80 | </div> | |||
70 | <p> |
|
81 | <p> | |
71 | <%= pagination_links_full @issue_pages %> |
|
82 | <%= pagination_links_full @issue_pages %> | |
72 | [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ] |
|
83 | [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ] | |
73 | </p> |
|
84 | </p> | |
74 | <%= submit_tag l(:button_move) %> |
|
85 | <%= submit_tag l(:button_move) %> | |
75 | <%= end_form_tag %> No newline at end of file |
|
86 | <%= end_form_tag %> | |
|
87 | <% end %> No newline at end of file |
@@ -29,17 +29,17 | |||||
29 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
29 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
30 | :set_filter => 1, |
|
30 | :set_filter => 1, | |
31 | "#{field_name}" => row.id, |
|
31 | "#{field_name}" => row.id, | |
32 |
"status_id" => " |
|
32 | "status_id" => "o" %></td> | |
33 | <td align="center"><%= link_to (aggregate data, { field_name => row.id, "closed" => 1 }), |
|
33 | <td align="center"><%= link_to (aggregate data, { field_name => row.id, "closed" => 1 }), | |
34 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
34 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
35 | :set_filter => 1, |
|
35 | :set_filter => 1, | |
36 | "#{field_name}" => row.id, |
|
36 | "#{field_name}" => row.id, | |
37 |
"status_id" => " |
|
37 | "status_id" => "c" %></td> | |
38 | <td align="center"><%= link_to (aggregate data, { field_name => row.id }), |
|
38 | <td align="center"><%= link_to (aggregate data, { field_name => row.id }), | |
39 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
39 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
40 | :set_filter => 1, |
|
40 | :set_filter => 1, | |
41 | "#{field_name}" => row.id, |
|
41 | "#{field_name}" => row.id, | |
42 |
"status_id" => " |
|
42 | "status_id" => "*" %></td> | |
43 | <% end %> |
|
43 | <% end %> | |
44 | </tr> |
|
44 | </tr> | |
45 | </table> |
|
45 | </table> |
@@ -18,17 +18,17 | |||||
18 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
18 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
19 | :set_filter => 1, |
|
19 | :set_filter => 1, | |
20 | "#{field_name}" => row.id, |
|
20 | "#{field_name}" => row.id, | |
21 |
"status_id" => " |
|
21 | "status_id" => "o" %></td> | |
22 | <td align="center"><%= link_to (aggregate data, { field_name => row.id, "closed" => 1 }), |
|
22 | <td align="center"><%= link_to (aggregate data, { field_name => row.id, "closed" => 1 }), | |
23 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
23 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
24 | :set_filter => 1, |
|
24 | :set_filter => 1, | |
25 | "#{field_name}" => row.id, |
|
25 | "#{field_name}" => row.id, | |
26 |
"status_id" => " |
|
26 | "status_id" => "c" %></td> | |
27 | <td align="center"><%= link_to (aggregate data, { field_name => row.id }), |
|
27 | <td align="center"><%= link_to (aggregate data, { field_name => row.id }), | |
28 | :controller => 'projects', :action => 'list_issues', :id => @project, |
|
28 | :controller => 'projects', :action => 'list_issues', :id => @project, | |
29 | :set_filter => 1, |
|
29 | :set_filter => 1, | |
30 | "#{field_name}" => row.id, |
|
30 | "#{field_name}" => row.id, | |
31 |
"status_id" => " |
|
31 | "status_id" => "*" %></td> | |
32 | <% end %> |
|
32 | <% end %> | |
33 | </tr> |
|
33 | </tr> | |
34 | </table> |
|
34 | </table> |
@@ -1,18 +1,30 | |||||
1 | <h2><%=l(:label_report_plural)%></h2> |
|
1 | <h2><%=l(:label_report_plural)%></h2> | |
2 |
|
2 | |||
|
3 | <h3><%= l(:label_query_plural) %></h3> | |||
|
4 | <div class="contextual"> | |||
|
5 | <%= link_to_if_authorized l(:label_query_new), {:controller => 'projects', :action => 'add_query', :id => @project}, :class => 'pic picAdd' %> | |||
|
6 | </div> | |||
|
7 | ||||
|
8 | <% if @queries.empty? %><p><i><%=l(:label_no_data)%></i></p><% end %> | |||
|
9 | <ul> | |||
|
10 | <% @queries.each do |query| %> | |||
|
11 | <li><%= link_to query.name, :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => query %></li> | |||
|
12 | <% end %> | |||
|
13 | </ul> | |||
|
14 | ||||
3 | <div class="splitcontentleft"> |
|
15 | <div class="splitcontentleft"> | |
4 |
<h3><%=l(:field_tracker)%> <%= link_to image_tag('details'), :detail => ' |
|
16 | <h3><%=l(:field_tracker)%> <%= link_to image_tag('details'), :detail => 'tracker' %></h3> | |
5 | <%= render :partial => 'simple', :locals => { :data => @issues_by_tracker, :field_name => "tracker_id", :rows => @trackers } %> |
|
17 | <%= render :partial => 'simple', :locals => { :data => @issues_by_tracker, :field_name => "tracker_id", :rows => @trackers } %> | |
6 | <br /> |
|
18 | <br /> | |
7 | <h3><%=l(:field_priority)%> <%= link_to image_tag('details'), :detail => 'priority' %></h3> |
|
|||
8 | <%= render :partial => 'simple', :locals => { :data => @issues_by_priority, :field_name => "priority_id", :rows => @priorities } %> |
|
|||
9 | <br /> |
|
|||
10 | <h3><%=l(:field_author)%> <%= link_to image_tag('details'), :detail => 'author' %></h3> |
|
19 | <h3><%=l(:field_author)%> <%= link_to image_tag('details'), :detail => 'author' %></h3> | |
11 | <%= render :partial => 'simple', :locals => { :data => @issues_by_author, :field_name => "author_id", :rows => @authors } %> |
|
20 | <%= render :partial => 'simple', :locals => { :data => @issues_by_author, :field_name => "author_id", :rows => @authors } %> | |
12 | <br /> |
|
21 | <br /> | |
13 | </div> |
|
22 | </div> | |
14 |
|
23 | |||
15 | <div class="splitcontentright"> |
|
24 | <div class="splitcontentright"> | |
|
25 | <h3><%=l(:field_priority)%> <%= link_to image_tag('details'), :detail => 'priority' %></h3> | |||
|
26 | <%= render :partial => 'simple', :locals => { :data => @issues_by_priority, :field_name => "priority_id", :rows => @priorities } %> | |||
|
27 | <br /> | |||
16 | <h3><%=l(:field_category)%> <%= link_to image_tag('details'), :detail => 'category' %></h3> |
|
28 | <h3><%=l(:field_category)%> <%= link_to image_tag('details'), :detail => 'category' %></h3> | |
17 | <%= render :partial => 'simple', :locals => { :data => @issues_by_category, :field_name => "category_id", :rows => @categories } %> |
|
29 | <%= render :partial => 'simple', :locals => { :data => @issues_by_category, :field_name => "category_id", :rows => @categories } %> | |
18 | <br /> |
|
30 | <br /> |
@@ -265,6 +265,23 label_comment_plural: Anmerkungen | |||||
265 | label_comment_add: Anmerkung addieren |
|
265 | label_comment_add: Anmerkung addieren | |
266 | label_comment_added: Anmerkung fügte hinzu |
|
266 | label_comment_added: Anmerkung fügte hinzu | |
267 | label_comment_delete: Anmerkungen löschen |
|
267 | label_comment_delete: Anmerkungen löschen | |
|
268 | label_query: Benutzerdefiniertes Frage | |||
|
269 | label_query_plural: Benutzerdefinierte Fragen | |||
|
270 | label_query_new: Neue Frage | |||
|
271 | label_filter_add: Filter addieren | |||
|
272 | label_filter_plural: Filter | |||
|
273 | label_equals: ist | |||
|
274 | label_not_equals: ist nicht | |||
|
275 | label_in_less_than: an weniger als | |||
|
276 | label_in_more_than: an mehr als | |||
|
277 | label_in: an | |||
|
278 | label_today: heute | |||
|
279 | label_less_than_ago: vor weniger als | |||
|
280 | label_more_than_ago: vor mehr als | |||
|
281 | label_ago: vor | |||
|
282 | label_contains: enthält | |||
|
283 | label_not_contains: enthält nicht | |||
|
284 | label_day_plural: Tage | |||
268 |
|
285 | |||
269 | button_login: Einloggen |
|
286 | button_login: Einloggen | |
270 | button_submit: Einreichen |
|
287 | button_submit: Einreichen |
@@ -265,6 +265,23 label_comment_plural: Comments | |||||
265 | label_comment_add: Add a comment |
|
265 | label_comment_add: Add a comment | |
266 | label_comment_added: Comment added |
|
266 | label_comment_added: Comment added | |
267 | label_comment_delete: Delete comments |
|
267 | label_comment_delete: Delete comments | |
|
268 | label_query: Custom query | |||
|
269 | label_query_plural: Custom queries | |||
|
270 | label_query_new: New query | |||
|
271 | label_filter_add: Add filter | |||
|
272 | label_filter_plural: Filters | |||
|
273 | label_equals: is | |||
|
274 | label_not_equals: is not | |||
|
275 | label_in_less_than: in less than | |||
|
276 | label_in_more_than: in more than | |||
|
277 | label_in: in | |||
|
278 | label_today: today | |||
|
279 | label_less_than_ago: less than days ago | |||
|
280 | label_more_than_ago: more than days ago | |||
|
281 | label_ago: days ago | |||
|
282 | label_contains: contains | |||
|
283 | label_not_contains: doesn't contain | |||
|
284 | label_day_plural: days | |||
268 |
|
285 | |||
269 | button_login: Login |
|
286 | button_login: Login | |
270 | button_submit: Submit |
|
287 | button_submit: Submit |
@@ -265,6 +265,23 label_comment_plural: Comentarios | |||||
265 | label_comment_add: Agregar un comentario |
|
265 | label_comment_add: Agregar un comentario | |
266 | label_comment_added: Comentario agregó |
|
266 | label_comment_added: Comentario agregó | |
267 | label_comment_delete: Suprimir comentarios |
|
267 | label_comment_delete: Suprimir comentarios | |
|
268 | label_query: Pregunta personalizada | |||
|
269 | label_query_plural: Preguntas personalizadas | |||
|
270 | label_query_new: Nueva preguntas | |||
|
271 | label_filter_add: Agregar el filtro | |||
|
272 | label_filter_plural: Filtros | |||
|
273 | label_equals: igual | |||
|
274 | label_not_equals: no igual | |||
|
275 | label_in_less_than: en menos que | |||
|
276 | label_in_more_than: en más que | |||
|
277 | label_in: en | |||
|
278 | label_today: hoy | |||
|
279 | label_less_than_ago: hace menos de | |||
|
280 | label_more_than_ago: hace más de | |||
|
281 | label_ago: hace | |||
|
282 | label_contains: contiene | |||
|
283 | label_not_contains: no contiene | |||
|
284 | label_day_plural: días | |||
268 |
|
285 | |||
269 | button_login: Conexión |
|
286 | button_login: Conexión | |
270 | button_submit: Someter |
|
287 | button_submit: Someter |
@@ -238,16 +238,16 label_confirmation: Confirmation | |||||
238 | label_export_to: Exporter en |
|
238 | label_export_to: Exporter en | |
239 | label_read: Lire... |
|
239 | label_read: Lire... | |
240 | label_public_projects: Projets publics |
|
240 | label_public_projects: Projets publics | |
241 |
label_open_issues: |
|
241 | label_open_issues: ouvert | |
242 |
label_open_issues_plural: |
|
242 | label_open_issues_plural: ouverts | |
243 |
label_closed_issues: |
|
243 | label_closed_issues: fermé | |
244 |
label_closed_issues_plural: |
|
244 | label_closed_issues_plural: fermés | |
245 | label_total: Total |
|
245 | label_total: Total | |
246 | label_permissions: Permissions |
|
246 | label_permissions: Permissions | |
247 | label_current_status: Statut actuel |
|
247 | label_current_status: Statut actuel | |
248 | label_new_statuses_allowed: Nouveaux statuts autorisés |
|
248 | label_new_statuses_allowed: Nouveaux statuts autorisés | |
249 |
label_all: |
|
249 | label_all: tous | |
250 |
label_none: |
|
250 | label_none: aucun | |
251 | label_next: Suivant |
|
251 | label_next: Suivant | |
252 | label_previous: Précédent |
|
252 | label_previous: Précédent | |
253 | label_used_by: Utilisé par |
|
253 | label_used_by: Utilisé par | |
@@ -266,6 +266,23 label_comment_plural: Commentaires | |||||
266 | label_comment_add: Ajouter un commentaire |
|
266 | label_comment_add: Ajouter un commentaire | |
267 | label_comment_added: Commentaire ajouté |
|
267 | label_comment_added: Commentaire ajouté | |
268 | label_comment_delete: Supprimer les commentaires |
|
268 | label_comment_delete: Supprimer les commentaires | |
|
269 | label_query: Rapport personnalisé | |||
|
270 | label_query_plural: Rapports personnalisés | |||
|
271 | label_query_new: Nouveau rapport | |||
|
272 | label_filter_add: Ajouter le filtre | |||
|
273 | label_filter_plural: Filtres | |||
|
274 | label_equals: égal | |||
|
275 | label_not_equals: différent | |||
|
276 | label_in_less_than: dans moins de | |||
|
277 | label_in_more_than: dans plus de | |||
|
278 | label_in: dans | |||
|
279 | label_today: aujourd'hui | |||
|
280 | label_less_than_ago: il y a moins de | |||
|
281 | label_more_than_ago: il y a plus de | |||
|
282 | label_ago: il y a | |||
|
283 | label_contains: contient | |||
|
284 | label_not_contains: ne contient pas | |||
|
285 | label_day_plural: jours | |||
269 |
|
286 | |||
270 | button_login: Connexion |
|
287 | button_login: Connexion | |
271 | button_submit: Soumettre |
|
288 | button_submit: Soumettre |
1 | NO CONTENT: file renamed from public/images/edit_small.png to public/images/edit.png |
|
NO CONTENT: file renamed from public/images/edit_small.png to public/images/edit.png |
@@ -128,10 +128,11 background-color: #80b0da; | |||||
128 | .picLogout { background: url(../images/logout.png) no-repeat 4px 50%; } |
|
128 | .picLogout { background: url(../images/logout.png) no-repeat 4px 50%; } | |
129 | .picHelp { background: url(../images/help.png) no-repeat 4px 50%; } |
|
129 | .picHelp { background: url(../images/help.png) no-repeat 4px 50%; } | |
130 |
|
130 | |||
131 |
.picEdit { background: url(../images/edit |
|
131 | .picEdit { background: url(../images/edit.png) no-repeat 4px 50%; } | |
132 | .picDelete { background: url(../images/delete.png) no-repeat 4px 50%; } |
|
132 | .picDelete { background: url(../images/delete.png) no-repeat 4px 50%; } | |
133 | .picAdd { background: url(../images/add.png) no-repeat 4px 50%; } |
|
133 | .picAdd { background: url(../images/add.png) no-repeat 4px 50%; } | |
134 | .picMove { background: url(../images/move.png) no-repeat 4px 50%; } |
|
134 | .picMove { background: url(../images/move.png) no-repeat 4px 50%; } | |
|
135 | .picCheck { background: url(../images/check.png) no-repeat 4px 70%; } | |||
135 | .picPdf { background: url(../images/pdf.png) no-repeat 4px 50%;} |
|
136 | .picPdf { background: url(../images/pdf.png) no-repeat 4px 50%;} | |
136 | .picCsv { background: url(../images/csv.png) no-repeat 4px 50%;} |
|
137 | .picCsv { background: url(../images/csv.png) no-repeat 4px 50%;} | |
137 |
|
138 | |||
@@ -221,7 +222,7 select { | |||||
221 | vertical-align: middle; |
|
222 | vertical-align: middle; | |
222 | } |
|
223 | } | |
223 |
|
224 | |||
224 |
|
|
225 | .select-small | |
225 | { |
|
226 | { | |
226 | border: 1px solid #7F9DB9; |
|
227 | border: 1px solid #7F9DB9; | |
227 | padding: 1px; |
|
228 | padding: 1px; |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now