europeana-blacklight 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-style.yml +2 -1
- data/QUICKSTART.md +42 -0
- data/README.md +31 -52
- data/app/controllers/concerns/europeana/blacklight/catalog.rb +73 -0
- data/europeana-blacklight.gemspec +4 -1
- data/lib/europeana/blacklight.rb +8 -2
- data/lib/europeana/blacklight/api_repository.rb +9 -64
- data/lib/europeana/blacklight/document.rb +15 -20
- data/lib/europeana/blacklight/document/relations.rb +25 -0
- data/lib/europeana/blacklight/document_presenter.rb +1 -1
- data/lib/europeana/blacklight/engine.rb +11 -0
- data/lib/europeana/blacklight/facet_paginator.rb +1 -1
- data/lib/europeana/blacklight/response/pagination.rb +10 -0
- data/lib/europeana/blacklight/routes.rb +26 -0
- data/lib/europeana/blacklight/search_builder.rb +42 -11
- data/lib/europeana/blacklight/search_builder/overlay_params.rb +39 -0
- data/lib/europeana/blacklight/search_builder/ranges.rb +1 -1
- data/lib/europeana/blacklight/search_helper.rb +41 -0
- data/lib/europeana/blacklight/version.rb +1 -1
- data/lib/generators/europeana/blacklight/install_generator.rb +28 -0
- data/lib/generators/europeana/blacklight/templates/catalog_controller.rb +81 -0
- data/lib/generators/europeana/blacklight/templates/config/blacklight.yml +8 -0
- metadata +61 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78442f9dbd68b04249c1bb5d6e0820ef4f75d925
|
4
|
+
data.tar.gz: bfcb4792d1cc6412a5551b76f67706f4b8aa7a6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e0cde651009ecd7b881c0f34edc745d2b431a9f4664cf168c9f436521f664b4f08e127d1e5d4efcfa3721bac065a36ea05dd313ad31dd58fd6d0079b9aca9e8
|
7
|
+
data.tar.gz: c88b697f78b65c586ac09b377e4b166b9c028de0284fc8c22ca7600c202434a069890b70e3cedcbdb57b5a9373285641beb06812860a32d7dea649febc07ab5c
|
data/.ruby-style.yml
CHANGED
@@ -6,6 +6,7 @@ AllCops:
|
|
6
6
|
Exclude:
|
7
7
|
- "vendor/**/*"
|
8
8
|
- "db/**/*"
|
9
|
+
- "lib/generators/europeana/blacklight/templates/**/*"
|
9
10
|
RunRailsCops: true
|
10
11
|
DisplayCopNames: false
|
11
12
|
StyleGuideCopsOnly: false
|
@@ -497,7 +498,7 @@ Metrics/LineLength:
|
|
497
498
|
Description: Limit lines to 80 characters.
|
498
499
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#80-character-limits
|
499
500
|
Enabled: true
|
500
|
-
Max:
|
501
|
+
Max: 140
|
501
502
|
AllowURI: true
|
502
503
|
URISchemes:
|
503
504
|
- http
|
data/QUICKSTART.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Europeana Blacklight Quick Start Guide
|
2
|
+
|
3
|
+
## Install Rails 4
|
4
|
+
```
|
5
|
+
gem install rails
|
6
|
+
rails -v
|
7
|
+
# Rails 4.2.4
|
8
|
+
```
|
9
|
+
|
10
|
+
## Create a new Rails application
|
11
|
+
```
|
12
|
+
rails new culture_vulture
|
13
|
+
cd culture_vulture
|
14
|
+
```
|
15
|
+
|
16
|
+
## Bundle europeana-blacklight
|
17
|
+
Add to the Gemfile:
|
18
|
+
```ruby
|
19
|
+
gem 'europeana-blacklight',
|
20
|
+
github: 'europeana/europeana-blacklight',
|
21
|
+
require: 'europeana/blacklight'
|
22
|
+
```
|
23
|
+
|
24
|
+
## Get a Europeana API key
|
25
|
+
From http://labs.europeana.eu/api/
|
26
|
+
|
27
|
+
## Install Blacklight with the Europeana API adapter
|
28
|
+
```
|
29
|
+
bundle install
|
30
|
+
bundle exec rails generate blacklight:install --devise
|
31
|
+
bundle exec rails generate europeana:blacklight:install YOUR_API_KEY
|
32
|
+
bundle exec rake db:migrate
|
33
|
+
```
|
34
|
+
|
35
|
+
## Customise the config
|
36
|
+
Review the generated `CatalogController` and adjust the default configuration
|
37
|
+
to your preferences.
|
38
|
+
|
39
|
+
## Start the application
|
40
|
+
```
|
41
|
+
bundle exec rails server
|
42
|
+
```
|
data/README.md
CHANGED
@@ -1,62 +1,40 @@
|
|
1
1
|
# Europeana::Blacklight
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/europeana/europeana-blacklight.svg?branch=master)](https://travis-ci.org/europeana/europeana-blacklight) [![Coverage Status](https://coveralls.io/repos/europeana/europeana-blacklight/badge.svg?branch=master&service=github)](https://coveralls.io/github/europeana/europeana-blacklight?branch=master) [![security](https://hakiri.io/github/europeana/europeana-blacklight/master.svg)](https://hakiri.io/github/europeana/europeana-blacklight/master)
|
3
|
+
[![Build Status](https://travis-ci.org/europeana/europeana-blacklight.svg?branch=master)](https://travis-ci.org/europeana/europeana-blacklight) [![Coverage Status](https://coveralls.io/repos/europeana/europeana-blacklight/badge.svg?branch=master&service=github)](https://coveralls.io/github/europeana/europeana-blacklight?branch=master) [![security](https://hakiri.io/github/europeana/europeana-blacklight/master.svg)](https://hakiri.io/github/europeana/europeana-blacklight/master) [![Dependency Status](https://gemnasium.com/europeana/europeana-blacklight.svg)](https://gemnasium.com/europeana/europeana-blacklight)
|
4
4
|
|
5
5
|
Ruby gem providing an adapter to use the
|
6
6
|
[Europeana REST API](http://labs.europeana.eu/api/introduction/) as a data
|
7
7
|
source for [Blacklight](http://projectblacklight.org/).
|
8
8
|
|
9
|
-
##
|
9
|
+
## Usage
|
10
10
|
|
11
|
-
|
11
|
+
See the [Quick Start Guide](QUICKSTART.md).
|
12
12
|
|
13
|
-
|
14
|
-
gem 'europeana-blacklight',
|
15
|
-
github: 'europeana/europeana-blacklight',
|
16
|
-
require: 'europeana/blacklight'
|
17
|
-
```
|
13
|
+
## Features
|
18
14
|
|
19
|
-
|
15
|
+
### Supported Blacklight features
|
20
16
|
|
21
|
-
|
17
|
+
* Search
|
18
|
+
* View record
|
19
|
+
* Pagination of search results
|
20
|
+
* Field facets
|
21
|
+
* [Query facets](#query-facets)
|
22
|
+
* Facet limits
|
23
|
+
* Fielded search
|
24
|
+
* Bookmarks
|
25
|
+
* Range queries
|
22
26
|
|
23
|
-
|
27
|
+
### Unsupported Blacklight features
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
```ruby
|
36
|
-
class CatalogController < ApplicationController
|
37
|
-
self.search_params_logic = Europeana::Blacklight::SearchBuilder.default_processor_chain
|
38
|
-
|
39
|
-
configure_blacklight do |config|
|
40
|
-
config.repository_class = Europeana::Blacklight::ApiRepository
|
41
|
-
config.search_builder_class = Europeana::Blacklight::SearchBuilder
|
42
|
-
config.response_model = Europeana::Blacklight::Response
|
43
|
-
config.document_model = Europeana::Blacklight::Document
|
44
|
-
config.document_presenter_class = Europeana::Blacklight::DocumentPresenter
|
45
|
-
config.facet_paginator_class = Europeana::Blacklight::FacetPaginator
|
46
|
-
end
|
47
|
-
end
|
48
|
-
```
|
49
|
-
|
50
|
-
4. Caching (optional)
|
51
|
-
|
52
|
-
To enable caching of API responses:
|
53
|
-
|
54
|
-
```ruby
|
55
|
-
configure_blacklight do |config|
|
56
|
-
config.europeana_api_cache = Rails.cache # or any {ActiveSupport::Cache} instance
|
57
|
-
config.europeana_api_cache_expires_in = 60.minutes # defaults to 24.hours
|
58
|
-
end
|
59
|
-
```
|
29
|
+
* Result sorting :(
|
30
|
+
* "Did you mean" spellcheck
|
31
|
+
* MLT Solr-style (but see custom features)
|
32
|
+
|
33
|
+
### Custom features
|
34
|
+
|
35
|
+
* Nested EDM field names
|
36
|
+
* MLT by record ID in :mlt URL parameter
|
37
|
+
* Query facets with arbitrary API parameters
|
60
38
|
|
61
39
|
## Query facets
|
62
40
|
|
@@ -65,13 +43,14 @@ permit specification of multiple parameters to be passed to the API:
|
|
65
43
|
|
66
44
|
```ruby
|
67
45
|
configure_blacklight do |config|
|
68
|
-
config.add_facet_field 'Cities (reusable content)', query:
|
69
|
-
{ label: 'Paris', fq: { qf: 'paris', reusability: 'open' } },
|
70
|
-
{ label: 'Berlin', fq: { qf: 'berlin', reusability: 'open' } }
|
71
|
-
|
46
|
+
config.add_facet_field 'Cities (reusable content)', query: {
|
47
|
+
paris: { label: 'Paris', fq: { qf: 'paris', reusability: 'open' } },
|
48
|
+
berlin: { label: 'Berlin', fq: { qf: 'berlin', reusability: 'open' } }
|
49
|
+
}
|
72
50
|
end
|
73
51
|
```
|
74
52
|
|
75
53
|
*Warning:* query facets are achieved by sending additional queries to the
|
76
|
-
API. If you configure
|
77
|
-
|
54
|
+
API. If you configure 2 query facets each with 10 facet values, this will result
|
55
|
+
in an additional 20 queries being sent to the API.
|
56
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Blacklight
|
3
|
+
module Catalog
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
include ::Blacklight::Catalog
|
7
|
+
include Europeana::Blacklight::SearchHelper
|
8
|
+
|
9
|
+
included do
|
10
|
+
self.search_params_logic = Europeana::Blacklight::SearchBuilder.default_processor_chain
|
11
|
+
|
12
|
+
configure_blacklight do |config|
|
13
|
+
# Adapter classes
|
14
|
+
config.repository_class = Europeana::Blacklight::ApiRepository
|
15
|
+
config.search_builder_class = Europeana::Blacklight::SearchBuilder
|
16
|
+
config.response_model = Europeana::Blacklight::Response
|
17
|
+
config.document_model = Europeana::Blacklight::Document
|
18
|
+
config.document_presenter_class = Europeana::Blacklight::DocumentPresenter
|
19
|
+
# config.facet_paginator_class = Europeana::Blacklight::FacetPaginator
|
20
|
+
|
21
|
+
# Prevent BL's "did you mean" spellcheck feature kicking in
|
22
|
+
config.spell_max = -1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Empty search returns all records
|
27
|
+
def has_search_parameters?
|
28
|
+
super || params.key?(:q) || params.key?(:mlt)
|
29
|
+
end
|
30
|
+
|
31
|
+
def search_results(user_params, _search_params_logic)
|
32
|
+
super.tap do |results|
|
33
|
+
if has_search_parameters?
|
34
|
+
results.first[:facet_queries] = europeana_api_query_facet_counts(user_params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def blacklight_query_facets
|
42
|
+
blacklight_config.facet_fields.select do |_, facet|
|
43
|
+
facet.query &&
|
44
|
+
(facet.include_in_request ||
|
45
|
+
(facet.include_in_request.nil? &&
|
46
|
+
blacklight_config.add_facet_fields_to_solr_request))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def europeana_api_query_facet_counts(user_params)
|
51
|
+
qf_counts = []
|
52
|
+
|
53
|
+
blacklight_query_facets.each_pair do |_facet_name, query_facet|
|
54
|
+
query_facet.query.each_pair do |_field_name, query_field|
|
55
|
+
count = europeana_api_query_facet_count(query_field[:fq], user_params)
|
56
|
+
qf_counts.push([query_field[:fq], count])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
qf_counts.sort_by(&:last).reverse.each_with_object({}) do |qf, hash|
|
61
|
+
hash[qf.first] = qf.last
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def europeana_api_query_facet_count(query_field_fq, user_params)
|
66
|
+
query = search_builder_class.new(search_params_logic, self).
|
67
|
+
with(user_params).with_overlay_params(query_field_fq || {}).query.
|
68
|
+
merge(rows: 0, start: 1, profile: 'minimal')
|
69
|
+
repository.search(query).total
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -20,12 +20,15 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.required_ruby_version = '>= 2.0.0'
|
22
22
|
|
23
|
+
spec.add_dependency 'activesupport', '>= 4.0', '< 5.0'
|
23
24
|
spec.add_dependency 'blacklight', '>= 5.12.0', '< 6.0.0'
|
24
|
-
spec.add_dependency 'europeana-api', '~> 0.
|
25
|
+
spec.add_dependency 'europeana-api', '~> 0.4.0'
|
25
26
|
spec.add_dependency 'iso-639', '~> 0.2.5'
|
26
27
|
spec.add_dependency 'kaminari', '~> 0.16'
|
27
28
|
|
28
29
|
spec.add_development_dependency 'bundler', '~> 1.8'
|
29
30
|
spec.add_development_dependency 'rake', '~> 10.0'
|
30
31
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
32
|
+
spec.add_development_dependency 'shoulda-matchers', '~> 2.8'
|
33
|
+
spec.add_development_dependency 'webmock', '~> 1.21'
|
31
34
|
end
|
data/lib/europeana/blacklight.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
3
3
|
require 'blacklight'
|
4
|
+
require 'europeana/api'
|
5
|
+
require 'europeana/blacklight/engine' if defined?(Rails)
|
6
|
+
require 'europeana/blacklight/version'
|
4
7
|
|
5
8
|
module Europeana
|
6
9
|
##
|
@@ -9,7 +12,10 @@ module Europeana
|
|
9
12
|
autoload :ApiRepository, 'europeana/blacklight/api_repository'
|
10
13
|
autoload :Document, 'europeana/blacklight/document'
|
11
14
|
autoload :DocumentPresenter, 'europeana/blacklight/document_presenter'
|
15
|
+
# autoload :FacetPaginator, 'europeana/blacklight/facet_paginator'
|
12
16
|
autoload :Response, 'europeana/blacklight/response'
|
17
|
+
autoload :Routes, 'europeana/blacklight/routes'
|
13
18
|
autoload :SearchBuilder, 'europeana/blacklight/search_builder'
|
19
|
+
autoload :SearchHelper, 'europeana/blacklight/search_helper'
|
14
20
|
end
|
15
21
|
end
|
@@ -13,11 +13,7 @@ module Europeana
|
|
13
13
|
# @return (see blacklight_config.response_model)
|
14
14
|
def find(id, params = {})
|
15
15
|
id = "/#{id}" unless id[0] == '/'
|
16
|
-
|
17
|
-
cache_key << ':' + params.to_query unless params.blank?
|
18
|
-
res = cached(cache_key) do
|
19
|
-
connection.record(id, auth_params(params))
|
20
|
-
end
|
16
|
+
res = connection.record(id, params)
|
21
17
|
|
22
18
|
blacklight_config.response_model.new(
|
23
19
|
res, params, document_model: blacklight_config.document_model,
|
@@ -26,10 +22,7 @@ module Europeana
|
|
26
22
|
end
|
27
23
|
|
28
24
|
def search(params = {})
|
29
|
-
|
30
|
-
res = cached(cache_key) do
|
31
|
-
connection.search(auth_params(params))
|
32
|
-
end
|
25
|
+
res = connection.search(params)
|
33
26
|
|
34
27
|
blacklight_config.response_model.new(
|
35
28
|
res, params, document_model: blacklight_config.document_model,
|
@@ -37,46 +30,6 @@ module Europeana
|
|
37
30
|
)
|
38
31
|
end
|
39
32
|
|
40
|
-
##
|
41
|
-
# Fetches the hierarchy data for a Europeana record
|
42
|
-
#
|
43
|
-
# If the hierarchy data for the requested record is cached, that will be
|
44
|
-
# returned, otherwise it will be obtained from the Europeana REST API.
|
45
|
-
#
|
46
|
-
# @param id [String] Europeana record ID, with leading slash
|
47
|
-
# @return [Hash] Record's hierarchy data, or false if it has none
|
48
|
-
def fetch_document_hierarchy(id)
|
49
|
-
cached("Europeana:API:Record:hierarchy:#{id}") do
|
50
|
-
begin
|
51
|
-
europeana_api_document_hierarchy(id)
|
52
|
-
rescue Europeana::API::Errors::RequestError => error
|
53
|
-
unless error.message == 'This record has no hierarchical structure!'
|
54
|
-
raise
|
55
|
-
end
|
56
|
-
false
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
##
|
62
|
-
# Requests hierarchy data for a Europeana record from the REST API
|
63
|
-
#
|
64
|
-
# The return value will contain a combination of the responses from the
|
65
|
-
# ancestor-self-siblings and children API endpoints.
|
66
|
-
#
|
67
|
-
# @param id [String] Europeana record ID, with leading slash
|
68
|
-
# @return [Hash] Record's hierarchy data
|
69
|
-
def europeana_api_document_hierarchy(id)
|
70
|
-
record = Europeana::API::Record.new(id, auth_params)
|
71
|
-
hierarchy = record.hierarchy('ancestor-self-siblings')
|
72
|
-
|
73
|
-
if hierarchy['self']['hasChildren']
|
74
|
-
hierarchy = record.hierarchy('ancestor-self-siblings', :children)
|
75
|
-
end
|
76
|
-
|
77
|
-
hierarchy
|
78
|
-
end
|
79
|
-
|
80
33
|
##
|
81
34
|
# Queries the API for items similar to a given document
|
82
35
|
def more_like_this(doc, field = nil, params = {})
|
@@ -88,19 +41,17 @@ module Europeana
|
|
88
41
|
end
|
89
42
|
|
90
43
|
def build_connection
|
91
|
-
Europeana::API
|
44
|
+
Europeana::API.tap do |api|
|
45
|
+
api.api_key = blacklight_config.connection_config[:europeana_api_key]
|
46
|
+
api.cache_store = cache_store
|
47
|
+
api.cache_expires_in = cache_expires_in
|
48
|
+
end
|
92
49
|
end
|
93
50
|
|
94
51
|
protected
|
95
52
|
|
96
|
-
def
|
97
|
-
|
98
|
-
wskey: blacklight_config.connection_config[:europeana_api_key]
|
99
|
-
}.merge(params)
|
100
|
-
end
|
101
|
-
|
102
|
-
def cache
|
103
|
-
@cache ||= begin
|
53
|
+
def cache_store
|
54
|
+
@cache_store ||= begin
|
104
55
|
blacklight_config.europeana_api_cache || ActiveSupport::Cache::NullStore.new
|
105
56
|
end
|
106
57
|
end
|
@@ -110,12 +61,6 @@ module Europeana
|
|
110
61
|
blacklight_config.europeana_api_cache_expires_in || 24.hours
|
111
62
|
end
|
112
63
|
end
|
113
|
-
|
114
|
-
def cached(key)
|
115
|
-
cache.fetch(key, expires_in: cache_expires_in) do
|
116
|
-
yield
|
117
|
-
end
|
118
|
-
end
|
119
64
|
end
|
120
65
|
end
|
121
66
|
end
|
@@ -12,11 +12,11 @@ module Europeana
|
|
12
12
|
|
13
13
|
include ActiveModel::Conversion
|
14
14
|
include ::Blacklight::Document
|
15
|
+
include ::Blacklight::Document::ActiveModelShim
|
15
16
|
include MoreLikeThis
|
16
17
|
include Relations
|
17
18
|
|
18
19
|
attr_writer :provider_id, :record_id
|
19
|
-
attr_accessor :hierarchy
|
20
20
|
|
21
21
|
class << self
|
22
22
|
# @todo Are three-letter language codes valid in EDM?
|
@@ -24,7 +24,12 @@ module Europeana
|
|
24
24
|
# output; remove when fixed at source
|
25
25
|
def lang_map?(obj)
|
26
26
|
return false unless obj.is_a?(Hash)
|
27
|
-
obj.keys.all? { |
|
27
|
+
obj.keys.map(&:to_s).all? { |key| known_lang_map_key?(key) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def known_lang_map_key?(key)
|
31
|
+
key = key.dup.downcase
|
32
|
+
['def', '', 'sh'].include?(key) || (!ISO_639.find(key.split('-').first).nil?)
|
28
33
|
end
|
29
34
|
|
30
35
|
def localize_lang_map(lang_map)
|
@@ -49,6 +54,8 @@ module Europeana
|
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
57
|
+
delegate :lang_map?, :localize_lang_map, to: :class
|
58
|
+
|
52
59
|
def initialize(source_doc = {}, response = nil)
|
53
60
|
fields, @relations = extract_relations(source_doc)
|
54
61
|
super(fields, response)
|
@@ -86,11 +93,11 @@ module Europeana
|
|
86
93
|
true
|
87
94
|
end
|
88
95
|
|
89
|
-
def private?(
|
90
|
-
|
96
|
+
def private?(_exhibit)
|
97
|
+
false
|
91
98
|
end
|
92
99
|
|
93
|
-
def public?(
|
100
|
+
def public?(_exhibit)
|
94
101
|
true
|
95
102
|
end
|
96
103
|
|
@@ -102,25 +109,13 @@ module Europeana
|
|
102
109
|
@record_id ||= id.to_s.split('/')[2]
|
103
110
|
end
|
104
111
|
|
105
|
-
def as_json(options =
|
106
|
-
|
107
|
-
unless @hierarchy.nil?
|
108
|
-
json.merge!('hierarchy' => @hierarchy.as_json(options))
|
109
|
-
end
|
110
|
-
json.tap do |j|
|
112
|
+
def as_json(options = {})
|
113
|
+
super.tap do |json|
|
111
114
|
relations.each do |k, v|
|
112
|
-
|
115
|
+
json[k] = v.as_json
|
113
116
|
end
|
114
117
|
end
|
115
118
|
end
|
116
|
-
|
117
|
-
def lang_map?(obj)
|
118
|
-
self.class.lang_map?(obj)
|
119
|
-
end
|
120
|
-
|
121
|
-
def localize_lang_map(lang_map)
|
122
|
-
self.class.localize_lang_map(lang_map)
|
123
|
-
end
|
124
119
|
end
|
125
120
|
end
|
126
121
|
end
|
@@ -68,6 +68,31 @@ module Europeana
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
def has?(k, *values)
|
72
|
+
if !key?(k)
|
73
|
+
false
|
74
|
+
elsif values.empty?
|
75
|
+
fetch(k, nil).present?
|
76
|
+
else
|
77
|
+
Array(values).any? do |expected|
|
78
|
+
Array(fetch(k, nil)).any? do |actual|
|
79
|
+
case expected
|
80
|
+
when Regexp
|
81
|
+
actual =~ expected
|
82
|
+
else
|
83
|
+
actual == expected
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def key?(k)
|
91
|
+
[nested_field_container(k)].flatten.any? do |container|
|
92
|
+
container._source.key?(nested_field_key(k))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
71
96
|
def has_relation?(name)
|
72
97
|
relations.key?(name.to_s)
|
73
98
|
end
|
@@ -3,7 +3,7 @@ module Europeana
|
|
3
3
|
##
|
4
4
|
# Blacklight document presenter for Europeana documents
|
5
5
|
class DocumentPresenter < ::Blacklight::DocumentPresenter
|
6
|
-
include ActionView::Helpers::AssetTagHelper
|
6
|
+
include ActionView::Helpers::AssetTagHelper # ?
|
7
7
|
|
8
8
|
def render_document_show_field_value(field, options = {})
|
9
9
|
render_nested_field_value(field, :show, options)
|
@@ -10,6 +10,7 @@ module Europeana
|
|
10
10
|
module Pagination
|
11
11
|
include Kaminari::PageScopeMethods
|
12
12
|
include Kaminari::ConfigurationMethods::ClassMethods
|
13
|
+
extend ActiveSupport::Concern
|
13
14
|
|
14
15
|
def limit_value
|
15
16
|
rows
|
@@ -28,6 +29,15 @@ module Europeana
|
|
28
29
|
docs.first.model_name
|
29
30
|
end
|
30
31
|
|
32
|
+
def max_pages
|
33
|
+
(defined?(@_max_pages) && @_max_pages) || (1000 / limit_value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def total_pages
|
37
|
+
total = super
|
38
|
+
total > max_pages ? max_pages : total
|
39
|
+
end
|
40
|
+
|
31
41
|
def next_page
|
32
42
|
current_page + 1 unless last_page?
|
33
43
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Blacklight
|
3
|
+
##
|
4
|
+
# URL routing for Blacklight
|
5
|
+
module Routes
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do |klass|
|
9
|
+
klass.default_route_sets -= [:solr_document]
|
10
|
+
unless klass.default_route_sets.include?(:europeana_document)
|
11
|
+
klass.default_route_sets += [:europeana_document]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def europeana_document(primary_resource)
|
16
|
+
add_routes do |options|
|
17
|
+
args = { only: [:show] }
|
18
|
+
args[:constraints] = options[:constraints] if options[:constraints]
|
19
|
+
|
20
|
+
post 'record/*id/track', args.merge(to: "#{primary_resource}#track", as: 'track_document')
|
21
|
+
get 'record/*id', args.merge(to: "#{primary_resource}#show", as: 'document')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -5,21 +5,26 @@ module Europeana
|
|
5
5
|
class SearchBuilder < ::Blacklight::SearchBuilder
|
6
6
|
require 'europeana/blacklight/search_builder/facet_pagination'
|
7
7
|
require 'europeana/blacklight/search_builder/more_like_this'
|
8
|
+
require 'europeana/blacklight/search_builder/overlay_params'
|
8
9
|
require 'europeana/blacklight/search_builder/ranges'
|
9
10
|
|
11
|
+
attr_accessor :default_processor_chain
|
10
12
|
self.default_processor_chain = [
|
11
13
|
:default_api_parameters, :add_profile_to_api,
|
12
|
-
:add_query_to_api, :add_qf_to_api, :add_facet_qf_to_api,
|
13
|
-
:
|
14
|
+
:add_query_to_api, :add_qf_to_api, :add_facet_qf_to_api, :add_query_facet_to_api,
|
15
|
+
:add_standalone_facets_to_api, :add_facetting_to_api, :add_paging_to_api,
|
14
16
|
:add_sorting_to_api
|
15
17
|
]
|
16
18
|
|
17
19
|
include FacetPagination
|
18
20
|
include MoreLikeThis
|
19
21
|
include Ranges
|
22
|
+
include OverlayParams
|
20
23
|
|
21
24
|
delegate :to_query, to: :to_hash
|
22
25
|
|
26
|
+
STANDALONE_FACETS = %w(COLOURPALETTE MEDIA REUSABILITY)
|
27
|
+
|
23
28
|
##
|
24
29
|
# Start with general defaults from BL config. Need to use custom
|
25
30
|
# merge to dup values, to avoid later mutating the original by mistake.
|
@@ -87,23 +92,47 @@ module Europeana
|
|
87
92
|
def add_facet_qf_to_api(api_parameters)
|
88
93
|
return unless blacklight_params[:f]
|
89
94
|
|
90
|
-
salient_facets = blacklight_params[:f].
|
91
|
-
k
|
95
|
+
salient_facets = blacklight_params[:f].select do |k, _v|
|
96
|
+
!STANDALONE_FACETS.include?(k) && api_request_facet_fields.keys.include?(k)
|
92
97
|
end
|
93
98
|
|
94
99
|
salient_facets.each_pair do |facet_field, value_list|
|
95
100
|
Array(value_list).reject(&:blank?).each do |value|
|
96
101
|
api_parameters[:qf] ||= []
|
97
|
-
|
102
|
+
if Europeana::API::Search::Fields::MEDIA.include?(facet_field)
|
103
|
+
api_parameters[:qf] << "#{facet_field}:#{value}"
|
104
|
+
else
|
105
|
+
api_parameters[:qf] << "#{facet_field}:\"#{value}\""
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Filter results by a query facet
|
113
|
+
def add_query_facet_to_api(_api_parameters)
|
114
|
+
return unless blacklight_params[:f]
|
115
|
+
|
116
|
+
salient_facets = blacklight_params[:f].select do |k, _v|
|
117
|
+
facet = blacklight_config.facet_fields[k]
|
118
|
+
facet.query && (facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request))
|
119
|
+
end
|
120
|
+
|
121
|
+
salient_facets.each_pair do |facet_field, value_list|
|
122
|
+
Array(value_list).reject(&:blank?).each do |value|
|
123
|
+
with_overlay_params(blacklight_config.facet_fields[facet_field].query[value][:fq])
|
98
124
|
end
|
99
125
|
end
|
100
126
|
end
|
101
127
|
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
128
|
+
##
|
129
|
+
# Some facets need to be filtered as distinct API params, even though
|
130
|
+
# they are returned with the facets in a search response
|
131
|
+
def add_standalone_facets_to_api(api_parameters)
|
132
|
+
STANDALONE_FACETS.each do |field|
|
133
|
+
if blacklight_params[:f] && blacklight_params[:f][field]
|
134
|
+
api_parameters[field.downcase.to_sym] = blacklight_params[:f][field].join(',')
|
135
|
+
end
|
107
136
|
end
|
108
137
|
end
|
109
138
|
|
@@ -115,7 +144,9 @@ module Europeana
|
|
115
144
|
# @see http://labs.europeana.eu/api/search/#individual-facets
|
116
145
|
# @see http://labs.europeana.eu/api/search/#offset-and-limit-of-facets
|
117
146
|
def add_facetting_to_api(api_parameters)
|
118
|
-
api_parameters[:facet] = api_request_facet_fields.keys.
|
147
|
+
api_parameters[:facet] = api_request_facet_fields.keys.map do |field|
|
148
|
+
Europeana::API::Search::Fields::MEDIA.include?(field) ? 'DEFAULT' : field
|
149
|
+
end.uniq.join(',')
|
119
150
|
|
120
151
|
api_request_facet_fields.each do |field_name, facet|
|
121
152
|
api_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Blacklight
|
3
|
+
class SearchBuilder
|
4
|
+
##
|
5
|
+
# "Overlay" params do not replace others, but are combined with them, into
|
6
|
+
# multiple values for those param keys
|
7
|
+
module OverlayParams
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
default_processor_chain << :add_overlay_params_to_api
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_overlay_params(overlay_params = {})
|
15
|
+
@overlay_params ||= []
|
16
|
+
@overlay_params << overlay_params
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_overlay_params_to_api(api_parameters)
|
21
|
+
return unless @overlay_params
|
22
|
+
|
23
|
+
@overlay_params.each do |param_set|
|
24
|
+
param_set.each_pair do |k, v|
|
25
|
+
k = k.to_sym
|
26
|
+
if api_parameters.key?(k)
|
27
|
+
api_parameters[k] = [api_parameters[k]].flatten # in case it's not an Array
|
28
|
+
else
|
29
|
+
api_parameters[k] = []
|
30
|
+
end
|
31
|
+
api_parameters[k] += [v]
|
32
|
+
api_parameters[k] = api_parameters[k].flatten.uniq
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Blacklight
|
3
|
+
##
|
4
|
+
# Local overrides for {Blacklight::SearchHelper}
|
5
|
+
module SearchHelper
|
6
|
+
def previous_and_next_document_params(index, window = 1)
|
7
|
+
api_params = {}
|
8
|
+
|
9
|
+
if index > 1
|
10
|
+
api_params[:start] = index - window # get one before
|
11
|
+
api_params[:rows] = 2 * window + 1 # and one after
|
12
|
+
else
|
13
|
+
api_params[:start] = 1 # there is no previous doc
|
14
|
+
api_params[:rows] = 2 * window # but there should be one after
|
15
|
+
end
|
16
|
+
|
17
|
+
api_params
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def fetch_many(ids = [], *args)
|
23
|
+
if args.length == 1
|
24
|
+
user_params = params
|
25
|
+
extra_controller_params = args.first || {}
|
26
|
+
else
|
27
|
+
user_params, extra_controller_params = args
|
28
|
+
user_params ||= params
|
29
|
+
extra_controller_params ||= {}
|
30
|
+
end
|
31
|
+
|
32
|
+
id_query = ids.map { |id| "europeana_id:\"/#{id}\"" }.join(' OR ')
|
33
|
+
|
34
|
+
query = search_builder.with(user_params).where(id_query)
|
35
|
+
api_response = repository.search(query.merge(extra_controller_params))
|
36
|
+
|
37
|
+
[api_response, api_response.documents]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Blacklight
|
3
|
+
class Install < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
argument :europeana_api_key, type: :string
|
7
|
+
argument :controller_name, type: :string, default: 'catalog'
|
8
|
+
|
9
|
+
def disable_rsolr_gem
|
10
|
+
comment_lines('Gemfile', /gem 'rsolr'/)
|
11
|
+
end
|
12
|
+
|
13
|
+
def bundle_install
|
14
|
+
Bundler.with_clean_env do
|
15
|
+
run 'bundle install'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_configuration_files
|
20
|
+
template 'config/blacklight.yml', 'config/blacklight.yml'
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_controller
|
24
|
+
template 'catalog_controller.rb', "app/controllers/#{controller_name}_controller.rb"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
class <%= controller_name.classify %>Controller < ApplicationController
|
3
|
+
include Europeana::Blacklight::Catalog
|
4
|
+
|
5
|
+
configure_blacklight do |config|
|
6
|
+
# Europeana API caching
|
7
|
+
config.europeana_api_cache = Rails.cache
|
8
|
+
config.europeana_api_cache_expires_in = 24.hours
|
9
|
+
|
10
|
+
# Default parameters to send to Europeana for all search-like requests.
|
11
|
+
# @see SolrHelper#solr_search_params
|
12
|
+
config.default_solr_params = {
|
13
|
+
rows: 24
|
14
|
+
}
|
15
|
+
|
16
|
+
# items to show per page, each number in the array represents another
|
17
|
+
# option to choose from.
|
18
|
+
config.per_page = [12, 24, 48, 96]
|
19
|
+
|
20
|
+
# Field configuration for search results/index views
|
21
|
+
config.index.title_field = 'title'
|
22
|
+
config.index.display_type_field = 'type'
|
23
|
+
config.index.timestamp_field = nil # Europeana's is in microseconds
|
24
|
+
config.index.thumbnail_field = 'edmPreview'
|
25
|
+
|
26
|
+
# Fields to be displayed in the index (search results) view
|
27
|
+
# The ordering of the field names is the order of the display
|
28
|
+
# @see http://labs.europeana.eu/api/data-fields
|
29
|
+
config.add_index_field 'edmAgentLabelLangAware', label: 'Creator'
|
30
|
+
config.add_index_field 'dcDescription', label: 'Description'
|
31
|
+
config.add_index_field 'edmConceptPrefLabelLangAware',
|
32
|
+
separator: '; ', limit: 4, label: 'Subject'
|
33
|
+
config.add_index_field 'year', label: 'Year'
|
34
|
+
config.add_index_field 'dataProvider', label: 'Data provider'
|
35
|
+
|
36
|
+
# Facet fields in the order they should be displayed.
|
37
|
+
# @see http://labs.europeana.eu/api/search#individual-facets
|
38
|
+
config.add_facet_field 'TYPE'
|
39
|
+
config.add_facet_field 'REUSABILITY'
|
40
|
+
config.add_facet_field 'COUNTRY'
|
41
|
+
config.add_facet_field 'LANGUAGE'
|
42
|
+
config.add_facet_field 'PROVIDER'
|
43
|
+
config.add_facet_field 'DATA_PROVIDER'
|
44
|
+
config.add_facet_field 'YEAR'
|
45
|
+
config.add_facet_field 'RIGHTS'
|
46
|
+
|
47
|
+
# Send all facet field names to the API.
|
48
|
+
config.add_facet_fields_to_solr_request!
|
49
|
+
|
50
|
+
# Fields to be displayed in the object view, in the order of display.
|
51
|
+
config.add_show_field 'agents.prefLabel', label: 'Agents'
|
52
|
+
config.add_show_field 'agents.begin', label: 'Start date'
|
53
|
+
config.add_show_field 'agents.end', label: 'End date'
|
54
|
+
config.add_show_field 'proxies.dcType', label: 'Type'
|
55
|
+
config.add_show_field 'proxies.dcCreator', label: 'Creator'
|
56
|
+
config.add_show_field 'proxies.dcFormat', label: 'Format'
|
57
|
+
config.add_show_field 'proxies.dcIdentifier', label: 'Identifier'
|
58
|
+
config.add_show_field 'proxies.dctermsCreated', label: 'Created'
|
59
|
+
config.add_show_field 'aggregations.webResources.dctermsCreated', label: 'Created'
|
60
|
+
config.add_show_field 'proxies.dctermsExtent', label: 'Extent'
|
61
|
+
config.add_show_field 'europeanaAggregation.edmCountry', label: 'Country'
|
62
|
+
config.add_show_field 'edmDatasetName', label: 'Dataset name'
|
63
|
+
config.add_show_field 'aggregations.edmIsShownAt', label: 'Is shown at'
|
64
|
+
config.add_show_field 'aggregations.edmIsShownBy', label: 'Is shown by'
|
65
|
+
config.add_show_field 'europeanaAggregation.edmLanguage', label: 'Language'
|
66
|
+
config.add_show_field 'europeanaAggregation.edmPreview', label: 'Preview'
|
67
|
+
config.add_show_field 'aggregations.edmProvider', label: 'Provider'
|
68
|
+
config.add_show_field 'aggregations.edmDataProvider', label: 'Data provider'
|
69
|
+
config.add_show_field 'aggregations.edmRights', label: 'Rights'
|
70
|
+
config.add_show_field 'places.latitude', label: 'Latitude'
|
71
|
+
config.add_show_field 'places.longitude', label: 'Longitude'
|
72
|
+
config.add_show_field 'type', label: 'Type'
|
73
|
+
config.add_show_field 'year', label: 'Year'
|
74
|
+
|
75
|
+
# "fielded" search configuration.
|
76
|
+
config.add_search_field('', label: 'All Fields')
|
77
|
+
%w(title who what when where subject).each do |field_name|
|
78
|
+
config.add_search_field(field_name)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: europeana-blacklight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Doe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.0'
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: blacklight
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -36,14 +56,14 @@ dependencies:
|
|
36
56
|
requirements:
|
37
57
|
- - "~>"
|
38
58
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
59
|
+
version: 0.4.0
|
40
60
|
type: :runtime
|
41
61
|
prerelease: false
|
42
62
|
version_requirements: !ruby/object:Gem::Requirement
|
43
63
|
requirements:
|
44
64
|
- - "~>"
|
45
65
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.
|
66
|
+
version: 0.4.0
|
47
67
|
- !ruby/object:Gem::Dependency
|
48
68
|
name: iso-639
|
49
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +134,34 @@ dependencies:
|
|
114
134
|
- - "~>"
|
115
135
|
- !ruby/object:Gem::Version
|
116
136
|
version: '3.2'
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: shoulda-matchers
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '2.8'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '2.8'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: webmock
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '1.21'
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - "~>"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '1.21'
|
117
165
|
description:
|
118
166
|
email:
|
119
167
|
- richard.doe@rwdit.net
|
@@ -129,8 +177,10 @@ files:
|
|
129
177
|
- ".travis.yml"
|
130
178
|
- Gemfile
|
131
179
|
- LICENSE.md
|
180
|
+
- QUICKSTART.md
|
132
181
|
- README.md
|
133
182
|
- Rakefile
|
183
|
+
- app/controllers/concerns/europeana/blacklight/catalog.rb
|
134
184
|
- bin/console
|
135
185
|
- bin/setup
|
136
186
|
- europeana-blacklight.gemspec
|
@@ -140,16 +190,23 @@ files:
|
|
140
190
|
- lib/europeana/blacklight/document/more_like_this.rb
|
141
191
|
- lib/europeana/blacklight/document/relations.rb
|
142
192
|
- lib/europeana/blacklight/document_presenter.rb
|
193
|
+
- lib/europeana/blacklight/engine.rb
|
143
194
|
- lib/europeana/blacklight/facet_paginator.rb
|
144
195
|
- lib/europeana/blacklight/response.rb
|
145
196
|
- lib/europeana/blacklight/response/facets.rb
|
146
197
|
- lib/europeana/blacklight/response/more_like_this.rb
|
147
198
|
- lib/europeana/blacklight/response/pagination.rb
|
199
|
+
- lib/europeana/blacklight/routes.rb
|
148
200
|
- lib/europeana/blacklight/search_builder.rb
|
149
201
|
- lib/europeana/blacklight/search_builder/facet_pagination.rb
|
150
202
|
- lib/europeana/blacklight/search_builder/more_like_this.rb
|
203
|
+
- lib/europeana/blacklight/search_builder/overlay_params.rb
|
151
204
|
- lib/europeana/blacklight/search_builder/ranges.rb
|
205
|
+
- lib/europeana/blacklight/search_helper.rb
|
152
206
|
- lib/europeana/blacklight/version.rb
|
207
|
+
- lib/generators/europeana/blacklight/install_generator.rb
|
208
|
+
- lib/generators/europeana/blacklight/templates/catalog_controller.rb
|
209
|
+
- lib/generators/europeana/blacklight/templates/config/blacklight.yml
|
153
210
|
homepage: https://github.com/europeana/europeana-blacklight
|
154
211
|
licenses:
|
155
212
|
- EUPL 1.1
|