diff --git a/app/assets/stylesheets/objects/_search-result.scss b/app/assets/stylesheets/objects/_search-result.scss index ff97374..715958d 100644 --- a/app/assets/stylesheets/objects/_search-result.scss +++ b/app/assets/stylesheets/objects/_search-result.scss @@ -12,6 +12,6 @@ margin-bottom: 0.1rem; } -.search-result .metainfo { - font-size: 0.8rem; +.search-result .current { + font-weight: $font-weight-bold; } diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index fefbf16..5948e6e 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -24,6 +24,36 @@ class SearchController < ApplicationController def execute_search @response = Paper.search(@search_definition.to_definition) @papers = @response.page(params[:page]).results + @sub = Hash.new + @papers.each do |paper| + unless paper.reference.nil? && paper.reference.contains("-") + segments = paper.reference.split("-") + id = (paper.reference.start_with?("VI-") && segments.count > 2 ? + segments[2] : segments[1]) + escaped_chars = Regexp.escape('\\+-*:()[]{}&!?^|\/') + sanitized_id = id.gsub(/([#{escaped_chars}])/, '\\\\\1') + ['AND', 'OR', 'NOT'].each do |reserved| + escaped_reserved = reserved.split('').map { |c| "\\#{c}" }.join('') + sanitized_id = sanitized_id.gsub('/\s*\b(#{reserved.upcase})\b\s*/', + " #{escaped_reserved} ") + end + @sub_search_definition = Elasticsearch::DSL::Search.search do + query do + query_string do + query "*" + sanitized_id + "*" + fields ["reference"] + end + end + + sort do + by :published_at, order: 'asc' + by :reference, order: 'asc' + end + end + @sub_papers = Paper.search(@sub_search_definition) + @sub[paper.reference] = @sub_papers + end + end @paper_type_facets = extract_facets('paper_types') @originator_facets = extract_facets('originators') end diff --git a/app/models/paper.rb b/app/models/paper.rb index 77ab1d3..e36b744 100644 --- a/app/models/paper.rb +++ b/app/models/paper.rb @@ -26,6 +26,7 @@ class Paper < ActiveRecord::Base indexes :name, type: :string, analyzer: "german" indexes :content, type: :string, analyzer: "german" indexes :resolution, type: :string, analyzer: "german" + indexes :reference, type: :string, index: :not_analyzed indexes :paper_type, type: :string, index: :not_analyzed indexes :published_at, type: :date, index: :not_analyzed indexes :originator, type: :string, index: :not_analyzed diff --git a/app/views/search/index.html.slim b/app/views/search/index.html.slim index 42bb61d..41bd921 100644 --- a/app/views/search/index.html.slim +++ b/app/views/search/index.html.slim @@ -5,8 +5,6 @@ div - if params[:q].present? .left | #{@papers.total} Treffer - .right - / button.button. TODO: Suche Abbonieren - else | #{pluralize(@papers.total, "Dokument", "Dokumente")} in der Datenbank div @@ -14,14 +12,13 @@ div - @papers.each do |doc| li.search-result article - h4 = link_to doc.name, doc.url, target: '_blank' - div.metainfo - span.paper_type = doc.paper_type - ' - span.originator = doc.originator - ' - span.published = l doc.published_at.to_date - /! score: #{doc._score} + h4 = doc.name + - if @sub[doc.reference] + ul + - @sub[doc.reference].each do |sub| + li class="#{'current' if sub.reference == doc.reference}" + div = link_to "#{l sub.published_at.to_date}: #{sub.paper_type} von #{sub.originator.join(", ")}", sub.url, target: '_blank' + div#pagination = paginate @papers diff --git a/spec/features/basic_search_spec.rb b/spec/features/basic_search_spec.rb index af46c9a..a78aba2 100644 --- a/spec/features/basic_search_spec.rb +++ b/spec/features/basic_search_spec.rb @@ -1,4 +1,5 @@ require 'rails_helper' +require 'pp' RSpec.feature "Basic search", type: :feature, elasticsearch: true do @@ -46,11 +47,19 @@ RSpec.feature "Basic search", type: :feature, elasticsearch: true do scenario "Search results have basic information" do visit search_path body: "leipzig" paper = @papers.first - result = page.find("li.search-result", match: :first) - expect(result).to have_link(paper.name, href: paper.url) - expect(result).to have_css("span.paper_type", text: paper.paper_type) - expect(result).to have_css("span.originator", text: paper.originator) - expect(result).to have_css("span.published", text: I18n.l(paper.published_at.to_date)) + resultEntry = page.find("li.search-result", match: :first) + expect(resultEntry).to have_content(paper.name) + + resultSubEntry = resultEntry.find("li.current", match: :first) + linkName = getLinkName(paper) + expect(resultSubEntry).to have_link(linkName, href: paper.url) + end + + def getLinkName(paper) + dateStr = I18n.l(paper.published_at.to_date) + originatorStr = (paper.originator.kind_of?(Array) ? + paper.originator.join(", ") : paper.originator) + return "#{dateStr}: #{paper.paper_type} von #{originatorStr}" end scenario "Finds papers by name" do @@ -58,8 +67,12 @@ RSpec.feature "Basic search", type: :feature, elasticsearch: true do Paper.__elasticsearch__.refresh_index! visit search_path body: "leipzig", paper_search: {query: "Opendata"} expect(page).to have_content("1 Dokument in der Datenbank") - result = page.find("li.search-result", match: :first) - expect(result).to have_link(paper.name, href: paper.url) + resultEntry = page.find("li.search-result", match: :first) + expect(resultEntry).to have_content(paper.name) + + resultSubEntry = resultEntry.find("li.current", match: :first) + linkName = getLinkName(paper) + expect(resultSubEntry).to have_link(linkName, href: paper.url) end scenario "Finds papers by content" do @@ -70,8 +83,50 @@ RSpec.feature "Basic search", type: :feature, elasticsearch: true do Paper.__elasticsearch__.refresh_index! visit search_path body: "leipzig", paper_search: {query: "Verwaltungsdokumente"} expect(page).to have_content("1 Dokument in der Datenbank") - result = page.find("li.search-result", match: :first) - expect(result).to have_link(paper.name, href: paper.url) + resultEntry = page.find("li.search-result", match: :first) + expect(resultEntry).to have_content(paper.name) + + resultSubEntry = resultEntry.find("li.current", match: :first) + linkName = getLinkName(paper) + expect(resultSubEntry).to have_link(linkName, href: paper.url) end + scenario "Papers with common reference id in search result ordered by date" do + mainPaper = FactoryGirl.create(:paper, published_at: '2016-12-19T19:00:00', + name: "Opendata als default", reference: "VI-0815") + newPaper = FactoryGirl.create(:paper, published_at: '2016-12-23T12:00:00', + name: "Opendata als optional", reference: "VI-0815-ÄA-01") + Paper.__elasticsearch__.refresh_index! + visit search_path body: "leipzig", paper_search: {query: "default"} + expect(page).to have_content("1 Dokument in der Datenbank") + resultEntry = page.find("li.search-result", match: :first) + expect(resultEntry).to have_content(mainPaper.name) + + resultSubEntry1 = resultEntry.find("li.current", match: :first) + linkName1 = getLinkName(mainPaper) + expect(resultSubEntry1).to have_link(linkName1, href: mainPaper.url) + + resultSubEntries = resultEntry.find("ul").all("li") + linkName2 = getLinkName(newPaper) + expect(resultSubEntries[1]).to have_link(linkName2, href: newPaper.url) + end + + scenario "Papers with common reference id in search result ordered by ref" do + mainPaper = FactoryGirl.create(:paper, published_at: '2016-12-19T19:00:00', + name: "Opendata als default", reference: "VI-0815") + newPaper1 = FactoryGirl.create(:paper, published_at: '2016-12-23T12:00:00', + name: "Opendata als optional", reference: "VI-0815-ÄA-02") + newPaper2 = FactoryGirl.create(:paper, published_at: '2016-12-23T12:00:00', + name: "Opendata als optional", reference: "VI-0815-ÄA-01") + Paper.__elasticsearch__.refresh_index! + visit search_path body: "leipzig", paper_search: {query: "default"} + expect(page).to have_content("1 Dokument in der Datenbank") + resultEntry = page.find("li.search-result", match: :first) + + resultSubEntries = resultEntry.find("ul").all("li") + linkName1 = getLinkName(newPaper1) + expect(resultSubEntries[2]).to have_link(linkName1, href: newPaper1.url) + linkName2 = getLinkName(newPaper2) + expect(resultSubEntries[1]).to have_link(linkName2, href: newPaper2.url) + end end