From 96dcebd54c2d698f23b93c78550e202bb1f1abab Mon Sep 17 00:00:00 2001 From: franpb14 Date: Wed, 12 May 2021 17:45:30 +0200 Subject: [PATCH 1/3] feat: the map is working with the leaflet-rails gem I have also added two attributes (latitude and longitude) for the organisation and therefore changed forms for active-admin and update. I have also created a personalised marker. Issue #636. --- Gemfile | 1 + Gemfile.lock | 3 + app/admin/organization.rb | 2 + app/assets/images/marker-icon.png | Bin 0 -> 1950 bytes app/assets/javascripts/application.js | 1 + app/assets/stylesheets/application.scss | 11 + .../stylesheets/application/leaflet.scss | 641 ++++++++++++++++++ app/controllers/organizations_controller.rb | 11 +- app/models/organization.rb | 2 + app/views/organizations/_form.html.erb | 2 + app/views/organizations/index.html.erb | 22 + config/locales/en.yml | 3 + ...latitude_and_longitude_to_organizations.rb | 8 + db/structure.sql | 9 +- 14 files changed, 712 insertions(+), 4 deletions(-) create mode 100644 app/assets/images/marker-icon.png create mode 100644 app/assets/stylesheets/application/leaflet.scss create mode 100644 db/migrate/20210511121353_add_latitude_and_longitude_to_organizations.rb diff --git a/Gemfile b/Gemfile index 173ad6a3b..9b603b861 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem 'pg_search', '~> 2.3.5' gem 'skylight', '~> 4.3.2' gem 'sidekiq', '~> 6.1.2' gem 'sidekiq-cron', '~> 1.2.0' +gem 'leaflet-rails', '~> 1.7.0' # Assets gem 'jquery-rails', '~> 4.3.5' diff --git a/Gemfile.lock b/Gemfile.lock index 29bae0528..580f89a0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -181,6 +181,8 @@ GEM kgio (2.11.3) launchy (2.5.0) addressable (~> 2.7) + leaflet-rails (1.7.0) + rails (>= 4.2.0) letter_opener (1.7.0) launchy (~> 2.2) listen (3.2.1) @@ -428,6 +430,7 @@ DEPENDENCIES jquery-rails (~> 4.3.5) json_translate (~> 4.0.0) kaminari (~> 1.2.1) + leaflet-rails (~> 1.7.0) letter_opener (~> 1.7.0) listen (~> 3.2.0) localeapp (~> 3.1) diff --git a/app/admin/organization.rb b/app/admin/organization.rb index a8d75a707..2e54f5582 100644 --- a/app/admin/organization.rb +++ b/app/admin/organization.rb @@ -23,6 +23,8 @@ f.input :address f.input :description f.input :public_opening_times + f.input :latitude + f.input :longitude end f.actions end diff --git a/app/assets/images/marker-icon.png b/app/assets/images/marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5106584a3b6e02e34896ff67d2d987db5b2c6a1f GIT binary patch literal 1950 zcmV;P2VwY$P)P001cn1^@s6z>|W`0004RX+uL$X=7sm z04R}lkvmHRK@^2QSA!B21uaA@Qm9xc1O>6wSl9#!QNdTUSvQH0U61VIr*Z2SYh8jh1#QAr8-BYLP-H___|Gt`|dByY$sB01)H5}I$9v68(G&99uV%ea(SbC9(9uz)1I4= z+AXsOk0evXh>#-BDmi?Hq}q~MZC|wLn`TWshWs50xZ=o=74M*^dFg6OO^a^Im!qI^ z|C^_m9vLomZ;3(ZISAhSpm7&|c7ovhI0$}Dp#BLi?TUX*avJ*-eW#-J9zxqDoL^P6 z)E-=HLD!?ByLwTom#L-G@OB2R3(#>3;iXbm<#kRUV0J^E=mz!=pkMa4E&l>)W@p77 zTbDlo000SaNLh0L01FZT01FZU(%pXi000HmNkl3$g6h8O9`)27B+On03 ztUs)wLK96%3{hf;8Wm&wqltT1l@NkU6H#h0AP5Nf10-P3L`g7g+CWT*2?=O01p?ZV z3b@d)6zEPnGjF?#_uevP`sTgP7|%;*I`5r(zO#Ji-1`vZk$G>utu@-qA0Lennjo+k zgE;DpnBqps)t@?!?AV&m1fYzOAkB_@=2kKjzh}qk%K#!SL72%f1C9VVj~JA63B->Y z4&KmM|5Q^Ln$*sfS?}(`eAK-kI|=WDD2a%E!#1+D5Filp!kKS|L@bGSla8B9PHkSy z{T6dTYE~ba2Bv68m9i>iU?k)UE|@eKEDBIY2oVQUc0T5&&fSoP;n_W$c&C za}83x{@^MWfhj_UkUs+D*}xSfDt$_5R7|R=JFrCkj~-fmxX3B?`e*`41`V*r&!iF~ z0Y=&b*K$GC$&{*zNEB`rxmw@9MjMtFNplwMH%Ah%tOudg)HitmKokg&Ykly<%!%;Q z?E7Hy*b&gylY)bdf5Uf8mw}hXAqjSFP^y(8fEl;v5ZPZf+>Bs9fLb*I7eS)ahBxL; zhu0syA8bm&;|$762MnpF^mA+|yF#>LIhTG$%%AN6-=Zi6 z?QOT=M9bAcpr+OiICG;57!Ia!%)$&O?L!z-c3O^tz#dG41*~Ee)b2SB2Toqlg>PQ` ztgg|~bN|4CZ;t^hD+=rr&rXLU4Du&4M1pIO?V;QxWWL;W>YfIngfs}wWc}37kfs@yV?!URD9DxG z?q~!z41%<5UFgdE?I$TFqY22d?$*M=u|=7Ybk=9K;=y^1d)->m+b7Kh7}FqO;JG1k z>VOOE>&%lukmhZRZ%U5tms{K2RhfCC(-;lRPiU!+^(y8U8 zMsd)3`JMu}BiS3{V%u;e$vcp$>c6RHV~gvBJl^;XVOwtCS9{-V-m>V+{|B;VUyOUa zUG~q2?CGMIhi~?E7N_j;ap^yTcRPu!-o)}oqCA|reCG?^hLcX`?X+v7OFQ4Bue_B3(&}PhCD1E224&>QJBQPeA z>#ZmRK svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Prevents IE11 from highlighting tiles in blue */ +.leaflet-tile::selection { + background: transparent; +} +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { + max-width: none !important; + max-height: none !important; + } + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: #2797af; +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; + } +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive, +svg.leaflet-image-layer.leaflet-interactive path { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #2797af; + font-weight: bold; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: image-url("/app/assets/images/marker-icon.png"); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #2797af; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #1d6f81; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + -ms-zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + } \ No newline at end of file diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 42eae556c..396ec2e0d 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -2,7 +2,9 @@ class OrganizationsController < ApplicationController before_action :load_resource, only: [:show, :edit, :update, :set_current] def index - organizations = Organization.all + @markers = [] + organizations = Organization.all + organizations.each { |org| add_marker(org) if org.latitude && org.longitude } organizations = organizations.search_by_query(params[:q]) if params[:q].present? @organizations = organizations.page(params[:page]).per(25) end @@ -46,6 +48,11 @@ def load_resource def organization_params params[:organization].permit(*%w[name theme email phone web public_opening_times description address - neighborhood city domain]) + neighborhood city domain latitude longitude]) + end + + def add_marker(org) + link_to_self = helpers.link_to(org, organization_path(org)) + @markers << { latlng: [org.latitude, org.longitude], popup: link_to_self } end end diff --git a/app/models/organization.rb b/app/models/organization.rb index dfc7a4b00..88484aa89 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -23,6 +23,8 @@ class Organization < ApplicationRecord has_many :documents, as: :documentable, dependent: :destroy validates :name, presence: true, uniqueness: true + validates :latitude, numericality: { less_than_or_equal_to: 90, greater_than_or_equal_to: -90 }, allow_blank: true + validates :longitude, numericality: { less_than_or_equal_to: 90, greater_than_or_equal_to: -90 }, allow_blank: true before_validation :ensure_url after_create :create_account diff --git a/app/views/organizations/_form.html.erb b/app/views/organizations/_form.html.erb index 56bfbbb17..6cd696669 100644 --- a/app/views/organizations/_form.html.erb +++ b/app/views/organizations/_form.html.erb @@ -9,5 +9,7 @@ <%= f.input :address %> <%= f.input :neighborhood %> <%= f.input :city %> + <%= f.input :latitude %> + <%= f.input :longitude %> <%= f.button :submit %> <% end %> diff --git a/app/views/organizations/index.html.erb b/app/views/organizations/index.html.erb index 1f3ccad94..c5ce35d58 100644 --- a/app/views/organizations/index.html.erb +++ b/app/views/organizations/index.html.erb @@ -13,6 +13,7 @@ value="<%= params[:q] %>"> + <%= link_to(t('.search_map'), "#map") %> @@ -46,3 +47,24 @@ +
+
+

+ <%= t '.search_map' %> +

+
+
+
+
+ <%= map(center: { latlng: [-8, -23], zoom: 3 }, + markers: @markers, + tile_layer: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + max_zoom: 19); %> +
+
+
+
+ <%= t '.visit_bdt_online' %> + <%= link_to(t('.map'), 'http://www.bdtonline.org/#buscatubanco') %>. +
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index 5b623ec2f..881770158 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -376,6 +376,9 @@ en: give_time: Give time to index: member_count: Number of users + search_map: Search on the map + visit_bdt_online: If you don't see any timebank here that you like you can look for another one on this + map: map new: new: New bank show: diff --git a/db/migrate/20210511121353_add_latitude_and_longitude_to_organizations.rb b/db/migrate/20210511121353_add_latitude_and_longitude_to_organizations.rb new file mode 100644 index 000000000..d188fb2da --- /dev/null +++ b/db/migrate/20210511121353_add_latitude_and_longitude_to_organizations.rb @@ -0,0 +1,8 @@ +class AddLatitudeAndLongitudeToOrganizations < ActiveRecord::Migration[6.1] + def change + change_table :organizations, bulk: true do |t| + t.decimal :latitude + t.decimal :longitude + end + end +end diff --git a/db/structure.sql b/db/structure.sql index 8c071d613..99f67ebec 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -390,7 +390,9 @@ CREATE TABLE public.organizations ( address text, neighborhood character varying, city character varying, - domain character varying + domain character varying, + latitude numeric, + longitude numeric ); @@ -1096,6 +1098,9 @@ INSERT INTO "schema_migrations" (version) VALUES ('20190523213421'), ('20190523225323'), ('20210423193937'), -('20210424174640'); +('20210424174640'), +('20210510195022'), +('20210511120417'), +('20210511121353'); From 372d496a2b1bfbed84f677732a6cf7b7f48b00a5 Mon Sep 17 00:00:00 2001 From: franpb14 Date: Wed, 12 May 2021 18:50:31 +0200 Subject: [PATCH 2/3] tests: the map markers and the update have been tested The validator has been tested and has also been tested with valid parameters. The assignment of markers has been tested as well. Issue #636 --- .../organizations_controller_spec.rb | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/spec/controllers/organizations_controller_spec.rb b/spec/controllers/organizations_controller_spec.rb index 20d71361f..a3baf1c25 100644 --- a/spec/controllers/organizations_controller_spec.rb +++ b/spec/controllers/organizations_controller_spec.rb @@ -2,7 +2,7 @@ let!(:organization) { Fabricate(:organization) } let(:member) { Fabricate(:member, organization: organization) } let(:user) { member.user } - let!(:second_organization) { Fabricate(:organization) } + let!(:second_organization) { Fabricate(:organization, latitude: 37.38, longitude: -6.98) } describe 'GET #index' do context 'without parameters' do @@ -11,6 +11,14 @@ expect(assigns(:organizations)).to eq([organization, second_organization]) end + + it 'assigns the markers' do + get :index + link = "#{second_organization}" + + expect(assigns(:markers)[0][:latlng]).to eq([37.38, -6.98]) + expect(assigns(:markers)[0][:popup]).to eq(link) + end end context 'a search is made' do @@ -95,6 +103,52 @@ organization.reload expect(organization.name).to eq('New org name') end + + it 'allows to update organization if latitude and longitude are fine' do + login(member.user) + coords = { latitude: 37.38, longitude: -6.98 } + post :update, params: { id: organization.id, organization: coords } + + organization.reload + expect(organization.latitude).to eq(37.38) + expect(organization.longitude).to eq(-6.98) + end + + it 'does not allow to update organization if latitude is greater than 90' do + login(member.user) + + post :update, params: { id: organization.id, organization: { latitude: 91 } } + + organization.reload + expect(organization.latitude).to eq(nil) + end + + it 'does not allow to update organization if longitude is greater than 90' do + login(member.user) + + post :update, params: { id: organization.id, organization: { longitude: 91 } } + + organization.reload + expect(organization.longitude).to eq(nil) + end + + it 'does not allow to update organization if longitude is less than 90' do + login(member.user) + + post :update, params: { id: organization.id, organization: { longitude: -91 } } + + organization.reload + expect(organization.longitude).to eq(nil) + end + + it 'does not allow to update organization if latitude is less than 90' do + login(member.user) + + post :update, params: { id: organization.id, organization: { latitude: -91 } } + + organization.reload + expect(organization.longitude).to eq(nil) + end end context 'without a logged user' do From 10bb5b0f7ee577835758c0254edaa02082653710 Mon Sep 17 00:00:00 2001 From: franpb14 Date: Wed, 12 May 2021 19:38:57 +0200 Subject: [PATCH 3/3] fix: checking the code I saw that I was validating the latitude as well as the longitude now the longitude can vary between [-180, 180]. --- app/models/organization.rb | 2 +- spec/controllers/organizations_controller_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/organization.rb b/app/models/organization.rb index 88484aa89..087f24489 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -24,7 +24,7 @@ class Organization < ApplicationRecord validates :name, presence: true, uniqueness: true validates :latitude, numericality: { less_than_or_equal_to: 90, greater_than_or_equal_to: -90 }, allow_blank: true - validates :longitude, numericality: { less_than_or_equal_to: 90, greater_than_or_equal_to: -90 }, allow_blank: true + validates :longitude, numericality: { less_than_or_equal_to: 180, greater_than_or_equal_to: -180 }, allow_blank: true before_validation :ensure_url after_create :create_account diff --git a/spec/controllers/organizations_controller_spec.rb b/spec/controllers/organizations_controller_spec.rb index a3baf1c25..9e78f7e38 100644 --- a/spec/controllers/organizations_controller_spec.rb +++ b/spec/controllers/organizations_controller_spec.rb @@ -126,7 +126,7 @@ it 'does not allow to update organization if longitude is greater than 90' do login(member.user) - post :update, params: { id: organization.id, organization: { longitude: 91 } } + post :update, params: { id: organization.id, organization: { longitude: 181 } } organization.reload expect(organization.longitude).to eq(nil) @@ -135,7 +135,7 @@ it 'does not allow to update organization if longitude is less than 90' do login(member.user) - post :update, params: { id: organization.id, organization: { longitude: -91 } } + post :update, params: { id: organization.id, organization: { longitude: -181 } } organization.reload expect(organization.longitude).to eq(nil)