blacklight-maps 0.2.0 → 0.3.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +120 -42
  4. data/app/assets/javascripts/blacklight-maps.js +1 -2
  5. data/app/assets/javascripts/blacklight-maps/blacklight-maps-browse.js +122 -96
  6. data/app/assets/stylesheets/blacklight_maps/blacklight-maps.css.scss +5 -1
  7. data/app/assets/stylesheets/blacklight_maps/default.css.scss +74 -12
  8. data/app/helpers/blacklight/blacklight_maps_helper_behavior.rb +125 -0
  9. data/app/helpers/blacklight_maps_helper.rb +1 -24
  10. data/app/views/catalog/_document_maps.html.erb +1 -3
  11. data/app/views/catalog/_index_map.html.erb +7 -0
  12. data/app/views/catalog/_map_placename_search.html.erb +8 -0
  13. data/app/views/catalog/_map_spatial_search.html.erb +6 -0
  14. data/app/views/catalog/_show_maplet_default.html.erb +11 -0
  15. data/app/views/catalog/map.html.erb +8 -0
  16. data/blacklight-maps.gemspec +1 -2
  17. data/config/locales/blacklight-maps.en.yml +17 -1
  18. data/config/routes.rb +2 -2
  19. data/docs/blacklight-maps_index-view.png +0 -0
  20. data/docs/blacklight-maps_map-view.png +0 -0
  21. data/docs/blacklight-maps_search-control.png +0 -0
  22. data/docs/blacklight-maps_show-view.png +0 -0
  23. data/lib/blacklight/maps.rb +16 -0
  24. data/lib/blacklight/maps/controller_override.rb +33 -0
  25. data/lib/blacklight/maps/engine.rb +14 -6
  26. data/lib/blacklight/maps/export.rb +102 -61
  27. data/lib/blacklight/maps/render_constraints_override.rb +62 -0
  28. data/lib/blacklight/maps/version.rb +1 -1
  29. data/lib/generators/blacklight_maps/templates/blacklight_maps.css.scss +1 -1
  30. data/solr_conf/conf/schema.xml +4 -1
  31. data/spec/controllers/catalog_controller_spec.rb +22 -0
  32. data/spec/features/maps_spec.rb +194 -61
  33. data/spec/fixtures/sample_solr_documents.yml +73 -72
  34. data/spec/helpers/blacklight_maps_helper_spec.rb +134 -12
  35. data/spec/lib/blacklight/maps/controller_override_spec.rb +34 -0
  36. data/spec/lib/blacklight/maps/export_spec.rb +178 -35
  37. data/spec/lib/blacklight/maps/render_constraints_override_spec.rb +95 -0
  38. data/spec/spec_helper.rb +1 -1
  39. data/spec/test_app_templates/Gemfile.extra +0 -2
  40. metadata +22 -21
  41. data/app/views/catalog/_index_maps.html.erb +0 -9
  42. data/docs/map-sidebar.png +0 -0
  43. data/docs/map-view.png +0 -0
@@ -1,4 +1,8 @@
1
1
  /* Master manifest file for engine, so local app can require
2
2
  * this one file, but get all our files -- and local app
3
3
  * require does not need to change if we change file list.
4
- */
4
+ */
5
+
6
+ @charset "UTF-8";
7
+
8
+ @import 'default';
@@ -1,27 +1,89 @@
1
1
  @import 'leaflet';
2
2
  @import 'leaflet.markercluster';
3
3
  @import 'leaflet.markercluster.default';
4
- @import 'L.Control.Sidebar';
4
+
5
+ body.blacklight-catalog-map {
6
+
7
+ #map_leader_text {
8
+ margin-bottom: 10px;
9
+ }
10
+
11
+ .view-type {
12
+ display:none;
13
+ }
14
+
15
+ }
5
16
 
6
17
  .view-icon-maps {
7
18
  &:before { content: "\e135"; }
8
19
  }
9
20
 
10
- #blacklight-map{
11
- height: 550px;
21
+ #sortAndPerPage {
22
+
23
+ .page_links {
24
+
25
+ .mapped-count {
26
+ margin-left: 7px;
27
+ color: dimgray;
28
+ }
29
+
30
+ .mapped-caveat {
31
+ margin-left: 7px;
32
+ font-size: 12px;
33
+ color: darkgray;
34
+ }
35
+
36
+ }
37
+
38
+ }
39
+
40
+ #documents {
41
+
42
+ #blacklight-index-map {
43
+ height: 550px;
44
+ margin: 10px 0;
45
+
46
+ & ~ div.record-padding {
47
+
48
+ div.pagination {
49
+ display: none;
50
+ }
51
+
52
+ }
53
+
54
+ }
55
+
56
+ }
57
+
58
+ #document #blacklight-show-map {
59
+ height: 300px;
12
60
  }
13
61
 
14
- .badge.mapped-count {
15
- margin-left: 8px;
62
+ .mapped-count .badge {
16
63
  vertical-align: text-bottom;
17
64
  }
18
65
 
19
- .sidebar-thumb{
20
- height: 64px;
21
- width: 64px;
66
+ a.leaflet-bar-part.search-control {
67
+ cursor: pointer;
68
+ }
69
+
70
+ /* Portrait tablet to landscape and desktop */
71
+ @media (min-width: 768px) and (max-width: 991px) {
72
+
73
+ #sortAndPerPage {
74
+
75
+ .page_links {
76
+ width: 75%;
77
+ padding: 0 12px 0 0;
78
+
79
+ .mapped-caveat {
80
+ margin-left: 0;
81
+ float: left;
82
+ }
83
+
84
+ }
85
+
86
+ }
87
+
22
88
  }
23
89
 
24
- .sidebar-list{
25
- padding-left: 0;
26
- list-style: none;
27
- }
@@ -0,0 +1,125 @@
1
+ module Blacklight::BlacklightMapsHelperBehavior
2
+
3
+ # @param [String] id the html id
4
+ # @param [Hash] tag_options options to put on the tag
5
+ def blacklight_map_tag id, tag_options = {}, &block
6
+ default_data = {
7
+ maxzoom: blacklight_config.view.maps.maxzoom,
8
+ tileurl: blacklight_config.view.maps.tileurl,
9
+ mapattribution: blacklight_config.view.maps.mapattribution
10
+ }
11
+
12
+ options = {id: id, data: default_data}.deep_merge(tag_options)
13
+ if block_given?
14
+ content_tag(:div, options, &block)
15
+ else
16
+ tag(:div, options)
17
+ end
18
+ end
19
+
20
+ # return the placename value to be used as a link
21
+ def placename_value(geojson_hash)
22
+ geojson_hash[:properties][blacklight_config.view.maps.placename_property.to_sym]
23
+ end
24
+
25
+ # create a link to a bbox spatial search
26
+ def link_to_bbox_search bbox_coordinates
27
+ coords_for_search = bbox_coordinates.map { |v| v.to_s }
28
+ link_to(t('blacklight.maps.interactions.bbox_search'),
29
+ catalog_index_path(spatial_search_type: "bbox",
30
+ coordinates: "[#{coords_for_search[1]},#{coords_for_search[0]} TO #{coords_for_search[3]},#{coords_for_search[2]}]"))
31
+ end
32
+
33
+ # create a link to a location name facet value
34
+ def link_to_placename_field field_value, field, displayvalue = nil
35
+ if params[:f] && params[:f][field] && params[:f][field].include?(field_value)
36
+ new_params = params
37
+ else
38
+ new_params = add_facet_params(field, field_value)
39
+ end
40
+ link_to(displayvalue.presence || field_value,
41
+ catalog_index_path(new_params.except(:view, :id, :spatial_search_type, :coordinates)))
42
+ end
43
+
44
+ # create a link to a spatial search for a set of point coordinates
45
+ def link_to_point_search point_coordinates
46
+ new_params = params.except(:controller, :action, :view, :id, :spatial_search_type, :coordinates)
47
+ new_params[:spatial_search_type] = "point"
48
+ new_params[:coordinates] = "#{point_coordinates[1]},#{point_coordinates[0]}"
49
+ link_to(t('blacklight.maps.interactions.point_search'), catalog_index_path(new_params))
50
+ end
51
+
52
+ # return the facet field containing geographic data
53
+ def map_facet_field
54
+ blacklight_config.view.maps.facet_mode == "coordinates" ?
55
+ blacklight_config.view.maps.coordinates_facet_field :
56
+ blacklight_config.view.maps.geojson_field
57
+ end
58
+
59
+ # return an array of Blacklight::SolrResponse::Facets::FacetItem items
60
+ def map_facet_values
61
+ if @response.facet_by_field_name(map_facet_field)
62
+ @response.facet_by_field_name(map_facet_field).items
63
+ else
64
+ []
65
+ end
66
+ end
67
+
68
+ # render the location name for the Leaflet popup
69
+ # separate from BlacklightMapsHelperBehavior#placename_value so
70
+ # location name display can be easily customized
71
+ def render_placename_heading(geojson_hash)
72
+ geojson_hash[:properties][blacklight_config.view.maps.placename_property.to_sym]
73
+ end
74
+
75
+ # render the map for #index and #map views
76
+ def render_index_map
77
+ render :partial => 'catalog/index_map',
78
+ :locals => {:geojson_features => serialize_geojson(map_facet_values)}
79
+ end
80
+
81
+ # determine the type of spatial search to use based on coordinates (bbox or point)
82
+ def render_spatial_search_link coordinates
83
+ if coordinates.length == 4
84
+ link_to_bbox_search(coordinates)
85
+ else
86
+ link_to_point_search(coordinates)
87
+ end
88
+ end
89
+
90
+ # pass the document or facet values to BlacklightMaps::GeojsonExport
91
+ def serialize_geojson(documents)
92
+ export = BlacklightMaps::GeojsonExport.new(controller,
93
+ controller.action_name,
94
+ documents)
95
+ export.to_geojson
96
+ end
97
+
98
+ # determine the best viewpoint for the map so all markers are visible
99
+ def set_viewpoint(geojson_features)
100
+ viewpoint = nil
101
+ geojson_docs = JSON.parse(geojson_features)["features"]
102
+ if !geojson_docs.blank?
103
+ if geojson_docs.length == 1
104
+ viewpoint = geojson_docs[0]["bbox"] ? nil : geojson_docs[0]["geometry"]["coordinates"].reverse
105
+ end
106
+ if geojson_docs.length > 1 || !viewpoint
107
+ longs, lats = [[],[]]
108
+ geojson_docs.each do |feature|
109
+ if feature["bbox"]
110
+ feature["bbox"].values_at(0,2).each {|long| longs << long }
111
+ feature["bbox"].values_at(1,3).each {|lat| lats << lat }
112
+ else
113
+ longs << feature["geometry"]["coordinates"][0]
114
+ lats << feature["geometry"]["coordinates"][1]
115
+ end
116
+ end
117
+ sorted_longs, sorted_lats = longs.sort, lats.sort
118
+ viewpoint = [[sorted_lats.first,sorted_longs.first],[sorted_lats.last,sorted_longs.last]]
119
+ end
120
+ end
121
+ viewpoint = [0,0] if !viewpoint
122
+ viewpoint
123
+ end
124
+
125
+ end
@@ -1,26 +1,3 @@
1
- # Helper methods used for Blacklight Maps
2
1
  module BlacklightMapsHelper
3
- # @param [String] id the html id
4
- # @param [Hash] tag_options options to put on the tag
5
- def blacklight_map_tag id, tag_options = {}, &block
6
- default_data = {
7
- maxzoom: blacklight_config.view.maps.maxzoom,
8
- tileurl: blacklight_config.view.maps.tileurl,
9
- type: blacklight_config.view.maps.type,
10
- mapattribution: blacklight_config.view.maps.mapattribution
11
- }
12
-
13
- options = {id: id, data: default_data}.deep_merge(tag_options)
14
- if block_given?
15
- content_tag(:div, options, &block)
16
- else
17
- tag(:div, options)
18
- end
19
- end
20
-
21
- def serialize_geojson
22
- export = BlacklightMaps::GeojsonExport.new(controller,
23
- @response.docs)
24
- export.to_geojson
25
- end
2
+ include Blacklight::BlacklightMapsHelperBehavior
26
3
  end
@@ -1,6 +1,4 @@
1
1
  <% # container for all documents in map view -%>
2
2
  <div id="documents" class="map">
3
- <%= blacklight_map_tag('blacklight-map') %>
4
- <div id="blacklight-map-sidebar"></div>
5
- <%= javascript_tag "$('#blacklight-map').blacklight_leaflet_map(#{serialize_geojson});" %>
3
+ <%= render_index_map %>
6
4
  </div>
@@ -0,0 +1,7 @@
1
+ <%= blacklight_map_tag('blacklight-index-map',
2
+ {data:{viewpoint: set_viewpoint(geojson_features),
3
+ searchcontrol: true,
4
+ catalogpath: catalog_index_path,
5
+ placenamefield: blacklight_config.view.maps.placename_field
6
+ }}) %>
7
+ <%= javascript_tag "$('#blacklight-index-map').blacklight_leaflet_map(#{geojson_features});" %>
@@ -0,0 +1,8 @@
1
+ <% # content for the popup for a point feature - run a new search for this location -%>
2
+ <h5 class="geo_popup_heading">
3
+ <%= render_placename_heading(geojson_hash) %>
4
+ <%= content_tag(:small, pluralize(hits, t('blacklight.maps.interactions.item'))) if hits %>
5
+ </h5>
6
+ <%= link_to_placename_field(placename_value(geojson_hash),
7
+ blacklight_config.view.maps.placename_field,
8
+ t('blacklight.maps.interactions.placename_search')) %>
@@ -0,0 +1,6 @@
1
+ <% # content for the popup for a point or bbox feature - run a new coordinate search for this location -%>
2
+ <h5 class="geo_popup_heading">
3
+ <%= coordinates.length == 2 ? coordinates.reverse : coordinates %>
4
+ <%= content_tag(:small, pluralize(hits, t('blacklight.maps.interactions.item'))) if hits %>
5
+ </h5>
6
+ <%= render_spatial_search_link(coordinates) %>
@@ -0,0 +1,11 @@
1
+ <% # map for catalog#show view %>
2
+ <div id="blacklight-show-map-container">
3
+ <% if @document[blacklight_config.view.maps.geojson_field.to_sym] || @document[blacklight_config.view.maps.coordinates_field.to_sym] %>
4
+ <% geojson_features = serialize_geojson(@document) %>
5
+ <%= blacklight_map_tag('blacklight-show-map',
6
+ {data:{viewpoint: set_viewpoint(geojson_features),
7
+ initialzoom:blacklight_config.view.maps.show_initial_zoom,
8
+ singlemarkermode:false}}) %>
9
+ <%= javascript_tag "$('#blacklight-show-map').blacklight_leaflet_map(#{geojson_features});" %>
10
+ <% end %>
11
+ </div>
@@ -0,0 +1,8 @@
1
+ <div id="content" class="col-md-12 col-sm-12">
2
+ <h1><%= t('blacklight.maps.title') %></h1>
3
+ <div id="map_leader_text"><%= t('blacklight.maps.leader') %></div>
4
+ <%= render 'search_results' %>
5
+ </div>
6
+
7
+ <%# have to put this at the end so it overrides 'catalog/search_results' %>
8
+ <% @page_title = t('blacklight.maps.title', :application_name => application_name) %>
@@ -22,11 +22,10 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "bootstrap-sass", "~> 3.0"
23
23
  spec.add_dependency "leaflet-rails"
24
24
  spec.add_dependency "leaflet-markercluster-rails"
25
- spec.add_dependency "leaflet-sidebar-rails", "~> 0.0.2"
26
25
 
27
26
  spec.add_development_dependency "bundler", "~> 1.5"
28
27
  spec.add_development_dependency "rake"
29
- spec.add_development_dependency "rspec-rails", "~> 2.9"
28
+ spec.add_development_dependency "rspec-rails", "~> 3.0"
30
29
  spec.add_development_dependency "jettywrapper"
31
30
  spec.add_development_dependency "engine_cart", "~> 0.4.0"
32
31
  spec.add_development_dependency "capybara"
@@ -1,5 +1,21 @@
1
1
  en:
2
2
  blacklight:
3
+
4
+ maps:
5
+ interactions:
6
+ bbox_search: 'View items that intersect with this bounding box'
7
+ placename_search: 'View items from this location'
8
+ item: 'item'
9
+ point_search: 'View items from this location'
10
+ search_ctrl_cue: 'Search for all items within the current map window'
11
+ title: 'Map'
12
+ leader: 'Click on a marker to search for items from that location.'
13
+
3
14
  search:
15
+ filters:
16
+ coordinates:
17
+ bbox: 'Bounding Box'
18
+ point: 'Coordinates'
4
19
  view:
5
- maps: "Map"
20
+ maps: 'Map'
21
+
data/config/routes.rb CHANGED
@@ -1,4 +1,4 @@
1
- Blacklight::Maps::Engine.routes.draw do
2
-
1
+ Rails.application.routes.draw do
2
+ get 'map', :to => 'catalog#map', :as => 'map'
3
3
  end
4
4
 
Binary file
Binary file
Binary file
@@ -2,8 +2,24 @@ require "blacklight/maps/version"
2
2
 
3
3
  module Blacklight
4
4
  module Maps
5
+ require 'blacklight/maps/controller_override'
6
+ require 'blacklight/maps/render_constraints_override'
5
7
  require 'blacklight/maps/engine'
6
8
  require 'blacklight/maps/export'
7
9
  require 'blacklight/maps/geometry'
10
+
11
+ def self.inject!
12
+ CatalogController.send(:include, BlacklightMaps::ControllerOverride)
13
+ CatalogController.send(:include, BlacklightMaps::RenderConstraintsOverride)
14
+ CatalogController.send(:helper, BlacklightMaps::RenderConstraintsOverride) unless
15
+ CatalogController.helpers.is_a?(BlacklightMaps::RenderConstraintsOverride)
16
+
17
+ # inject into SearchHistory and SavedSearches so spatial queries display properly
18
+ SearchHistoryController.send(:helper, BlacklightMaps::RenderConstraintsOverride) unless
19
+ SearchHistoryController.helpers.is_a?(BlacklightMaps::RenderConstraintsOverride)
20
+ SavedSearchesController.send(:helper, BlacklightMaps::RenderConstraintsOverride) unless
21
+ SavedSearchesController.helpers.is_a?(BlacklightMaps::RenderConstraintsOverride)
22
+ end
23
+
8
24
  end
9
25
  end
@@ -0,0 +1,33 @@
1
+ module BlacklightMaps
2
+ module ControllerOverride
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ solr_search_params_logic << :add_spatial_search_to_solr
6
+ end
7
+
8
+ def map
9
+ (@response, @document_list) = get_search_results
10
+ params[:view] = 'maps'
11
+ respond_to do |format|
12
+ format.html
13
+ end
14
+ end
15
+
16
+ # add spatial search params to solr
17
+ def add_spatial_search_to_solr(solr_parameters, user_parameters)
18
+ if user_parameters[:spatial_search_type] && user_parameters[:coordinates]
19
+ solr_parameters[:fq] ||= []
20
+ if user_parameters[:spatial_search_type] == 'bbox'
21
+ solr_parameters[:fq] << blacklight_config.view.maps.coordinates_field + ":" + user_parameters[:coordinates]
22
+ else
23
+ solr_parameters[:fq] << "{!geofilt sfield=#{blacklight_config.view.maps.coordinates_field}}"
24
+ solr_parameters[:pt] = user_parameters[:coordinates]
25
+ solr_parameters[:d] = blacklight_config.view.maps.spatial_query_dist
26
+ end
27
+ end
28
+ solr_parameters
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -1,25 +1,33 @@
1
1
  require 'blacklight'
2
2
  require 'leaflet-rails'
3
3
  require 'leaflet-markercluster-rails'
4
- require 'leaflet-sidebar-rails'
5
4
 
6
5
  module Blacklight
7
6
  module Maps
8
7
  class Engine < Rails::Engine
9
8
  # Set some default configurations
10
- Blacklight::Configuration.default_values[:view].maps.type = 'bbox'
11
- Blacklight::Configuration.default_values[:view].maps.bbox_field = 'place_bbox'
12
- Blacklight::Configuration.default_values[:view].maps.placename_coord_field = 'placename_coords'
9
+ Blacklight::Configuration.default_values[:view].maps.geojson_field = "geojson"
10
+ Blacklight::Configuration.default_values[:view].maps.placename_property = "placename"
11
+ Blacklight::Configuration.default_values[:view].maps.coordinates_field = "coordinates"
12
+ Blacklight::Configuration.default_values[:view].maps.search_mode = "placename" # or 'coordinates'
13
+ Blacklight::Configuration.default_values[:view].maps.spatial_query_dist = 0.5
14
+ Blacklight::Configuration.default_values[:view].maps.placename_field = "placename_field"
15
+ Blacklight::Configuration.default_values[:view].maps.coordinates_facet_field = "coordinates_facet_field"
16
+ Blacklight::Configuration.default_values[:view].maps.facet_mode = "geojson" # or 'coordinates'
13
17
  Blacklight::Configuration.default_values[:view].maps.tileurl = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
14
18
  Blacklight::Configuration.default_values[:view].maps.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>'
15
- Blacklight::Configuration.default_values[:view].maps.maxzoom = 8
16
- Blacklight::Configuration.default_values[:view].maps.placename_coord_delimiter = '-|-'
19
+ Blacklight::Configuration.default_values[:view].maps.maxzoom = 18
20
+ Blacklight::Configuration.default_values[:view].maps.show_initial_zoom = 5
17
21
 
18
22
  # Add our helpers
19
23
  initializer 'blacklight-maps.helpers' do |app|
20
24
  ActionView::Base.send :include, BlacklightMapsHelper
21
25
  end
22
26
 
27
+ config.to_prepare do
28
+ Blacklight::Maps.inject!
29
+ end
30
+
23
31
  # This makes our rake tasks visible.
24
32
  rake_tasks do
25
33
  Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))) do