blacklight-maps 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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