diff --git a/config/locales/sv.yml b/config/locales/sv.yml new file mode 100644 index 0000000..0cef7ed --- /dev/null +++ b/config/locales/sv.yml @@ -0,0 +1,7 @@ +sv: + label_orfilter: "Eller-filter" + label_orfilter_and_any: "OCH någon av följande" + label_orfilter_or_any: "Eller någon av följande" + label_orfilter_or_all: "Eller alla följande" + label_match: "träff" + label_not_match: "ingen träff" \ No newline at end of file diff --git a/init.rb b/init.rb index 8733963..a6a6e44 100644 --- a/init.rb +++ b/init.rb @@ -1,4 +1,4 @@ -Redmine::Plugin.register :redmine_or_filter do +Redmine::Plugin.register :redmine_or_filters do name 'Redmine or filter' author 'Alexey Smirnov' description 'This is a plugin for Redmine which adds OR filters. Development based on discussion https://www.redmine.org/issues/4939' @@ -10,4 +10,4 @@ require_dependency File.dirname(__FILE__) + '/lib/queries_helper_patch' require_dependency File.dirname(__FILE__) + '/lib/issue_query_patch' -require_dependency File.dirname(__FILE__) + '/lib/query_patch' \ No newline at end of file +require_dependency File.dirname(__FILE__) + '/lib/query_patch' diff --git a/lib/query_patch.rb b/lib/query_patch.rb index e52ec5a..77c0bb9 100644 --- a/lib/query_patch.rb +++ b/lib/query_patch.rb @@ -4,16 +4,24 @@ def statement # filters clauses filters_clauses = [] - and_clauses=[] - and_any_clauses=[] - or_any_clauses=[] - or_all_clauses=[] - and_any_op = "" - or_any_op = "" - or_all_op = "" + and_clauses=[] + and_any_clauses=[] + or_any_clauses=[] + or_all_clauses=[] + and_any_op = "" + or_any_op = "" + or_all_op = "" - #the AND filter start first - filters_clauses = and_clauses + #the AND filter start first + filters_clauses = and_clauses + + # helper: join non-blank parts with op, wrap in () + join_group = lambda do |parts, op, fallback = " AND "| + parts = parts.reject(&:blank?) + return nil if parts.empty? + joined = parts.join(op.present? ? op : fallback) + "(#{joined})" + end filters.each_key do |field| next if field == "subproject_id" @@ -82,37 +90,41 @@ def statement filters_clauses << c.custom_field.visibility_by_project_condition end - # filters_clauses << project_statement - # filters_clauses.reject!(&:blank?) - - # filters_clauses.any? ? filters_clauses.join(' AND ') : nil - - #now start build the full statement, project filter is allways AND + # Build base AND statement (WITHOUT project_statement here) filters_clauses.reject!(&:blank?) and_clauses.reject!(&:blank?) and_statement = and_clauses.any? ? and_clauses.join(" AND ") : nil - all_and_statement = ["#{project_statement}", "#{and_statement}"].reject(&:blank?) - all_and_statement = all_and_statement.any? ? all_and_statement.join(" AND ") : nil - # finish the traditional part. Now extended part - # add the and_any first + # Extended part + # 1) and_any (OR-join within group, attach to AND/AND NOT) and_any_clauses.reject!(&:blank?) - and_any_statement = and_any_clauses.any? ? "("+ and_any_clauses.join(" OR ") +")" : nil - full_statement_ext_1 = ["#{all_and_statement}", "#{and_any_statement}"].reject(&:blank?) - full_statement_ext_1 = full_statement_ext_1.any? ? full_statement_ext_1.join(and_any_op) : nil + and_any_statement = and_any_clauses.any? ? "(" + and_any_clauses.join(" OR ") + ")" : nil + full_statement_ext_1 = [and_statement, and_any_statement] + full_statement_ext_1 = join_group.call(full_statement_ext_1.compact, and_any_op, " AND ") - # then add the or_all + # 2) or_all (AND-join within group, attach to OR/OR NOT) or_all_clauses.reject!(&:blank?) - or_all_statement = or_all_clauses.any? ? "("+ or_all_clauses.join(" AND ") +")" : nil - full_statement_ext_2 = ["#{full_statement_ext_1}", "#{or_all_statement}"].reject(&:blank?) - full_statement_ext_2 = full_statement_ext_2.any? ? full_statement_ext_2.join(or_all_op) : nil + or_all_statement = or_all_clauses.any? ? "(" + or_all_clauses.join(" AND ") + ")" : nil + full_statement_ext_2 = [full_statement_ext_1, or_all_statement] + full_statement_ext_2 = join_group.call(full_statement_ext_2.compact, or_all_op, " AND ") - # then add the or_any + # 3) or_any (OR-join within group, attach to OR/OR NOT) or_any_clauses.reject!(&:blank?) - or_any_statement = or_any_clauses.any? ? "("+ or_any_clauses.join(" OR ") +")" : nil - filters_clauses.any? ? filters_clauses.join(' AND ') : nil - full_statement = ["#{full_statement_ext_2}", "#{or_any_statement}"].reject(&:blank?) - full_statement = full_statement.any? ? full_statement.join(or_any_op) : nil + or_any_statement = or_any_clauses.any? ? "(" + or_any_clauses.join(" OR ") + ")" : nil + core_statement = [full_statement_ext_2, or_any_statement] + core_statement = join_group.call(core_statement.compact, or_any_op, " AND ") + + # FINAL: always add AND for project_statement enclosing core_statement + if project_statement.present? + if core_statement.present? + full_statement = "#{project_statement} AND #{core_statement}" + else + full_statement = project_statement + end + else + full_statement = core_statement + end + Rails.logger.info "STATEMENT #{full_statement}" return full_statement end @@ -436,4 +448,4 @@ def sql_for_match_operators(field, operator, value, db_table, db_field, is_custo Query.operators.store("match", :label_match) Query.operators.store("!match", :label_not_match) -Query.send(:prepend, QueryPatch) \ No newline at end of file +Query.send(:prepend, QueryPatch)