umlaut 3.0.0beta4 → 3.0.0beta5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/assets/javascripts/umlaut/#simple_visible_toggle.js# +8 -0
- data/app/assets/javascripts/umlaut/#update_html.js# +181 -0
- data/app/assets/javascripts/umlaut/{expand_contract_toggle.js.erb → expand_contract_toggle.js} +12 -4
- data/app/assets/javascripts/umlaut/update_html.js +11 -3
- data/app/helpers/resolve_helper.rb +6 -8
- data/app/views/resolve/_fulltext.html.erb +2 -4
- data/lib/service_adaptors/#blacklight.rb# +327 -0
- data/lib/service_adaptors/scopus.rb +5 -1
- data/lib/umlaut/#routes.rb# +164 -0
- data/lib/umlaut/routes.rb +6 -0
- data/lib/umlaut/version.rb +1 -1
- metadata +36 -32
@@ -0,0 +1,8 @@
|
|
1
|
+
/* simple_visible_toggle.js. Used for toggling visibility of error information. Can possibly be combined with more powerful expand_contract_toggle.js */
|
2
|
+
jQuery(document).ready(function($) {
|
3
|
+
|
4
|
+
$("a.simple_visible_toggle").live("click", function() {
|
5
|
+
$(this).next().toggle();
|
6
|
+
});
|
7
|
+
|
8
|
+
});
|
@@ -0,0 +1,181 @@
|
|
1
|
+
/* update_html.js: Provide functions to update content on page with background responses from Umlaut. Used by Umlaut itself, as well as by third party callers.*/
|
2
|
+
(function($) {
|
3
|
+
|
4
|
+
function SectionTarget(config) {
|
5
|
+
//Add properties from config to ourself
|
6
|
+
$.extend(this, config);
|
7
|
+
|
8
|
+
//Defaults
|
9
|
+
if (this.selector == undefined)
|
10
|
+
this.selector = "#" + this.umlaut_section_id;
|
11
|
+
if (this.position == undefined)
|
12
|
+
this.position = "html";
|
13
|
+
|
14
|
+
}
|
15
|
+
//Callback default to no-op function please.
|
16
|
+
var noop = function() {};
|
17
|
+
SectionTarget.prototype.before_update = noop;
|
18
|
+
SectionTarget.prototype.after_update = noop;
|
19
|
+
SectionTarget.prototype.complete = noop;
|
20
|
+
|
21
|
+
SectionTarget.prototype.ensure_placement_destination = function() {
|
22
|
+
if ( this.selector == undefined) {
|
23
|
+
return null;
|
24
|
+
}
|
25
|
+
|
26
|
+
//Already have it cached?
|
27
|
+
if ( this.host_div_element ) {
|
28
|
+
return this.host_div_element;
|
29
|
+
}
|
30
|
+
|
31
|
+
var new_div = $('<div class="umlaut" style="display:none"></div>');
|
32
|
+
// Find the first thing matched by selector, and call the
|
33
|
+
// method specified in "action" string on it, giving it our
|
34
|
+
// HTML to replace. This works because our actions are
|
35
|
+
// all arguments that will take one method: html, before, after, append,
|
36
|
+
// prepend.
|
37
|
+
$(this.selector).eq(0)[ this.position ]( new_div );
|
38
|
+
|
39
|
+
//Cache for later
|
40
|
+
this.host_div_element = new_div;
|
41
|
+
return this.host_div_element;
|
42
|
+
};
|
43
|
+
|
44
|
+
|
45
|
+
// Define an object constructor on the global window object
|
46
|
+
// For our UmlautHtmlUpdater object.
|
47
|
+
function HtmlUpdater(umlaut_base, context_object) {
|
48
|
+
if (context_object == undefined)
|
49
|
+
context_object = "";
|
50
|
+
|
51
|
+
umlaut_base = umlaut_base.replace(/\/$/,'');
|
52
|
+
this.umlaut_uri = umlaut_base + '/resolve/partial_html_sections?umlaut.response_format=json&' + context_object;
|
53
|
+
|
54
|
+
this.section_targets = [];
|
55
|
+
|
56
|
+
this.add_section_target = function(config) {
|
57
|
+
this.section_targets.push( new SectionTarget(config) );
|
58
|
+
};
|
59
|
+
|
60
|
+
//default no-op call-backs
|
61
|
+
this.complete = noop;
|
62
|
+
this.before_update = noop;
|
63
|
+
this.after_update = noop;
|
64
|
+
|
65
|
+
|
66
|
+
//Code for seeing if a URI is same origin or not borrowed from jQuery
|
67
|
+
this.is_remote_url = function(url) {
|
68
|
+
var regexp = /^(\w+:)?\/\/([^\/?#]+)/;
|
69
|
+
var parts = regexp.exec( url );
|
70
|
+
return (parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host));
|
71
|
+
}
|
72
|
+
|
73
|
+
this.update = function() {
|
74
|
+
// Need to capture because we won't have 'this' inside the ajax
|
75
|
+
// success handler.
|
76
|
+
var myself = this;
|
77
|
+
var dataType = this.is_remote_url( this.umlaut_uri ) ? "jsonp" : "json";
|
78
|
+
$.ajax({
|
79
|
+
url: myself.umlaut_uri,
|
80
|
+
dataType: dataType,
|
81
|
+
jsonp: "umlaut.jsonp",
|
82
|
+
error: function() {
|
83
|
+
$.error("Problem loading background elements.");
|
84
|
+
},
|
85
|
+
success: function(umlaut_response) {
|
86
|
+
for (var i = 0; i < myself.section_targets.length; i++) {
|
87
|
+
var section_target = myself.section_targets[i];
|
88
|
+
|
89
|
+
var umlaut_html_section = myself.find_umlaut_response_section(umlaut_response, section_target.umlaut_section_id);
|
90
|
+
|
91
|
+
if (umlaut_html_section == undefined) {
|
92
|
+
continue;
|
93
|
+
}
|
94
|
+
var count = null;
|
95
|
+
if (typeof umlaut_html_section.response_count != "undefined") {
|
96
|
+
count = parseInt(umlaut_html_section.response_count.value);
|
97
|
+
}
|
98
|
+
var existing_element = section_target.ensure_placement_destination();
|
99
|
+
var new_element = $('<div class="umlaut" style="display:none" class="' + section_target.umlaut_section_id +'"></div>');
|
100
|
+
new_element.html(umlaut_html_section.html_content);
|
101
|
+
|
102
|
+
|
103
|
+
var should_continue = section_target.before_update(new_element, count, section_target);
|
104
|
+
if (should_continue != false) {
|
105
|
+
should_continue = myself.before_update(new_element, count, section_target);
|
106
|
+
}
|
107
|
+
|
108
|
+
if (should_continue != false) {
|
109
|
+
existing_element.replaceWith(new_element);
|
110
|
+
|
111
|
+
section_target.host_div_element = new_element;
|
112
|
+
|
113
|
+
new_element.show();
|
114
|
+
|
115
|
+
section_target.after_update(new_element, count, section_target);
|
116
|
+
myself.after_update(new_element, count, section_target);
|
117
|
+
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
//Do we need to update again?
|
122
|
+
if (umlaut_response.partial_html_sections.in_progress) {
|
123
|
+
//Fix our update URI to be the one umlaut suggests
|
124
|
+
//Except strip out the umlaut.jsonp parameter, jquery is
|
125
|
+
//going to add that back in as desired.
|
126
|
+
myself.umlaut_uri =
|
127
|
+
umlaut_response.partial_html_sections.in_progress.refresh_url.replace(/[?;&]umlaut\.jsonp=[^;&]+/, '');
|
128
|
+
|
129
|
+
|
130
|
+
var refresh_seconds =
|
131
|
+
umlaut_response.partial_html_sections.in_progress.requested_wait_seconds;
|
132
|
+
window.setTimeout(function() { myself.update(); }, refresh_seconds * 1000);
|
133
|
+
|
134
|
+
} else {
|
135
|
+
myself.complete();
|
136
|
+
for (var i = 0; i < myself.section_targets.length; i++) {
|
137
|
+
var section_target = myself.section_targets[i];
|
138
|
+
section_target.complete(section_target);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
}
|
143
|
+
});
|
144
|
+
};
|
145
|
+
this.find_umlaut_response_section = function(response, id) {
|
146
|
+
return $.grep(response.partial_html_sections.html_section, function(section) {
|
147
|
+
return section.id == id;
|
148
|
+
})[0];
|
149
|
+
};
|
150
|
+
|
151
|
+
};
|
152
|
+
|
153
|
+
//Put it in a global object, leave space for other things in "Umlaut" later.
|
154
|
+
if (window.Umlaut == undefined)
|
155
|
+
window.Umlaut = new Object();
|
156
|
+
window.Umlaut.HtmlUpdater = HtmlUpdater;
|
157
|
+
|
158
|
+
/* LEGACY Loader was recommended for loading Umlaut JS behaviors
|
159
|
+
in an external page, for JQuery Content Utility.
|
160
|
+
|
161
|
+
var loader = new Umlaut.Loader();
|
162
|
+
loader.load();
|
163
|
+
|
164
|
+
We will provide just enough code to keep that from
|
165
|
+
error'ing (and halting js execution), although at present it does not
|
166
|
+
actually load the JS behaviors using new style, app wont' have
|
167
|
+
JS behaviors. */
|
168
|
+
|
169
|
+
window.Umlaut.Loader = function() {
|
170
|
+
this.load = function(option_list) {
|
171
|
+
// log problem in browsers that support it.
|
172
|
+
if (typeof console != "undefined" && typeof console.log != "undefined") {
|
173
|
+
console.log("WARN: Umlaut.Loader no longer supported in Umlaut 3.x, you may have not loaded Umlaut JS Behaviors as desired. See Umlaut documentation for new way.");
|
174
|
+
|
175
|
+
}
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
})(jQuery);
|
181
|
+
|
data/app/assets/javascripts/umlaut/{expand_contract_toggle.js.erb → expand_contract_toggle.js}
RENAMED
@@ -1,19 +1,27 @@
|
|
1
|
-
/* expand_contract_toggle.js: Support for show more/hide more in lists of umlaut content.
|
1
|
+
/* expand_contract_toggle.js: Support for show more/hide more in lists of umlaut content.
|
2
|
+
|
3
|
+
The JS needs to swap out the image for expand/contract toggle. AND we need
|
4
|
+
the URL it swaps in to be an ABSOLUTE url when we're using partial html
|
5
|
+
widget.
|
6
|
+
|
7
|
+
So we swap in a non-fingerprinted URL, even if the original was asset
|
8
|
+
pipline fingerprinted. sorry, best way to make it work!
|
9
|
+
*/
|
2
10
|
jQuery(document).ready(function($) {
|
3
11
|
|
4
12
|
$(".expand_contract_toggle").live("click", function() {
|
5
13
|
var content = $(this).next(".expand_contract_content");
|
6
14
|
var icon = $(this).parent().find('img.toggle_icon');
|
7
15
|
|
8
|
-
if (content.is(":visible")) {
|
9
|
-
icon.attr("src",
|
16
|
+
if (content.is(":visible")) {
|
17
|
+
icon.attr("src", icon.attr("src").replace(/list_open[^.]*\.png/, "list_closed.png"));
|
10
18
|
$(this).find(".expand_contract_action_label").text("Show ");
|
11
19
|
|
12
20
|
content.hide();
|
13
21
|
|
14
22
|
}
|
15
23
|
else {
|
16
|
-
icon.attr("src",
|
24
|
+
icon.attr("src", icon.attr("src").replace(/list_closed[^.]*\.png/, "list_open.png"));
|
17
25
|
$(this).find(".expand_contract_action_label").text("Hide ");
|
18
26
|
content.show();
|
19
27
|
}
|
@@ -58,7 +58,10 @@
|
|
58
58
|
};
|
59
59
|
|
60
60
|
//default no-op call-backs
|
61
|
-
this.complete =
|
61
|
+
this.complete = noop;
|
62
|
+
this.before_update = noop;
|
63
|
+
this.after_update = noop;
|
64
|
+
|
62
65
|
|
63
66
|
//Code for seeing if a URI is same origin or not borrowed from jQuery
|
64
67
|
this.is_remote_url = function(url) {
|
@@ -98,6 +101,9 @@
|
|
98
101
|
|
99
102
|
|
100
103
|
var should_continue = section_target.before_update(new_element, count, section_target);
|
104
|
+
if (should_continue != false) {
|
105
|
+
should_continue = myself.before_update(new_element, count, section_target);
|
106
|
+
}
|
101
107
|
|
102
108
|
if (should_continue != false) {
|
103
109
|
existing_element.replaceWith(new_element);
|
@@ -106,7 +112,8 @@
|
|
106
112
|
|
107
113
|
new_element.show();
|
108
114
|
|
109
|
-
section_target.after_update(new_element, count, section_target)
|
115
|
+
section_target.after_update(new_element, count, section_target);
|
116
|
+
myself.after_update(new_element, count, section_target);
|
110
117
|
|
111
118
|
}
|
112
119
|
}
|
@@ -163,7 +170,8 @@
|
|
163
170
|
this.load = function(option_list) {
|
164
171
|
// log problem in browsers that support it.
|
165
172
|
if (typeof console != "undefined" && typeof console.log != "undefined") {
|
166
|
-
console.log("WARN: Umlaut.Loader no longer supported in Umlaut 3.x, you have not loaded Umlaut JS Behaviors. See Umlaut documentation for new way.");
|
173
|
+
console.log("WARN: Umlaut.Loader no longer supported in Umlaut 3.x, you may have not loaded Umlaut JS Behaviors as desired. See Umlaut documentation for new way.");
|
174
|
+
|
167
175
|
}
|
168
176
|
}
|
169
177
|
}
|
@@ -158,9 +158,7 @@ module ResolveHelper
|
|
158
158
|
# <li>Item Number: <%= index %>: <%= item.title %></li>
|
159
159
|
# <% end %>
|
160
160
|
def list_with_limit(id, list, options = {}, &block)
|
161
|
-
|
162
|
-
|
163
|
-
|
161
|
+
|
164
162
|
# backwards compatible to when third argument was just a number
|
165
163
|
# for limit.
|
166
164
|
options = {:limit => options} unless options.kind_of?(Hash)
|
@@ -172,17 +170,17 @@ module ResolveHelper
|
|
172
170
|
content = "".html_safe
|
173
171
|
content <<
|
174
172
|
content_tag(:ul, :class => options[:ul_class]) do
|
175
|
-
|
176
|
-
|
173
|
+
list.slice(0, options[:limit]).enum_for(:each_with_index).collect do |item, index|
|
174
|
+
yield(item, index)
|
177
175
|
end.join(" \n ").html_safe
|
178
176
|
end
|
179
177
|
|
180
178
|
if (list.length > options[:limit] )
|
181
179
|
content <<
|
182
|
-
expand_contract_section("#{list.length - options[:limit]
|
180
|
+
expand_contract_section("#{list.length - options[:limit] } more", id) do
|
183
181
|
content_tag(:ul, :class=>options[:ul_class]) do
|
184
|
-
list.slice(options[:limit]
|
185
|
-
yield(item, index)
|
182
|
+
list.slice(options[:limit]..list.length-1).enum_for(:each_with_index).each do |item, index|
|
183
|
+
yield(item, index + options[:limit])
|
186
184
|
end.join(" \n ").html_safe
|
187
185
|
end
|
188
186
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<%
|
2
2
|
|
3
|
-
#debugger
|
4
3
|
all_responses = fulltext
|
5
|
-
|
4
|
+
|
5
|
+
|
6
6
|
(title_level_fulltxt, fulltxt) =
|
7
7
|
all_responses.partition {|i| i.view_data[:coverage_checked] == false || i.view_data[:can_link_to_article] == false}
|
8
8
|
# order em with full fulltxt before title_level_fulltxt
|
@@ -15,7 +15,6 @@
|
|
15
15
|
|
16
16
|
|
17
17
|
<div class="umlaut_section_content">
|
18
|
-
|
19
18
|
<%= list_with_limit('umlaut_fulltext',
|
20
19
|
all_responses,
|
21
20
|
:ul_class => "response_list",
|
@@ -36,7 +35,6 @@
|
|
36
35
|
</div>
|
37
36
|
<ul class="response_list">
|
38
37
|
<% end %>
|
39
|
-
|
40
38
|
<%= render(:partial => "standard_response_item", :object=> item) %>
|
41
39
|
<% end %>
|
42
40
|
|
@@ -0,0 +1,327 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'base64'
|
4
|
+
require 'marc'
|
5
|
+
|
6
|
+
# Searches a Blacklight with the cql extension installed.
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# Params include:
|
10
|
+
# [base_url]
|
11
|
+
# required. Complete URL to catalog.atom action. Eg "https://blacklight.mse.jhu.edu/catalog.atom"
|
12
|
+
# [bl_fields]
|
13
|
+
# required with at least some entries if you want this to do anything. Describe the names of given semantic fields in your BL instance.
|
14
|
+
# * issn
|
15
|
+
# * isbn
|
16
|
+
# * lccn
|
17
|
+
# * oclcnum
|
18
|
+
# * id (defaults to 'id')
|
19
|
+
# * title
|
20
|
+
# * author
|
21
|
+
# * serials_limit_clause => not an index name, full URL clause for a limit to apply to known serials searches, for instance "f[format][]=Serial"
|
22
|
+
# [identifier_search]
|
23
|
+
# Do catalog search on issn/isbn/oclcnum/lccn/bibId. Default true.
|
24
|
+
# [keyword_search]
|
25
|
+
# Do catalog search on title/author keywords where applicable. Generally only used when identifier_search finds no hits, if identifier_search is on. Default true.
|
26
|
+
# [keyword_per_page]
|
27
|
+
# How many records to fetch from blacklight when doing keyword searches.
|
28
|
+
# [exclude_holdings]
|
29
|
+
# Can be used to exclude certain 'dummy' holdings that have certain collection, location, or other values. Eg:
|
30
|
+
# exclude_holdings:
|
31
|
+
# collection_str:
|
32
|
+
# - World Wide Web
|
33
|
+
# - Internet
|
34
|
+
# [rft_id_bibnum_prefixes]
|
35
|
+
# Array of URI prefixes in an rft_id that indicate that the actual solr id comes next. For instance, if your blacklight will send "http://blacklight.com/catalog/some_id" in an rft_id, then include "http://blacklight.com/catalog/". Optional.
|
36
|
+
class Blacklight < Service
|
37
|
+
required_config_params :base_url, :display_name
|
38
|
+
attr_reader :base_url, :cql_search_field
|
39
|
+
attr_reader :bl_fields, :issn
|
40
|
+
|
41
|
+
include UmlautHttp
|
42
|
+
include MetadataHelper
|
43
|
+
include MarcHelper
|
44
|
+
include XmlSchemaHelper
|
45
|
+
|
46
|
+
def initialize(config)
|
47
|
+
# defaults
|
48
|
+
# If you are sending an OpenURL from a library service, you may
|
49
|
+
# have the HIP bibnum, and include it in the OpenURL as, eg.
|
50
|
+
# rft_id=http://catalog.library.jhu.edu/bib/343434 (except URL-encoded)
|
51
|
+
# Then you'd set rft_id_bibnum_prefix to http://catalog.library.jhu.edu/bib/
|
52
|
+
@rft_id_bibnum_prefixes = []
|
53
|
+
@cql_search_field = "cql"
|
54
|
+
@keyword_per_page = 10
|
55
|
+
@identifier_search = true
|
56
|
+
@keyword_search = true
|
57
|
+
@link_to_search = true
|
58
|
+
super(config)
|
59
|
+
@bl_fields = { "id" => "id "}.merge(@bl_fields)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Standard method, used by background service updater. See Service docs.
|
63
|
+
def service_types_generated
|
64
|
+
types = [ ServiceTypeValue[:fulltext], ServiceTypeValue[:holding], ServiceTypeValue[:table_of_contents], ServiceTypeValue[:relevant_link] ]
|
65
|
+
|
66
|
+
return types
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def handle(request)
|
71
|
+
ids_processed = []
|
72
|
+
holdings_added = 0
|
73
|
+
|
74
|
+
if (@identifier_search && url = blacklight_precise_search_url(request) )
|
75
|
+
doc = Nokogiri::XML( http_fetch(url).body )
|
76
|
+
|
77
|
+
ids_processed.concat( bib_ids_from_atom_entries( doc.xpath("atom:feed/atom:entry", xml_ns) ) )
|
78
|
+
|
79
|
+
# namespaces make xpath harder than it should be, but css
|
80
|
+
# selector still easy, thanks nokogiri! Grab the marc from our
|
81
|
+
# results.
|
82
|
+
marc_matches = doc.xpath("atom:feed/atom:entry/atom:content[@type='application/marc']", xml_ns).collect do |encoded_marc21|
|
83
|
+
MARC::Reader.decode( Base64.decode64(encoded_marc21.text) )
|
84
|
+
end
|
85
|
+
|
86
|
+
add_856_links(request, marc_matches )
|
87
|
+
|
88
|
+
# Got to make a second fetch for dlf_expanded info, cause BL doens't
|
89
|
+
# (yet) let us ask for more than one at once
|
90
|
+
holdings_url = blacklight_precise_search_url( request, "dlf_expanded" )
|
91
|
+
holdings_added += add_holdings( holdings_url ) if holdings_url
|
92
|
+
end
|
93
|
+
#keyword search.
|
94
|
+
if (@keyword_search &&
|
95
|
+
url = blacklight_keyword_search_url(request))
|
96
|
+
|
97
|
+
doc = Nokogiri::XML( http_fetch(url).body )
|
98
|
+
# filter out matches whose titles don't really match at all, or
|
99
|
+
# which have already been seen in identifier search.
|
100
|
+
entries = filter_keyword_entries( doc.xpath("atom:feed/atom:entry", xml_ns) , :exclude_ids => ids_processed, :remove_subtitle => (! title_is_serial?(request.referent)) )
|
101
|
+
|
102
|
+
marc_by_atom_id = {}
|
103
|
+
|
104
|
+
# Grab the marc from our entries. Important not to do a // xpath
|
105
|
+
# search, or we'll wind up matching parent elements not actually
|
106
|
+
# included in our 'entries' list.
|
107
|
+
marc_matches = entries.xpath("atom:content[@type='application/marc']", xml_ns).collect do |encoded_marc21|
|
108
|
+
marc = MARC::Reader.decode( Base64.decode64(encoded_marc21.text) )
|
109
|
+
|
110
|
+
marc_by_atom_id[ encoded_marc21.at_xpath("ancestor::atom:entry/atom:id/text()", xml_ns).to_s ] = marc
|
111
|
+
|
112
|
+
marc
|
113
|
+
end
|
114
|
+
|
115
|
+
# We've filtered out those we consider just plain bad
|
116
|
+
# matches, everything else we're going to call
|
117
|
+
# an approximate match. Sort so that those with
|
118
|
+
# a date close to our request date are first.
|
119
|
+
if ( year = get_year(request.referent))
|
120
|
+
marc_matches = marc_matches.partition {|marc| get_years(marc).include?( year )}.flatten
|
121
|
+
end
|
122
|
+
# And add in the 856's
|
123
|
+
add_856_links(request, marc_matches, :match_reliability => ServiceResponse::MatchUnsure)
|
124
|
+
|
125
|
+
# Fetch and add in the holdings
|
126
|
+
url = blacklight_url_for_ids(bib_ids_from_atom_entries(entries))
|
127
|
+
|
128
|
+
holdings_added += add_holdings( url, :match_reliability => ServiceResponse::MatchUnsure, :marc_data => marc_by_atom_id ) if url
|
129
|
+
|
130
|
+
if (@link_to_search && holdings_added ==0)
|
131
|
+
hit_count = doc.at_xpath("atom:feed/opensearch:totalResults/text()", xml_ns).to_s.to_i
|
132
|
+
html_result_url = doc.at_xpath("atom:feed/atom:link[@rel='alternate'][@type='text/html']/attribute::href", xml_ns).to_s
|
133
|
+
|
134
|
+
if hit_count > 0
|
135
|
+
request.add_service_response(
|
136
|
+
:service => self,
|
137
|
+
:source_name => @display_name,
|
138
|
+
:count => hit_count,
|
139
|
+
:display_text => "#{hit_count} possible #{case; when hit_count > 1 ; 'matches' ; else; 'match' ; end} in #{@display_name}",
|
140
|
+
:url => html_result_url,
|
141
|
+
:service_type_value => :holding_search )
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
return request.dispatched(self, true)
|
150
|
+
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
# Send a CQL request for any identifiers present.
|
155
|
+
# Ask for for an atom response with embedded marc21 back.
|
156
|
+
def blacklight_precise_search_url(request, format = "marc")
|
157
|
+
# Add search clauses for our identifiers, if we have them and have a configured search field for them.
|
158
|
+
clauses = []
|
159
|
+
added = []
|
160
|
+
["lccn", "isbn", "oclcnum"].each do |key|
|
161
|
+
if bl_fields[key] && request.referent.send(key)
|
162
|
+
clauses.push( "#{bl_fields[key]} = \"#{request.referent.send(key)}\"")
|
163
|
+
added << key
|
164
|
+
end
|
165
|
+
end
|
166
|
+
# Only add ISSN if we don't have an ISBN, reduces false matches
|
167
|
+
if ( !added.include?("isbn") &&
|
168
|
+
bl_fields["issn"] &&
|
169
|
+
request.referent.issn)
|
170
|
+
clauses.push("#{bl_fields["issn"]} = \"#{request.referent.issn}\"")
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
# Add Solr document identifier if we can get one from the URL
|
175
|
+
|
176
|
+
if (id = get_solr_id(request.referent))
|
177
|
+
clauses.push("#{bl_fields['id']} = \"#{id}\"")
|
178
|
+
end
|
179
|
+
|
180
|
+
# if we have nothing, we can do no search.
|
181
|
+
return nil if clauses.length == 0
|
182
|
+
|
183
|
+
cql = clauses.join(" OR ")
|
184
|
+
|
185
|
+
return base_url + "?search_field=#{@cql_search_field}&content_format=#{format}&q=#{CGI.escape(cql)}"
|
186
|
+
end
|
187
|
+
|
188
|
+
# Construct a CQL search against blacklight for author and title,
|
189
|
+
# possibly with serial limit. Ask for Atom with embedded MARC back.
|
190
|
+
def blacklight_keyword_search_url(request, options = {})
|
191
|
+
options[:format] ||= "atom"
|
192
|
+
options[:content_format] ||= "marc"
|
193
|
+
|
194
|
+
clauses = []
|
195
|
+
|
196
|
+
# We need both title and author to search keyword style, or
|
197
|
+
# we get too many false positives. Except serials we'll do
|
198
|
+
# title only. sigh, logic tree.
|
199
|
+
title = get_search_title(request.referent)
|
200
|
+
author = get_top_level_creator(request.referent)
|
201
|
+
return nil unless title && (author || (@bl_fields["serials_limit_clause"] && title_is_serial?(request.referent)))
|
202
|
+
# phrase search for title, just raw dismax for author
|
203
|
+
# Embed quotes inside the quoted value, need to backslash-quote for CQL,
|
204
|
+
# and backslash the backslashes for ruby literal.
|
205
|
+
clauses.push("#{@bl_fields["title"]} = \"\\\"#{title}\\\"\"")
|
206
|
+
clauses.push("#{@bl_fields["author"]} = \"#{author}\"") if author
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
url = base_url + "?search_field=#{@cql_search_field}&content_format=#{options[:content_format]}&q=#{CGI.escape(clauses.join(" AND "))}"
|
211
|
+
|
212
|
+
if (@bl_fields["serials_limit_clause"] &&
|
213
|
+
title_is_serial?(request.referent))
|
214
|
+
url += "&" + @bl_fields["serials_limit_clause"]
|
215
|
+
end
|
216
|
+
|
217
|
+
return url
|
218
|
+
end
|
219
|
+
|
220
|
+
# Takes a url that will return atom response of dlf_expanded content.
|
221
|
+
# Adds Umlaut "holding" ServiceResponses for dlf_expanded, as appropriate.
|
222
|
+
# Returns number of holdings added.
|
223
|
+
def add_holdings(holdings_url, options = {})
|
224
|
+
options[:match_reliability] ||= ServiceResponse::MatchExact
|
225
|
+
options[:marc_data] ||= {}
|
226
|
+
|
227
|
+
atom = Nokogiri::XML( http_fetch(holdings_url).body )
|
228
|
+
content_entries = atom.search("/atom:feed/atom:entry/atom:content", xml_ns)
|
229
|
+
|
230
|
+
# For each atom entry, find the dlf_expanded record. For each dlf_expanded
|
231
|
+
# record, take all of it's holdingsrec's if it has them, or all of it's
|
232
|
+
# items if it doesn't, and add them to list. We wind up with a list
|
233
|
+
# of mixed holdingsrec's and items.
|
234
|
+
holdings_xml = content_entries.collect do |dlf_expanded|
|
235
|
+
copies = dlf_expanded.xpath("dlf:record/dlf:holdings/dlf:holdingset/dlf:holdingsrec", xml_ns)
|
236
|
+
copies.length > 0 ? copies : dlf_expanded.xpath("dlf:record/dlf:items/dlf:item", xml_ns)
|
237
|
+
end.flatten
|
238
|
+
|
239
|
+
service_data = holdings_xml.collect do | xml_metadata |
|
240
|
+
atom_entry = xml_metadata.at_xpath("ancestor::atom:entry", xml_ns)
|
241
|
+
atom_id = atom_entry.at_xpath("atom:id/text()", xml_ns).to_s
|
242
|
+
|
243
|
+
edition_str = edition_statement(options[:marc_data][atom_id])
|
244
|
+
url = atom_entry.at_xpath("atom:link[@rel='alternate'][@type='text/html']/attribute::href", xml_ns).to_s
|
245
|
+
|
246
|
+
xml_to_holdings( xml_metadata ).merge(
|
247
|
+
:service => self,
|
248
|
+
:match_reliability => options[:match_reliability],
|
249
|
+
:edition_str => edition_str,
|
250
|
+
:url => url
|
251
|
+
)
|
252
|
+
end
|
253
|
+
|
254
|
+
# strip out holdings that aren't really holdings
|
255
|
+
service_data.delete_if do |data|
|
256
|
+
@exclude_holdings.collect do |key, values|
|
257
|
+
values.include?(data[key.to_sym])
|
258
|
+
end.include?(true)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Sort by "collection"
|
262
|
+
service_data.sort do |a, b|
|
263
|
+
a[:collection_str] <=> b[:collection_str]
|
264
|
+
end
|
265
|
+
|
266
|
+
service_data.each do |data|
|
267
|
+
request.add_service_response(data.merge(:service => self, :service_type_value =>"holding"))
|
268
|
+
end
|
269
|
+
|
270
|
+
return service_data.length
|
271
|
+
end
|
272
|
+
|
273
|
+
def filter_keyword_entries(atom_entries, options = {})
|
274
|
+
options[:exclude_ids] ||= []
|
275
|
+
options[:remove_subtitle] ||= true
|
276
|
+
request_title_forms = [
|
277
|
+
raw_search_title(request.referent).downcase,
|
278
|
+
normalize_title( raw_search_title(request.referent) )
|
279
|
+
]
|
280
|
+
request_title_forms << normalize_title( raw_search_title(request.referent), :remove_subtitle => true) if options[:remove_subtitle]
|
281
|
+
request_title_forms.compact
|
282
|
+
|
283
|
+
# Only keep entries with title match, and that aren't in the
|
284
|
+
# exclude_ids list.
|
285
|
+
good_entries = atom_entries.find_all do |atom_entry|
|
286
|
+
title = atom_entry.xpath("atom:title/text()", xml_ns).to_s
|
287
|
+
|
288
|
+
entry_title_forms = [
|
289
|
+
title.downcase,
|
290
|
+
normalize_title(title)
|
291
|
+
]
|
292
|
+
entry_title_forms << normalize_title(title, :remove_subtitle=>true) if options[:remove_subtitle]
|
293
|
+
entry_title_forms.compact
|
294
|
+
|
295
|
+
((entry_title_forms & request_title_forms).length > 0 &&
|
296
|
+
(bib_ids_from_atom_entries(atom_entry) & options[:exclude_ids]).length == 0)
|
297
|
+
end
|
298
|
+
return Nokogiri::XML::NodeSet.new( atom_entries.document, good_entries)
|
299
|
+
end
|
300
|
+
|
301
|
+
def bib_ids_from_atom_entries(entries)
|
302
|
+
entries.xpath("atom:id/text()", xml_ns).to_a.collect do |atom_id|
|
303
|
+
atom_id.to_s =~ /([^\/]+)$/
|
304
|
+
$1
|
305
|
+
end.compact
|
306
|
+
end
|
307
|
+
|
308
|
+
def blacklight_url_for_ids(ids, format="dlf_expanded")
|
309
|
+
return nil unless ids.length > 0
|
310
|
+
|
311
|
+
return base_url + "?search_field=#{@cql_search_field}&content_format=#{format}&q=" + CGI.escape("#{@bl_fields["id"]} any \"#{ids.join(" ")}\"")
|
312
|
+
end
|
313
|
+
|
314
|
+
|
315
|
+
def get_solr_id(rft)
|
316
|
+
rft.identifiers.each do |id|
|
317
|
+
@rft_id_bibnum_prefixes.each do |prefix|
|
318
|
+
if id[0, prefix.length] == prefix
|
319
|
+
return id[prefix.length, id.length]
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
return nil
|
325
|
+
end
|
326
|
+
|
327
|
+
end
|
@@ -33,6 +33,9 @@
|
|
33
33
|
class Scopus < Service
|
34
34
|
require 'open-uri'
|
35
35
|
require 'multi_json'
|
36
|
+
|
37
|
+
include ActionView::Helpers::SanitizeHelper
|
38
|
+
|
36
39
|
include MetadataHelper
|
37
40
|
include UmlautHttp
|
38
41
|
|
@@ -237,7 +240,8 @@ class Scopus < Service
|
|
237
240
|
request.add_service_response(
|
238
241
|
:service=>self,
|
239
242
|
:display_text => "Abstract from #{@display_name}",
|
240
|
-
:content => first_hit["abstract"],
|
243
|
+
:content => sanitize(first_hit["abstract"]),
|
244
|
+
:content_html_safe => true,
|
241
245
|
:url => detail_url(first_hit),
|
242
246
|
:service_type_value => :abstract)
|
243
247
|
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Umlaut
|
3
|
+
# Class to inject Umlaut routes, design copied from Blacklight project.
|
4
|
+
# you would do a:
|
5
|
+
# Umlaut::Routes.new(self, optional_args).draw
|
6
|
+
# in local
|
7
|
+
# app routes.rb, that line is generated into local app by Umlaut generator.
|
8
|
+
# options include :only and :except to limit what route groups are generated.
|
9
|
+
class Routes
|
10
|
+
|
11
|
+
def initialize(router, options ={})
|
12
|
+
@router = router
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def draw
|
17
|
+
route_sets.each do |r|
|
18
|
+
self.send(r)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def add_routes &blk
|
25
|
+
@router.instance_exec(@options, &blk)
|
26
|
+
end
|
27
|
+
|
28
|
+
def route_sets
|
29
|
+
# :admin is not included by default, needs to be turned on.
|
30
|
+
(@options[:only] || default_route_sets) - (@options[:except] || []) + (@options[:admin] == true ? [:admin] : [])
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_route_sets
|
34
|
+
[:root, :permalinks, :a_z, :resolve, :open_search, :link_router, :export_email, :resources, :search, :javascript]
|
35
|
+
end
|
36
|
+
|
37
|
+
module RouteSets
|
38
|
+
# for now include root generation in Umlaut auto-generation
|
39
|
+
def root
|
40
|
+
add_routes do |options|
|
41
|
+
root :to => "search#index"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def permalinks
|
46
|
+
add_routes do |options|
|
47
|
+
match 'go/:id' => 'store#index'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# some special direct links to A-Z type searches, including
|
52
|
+
# legacy redirects for SFX-style urls, to catch any bookmarks.
|
53
|
+
def a_z
|
54
|
+
add_routes do |options|
|
55
|
+
# Special one for alpha list
|
56
|
+
match 'journal_list/:id/:page' => 'search#journal_list', :defaults => { :page => 1, :id => 'A' }
|
57
|
+
|
58
|
+
|
59
|
+
# Catch redirected from SFX A-Z and citation linker urls
|
60
|
+
# v2 A-Z links redirected to umlaut, point to journal_list
|
61
|
+
# code in journal_list filter picks out SFX URL vars for
|
62
|
+
# letter.
|
63
|
+
match '/resolve/azlist/default' => 'search#journal_list', :page => 1, :id => 'A'
|
64
|
+
|
65
|
+
# SFX v3 A-Z list url format
|
66
|
+
match 'resolve/az' => 'search#journal_list', :page => 1, :id => 'A'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
71
|
+
# Note: This route will make all actions in every controller accessible via GET requests.
|
72
|
+
# match ':controller(/:action(/:id(.:format)))'
|
73
|
+
|
74
|
+
def resolve
|
75
|
+
add_routes do |options|
|
76
|
+
# ResolveController still uses rails 2.0 style 'wildcard' routes,
|
77
|
+
# TODO tighten this up to only match what oughta be matched.
|
78
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
79
|
+
|
80
|
+
match 'resolve(/:action(/:id(.:format)))' => "resolve"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def open_search
|
85
|
+
add_routes do |options|
|
86
|
+
# OpenSearchController still uses rails 2.0 style 'wildcard' routes,
|
87
|
+
# TODO tighten this up to only match what oughta be matched.
|
88
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
89
|
+
|
90
|
+
match 'open_search(/:action(/:id(.:format)))' => "open_search"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def link_router
|
95
|
+
add_routes do |options|
|
96
|
+
# LinkRouterController still uses rails 2.0 style 'wildcard' routes,
|
97
|
+
# TODO tighten this up to only match what oughta be matched.
|
98
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
99
|
+
|
100
|
+
match 'link_router(/:action(/:id(.:format)))' => "link_router"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def export_email
|
105
|
+
add_routes do |options|
|
106
|
+
# ExportEmailController still uses rails 2.0 style 'wildcard' routes,
|
107
|
+
# TODO tighten this up to only match what oughta be matched.
|
108
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
109
|
+
|
110
|
+
match 'export_email(/:action(/:id(.:format)))' => "export_email"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def resources
|
115
|
+
add_routes do |options|
|
116
|
+
# ResourceController still uses rails 2.0 style 'wildcard' routes,
|
117
|
+
# TODO tighten this up to only match what oughta be matched.
|
118
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
119
|
+
|
120
|
+
match 'resource(/:action(/:id(.:format)))' => "resource"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def search
|
125
|
+
add_routes do |options|
|
126
|
+
# SearchController still uses rails 2.0 style 'wildcard' routes,
|
127
|
+
# TODO tighten this up to only match what oughta be matched.
|
128
|
+
# Note: This route will make all actions in this controller accessible via GET requests.
|
129
|
+
|
130
|
+
match 'search(/:action(/:id(.:format)))' => "search"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def javascript
|
135
|
+
add_routes do |options|
|
136
|
+
# Legacy location for update_html.js used by JQuery Content Utility
|
137
|
+
# to embed JS on external sites. Redirect to new location.
|
138
|
+
# Intentionally non-fingerprinted, most efficient thing
|
139
|
+
# we can do in this case is let the web server take care
|
140
|
+
# of Last-modified-by etc headers.
|
141
|
+
match 'javascripts/jquery/umlaut/update_html.js' => redirect("/assets/umlaut/update_html.js", :status => 301)
|
142
|
+
|
143
|
+
# The loader doens't work _exactly_ like the new umlaut-ui.js, but
|
144
|
+
# it's close enough that it'll work better redirecting than just
|
145
|
+
# 404'ing.
|
146
|
+
match 'js_helper/loader' => redirect("/assets/umlaut_ui.js")
|
147
|
+
|
148
|
+
|
149
|
+
match 'images/spinner.gif' => redirect("/assets/spinner.gif")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def admin
|
154
|
+
add_routes do |options|
|
155
|
+
namespace "admin" do
|
156
|
+
match 'service_errors(/:service_id)' => "service_errors#index"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
include RouteSets
|
163
|
+
end
|
164
|
+
end
|
data/lib/umlaut/routes.rb
CHANGED
@@ -140,6 +140,12 @@ module Umlaut
|
|
140
140
|
# of Last-modified-by etc headers.
|
141
141
|
match 'javascripts/jquery/umlaut/update_html.js' => redirect("/assets/umlaut/update_html.js", :status => 301)
|
142
142
|
|
143
|
+
# The loader doens't work _exactly_ like the new umlaut-ui.js, but
|
144
|
+
# it's close enough that it'll work better redirecting than just
|
145
|
+
# 404'ing.
|
146
|
+
match 'js_helper/loader' => redirect("/assets/umlaut_ui.js")
|
147
|
+
|
148
|
+
|
143
149
|
match 'images/spinner.gif' => redirect("/assets/spinner.gif")
|
144
150
|
end
|
145
151
|
end
|
data/lib/umlaut/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: umlaut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.0beta5
|
5
5
|
prerelease: 5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &17186100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *17186100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: jquery-rails
|
27
|
-
requirement: &
|
27
|
+
requirement: &17185560 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *17185560
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: nokogiri
|
38
|
-
requirement: &
|
38
|
+
requirement: &17184800 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - =
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.5.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *17184800
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: openurl
|
49
|
-
requirement: &
|
49
|
+
requirement: &17184180 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.3.0
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *17184180
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: marc
|
60
|
-
requirement: &
|
60
|
+
requirement: &17183420 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.4.3
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *17183420
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: isbn
|
71
|
-
requirement: &
|
71
|
+
requirement: &17182120 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *17182120
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: htmlentities
|
82
|
-
requirement: &
|
82
|
+
requirement: &17180260 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *17180260
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: multi_json
|
93
|
-
requirement: &
|
93
|
+
requirement: &17179300 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *17179300
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: confstruct
|
104
|
-
requirement: &
|
104
|
+
requirement: &17132240 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0.2'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *17132240
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: exlibris-primo
|
115
|
-
requirement: &
|
115
|
+
requirement: &17130980 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: 0.1.0
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *17130980
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: single_test
|
126
|
-
requirement: &
|
126
|
+
requirement: &17129720 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: 0.5.1
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *17129720
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: uglifier
|
137
|
-
requirement: &
|
137
|
+
requirement: &17128300 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ! '>='
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: '0'
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *17128300
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: therubyracer
|
148
|
-
requirement: &
|
148
|
+
requirement: &17126180 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ! '>='
|
@@ -153,10 +153,10 @@ dependencies:
|
|
153
153
|
version: '0'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *17126180
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: ruby-prof
|
159
|
-
requirement: &
|
159
|
+
requirement: &17523620 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ! '>='
|
@@ -164,7 +164,7 @@ dependencies:
|
|
164
164
|
version: '0'
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *17523620
|
168
168
|
description:
|
169
169
|
email:
|
170
170
|
- umlaut-general@rubyforge.org
|
@@ -213,11 +213,13 @@ files:
|
|
213
213
|
- app/assets/javascripts/umlaut_ui.js
|
214
214
|
- app/assets/javascripts/umlaut.js
|
215
215
|
- app/assets/javascripts/umlaut/update_html.js
|
216
|
+
- app/assets/javascripts/umlaut/#simple_visible_toggle.js#
|
216
217
|
- app/assets/javascripts/umlaut/ajax_windows.js
|
217
218
|
- app/assets/javascripts/umlaut/simple_visible_toggle.js
|
218
219
|
- app/assets/javascripts/umlaut/ensure_window_size.js.erb
|
220
|
+
- app/assets/javascripts/umlaut/expand_contract_toggle.js
|
219
221
|
- app/assets/javascripts/umlaut/search_autocomplete.js
|
220
|
-
- app/assets/javascripts/umlaut
|
222
|
+
- app/assets/javascripts/umlaut/#update_html.js#
|
221
223
|
- app/assets/stylesheets/umlaut.css
|
222
224
|
- app/models/sfx_url.rb
|
223
225
|
- app/models/crossref_lookup.rb
|
@@ -321,6 +323,7 @@ files:
|
|
321
323
|
- lib/opensearch_feed.rb
|
322
324
|
- lib/holding.rb
|
323
325
|
- lib/umlaut_configurable.rb
|
326
|
+
- lib/umlaut/#routes.rb#
|
324
327
|
- lib/umlaut/routes.rb
|
325
328
|
- lib/umlaut/version.rb
|
326
329
|
- lib/umlaut/default_configuration.rb
|
@@ -333,6 +336,7 @@ files:
|
|
333
336
|
- lib/service_adaptors/primo_service.rb
|
334
337
|
- lib/service_adaptors/open_library.rb
|
335
338
|
- lib/service_adaptors/elsevier_cover.rb
|
339
|
+
- lib/service_adaptors/#blacklight.rb#
|
336
340
|
- lib/service_adaptors/ulrichs_link.rb
|
337
341
|
- lib/service_adaptors/ulrichs_cover.rb
|
338
342
|
- lib/service_adaptors/scopus.rb
|
@@ -481,7 +485,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
481
485
|
version: '0'
|
482
486
|
segments:
|
483
487
|
- 0
|
484
|
-
hash: -
|
488
|
+
hash: -986297622485492728
|
485
489
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
486
490
|
none: false
|
487
491
|
requirements:
|