Patch #1898 » watcher_filter.diff
| app/models/query.rb | ||
|---|---|---|
| 76 | 76 |
"<t-" => :label_more_than_ago, |
| 77 | 77 |
"t-" => :label_ago, |
| 78 | 78 |
"~" => :label_contains, |
| 79 |
"!~" => :label_not_contains } |
|
| 79 |
"!~" => :label_not_contains, |
|
| 80 |
"<w" => :label_equals, |
|
| 81 |
">w" => :label_not_equals} |
|
| 80 | 82 | |
| 81 | 83 |
cattr_reader :operators |
| 82 | 84 |
|
| 83 | 85 |
@@operators_by_filter_type = { :list => [ "=", "!" ],
|
| 86 |
:list_watcher => [ "<w", ">w" ], |
|
| 84 | 87 |
:list_status => [ "o", "=", "!", "c", "*" ], |
| 85 | 88 |
:list_optional => [ "=", "!", "!*", "*" ], |
| 86 | 89 |
:list_subprojects => [ "*", "!*", "=" ], |
| ... | ... | |
| 107 | 110 |
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
|
| 108 | 111 |
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio"),
|
| 109 | 112 |
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
|
| 113 |
QueryColumn.new(:watcher), |
|
| 110 | 114 |
] |
| 111 | 115 |
cattr_reader :available_columns |
| 112 | 116 |
|
| ... | ... | |
| 165 | 169 |
end |
| 166 | 170 |
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
|
| 167 | 171 |
@available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
|
| 172 |
@available_filters["watcher_id"] = { :type => :list_watcher, :order => 15, :values => user_values } unless user_values.empty?
|
|
| 168 | 173 |
|
| 169 | 174 |
if project |
| 170 | 175 |
# project specific filters |
| ... | ... | |
| 305 | 310 |
end |
| 306 | 311 |
|
| 307 | 312 |
# "me" value subsitution |
| 308 |
if %w(assigned_to_id author_id).include?(field) |
|
| 313 |
if %w(assigned_to_id author_id watcher_id).include?(field)
|
|
| 309 | 314 |
v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me")
|
| 310 | 315 |
end |
| 311 | 316 |
|
| ... | ... | |
| 353 | 358 |
sql = sql + "#{db_table}.#{db_field} LIKE '%#{connection.quote_string(v.first)}%'"
|
| 354 | 359 |
when "!~" |
| 355 | 360 |
sql = sql + "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(v.first)}%'"
|
| 361 |
when "<w" |
|
| 362 |
sql = sql + "#{Issue.table_name}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 363 |
when ">w" |
|
| 364 |
sql = sql + "#{Issue.table_name}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 356 | 365 |
end |
| 357 | 366 |
sql << ')' |
| 358 | 367 |
filters_clauses << sql |
| app/views/queries/_filters.rhtml | ||
|---|---|---|
| 74 | 74 |
<td> |
| 75 | 75 |
<div id="div_values_<%= field %>" style="display:none;"> |
| 76 | 76 |
<% case options[:type] |
| 77 |
when :list, :list_optional, :list_status, :list_subprojects %> |
|
| 77 |
when :list, :list_optional, :list_status, :list_subprojects, :list_watcher %>
|
|
| 78 | 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 | 79 |
<%= options_for_select options[:values], query.values_for(field) %> |
| 80 | 80 |
</select> |
| lang/en.yml | ||
|---|---|---|
| 183 | 183 |
field_default_value: Default value |
| 184 | 184 |
field_comments_sorting: Display comments |
| 185 | 185 |
field_parent_title: Parent page |
| 186 |
field_watcher: Watcher |
|
| 186 | 187 | |
| 187 | 188 |
setting_app_title: Application title |
| 188 | 189 |
setting_app_subtitle: Application subtitle |
| 189 |
- |
|
| lang/bg.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Пренасочване на съществуващи линкове |
| 166 | 166 |
field_estimated_hours: Изчислено време |
| 167 | 167 |
field_default_value: Стойност по подразбиране |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Заглавие |
| 170 | 171 |
setting_app_subtitle: Описание |
| lang/cs.yml | ||
|---|---|---|
| 183 | 183 |
field_searchable: Umožnit vyhledávání |
| 184 | 184 |
field_default_value: Výchozí hodnota |
| 185 | 185 |
field_comments_sorting: Zobrazit komentáře |
| 186 |
field_watcher: Watcher |
|
| 186 | 187 | |
| 187 | 188 |
setting_app_title: Název aplikace |
| 188 | 189 |
setting_app_subtitle: Podtitulek aplikace |
| lang/da.yml | ||
|---|---|---|
| 177 | 177 |
field_time_zone: Tids zone |
| 178 | 178 |
field_searchable: Søgbar |
| 179 | 179 |
field_default_value: Standard værdi |
| 180 |
field_watcher: Watcher |
|
| 180 | 181 | |
| 181 | 182 |
setting_app_title: Applikations titel |
| 182 | 183 |
setting_app_subtitle: Applikations undertekst |
| lang/de.yml | ||
|---|---|---|
| 180 | 180 |
field_searchable: Durchsuchbar |
| 181 | 181 |
field_default_value: Standardwert |
| 182 | 182 |
field_comments_sorting: Kommentare anzeigen |
| 183 |
field_watcher: Watcher |
|
| 183 | 184 | |
| 184 | 185 |
setting_app_title: Applikations-Titel |
| 185 | 186 |
setting_app_subtitle: Applikations-Untertitel |
| lang/es.yml | ||
|---|---|---|
| 159 | 159 |
field_issue_to_id: Petición Relacionada |
| 160 | 160 |
field_delay: Retraso |
| 161 | 161 |
field_default_value: Estado por defecto |
| 162 |
field_watcher: Watcher |
|
| 162 | 163 | |
| 163 | 164 |
setting_app_title: Título de la aplicación |
| 164 | 165 |
setting_app_subtitle: Subtítulo de la aplicación |
| lang/fi.yml | ||
|---|---|---|
| 177 | 177 |
field_time_zone: Aikavyöhyke |
| 178 | 178 |
field_searchable: Haettava |
| 179 | 179 |
field_default_value: Vakioarvo |
| 180 |
field_watcher: Watcher |
|
| 180 | 181 | |
| 181 | 182 |
setting_app_title: Ohjelman otsikko |
| 182 | 183 |
setting_app_subtitle: Ohjelman alaotsikko |
| lang/fr.yml | ||
|---|---|---|
| 184 | 184 |
field_default_value: Valeur par défaut |
| 185 | 185 |
field_comments_sorting: Afficher les commentaires |
| 186 | 186 |
field_parent_title: Page parent |
| 187 |
field_watcher: Watcher |
|
| 187 | 188 | |
| 188 | 189 |
setting_app_title: Titre de l'application |
| 189 | 190 |
setting_app_subtitle: Sous-titre de l'application |
| lang/he.yml | ||
|---|---|---|
| 168 | 168 |
field_estimated_hours: זמן משוער |
| 169 | 169 |
field_column_names: עמודות |
| 170 | 170 |
field_default_value: ערך ברירת מחדל |
| 171 |
field_watcher: Watcher |
|
| 171 | 172 | |
| 172 | 173 |
setting_app_title: כותרת ישום |
| 173 | 174 |
setting_app_subtitle: תת-כותרת ישום |
| lang/hu.yml | ||
|---|---|---|
| 180 | 180 |
field_searchable: Kereshető |
| 181 | 181 |
field_default_value: Alapértelmezett érték |
| 182 | 182 |
field_comments_sorting: Feljegyzések megjelenítése |
| 183 |
field_watcher: Watcher |
|
| 183 | 184 | |
| 184 | 185 |
setting_app_title: Alkalmazás címe |
| 185 | 186 |
setting_app_subtitle: Alkalmazás alcíme |
| lang/it.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirige i collegamenti esistenti |
| 166 | 166 |
field_estimated_hours: Tempo stimato |
| 167 | 167 |
field_default_value: Stato predefinito |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Titolo applicazione |
| 170 | 171 |
setting_app_subtitle: Sottotitolo applicazione |
| lang/ja.yml | ||
|---|---|---|
| 166 | 166 |
field_redirect_existing_links: 既存のリンクをリダイレクトする |
| 167 | 167 |
field_estimated_hours: 予定工数 |
| 168 | 168 |
field_default_value: デフォルトのステータス |
| 169 |
field_watcher: Watcher |
|
| 169 | 170 | |
| 170 | 171 |
setting_app_title: アプリケーションのタイトル |
| 171 | 172 |
setting_app_subtitle: アプリケーションのサブタイトル |
| lang/ko.yml | ||
|---|---|---|
| 168 | 168 |
field_estimated_hours: 추정시간 |
| 169 | 169 |
field_column_names: 컬럼 |
| 170 | 170 |
field_default_value: 기본값 |
| 171 |
field_watcher: Watcher |
|
| 171 | 172 | |
| 172 | 173 |
setting_app_title: 레드마인 제목 |
| 173 | 174 |
setting_app_subtitle: 레드마인 부제목 |
| lang/lt.yml | ||
|---|---|---|
| 176 | 176 |
field_time_zone: Laiko juosta |
| 177 | 177 |
field_searchable: Randamas |
| 178 | 178 |
field_default_value: Numatytoji vertė |
| 179 |
field_watcher: Watcher |
|
| 180 | ||
| 179 | 181 |
setting_app_title: Programos pavadinimas |
| 180 | 182 |
setting_app_subtitle: Programos paantraštė |
| 181 | 183 |
setting_welcome_text: Pasveikinimas |
| lang/no.yml | ||
|---|---|---|
| 182 | 182 |
field_searchable: Søkbar |
| 183 | 183 |
field_default_value: Standardverdi |
| 184 | 184 |
field_comments_sorting: Vis kommentarer |
| 185 |
field_watcher: Watcher |
|
| 185 | 186 | |
| 186 | 187 |
setting_app_title: Applikasjonstittel |
| 187 | 188 |
setting_app_subtitle: Applikasjonens undertittel |
| lang/pl.yml | ||
|---|---|---|
| 159 | 159 |
field_issue_to_id: Powiązania zagadnienia |
| 160 | 160 |
field_delay: Opóźnienie |
| 161 | 161 |
field_default_value: Domyślny |
| 162 |
field_watcher: Watcher |
|
| 162 | 163 | |
| 163 | 164 |
setting_app_title: Tytuł aplikacji |
| 164 | 165 |
setting_app_subtitle: Podtytuł aplikacji |
| lang/pt-br.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirecionar links existentes |
| 166 | 166 |
field_estimated_hours: Tempo estimado |
| 167 | 167 |
field_default_value: Padrão |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 |
|
| 169 | 170 |
setting_app_title: Título da aplicação |
| 170 | 171 |
setting_app_subtitle: Sub-título da aplicação |
| lang/pt.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirect existing links |
| 166 | 166 |
field_estimated_hours: Estimated time |
| 167 | 167 |
field_default_value: Padrão |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Título da aplicação |
| 170 | 171 |
setting_app_subtitle: Sub-título da aplicação |
| lang/ro.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirectare linkuri existente |
| 166 | 166 |
field_estimated_hours: Timpul estimat |
| 167 | 167 |
field_default_value: Default value |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Titlul aplicatiei |
| 170 | 171 |
setting_app_subtitle: Subtitlul aplicatiei |
| lang/ru.yml | ||
|---|---|---|
| 178 | 178 |
field_default_value: Значение по умолчанию |
| 179 | 179 |
field_time_zone: Часовой пояс |
| 180 | 180 |
field_searchable: Доступно для поиска |
| 181 |
field_watcher: Watcher |
|
| 181 | 182 | |
| 182 | 183 |
setting_app_title: Название приложения |
| 183 | 184 |
setting_app_subtitle: Подзаголовок приложения |
| lang/sr.yml | ||
|---|---|---|
| 170 | 170 |
field_estimated_hours: Procenjeno vreme |
| 171 | 171 |
field_column_names: Kolone |
| 172 | 172 |
field_default_value: Default value |
| 173 |
field_watcher: Watcher |
|
| 173 | 174 | |
| 174 | 175 |
setting_app_title: Naziv aplikacije |
| 175 | 176 |
setting_app_subtitle: Podnaslov aplikacije |
| lang/sv.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirect existing links |
| 166 | 166 |
field_estimated_hours: Estimated time |
| 167 | 167 |
field_default_value: Default value |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Applikationstitel |
| 170 | 171 |
setting_app_subtitle: Applicationsunderrubrik |
| lang/th.yml | ||
|---|---|---|
| 180 | 180 |
field_searchable: ค้นหาได้ |
| 181 | 181 |
field_default_value: ค่าเริ่มต้น |
| 182 | 182 |
field_comments_sorting: แสดงความเห็น |
| 183 |
field_watcher: Watcher |
|
| 183 | 184 | |
| 184 | 185 |
setting_app_title: ชื่อโปรแกรม |
| 185 | 186 |
setting_app_subtitle: ชื่อโปรแกรมรอง |
| lang/uk.yml | ||
|---|---|---|
| 172 | 172 |
field_column_names: Колонки |
| 173 | 173 |
field_time_zone: Часовий пояс |
| 174 | 174 |
field_searchable: Вживається у пошуку |
| 175 |
field_watcher: Watcher |
|
| 175 | 176 | |
| 176 | 177 |
setting_app_title: Назва додатку |
| 177 | 178 |
setting_app_subtitle: Підзаголовок додатку |
| lang/zh-tw.yml | ||
|---|---|---|
| 182 | 182 |
field_searchable: 可用做搜尋條件 |
| 183 | 183 |
field_default_value: 預設值 |
| 184 | 184 |
field_comments_sorting: 註解排序 |
| 185 |
field_watcher: Watcher |
|
| 185 | 186 | |
| 186 | 187 |
setting_app_title: 標題 |
| 187 | 188 |
setting_app_subtitle: 副標題 |
| lang/zh.yml | ||
|---|---|---|
| 183 | 183 |
field_default_value: 默认值 |
| 184 | 184 |
field_comments_sorting: 显示注释 |
| 185 | 185 |
field_parent_title: 上级页面 |
| 186 |
field_watcher: Watcher |
|
| 186 | 187 | |
| 187 | 188 |
setting_app_title: 应用程序标题 |
| 188 | 189 |
setting_app_subtitle: 应用程序子标题 |
| 189 |
- |
|
| lang/nl.yml | ||
|---|---|---|
| 165 | 165 |
field_redirect_existing_links: Redirect existing links |
| 166 | 166 |
field_estimated_hours: Estimated time |
| 167 | 167 |
field_default_value: Default value |
| 168 |
field_watcher: Watcher |
|
| 168 | 169 | |
| 169 | 170 |
setting_app_title: Applicatie titel |
| 170 | 171 |
setting_app_subtitle: Applicatie ondertitel |
| 171 |
- |
|
| app/models/query.rb | ||
|---|---|---|
| 359 | 359 |
when "!~" |
| 360 | 360 |
sql = sql + "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(v.first)}%'"
|
| 361 | 361 |
when "<w" |
| 362 |
sql = sql + "#{Issue.table_name}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 362 |
sql = sql + "#{db_table}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 363 | 363 |
when ">w" |
| 364 |
sql = sql + "#{Issue.table_name}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 364 |
sql = sql + "#{db_table}.id NOT IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" if field == "watcher_id"
|
|
| 365 | 365 |
end |
| 366 | 366 |
sql << ')' |
| 367 | 367 |
filters_clauses << sql |
| 368 |
- |
|
| test/unit/query_test.rb | ||
|---|---|---|
| 123 | 123 |
find_issues_with_query(query) |
| 124 | 124 |
end |
| 125 | 125 |
|
| 126 |
def test_operator_equals_watcher |
|
| 127 |
query = Query.new(:project => Project.find(1), :name => '_') |
|
| 128 |
user = User.find(1) |
|
| 129 |
query.add_filter('watcher_id', '<w', [user.id.to_s])
|
|
| 130 |
assert query.statement.include?("#{Issue.table_name}.id IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN ('" + user.id.to_s + "'))")
|
|
| 131 |
find_issues_with_query(query) |
|
| 132 |
end |
|
| 133 |
|
|
| 134 |
def test_operator_not_equals_watcher |
|
| 135 |
query = Query.new(:project => Project.find(1), :name => '_') |
|
| 136 |
user = User.find(1) |
|
| 137 |
query.add_filter('watcher_id', '>w', [user.id.to_s])
|
|
| 138 |
assert query.statement.include?("#{Issue.table_name}.id NOT IN (SELECT #{Watcher.table_name}.watchable_id FROM #{Watcher.table_name} WHERE #{Watcher.table_name}.watchable_type = 'Issue' AND #{Watcher.table_name}.user_id IN ('" + user.id.to_s + "'))")
|
|
| 139 |
find_issues_with_query(query) |
|
| 140 |
end |
|
| 141 |
|
|
| 126 | 142 |
def test_default_columns |
| 127 | 143 |
q = Query.new |
| 128 | 144 |
assert !q.columns.empty? |