birds 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +663 -0
- data/ChangeLog +7 -0
- data/README +41 -0
- data/Rakefile +46 -0
- data/config.ru.sample +4 -0
- data/lib/birds/app/controllers.rb +115 -0
- data/lib/birds/app/helpers/controller.rb +110 -0
- data/lib/birds/app/helpers/view.rb +131 -0
- data/lib/birds/app/helpers.rb +31 -0
- data/lib/birds/app/public/favicon.ico +0 -0
- data/lib/birds/app/settings.rb +86 -0
- data/lib/birds/app/views/_documents.erb +13 -0
- data/lib/birds/app/views/_facets.erb +30 -0
- data/lib/birds/app/views/browse.erb +22 -0
- data/lib/birds/app/views/document.erb +12 -0
- data/lib/birds/app/views/index.erb +64 -0
- data/lib/birds/app/views/layout.erb +83 -0
- data/lib/birds/app/views/scroll.erb +23 -0
- data/lib/birds/app.rb +52 -0
- data/lib/birds/rack_app.rb +2 -0
- data/lib/birds/version.rb +27 -0
- data/lib/birds.rb +67 -0
- metadata +169 -0
data/README
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
= Birds - Bibliographic information retrieval & document search
|
2
|
+
|
3
|
+
== VERSION
|
4
|
+
|
5
|
+
This documentation refers to Birds version 0.0.0
|
6
|
+
|
7
|
+
|
8
|
+
== DESCRIPTION
|
9
|
+
|
10
|
+
Experimental information retrieval system for bibliographic data.
|
11
|
+
|
12
|
+
|
13
|
+
== LINKS
|
14
|
+
|
15
|
+
Demo:: http://ixtrieve.fh-koeln.de/birds/litie
|
16
|
+
Documentation:: https://blackwinter.github.com/birds
|
17
|
+
Source code:: https://github.com/blackwinter/birds
|
18
|
+
RubyGem:: https://rubygems.org/gems/birds
|
19
|
+
|
20
|
+
|
21
|
+
== AUTHORS
|
22
|
+
|
23
|
+
* Jens Wille <mailto:jens.wille@gmail.com>
|
24
|
+
|
25
|
+
|
26
|
+
== LICENSE AND COPYRIGHT
|
27
|
+
|
28
|
+
Copyright (C) 2014-2015 Jens Wille
|
29
|
+
|
30
|
+
Birds is free software: you can redistribute it and/or modify it under the
|
31
|
+
terms of the GNU Affero General Public License as published by the Free
|
32
|
+
Software Foundation, either version 3 of the License, or (at your option)
|
33
|
+
any later version.
|
34
|
+
|
35
|
+
Birds is distributed in the hope that it will be useful, but WITHOUT ANY
|
36
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
37
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
38
|
+
more details.
|
39
|
+
|
40
|
+
You should have received a copy of the GNU Affero General Public License
|
41
|
+
along with Birds. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path(%q{../lib/birds/version}, __FILE__)
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'hen'
|
5
|
+
|
6
|
+
Hen.lay! {{
|
7
|
+
gem: {
|
8
|
+
name: %q{birds},
|
9
|
+
version: Birds::VERSION,
|
10
|
+
summary: %q{Bibliographic information retrieval & document search.},
|
11
|
+
description: %q{Experimental information retrieval system for bibliographic data.},
|
12
|
+
author: %q{Jens Wille},
|
13
|
+
email: %q{jens.wille@gmail.com},
|
14
|
+
license: %q{AGPL-3.0},
|
15
|
+
homepage: :blackwinter,
|
16
|
+
extra_files: FileList['*.sample', 'lib/**/{public,views}/*'].to_a,
|
17
|
+
dependencies: {
|
18
|
+
'sinatra-bells' => ['~> 0.0', '>= 0.0.2'],
|
19
|
+
'solr4r' => ['~> 0.0', '>= 0.0.4'],
|
20
|
+
'unicode' => '~> 0.4'
|
21
|
+
},
|
22
|
+
|
23
|
+
required_ruby_version: '>= 1.9.3'
|
24
|
+
}
|
25
|
+
}}
|
26
|
+
rescue LoadError => err
|
27
|
+
warn "Please install the `hen' gem. (#{err})"
|
28
|
+
end
|
29
|
+
|
30
|
+
task c: :_ do
|
31
|
+
require 'irb'; IRB.start
|
32
|
+
end
|
33
|
+
|
34
|
+
task r: :_ do
|
35
|
+
load Gem.bin_path('rack', 'rackup')
|
36
|
+
end
|
37
|
+
|
38
|
+
task :_ do
|
39
|
+
ARGV.clear
|
40
|
+
|
41
|
+
b = File.expand_path('~/devel') # XXX
|
42
|
+
$:.unshift(*%w[birds solr4r sinatra-bells].map { |i| File.join(b, i, 'lib') })
|
43
|
+
|
44
|
+
require 'birds'
|
45
|
+
require 'birds/app'
|
46
|
+
end
|
data/config.ru.sample
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# Birds -- Bibliographic information retrieval & document search #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014-2015 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Birds is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# Birds is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with Birds. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'unicode'
|
27
|
+
|
28
|
+
class Birds::App
|
29
|
+
|
30
|
+
get '/', render: :index do
|
31
|
+
result = settings.solr.count
|
32
|
+
@page_title, @page_title_extra = 'Home', "#{result.to_i} documents"
|
33
|
+
end
|
34
|
+
|
35
|
+
get '/search', render: :index do
|
36
|
+
@page_title = 'Search'
|
37
|
+
|
38
|
+
@query, @filter = params[:q] || params[:qq], Array(params[:fq])
|
39
|
+
|
40
|
+
paginate_query(@query, :results,
|
41
|
+
facet_params(debug: 'results', fq: @filter))
|
42
|
+
|
43
|
+
@explain, @facets = explain_result(@result), facet_counts(@result)
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/browse', render: :browse do
|
47
|
+
@page_title, @fields = 'Browse', settings.browse_fields
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/browse/:field', render: :browse do
|
51
|
+
@page_title, @field = 'Browse', params[:field]
|
52
|
+
bad_request unless labels = settings.browse_fields[@field]
|
53
|
+
|
54
|
+
@hierarchy, @page_title_extra = terms, labels.last
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/browse/:field/*', render: :browse do
|
58
|
+
@page_title, @field = 'Browse', params[:field]
|
59
|
+
bad_request unless labels = settings.browse_fields[@field]
|
60
|
+
|
61
|
+
category = params[:splat].join('/')
|
62
|
+
bad_request if category.empty?
|
63
|
+
|
64
|
+
@page_title_extra = "#{labels.first}: #{category}"
|
65
|
+
|
66
|
+
@result = search_query(@field => category)
|
67
|
+
not_found if @result.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
get '/scroll', render: :scroll do
|
71
|
+
@page_title, @fields = 'Scroll', settings.scroll_fields
|
72
|
+
end
|
73
|
+
|
74
|
+
get '/scroll/:field', render: :scroll do
|
75
|
+
@page_title, @field = 'Scroll', params[:field]
|
76
|
+
bad_request unless label = settings.scroll_fields[@field]
|
77
|
+
|
78
|
+
@letters = terms.group_by { |term,|
|
79
|
+
Unicode.upcase(term[0])
|
80
|
+
}.map { |letter, values|
|
81
|
+
[letter, values.map(&:last).inject(:+)] if letter =~ /\p{Letter}/
|
82
|
+
}.compact
|
83
|
+
|
84
|
+
@page_title_extra = label
|
85
|
+
end
|
86
|
+
|
87
|
+
get '/scroll/:field/:letter', render: :scroll do
|
88
|
+
@page_title, @field = 'Scroll', params[:field]
|
89
|
+
bad_request unless label = settings.scroll_fields[@field]
|
90
|
+
|
91
|
+
@letter = params[:letter]
|
92
|
+
paginate_query({ @field => "#{@letter}*" }, :documents)
|
93
|
+
|
94
|
+
@page_title_extra = "#{label}: #{@letter}"
|
95
|
+
end
|
96
|
+
|
97
|
+
get '/document/*', render: :document do
|
98
|
+
id = params[:splat].join('/')
|
99
|
+
|
100
|
+
bad_request if id.empty?
|
101
|
+
not_found unless @document = search_document(id)
|
102
|
+
|
103
|
+
@similar = @document.more_like_this(settings.mlt_fields,
|
104
|
+
debugQuery: true, mlt: { boost: true, mintf: 1, minwl: 4 })
|
105
|
+
|
106
|
+
@explain = explain_result(@similar)
|
107
|
+
|
108
|
+
@page_title, @page_title_extra = 'Document', "##{id}"
|
109
|
+
end
|
110
|
+
|
111
|
+
get 'schema.xml' do
|
112
|
+
erb :schema
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# Birds -- Bibliographic information retrieval & document search #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014-2015 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Birds is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# Birds is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with Birds. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
class Birds::App
|
27
|
+
|
28
|
+
module Helpers
|
29
|
+
|
30
|
+
module Controller
|
31
|
+
|
32
|
+
def search(params)
|
33
|
+
settings.solr.json_query(params)
|
34
|
+
end
|
35
|
+
|
36
|
+
def search_query(query, params = {})
|
37
|
+
search(params.merge(q: query, fl: '*,score', defType: 'edismax'))
|
38
|
+
end
|
39
|
+
|
40
|
+
def search_document(id)
|
41
|
+
search(q: { id: id }).first
|
42
|
+
end
|
43
|
+
|
44
|
+
def paginate_query(query, what, query_params = {}, per_page = 20)
|
45
|
+
return unless query
|
46
|
+
|
47
|
+
page = params[:page].to_i
|
48
|
+
page = 1 if page < 1
|
49
|
+
|
50
|
+
@prev_page, @next_page = page - 1, page + 1
|
51
|
+
|
52
|
+
@result = search_query(query, query_params.merge(
|
53
|
+
rows: per_page, start: @offset = @prev_page * per_page))
|
54
|
+
|
55
|
+
@page_title_extra = '%d %s, page %d of %d' % [
|
56
|
+
@result, what, page, @total_pages = (@result.to_i / per_page.to_f).ceil]
|
57
|
+
|
58
|
+
@prev_page = nil if @prev_page < 1
|
59
|
+
@next_page = nil if @next_page > @total_pages
|
60
|
+
end
|
61
|
+
|
62
|
+
def facet_params(params = {})
|
63
|
+
params.merge(f: f = params[:f] || {}, facet: {
|
64
|
+
field: fields = [], range: ranges = [], mincount: 1
|
65
|
+
}).tap { settings.facet_fields.each { |facet, (_, options)|
|
66
|
+
options.nil? ? fields << facet : begin ranges << facet
|
67
|
+
((f[facet] ||= {})[:facet] ||= {})[:range] = options
|
68
|
+
end
|
69
|
+
} }
|
70
|
+
end
|
71
|
+
|
72
|
+
def terms(f = @field)
|
73
|
+
settings.solr.json('terms', terms: { fl: f, limit: -1 }).to_h[f].sort
|
74
|
+
end
|
75
|
+
|
76
|
+
def explain_result(result)
|
77
|
+
result % %w[debug explain] if result
|
78
|
+
end
|
79
|
+
|
80
|
+
def facet_counts(result)
|
81
|
+
return {} unless result && result.to_i > 1
|
82
|
+
|
83
|
+
exclude, prepare = [@query, *@filter], lambda { |facet_hash, &block|
|
84
|
+
facet_hash.delete_if { |key, hash|
|
85
|
+
gap = block[hash] if block
|
86
|
+
|
87
|
+
hash.delete_if { |term,|
|
88
|
+
exclude.include?(facet_query(key, term, *gap)) }.size < 2
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
prepare.(result.facet_fields.to_h).merge(
|
93
|
+
prepare.(result.facet_ranges.to_h) { |hash|
|
94
|
+
counts, before, start, gap = hash
|
95
|
+
.values_at(*%w[counts before start gap])
|
96
|
+
|
97
|
+
hash.clear
|
98
|
+
hash[-start] = before if before > 1
|
99
|
+
counts.each { |value, count| hash[value.to_i] = count }
|
100
|
+
|
101
|
+
hash.singleton_class.send(:define_method, :gap) { gap }
|
102
|
+
gap
|
103
|
+
})
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# Birds -- Bibliographic information retrieval & document search #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014-2015 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Birds is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# Birds is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with Birds. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
class Birds::App
|
27
|
+
|
28
|
+
module Helpers
|
29
|
+
|
30
|
+
module View
|
31
|
+
|
32
|
+
def nav_item(path, name, title = nil)
|
33
|
+
li_(link_to(name, path, title: title), class: active?(path))
|
34
|
+
end
|
35
|
+
|
36
|
+
def link_to_document(document)
|
37
|
+
label = format_label(settings.document_label, document)
|
38
|
+
link_to(h(label), :document, document['id'])
|
39
|
+
end
|
40
|
+
|
41
|
+
def link_to_search(text, query, *filters)
|
42
|
+
options = filters.last.is_a?(Hash) ? filters.pop : {}
|
43
|
+
|
44
|
+
link_to(text, :search, options.merge(params:
|
45
|
+
query ? query_params(query, filters) : { q: filters.first }))
|
46
|
+
end
|
47
|
+
|
48
|
+
def link_to_filter(text, query, filter)
|
49
|
+
link_to_search(h(text), query, filter, *@filter)
|
50
|
+
end
|
51
|
+
|
52
|
+
def link_to_field(field, value, query = nil)
|
53
|
+
link_to_filter(value, query, field_query(field, value))
|
54
|
+
end
|
55
|
+
|
56
|
+
def link_to_facet(field, value, gap = nil)
|
57
|
+
link_to_filter(
|
58
|
+
gap ? range_label(value, gap) : value,
|
59
|
+
@query, facet_query(field, value, gap))
|
60
|
+
end
|
61
|
+
|
62
|
+
def facet_query(field, value, gap = nil)
|
63
|
+
gap ? range_query(field, value, gap) : field_query(field, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def field_query(field, value)
|
67
|
+
%Q{#{field}:"#{value}"}
|
68
|
+
end
|
69
|
+
|
70
|
+
def range_query(field, value, gap)
|
71
|
+
value < 0 ?
|
72
|
+
%Q|#{field}:[* TO #{-value}}| :
|
73
|
+
%Q|#{field}:[#{value} TO #{value + gap}}|
|
74
|
+
end
|
75
|
+
|
76
|
+
def range_label(value, gap)
|
77
|
+
value < 0 ? "before #{-value}" : "#{value}–#{value + gap - 1}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def query_params(q = @query, fq = @filter)
|
81
|
+
{ q: q, 'fq[]' => fq }
|
82
|
+
end
|
83
|
+
|
84
|
+
def pagination_for(*args)
|
85
|
+
params = args.last.is_a?(Hash) ? args.pop.reject { |_, v| v.nil? } : {}
|
86
|
+
|
87
|
+
ul_([
|
88
|
+
[@prev_page, :first, 1],
|
89
|
+
[@prev_page, :prev, @prev_page],
|
90
|
+
[@next_page, :next, @next_page],
|
91
|
+
[@next_page, :last, @total_pages]
|
92
|
+
], class: 'pagination') { |condition, type, page|
|
93
|
+
li_(link_to_if(condition, pagination_icon(type),
|
94
|
+
*args, params: params.merge(page: page)),
|
95
|
+
class: disabled?(condition))
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def pagination_icon(type)
|
100
|
+
tag_(:span, glyphicon(*{
|
101
|
+
first: [:fast_backward, 'First page'],
|
102
|
+
prev: [:backward, 'Previous page'],
|
103
|
+
next: [:forward, 'Next page'],
|
104
|
+
last: [:fast_forward, 'Last page']
|
105
|
+
}[type]))
|
106
|
+
end
|
107
|
+
|
108
|
+
def glyphicon(name, title = nil)
|
109
|
+
name = name.to_s.tr('_', '-')
|
110
|
+
tag_(:span, class: "glyphicon glyphicon-#{name}", title: title)
|
111
|
+
end
|
112
|
+
|
113
|
+
def values_for(key, document = @document)
|
114
|
+
Array(document[key = key.to_s]).dup.tap { |values|
|
115
|
+
return if values.empty?
|
116
|
+
|
117
|
+
if settings.browse_fields.include?(key)
|
118
|
+
values.map! { |v| link_to(v = h(v), :browse, key, v) }
|
119
|
+
elsif field = settings.linkable_fields[key]
|
120
|
+
values.map! { |v| link_to_field(field, v) }
|
121
|
+
else
|
122
|
+
values.map!(&method(:h))
|
123
|
+
end
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# Birds -- Bibliographic information retrieval & document search #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014-2015 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Birds is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# Birds is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with Birds. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require_relative 'helpers/controller'
|
27
|
+
require_relative 'helpers/view'
|
28
|
+
|
29
|
+
class Birds::App
|
30
|
+
helpers *Helpers.constants.map { |mod| Helpers.const_get(mod) }
|
31
|
+
end
|
Binary file
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# Birds -- Bibliographic information retrieval & document search #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014-2015 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Birds is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# Birds is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with Birds. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
class Birds::App
|
27
|
+
|
28
|
+
set :site_title,
|
29
|
+
'Birds – Bibliographic information retrieval & document search'
|
30
|
+
|
31
|
+
set :bootstrap_url,
|
32
|
+
'//netdna.bootstrapcdn.com/bootstrap/3.1.1'
|
33
|
+
|
34
|
+
set :solr_client do
|
35
|
+
require 'solr4r'
|
36
|
+
Solr4R::Client
|
37
|
+
end
|
38
|
+
|
39
|
+
solr_opts = Hash[%w[host port path core].map { |key| [key, "solr_#{key}"] }]
|
40
|
+
|
41
|
+
set :solr_opts do
|
42
|
+
Hash[solr_opts.map { |key, opt| [key.to_sym, settings.send(opt)] }]
|
43
|
+
end
|
44
|
+
|
45
|
+
solr_opts.each { |key, opt| set(opt) {
|
46
|
+
settings.solr_client.const_get("DEFAULT_#{key.upcase}") } }
|
47
|
+
|
48
|
+
set :solr do
|
49
|
+
settings.solr_client.new(settings.solr_opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
set_hash :display_fields, %w[
|
53
|
+
title author year abstract language theme subject
|
54
|
+
], %w[_txt] do |f, l| [f, l.capitalize] end
|
55
|
+
|
56
|
+
set_hash :linkable_fields, %w[
|
57
|
+
author theme subject
|
58
|
+
], %w[_txt _ss]
|
59
|
+
|
60
|
+
set_hash :facet_fields, %w[
|
61
|
+
author language theme subject
|
62
|
+
].insert(2,
|
63
|
+
[:year, start: 1900, end: 2100, gap: 10, other: 'before']
|
64
|
+
) do |f, o| ["#{f}_#{o ? :i : :ss}", ["#{f}s".capitalize, o]] end
|
65
|
+
|
66
|
+
set :mlt_fields, %w[
|
67
|
+
author_txt title_txt abstract_txt subject_txt
|
68
|
+
]
|
69
|
+
|
70
|
+
set :browse_fields, {
|
71
|
+
# 'cat' => %w[Category Categories],
|
72
|
+
# 'manu_exact' => %w[Manufacturer Manufacturers]
|
73
|
+
}
|
74
|
+
|
75
|
+
set :scroll_fields, {
|
76
|
+
# 'author_s' => 'Author'
|
77
|
+
}
|
78
|
+
|
79
|
+
set :sample_queries, {
|
80
|
+
'Sample query 1' => 'author_txt:fugmann',
|
81
|
+
'Sample query 2' => 'fugmann -author_txt:fugmann'
|
82
|
+
}
|
83
|
+
|
84
|
+
set :document_label, '{author_ss:%s: }{title_ss( : )}{year_ss: (%s)}'
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<ol start="<%= defined?(start) && start || 1 %>" style="margin-top: 1em"><!-- XXX -->
|
2
|
+
<% for document in documents; id, score = document['id'], h('%.2f' % document['score']); next if @document && id == @document['id'] %>
|
3
|
+
<li>
|
4
|
+
<%= link_to_document(document) %>
|
5
|
+
<% unless defined?(explain) && explain %>
|
6
|
+
<span class="badge"><%= score %></span>
|
7
|
+
<% else; eid = h("explain-#{id}") %>
|
8
|
+
<span class="badge toggle-explain" data-toggle="collapse" data-target="#<%= eid %>" title="Toggle score explanation"><%= score %></span>
|
9
|
+
<pre id="<%= eid %>" class="collapse small"><%=h explain[id] %></pre>
|
10
|
+
<% end %>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
13
|
+
</ol>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% position = 0; for facet, (label, _) in settings.facet_fields; counts = @facets[facet] or next; collapse = max = nil %>
|
2
|
+
<div class="panel panel-default">
|
3
|
+
<div class="panel-heading">
|
4
|
+
<h4 class="panel-title toggle-facet" data-toggle="collapse" data-target="#<%= fid = "facet-#{h(facet)}" %>" title="Toggle facet list"><%=h label %></h4>
|
5
|
+
</div>
|
6
|
+
<ul class="list-group compact-list-group collapse<%= ' in' if (position += 1) < 4 %>" id="<%= fid %>">
|
7
|
+
<% if counts.respond_to?(:gap) %>
|
8
|
+
<% for (value, count), index in counts.reverse_each.with_index %>
|
9
|
+
<li class="list-group-item clearfix<%= ' facet-collapse collapse' if collapse ||= index > 2 %>">
|
10
|
+
<%= link_to_facet(facet, value, counts.gap) %>
|
11
|
+
<span class="badge"><%= count %></span>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
<% else %>
|
15
|
+
<% for (value, count), index in counts.each_with_index; max ||= count %>
|
16
|
+
<li class="list-group-item clearfix<%= ' facet-collapse collapse' if collapse ||= index > 5 || count < max / 10 %>">
|
17
|
+
<%= link_to_facet(facet, value) %>
|
18
|
+
<span class="badge"><%= count %></span>
|
19
|
+
</li>
|
20
|
+
<% end %>
|
21
|
+
<% end %>
|
22
|
+
<% if collapse %>
|
23
|
+
<li class="list-group-item toggle-facet" data-toggle="collapse" data-target="#<%= fid %> .facet-collapse.collapse">
|
24
|
+
<span class="facet-collapse collapse in">More…</span>
|
25
|
+
<span class="facet-collapse collapse">Less…</span>
|
26
|
+
</li>
|
27
|
+
<% end %>
|
28
|
+
</ul>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% if @result %>
|
2
|
+
<ol>
|
3
|
+
<% for document in @result %>
|
4
|
+
<li><%= link_to_document(document) %></li>
|
5
|
+
<% end %>
|
6
|
+
</ol>
|
7
|
+
<% elsif @fields %>
|
8
|
+
<ul>
|
9
|
+
<% for field, labels in @fields %>
|
10
|
+
<li><%= link_to(h(labels.last), :browse, field) %></li>
|
11
|
+
<% end %>
|
12
|
+
</ul>
|
13
|
+
<% else %>
|
14
|
+
<ul>
|
15
|
+
<% for category, count in @hierarchy %>
|
16
|
+
<li>
|
17
|
+
<%= link_to(h(category), :browse, @field, category) %>
|
18
|
+
<span class="badge"><%=h count %></span>
|
19
|
+
</li>
|
20
|
+
<% end %>
|
21
|
+
</ul>
|
22
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<dl class="dl-horizontal">
|
2
|
+
<% for key, label in settings.display_fields; values = values_for(key) or next %>
|
3
|
+
<dt class="text-muted" title="<%=h key %>:"><%=h label || key %></dt>
|
4
|
+
<dd><%= values.join('<br />') %></dd>
|
5
|
+
<% end %>
|
6
|
+
</dl>
|
7
|
+
|
8
|
+
<% unless @similar.empty? %>
|
9
|
+
<h2>Similar documents</h2>
|
10
|
+
|
11
|
+
<%= erb :_documents, locals: { documents: @similar, explain: @explain } %>
|
12
|
+
<% end %>
|