blacklight-maps 0.0.1

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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +18 -0
  4. data/Gemfile +16 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +81 -0
  7. data/Rakefile +43 -0
  8. data/app/assets/javascripts/blacklight-maps.js +8 -0
  9. data/app/assets/javascripts/blacklight-maps/blacklight-maps-browse.js +141 -0
  10. data/app/assets/stylesheets/blacklight_maps/blacklight-maps.css.scss +4 -0
  11. data/app/assets/stylesheets/blacklight_maps/default.css.scss +24 -0
  12. data/app/helpers/blacklight_maps_helper.rb +36 -0
  13. data/app/views/catalog/_document_maps.html.erb +6 -0
  14. data/app/views/catalog/_index_maps.html.erb +9 -0
  15. data/blacklight-maps.gemspec +34 -0
  16. data/config/jetty.yml +7 -0
  17. data/config/locales/blacklight-maps.en.yml +5 -0
  18. data/config/routes.rb +4 -0
  19. data/docs/map-sidebar.png +0 -0
  20. data/docs/map-view.png +0 -0
  21. data/lib/blacklight/maps.rb +7 -0
  22. data/lib/blacklight/maps/engine.rb +32 -0
  23. data/lib/blacklight/maps/version.rb +5 -0
  24. data/lib/generators/blacklight_maps/install_generator.rb +25 -0
  25. data/lib/generators/blacklight_maps/templates/blacklight_maps.css.scss +3 -0
  26. data/lib/railties/blacklight_maps.rake +13 -0
  27. data/solr_conf/conf/schema.xml +673 -0
  28. data/solr_conf/conf/solrconfig.xml +523 -0
  29. data/spec/features/maps_spec.rb +79 -0
  30. data/spec/fixtures/sample_solr_documents.yml +2742 -0
  31. data/spec/helpers/blacklight_maps_helper_spec.rb +28 -0
  32. data/spec/spec_helper.rb +38 -0
  33. data/spec/test_app_templates/Gemfile.extra +7 -0
  34. data/spec/test_app_templates/lib/generators/test_app_generator.rb +23 -0
  35. metadata +268 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e35e471feb601eeeec9355dc1cc7e31d158f03bb
4
+ data.tar.gz: 8be5024c30a03decfb0e15563f79117606be1fec
5
+ SHA512:
6
+ metadata.gz: b019eae752da2b6cc576a759b09abb1d7799748c82603b0d13f20990f592e0ad51b35785abb6dda9370d5cbbd477c506ee26db9f73ae2cfa8aa7380ea584c707
7
+ data.tar.gz: a999abc043657b6f52ae34f1ce6d5479491b49812e2fa87b93257a3173de069a4e237d09e4cfb53869849d939803554842a918aec59e78c182d94be3d02f787b
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/internal
19
+ jetty
20
+ .DS_Store
data/.travis.yml ADDED
@@ -0,0 +1,18 @@
1
+ notifications:
2
+ email: false
3
+
4
+ rvm:
5
+ - 2.1.0
6
+ - 2.0.0
7
+ - 1.9.3
8
+ - jruby-19mode
9
+
10
+ notifications:
11
+ irc: "irc.freenode.org#blacklight"
12
+ email:
13
+ - blacklight-commits@googlegroups.com
14
+
15
+ env:
16
+ global:
17
+ - JRUBY_OPTS="-J-Xms512m -J-Xmx1024m"
18
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in blacklight-maps.gemspec
4
+ gemspec
5
+
6
+ gem 'simplecov', require: false
7
+ gem 'coveralls', require: false
8
+
9
+ gem 'engine_cart', git: 'https://github.com/cbeer/engine_cart'
10
+
11
+
12
+ file = File.expand_path("Gemfile", ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path("../spec/internal", __FILE__))
13
+ if File.exists?(file)
14
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
15
+ instance_eval File.read(file)
16
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014 The Board of Trustees of the Leland Stanford Junior University.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Blacklight::Maps
2
+
3
+ [![Build Status](https://travis-ci.org/sul-dlss/blacklight-maps.png?branch=master)](https://travis-ci.org/sul-dlss/blacklight-maps)
4
+
5
+ Provides a map view for Blacklight search results.
6
+
7
+ ![Screen shot](docs/map-view.png)
8
+ ![Screen shot](docs/map-sidebar.png)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'blacklight-maps'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install blacklight-maps
23
+
24
+ ## Usage
25
+
26
+ Blacklight-Maps adds a map view capability for a results set that contains geospatial coordinates (latitude/longitude).
27
+
28
+ For now, Blacklight-Maps requires that your SOLR index includes a field containing placenames with latitude and longitude coordinates delimited by `|`. This field can be multivalued.
29
+
30
+ A document requires the following field:
31
+ ```
32
+ placename_coords:
33
+ - China|35.86166|104.195397
34
+ - Tibet|29.646923|91.117212
35
+ - India|20.593684|78.96288
36
+ ```
37
+
38
+ Note: We are looking at implementing support for additional fields.
39
+
40
+ ### Configuration
41
+
42
+ #### Required
43
+ Blacklight-Maps expects you to provide:
44
+
45
+ - a field to map the placename coordinates (`placename_coords` in the example above)
46
+
47
+ #### Optional
48
+
49
+ - the maxZoom [property of the map](http://leafletjs.com/reference.html#map-maxzoom)
50
+ - a [tileLayer url](http://leafletjs.com/reference.html#tilelayer-l.tilelayer) to change the basemap
51
+ - an [attribution string](http://leafletjs.com/reference.html#tilelayer-attribution) to describe the basemap layer
52
+
53
+
54
+ All of these options can easily be configured in `CatalogController.rb` in the `config` block.
55
+
56
+ ```
57
+ ...
58
+ configure_blacklight do |config|
59
+ ## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
60
+ config.default_solr_params = {
61
+ :qt => 'search',
62
+ :rows => 10,
63
+ :fl => '*'
64
+ }
65
+
66
+ ## Default values
67
+ config.view.maps.placename_coords_field = "placename_coords"
68
+ config.view.maps.tileurl = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
69
+ config.view.maps.attribution = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
70
+ ...
71
+
72
+ ```
73
+
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( http://github.com/<my-github-username>/blacklight-maps/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ ZIP_URL = "https://github.com/projectblacklight/blacklight-jetty/archive/v4.6.0.zip"
4
+ APP_ROOT = File.dirname(__FILE__)
5
+
6
+ require 'rspec/core/rake_task'
7
+ require 'engine_cart/rake_task'
8
+
9
+ require 'jettywrapper'
10
+
11
+ task default: :ci
12
+
13
+ RSpec::Core::RakeTask.new(:spec)
14
+
15
+ desc "Load fixtures"
16
+ task :fixtures => ['engine_cart:generate'] do
17
+ EngineCart.within_test_app do
18
+ system "rake blacklight_maps:solr:seed RAILS_ENV=test"
19
+ end
20
+ end
21
+
22
+ desc "Execute Continuous Integration build"
23
+ task :ci => ['engine_cart:generate', 'jetty:clean', 'blacklight_maps:configure_jetty'] do
24
+
25
+ require 'jettywrapper'
26
+ jetty_params = Jettywrapper.load_config('test')
27
+
28
+ error = Jettywrapper.wrap(jetty_params) do
29
+ Rake::Task['fixtures'].invoke
30
+ Rake::Task['spec'].invoke
31
+ end
32
+ raise "test failures: #{error}" if error
33
+ end
34
+
35
+
36
+ namespace :blacklight_maps do
37
+ desc "Copies the default SOLR config for the bundled Testing Server"
38
+ task :configure_jetty do
39
+ FileList['solr_conf/conf/*'].each do |f|
40
+ cp("#{f}", 'jetty/solr/blacklight-core/conf/', :verbose => true)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+ // for Blacklight.onLoad:
2
+ //= require blacklight/core
3
+
4
+ //= require leaflet
5
+ //= require leaflet.markercluster
6
+ //= require L.Control.Sidebar
7
+
8
+ //= require_tree './blacklight-maps'
@@ -0,0 +1,141 @@
1
+ var map, sidebar;
2
+
3
+ Blacklight.onLoad(function() {
4
+
5
+ // Stop doing stuff if the map div isn't there
6
+ if ($("#blacklight-map").length === 0){
7
+ return;
8
+ }
9
+
10
+ // Get the configuration options from the data-attributes
11
+ $.extend(Blacklight.mapOptions, $("#blacklight-map").data());
12
+
13
+ map = L.map('blacklight-map').setView([0,0], 2);
14
+ L.tileLayer(Blacklight.mapOptions.tileurl, {
15
+ attribution: Blacklight.mapOptions.mapattribution,
16
+ maxZoom: Blacklight.mapOptions.maxzoom
17
+ }).addTo(map);
18
+
19
+ // Sets up leaflet-sidebar
20
+ sidebar = L.control.sidebar('blacklight-map-sidebar', {
21
+ position: 'right',
22
+ autoPan: false
23
+ });
24
+
25
+ // Adds leaflet-sidebar control to map (object)
26
+ map.addControl(sidebar);
27
+
28
+ // Create a marker cluster object and set options
29
+ markers = new L.MarkerClusterGroup({
30
+ showCoverageOnHover: false,
31
+ spiderfyOnMaxZoom: false,
32
+ singleMarkerMode: true,
33
+ animateAddingMarkers: true
34
+ });
35
+
36
+ geoJsonLayer = L.geoJson(geojson_docs, {
37
+ onEachFeature: function(feature, layer){
38
+ layer.defaultOptions.title = feature.properties.placename;
39
+ layer.on('click', function(e){
40
+ if (sidebar.isVisible()){
41
+ sidebar.hide();
42
+ }
43
+ var placenames = {};
44
+ placenames[feature.properties.placename] = [feature.properties.html];
45
+ offsetMap(e);
46
+ $('#blacklight-map-sidebar').html(buildList(placenames));
47
+ sidebar.show();
48
+ });
49
+ }
50
+ });
51
+
52
+ // Add GeoJSON layer to marker cluster object
53
+ markers.addLayer(geoJsonLayer);
54
+
55
+ // Add marker cluster object to map
56
+ map.addLayer(markers);
57
+
58
+ // Listeners for marker cluster clicks
59
+ markers.on('clusterclick', function(e){
60
+
61
+ //hide sidebar if it is visible
62
+ if (sidebar.isVisible()){
63
+ sidebar.hide();
64
+ }
65
+
66
+ //if map is at the lowest zoom level
67
+ if (map.getZoom() === Blacklight.mapOptions.maxzoom){
68
+
69
+ var placenames = generatePlacenamesObject(e.layer._markers);
70
+
71
+
72
+ offsetMap(e);
73
+
74
+ //Update sidebar div with new html
75
+ $('#blacklight-map-sidebar').html(buildList(placenames));
76
+
77
+ //Show the sidebar!
78
+ sidebar.show();
79
+ }
80
+ });
81
+
82
+ //Add click listener to map
83
+ map.on('click', function(e){
84
+
85
+ //hide the sidebar if it is visible
86
+ if (sidebar.isVisible()){
87
+ sidebar.hide();
88
+ }
89
+ });
90
+
91
+ //drag listener on map
92
+ map.on('drag', function(e){
93
+
94
+ //hide the sidebar if it is visible
95
+ if (sidebar.isVisible()){
96
+ sidebar.hide();
97
+ }
98
+ });
99
+
100
+ });
101
+
102
+ Blacklight.mapOptions = {
103
+ tileurl : 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
104
+ mapattribution : 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
105
+ };
106
+
107
+ function buildList(placenames){
108
+ var html = "";
109
+ $.each(placenames, function(i,val){
110
+ html += "<h2>" + i + "</h2>";
111
+ html += "<ul class='sidebar-list'>";
112
+ $.each(val, function(j, val2){
113
+ html += val2;
114
+ });
115
+ html += "</ul>";
116
+ });
117
+ return html;
118
+ }
119
+
120
+ // Generates placenames object
121
+ function generatePlacenamesObject(markers){
122
+ var placenames = {};
123
+ $.each(markers, function(i,val){
124
+ if (!(val.feature.properties.placename in placenames)){
125
+ placenames[val.feature.properties.placename] = [];
126
+ }
127
+ placenames[val.feature.properties.placename].push(val.feature.properties.html);
128
+ });
129
+ return placenames;
130
+ }
131
+
132
+ // Move the map so that it centers the clicked cluster TODO account for various size screens
133
+ function offsetMap(e){
134
+ mapWidth = $('#blacklight-map').width();
135
+ mapHeight = $('#blacklight-map').height();
136
+ if (!e.latlng.equals(map.getCenter())){
137
+ map.panBy([(e.originalEvent.layerX - (mapWidth/4)), (e.originalEvent.layerY - (mapHeight/2))]);
138
+ }else{
139
+ map.panBy([(mapWidth/4), 0]);
140
+ }
141
+ }
@@ -0,0 +1,4 @@
1
+ /* Master manifest file for engine, so local app can require
2
+ * this one file, but get all our files -- and local app
3
+ * require does not need to change if we change file list.
4
+ */
@@ -0,0 +1,24 @@
1
+ /*
2
+ *= require leaflet
3
+ *= require leaflet.markercluster
4
+ *= require leaflet.markercluster.default
5
+ *= require L.Control.Sidebar.css
6
+ */
7
+
8
+ .view-icon-maps {
9
+ &:before { content: "\e135"; }
10
+ }
11
+
12
+ #blacklight-map{
13
+ height: 550px;
14
+ }
15
+
16
+ .sidebar-thumb{
17
+ height: 64px;
18
+ width: 64px;
19
+ }
20
+
21
+ .sidebar-list{
22
+ padding-left: 0;
23
+ list-style: none;
24
+ }
@@ -0,0 +1,36 @@
1
+ module BlacklightMapsHelper
2
+
3
+ def show_map_div
4
+ data_attributes = {
5
+ :maxzoom => blacklight_config.view.maps.maxzoom,
6
+ :tileurl => blacklight_config.view.maps.tileurl
7
+
8
+ }
9
+
10
+ content_tag(:div, "", id: "blacklight-map",
11
+ data: data_attributes
12
+ )
13
+ end
14
+
15
+ def serialize_geojson
16
+ geojson_docs = {type: "FeatureCollection", features: []}
17
+ @response.docs.each_with_index do |doc, counter|
18
+ if doc[blacklight_config.view.maps.placename_coord_field]
19
+ doc[blacklight_config.view.maps.placename_coord_field].each do |loc|
20
+ values = loc.split('|')
21
+ feature = {type: "Feature", geometry: {type: "Point",
22
+ coordinates: [values[2].to_f, values[1].to_f]},
23
+ properties: {placename: values[0],
24
+ html: render_leaflet_sidebar_partial(doc)}}
25
+ geojson_docs[:features].push feature
26
+ end
27
+ end
28
+ end
29
+ return geojson_docs.to_json
30
+ end
31
+
32
+ def render_leaflet_sidebar_partial(doc)
33
+ render partial: 'catalog/index_maps', locals: {document: SolrDocument.new(doc)}
34
+ end
35
+
36
+ end
@@ -0,0 +1,6 @@
1
+ <% # container for all documents in map view -%>
2
+ <div id="documents" class="map">
3
+ <%= show_map_div() %>
4
+ <div id="blacklight-map-sidebar"></div>
5
+ <%= javascript_tag "var geojson_docs = #{serialize_geojson}" %>
6
+ </div>
@@ -0,0 +1,9 @@
1
+ <% # the way each document will be viewed in the sidebar list -%>
2
+ <li class='media'>
3
+ <%= render_thumbnail_tag document, {class: 'sidebar-thumb media-object'}, {class: 'pull-left'} %>
4
+ <div class='media-body'>
5
+ <h4 class='media-heading'>
6
+ <%= link_to_document document, :label=>document_show_link_field(document) %>
7
+ </h4>
8
+ </div>
9
+ </li>