From 298e195a8fdc0f1bd024809fcda7f19c331b01bb Mon Sep 17 00:00:00 2001 From: zaziemo Date: Fri, 17 Jul 2015 16:58:53 +0200 Subject: [PATCH 01/11] add a map subview - add coordinates in post_presenter - add map to the SPV if location is provided - add leaflet.js to render map and marker of position - make coordinates available in frontend - add map scss - make stream post location clickable and redirect to the SPV - prevent render map if no location data is provided - add tests for coordinates - use the leaflet gem instead of the JS assets (#5813) --- Gemfile | 3 + Gemfile.lock | 2 + .../javascripts/app/views/content_view.js | 2 +- .../javascripts/app/views/location_map.js | 34 ++ .../single_post_content_view.js | 4 +- app/assets/javascripts/main.js | 1 + app/assets/stylesheets/_application.scss | 4 + app/assets/stylesheets/map.scss | 13 + app/assets/stylesheets/single-post-view.scss | 1 + app/assets/stylesheets/stream_element.scss | 2 +- .../single-post-content_tpl.jst.hbs | 1 + .../status-message-location_tpl.jst.hbs | 2 +- .../templates/status-message-map_tpl.jst.hbs | 4 + app/models/reshare.rb | 5 +- app/models/status_message.rb | 4 + app/presenters/post_presenter.rb | 1 + spec/factories.rb | 7 +- .../app/views/content_view_spec.js | 6 + spec/models/reshare_spec.rb | 266 ++++++------ spec/models/status_message_spec.rb | 380 +++++++++--------- 20 files changed, 424 insertions(+), 318 deletions(-) create mode 100644 app/assets/javascripts/app/views/location_map.js create mode 100644 app/assets/stylesheets/map.scss create mode 100644 app/assets/templates/status-message-map_tpl.jst.hbs diff --git a/Gemfile b/Gemfile index 0dd8f16ab..1017a84ac 100644 --- a/Gemfile +++ b/Gemfile @@ -128,6 +128,9 @@ gem "rails-i18n", "4.0.4" gem "markerb", "1.0.2" gem "messagebus_ruby_api", "1.0.3" +# Map +gem "leaflet-rails", "0.7.4" + # Parsing gem "nokogiri", "1.6.6.2" diff --git a/Gemfile.lock b/Gemfile.lock index 250f3e955..a73133859 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -409,6 +409,7 @@ GEM actionpack (>= 3.0.0) activesupport (>= 3.0.0) kgio (2.9.3) + leaflet-rails (0.7.4) listen (3.0.3) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) @@ -833,6 +834,7 @@ DEPENDENCIES jshintrb (= 0.3.0) json (= 1.8.3) json-schema (= 2.5.1) + leaflet-rails (= 0.7.4) logging-rails (= 0.5.0) markerb (= 1.0.2) messagebus_ruby_api (= 1.0.3) diff --git a/app/assets/javascripts/app/views/content_view.js b/app/assets/javascripts/app/views/content_view.js index bd00d36a4..20ddadb0d 100644 --- a/app/assets/javascripts/app/views/content_view.js +++ b/app/assets/javascripts/app/views/content_view.js @@ -29,7 +29,6 @@ app.views.Content = app.views.Base.extend({ return photos; }, - expandPost: function(evt) { var el = $(this.el).find('.collapsible'); el.removeClass('collapsed').addClass('opened'); @@ -155,4 +154,5 @@ app.views.SPVOpenGraph = app.views.OpenGraph.extend({ // override with nothing } }); + // @license-end diff --git a/app/assets/javascripts/app/views/location_map.js b/app/assets/javascripts/app/views/location_map.js new file mode 100644 index 000000000..e499e2371 --- /dev/null +++ b/app/assets/javascripts/app/views/location_map.js @@ -0,0 +1,34 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.views.LocationMap = app.views.Content.extend({ + templateName: "status-message-map", + + map: function() { + var coordinates = this.model.get("coordinates"); + + // if (coordinates != "" && tileserver.enable) { // for when the tileserver is set via the diaspora.yml + if (coordinates.lat) { + var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; + var map = L.map("map").setView([coordinates.lat, coordinates.lng], 16); + var attribution = "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox"; + + L.tileLayer(tileLayerSource, { + attribution: attribution, + maxZoom: 18, + id: "zaziemo.mpn66kn8", + accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" + }).addTo(map); + + var markerOnMap = L.marker(coordinates).addTo(map); + + return map; + } + }, + + postRenderTemplate : function(){ + _.defer(_.bind(this.map, this)); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 57bbbb791..92e5cb29e 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -11,7 +11,8 @@ app.views.SinglePostContent = app.views.Base.extend({ ".oembed" : "oEmbedView", ".opengraph" : "openGraphView", ".status-message-location" : "postLocationStreamView", - ".poll": "pollView" + ".map" : "postMapView", + '.poll': 'pollView', }, initialize : function() { @@ -20,6 +21,7 @@ app.views.SinglePostContent = app.views.Base.extend({ this.oEmbedView = new app.views.OEmbed({model : this.model}); this.openGraphView = new app.views.SPVOpenGraph({model : this.model}); this.postContentView = new app.views.ExpandedStatusMessage({model: this.model}); + this.postMapView = new app.views.LocationMap({model: this.model}); this.pollView = new app.views.Poll({ model: this.model }); }, diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 93891fb97..adc3bcc7a 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -45,3 +45,4 @@ //= require osmlocator //= require bootstrap-switch //= require blueimp-gallery +//= require leaflet diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss index b47584a22..edabd4527 100644 --- a/app/assets/stylesheets/_application.scss +++ b/app/assets/stylesheets/_application.scss @@ -42,6 +42,10 @@ @import 'single-post-view'; @import 'new_styles/poll'; +/* map*/ +@import 'leaflet'; +@import 'map'; + /* conversations */ @import 'conversations'; diff --git a/app/assets/stylesheets/map.scss b/app/assets/stylesheets/map.scss new file mode 100644 index 000000000..f210f8dbb --- /dev/null +++ b/app/assets/stylesheets/map.scss @@ -0,0 +1,13 @@ +#map { + height: 180px; + position: relative; + overflow: hidden; +} + +.leaflet-bottom .leaflet-control { + margin-bottom: 0; +} + +.leaflet-right .leaflet-control { + margin-right: 0; +} diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss index 82bf4d5bc..71ca37235 100644 --- a/app/assets/stylesheets/single-post-view.scss +++ b/app/assets/stylesheets/single-post-view.scss @@ -13,6 +13,7 @@ color: lighten($text-grey,10%); font-size: 12px; .post-time a { color: $text-grey; } + .near-from a { color: $text-grey; } .post_scope { margin-right: 5px; } .status-message-location { padding-top: 2px; diff --git a/app/assets/stylesheets/stream_element.scss b/app/assets/stylesheets/stream_element.scss index 9b2861c5a..1cf764c64 100644 --- a/app/assets/stylesheets/stream_element.scss +++ b/app/assets/stylesheets/stream_element.scss @@ -83,7 +83,7 @@ float: left; margin-top: 6px; } - .status-message-location .near-from { + .status-message-location .near-from a { font-size: $font-size-small; color: $text-grey; } diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs index 7c61fe741..4da6a3ead 100644 --- a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs @@ -99,4 +99,5 @@
+
diff --git a/app/assets/templates/status-message-location_tpl.jst.hbs b/app/assets/templates/status-message-location_tpl.jst.hbs index c6c7ea7ec..0d648125c 100644 --- a/app/assets/templates/status-message-location_tpl.jst.hbs +++ b/app/assets/templates/status-message-location_tpl.jst.hbs @@ -1,5 +1,5 @@ {{#if location}}
- {{ t "publisher.near_from" location=location}} + {{ t "publisher.near_from" location=location}}
{{/if}} diff --git a/app/assets/templates/status-message-map_tpl.jst.hbs b/app/assets/templates/status-message-map_tpl.jst.hbs new file mode 100644 index 000000000..87207d39c --- /dev/null +++ b/app/assets/templates/status-message-map_tpl.jst.hbs @@ -0,0 +1,4 @@ +{{#if location}} +
+
+{{/if}} diff --git a/app/models/reshare.rb b/app/models/reshare.rb index 93803af1d..f3cbdb2ed 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -3,7 +3,6 @@ # the COPYRIGHT file. class Reshare < Post - belongs_to :root, :class_name => 'Post', :foreign_key => :root_guid, :primary_key => :guid validate :root_must_be_public validates_presence_of :root, :on => :create @@ -49,6 +48,10 @@ class Reshare < Post absolute_root.try(:location).try(:address) end + def coordinates + {lat: absolute_root.try(:location).try(:lat), lng: absolute_root.try(:location).try(:lng)} + end + def poll absolute_root.try(:poll) || super end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 4dacee42c..b69a682d6 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -162,6 +162,10 @@ class StatusMessage < Post location.try(:address) end + def coordinates + {lat: location.try(:lat), lng: location.try(:lng)} + end + protected def presence_of_content if text_and_photos_blank? diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index b1df1a917..ea77b1530 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -32,6 +32,7 @@ class PostPresenter < BasePresenter root: root, title: title, address: @post.address, + coordinates: @post.coordinates, poll: @post.poll, already_participated_in_poll: already_participated_in_poll, participation: participate?, diff --git a/spec/factories.rb b/spec/factories.rb index 1f99c0f0b..a7cddc2b7 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -140,9 +140,10 @@ FactoryGirl.define do end factory(:location) do - address "unicorn city" - lat 1 - lng 2 + address "Starco Mart, Mission Street, West SoMa, San Francisco, San Francisco "\ + "City and County, Kalifornien, 94103, Vereinigte Staaten von Amerika" + lat 37.78 + lng -122.41 end factory(:poll) do diff --git a/spec/javascripts/app/views/content_view_spec.js b/spec/javascripts/app/views/content_view_spec.js index 6a701aaa3..218bc4e0f 100644 --- a/spec/javascripts/app/views/content_view_spec.js +++ b/spec/javascripts/app/views/content_view_spec.js @@ -24,5 +24,11 @@ describe("app.views.Content", function(){ this.post.set({post_type : "Reshare"}); expect(this.view.presenter().isReshare).toBeTruthy(); }); + + // it("provides coordinates", function(){ + // this.post.location; + // console.log(this.view.presenter()); + // console.log(this.post.location); + // }); }); }); diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index e235c4066..3661bae94 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -1,33 +1,33 @@ -require 'spec_helper' +require "spec_helper" -describe Reshare, :type => :model do - it 'has a valid Factory' do +describe Reshare, type: :model do + it "has a valid Factory" do expect(FactoryGirl.build(:reshare)).to be_valid end - it 'requires root' do - reshare = FactoryGirl.build(:reshare, :root => nil) + it "requires root" do + reshare = FactoryGirl.build(:reshare, root: nil) expect(reshare).not_to be_valid end - it 'require public root' do - reshare = FactoryGirl.build(:reshare, :root => FactoryGirl.create(:status_message, :public => false)) + it "require public root" do + reshare = FactoryGirl.build(:reshare, root: FactoryGirl.create(:status_message, public: false)) expect(reshare).not_to be_valid - expect(reshare.errors[:base]).to include('Only posts which are public may be reshared.') + expect(reshare.errors[:base]).to include("Only posts which are public may be reshared.") end - it 'forces public' do - expect(FactoryGirl.create(:reshare, :public => false).public).to be true + it "forces public" do + expect(FactoryGirl.create(:reshare, public: false).public).to be true end describe "#root_diaspora_id" do + let(:reshare) { create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) } + it "should return the root diaspora id" do - reshare = FactoryGirl.create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) expect(reshare.root_diaspora_id).to eq(bob.person.diaspora_handle) end it "should be nil if no root found" do - reshare = FactoryGirl.create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) reshare.root = nil expect(reshare.root_diaspora_id).to be_nil end @@ -37,195 +37,188 @@ describe Reshare, :type => :model do let(:receive_reshare) { @reshare.receive(@root.author.owner, @reshare.author) } before do - @reshare = FactoryGirl.create(:reshare, :root => FactoryGirl.build(:status_message, :author => bob.person, :public => true)) + @reshare = FactoryGirl.create(:reshare, root: + FactoryGirl.build(:status_message, author: bob.person, public: true)) @root = @reshare.root end - it 'increments the reshare count' do + it "increments the reshare count" do receive_reshare expect(@root.resharers.count).to eq(1) end - it 'adds the resharer to the re-sharers of the post' do + it "adds the resharer to the re-sharers of the post" do receive_reshare expect(@root.resharers).to include(@reshare.author) end - it 'does not error if the root author has a contact for the resharer' do + it "does not error if the root author has a contact for the resharer" do bob.share_with @reshare.author, bob.aspects.first expect { Timeout.timeout(5) do - receive_reshare #This doesn't ever terminate on my machine before it was fixed. + receive_reshare # This doesn't ever terminate on my machine before it was fixed. end }.not_to raise_error end end - describe '#nsfw' do - before do - sfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - nsfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true, :text => "This is #nsfw") - @sfw_reshare = FactoryGirl.build(:reshare, :root => sfw) - @nsfw_reshare = FactoryGirl.build(:reshare, :root => nsfw) - end + describe "#nsfw" do + let(:sfw) { build(:status_message, author: alice.person, public: true) } + let(:nsfw) { build(:status_message, author: alice.person, public: true, text: "This is #nsfw") } + let(:sfw_reshare) { build(:reshare, root: sfw) } + let(:nsfw_reshare) { build(:reshare, root: nsfw) } - it 'deletates #nsfw to the root post' do - expect(@sfw_reshare.nsfw).not_to be true - expect(@nsfw_reshare.nsfw).to be_truthy + it "deletates #nsfw to the root post" do + expect(sfw_reshare.nsfw).not_to be true + expect(nsfw_reshare.nsfw).to be_truthy end end - describe '#poll' do - before do - @root_post = FactoryGirl.create(:status_message_with_poll, public: true) - @reshare = FactoryGirl.create(:reshare, root: @root_post) - end + describe "#poll" do + let(:root_post) { create(:status_message_with_poll, public: true) } + let(:reshare) { create(:reshare, root: root_post) } - it 'contains root poll' do - expect(@reshare.poll).to eq @root_post.poll + it "contains root poll" do + expect(reshare.poll).to eq root_post.poll end end - describe '#notification_type' do - before do - sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - @reshare = FactoryGirl.build(:reshare, :root => sm) - end - it 'does not return anything for non-author of the original post' do - expect(@reshare.notification_type(bob, @reshare.author)).to be_nil + describe "#notification_type" do + let(:status_message) { build(:status_message, author: alice.person, public: true) } + let(:reshare) { build(:reshare, root: status_message) } + + it "does not return anything for non-author of the original post" do + expect(reshare.notification_type(bob, reshare.author)).to be_nil end - it 'returns "Reshared" for the original post author' do - expect(@reshare.notification_type(alice, @reshare.author)).to eq(Notifications::Reshared) + it "returns 'Reshared' for the original post author" do + expect(reshare.notification_type(alice, reshare.author)).to eq(Notifications::Reshared) end - it 'does not error out if the root was deleted' do - @reshare.root = nil + it "does not error out if the root was deleted" do + reshare.root = nil expect { - @reshare.notification_type(alice, @reshare.author) + reshare.notification_type(alice, reshare.author) }.to_not raise_error end end - describe '#absolute_root' do + describe "#absolute_root" do before do - @sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - rs1 = FactoryGirl.build(:reshare, :root=>@sm) - rs2 = FactoryGirl.build(:reshare, :root=>rs1) - @rs3 = FactoryGirl.build(:reshare, :root=>rs2) + @status_message = FactoryGirl.build(:status_message, author: alice.person, public: true) + reshare_1 = FactoryGirl.build(:reshare, root: @status_message) + reshare_2 = FactoryGirl.build(:reshare, root: reshare_1) + @reshare_3 = FactoryGirl.build(:reshare, root: reshare_2) - sm = FactoryGirl.create(:status_message, :author => alice.person, :public => true) - rs1 = FactoryGirl.create(:reshare, :root => sm) - @of_deleted = FactoryGirl.build(:reshare, :root => rs1) - sm.destroy - rs1.reload + status_message = FactoryGirl.create(:status_message, author: alice.person, public: true) + reshare_1 = FactoryGirl.create(:reshare, root: status_message) + @of_deleted = FactoryGirl.build(:reshare, root: reshare_1) + status_message.destroy + reshare_1.reload end - it 'resolves root posts to the top level' do - expect(@rs3.absolute_root).to eq(@sm) + it "resolves root posts to the top level" do + expect(@reshare_3.absolute_root).to eq(@status_message) end - it 'can handle deleted reshares' do + it "can handle deleted reshares" do expect(@of_deleted.absolute_root).to be_nil end - it 'is used everywhere' do - expect(@rs3.message).to eq @sm.message + it "is used everywhere" do + expect(@reshare_3.message).to eq @status_message.message expect(@of_deleted.message).to be_nil - expect(@rs3.photos).to eq @sm.photos + expect(@reshare_3.photos).to eq @status_message.photos expect(@of_deleted.photos).to be_empty - expect(@rs3.o_embed_cache).to eq @sm.o_embed_cache + expect(@reshare_3.o_embed_cache).to eq @status_message.o_embed_cache expect(@of_deleted.o_embed_cache).to be_nil - expect(@rs3.open_graph_cache).to eq @sm.open_graph_cache + expect(@reshare_3.open_graph_cache).to eq @status_message.open_graph_cache expect(@of_deleted.open_graph_cache).to be_nil - expect(@rs3.mentioned_people).to eq @sm.mentioned_people + expect(@reshare_3.mentioned_people).to eq @status_message.mentioned_people expect(@of_deleted.mentioned_people).to be_empty - expect(@rs3.nsfw).to eq @sm.nsfw + expect(@reshare_3.nsfw).to eq @status_message.nsfw expect(@of_deleted.nsfw).to be_nil - expect(@rs3.address).to eq @sm.location.try(:address) + expect(@reshare_3.address).to eq @status_message.location.try(:address) expect(@of_deleted.address).to be_nil end end describe "XML" do - before do - @reshare = FactoryGirl.build(:reshare) - @xml = @reshare.to_xml.to_s - end + let(:reshare) { build(:reshare) } + let(:xml) { reshare.to_xml.to_s } - context 'serialization' do - it 'serializes root_diaspora_id' do - expect(@xml).to include("root_diaspora_id") - expect(@xml).to include(@reshare.author.diaspora_handle) + context "serialization" do + it "serializes root_diaspora_id" do + expect(xml).to include("root_diaspora_id") + expect(xml).to include(reshare.author.diaspora_handle) end - it 'serializes root_guid' do - expect(@xml).to include("root_guid") - expect(@xml).to include(@reshare.root.guid) + it "serializes root_guid" do + expect(xml).to include("root_guid") + expect(xml).to include(reshare.root.guid) end end - context 'marshalling' do - context 'local' do - before do - @original_author = @reshare.root.author - @root_object = @reshare.root + context "marshalling" do + let(:root_object) { reshare.root } + + context "local" do + let(:original_author) { reshare.root.author } + + it "marshals the guid" do + expect(Reshare.from_xml(xml).root_guid).to eq(root_object.guid) end - it 'marshals the guid' do - expect(Reshare.from_xml(@xml).root_guid).to eq(@root_object.guid) + it "fetches the root post from root_guid" do + expect(Reshare.from_xml(xml).root).to eq(root_object) end - it 'fetches the root post from root_guid' do - expect(Reshare.from_xml(@xml).root).to eq(@root_object) - end - - it 'fetches the root author from root_diaspora_id' do - expect(Reshare.from_xml(@xml).root.author).to eq(@original_author) + it "fetches the root author from root_diaspora_id" do + expect(Reshare.from_xml(xml).root.author).to eq(original_author) end end - describe 'destroy' do - it 'allows you to destroy the reshare if the root post is missing' do - reshare = FactoryGirl.build(:reshare) + describe "destroy" do + it "allows you to destroy the reshare if the root post is missing" do + reshare reshare.root = nil - expect{ + expect { reshare.destroy }.to_not raise_error end end - context 'remote' do + context "remote" do before do - @root_object = @reshare.root - @root_object.delete + # root_object = reshare.root + root_object.delete @response = double allow(@response).to receive(:status).and_return(200) allow(@response).to receive(:success?).and_return(true) end - it 'fetches the root author from root_diaspora_id' do - @original_profile = @reshare.root.author.profile.dup - @reshare.root.author.profile.delete - @original_author = @reshare.root.author.dup - @reshare.root.author.delete + it "fetches the root author from root_diaspora_id" do + @original_profile = reshare.root.author.profile.dup + reshare.root.author.profile.delete + @original_author = reshare.root.author.dup + reshare.root.author.delete @original_author.profile = @original_profile expect(Person).to receive(:find_or_fetch_by_identifier).and_return(@original_author) - allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml) + allow(@response).to receive(:body).and_return(root_object.to_diaspora_xml) expect(Faraday.default_connection).to receive(:get).with( URI.join( @original_author.url, Rails.application.routes.url_helpers.short_post_path( - @root_object.guid, + root_object.guid, format: "xml" ) ) ).and_return(@response) - Reshare.from_xml(@xml) + Reshare.from_xml(xml) end context "fetching post" do @@ -234,7 +227,7 @@ describe Reshare, :type => :model do expect(Faraday.default_connection).to receive(:get).and_return(@response) expect { - Reshare.from_xml(@xml) + Reshare.from_xml(xml) }.to raise_error(Diaspora::PostNotFetchable) end @@ -244,57 +237,78 @@ describe Reshare, :type => :model do expect(Faraday.default_connection).to receive(:get).and_return(@response) expect { - Reshare.from_xml(@xml) + Reshare.from_xml(xml) }.to raise_error RuntimeError end end - context 'saving the post' do + context "saving the post" do before do - allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml) + allow(@response).to receive(:body).and_return(root_object.to_diaspora_xml) allow(Faraday.default_connection).to receive(:get).with( URI.join( - @reshare.root.author.url, + reshare.root.author.url, Rails.application.routes.url_helpers.short_post_path( - @root_object.guid, + root_object.guid, format: "xml" ) ) ).and_return(@response) end - it 'fetches the root post from root_guid' do - root = Reshare.from_xml(@xml).root + it "fetches the root post from root_guid" do + root = Reshare.from_xml(xml).root - [:text, :guid, :diaspora_handle, :type, :public].each do |attr| - expect(root.send(attr)).to eq(@reshare.root.send(attr)) + %i(text guid diaspora_handle type public).each do |attr| + expect(root.send(attr)).to eq(reshare.root.send(attr)) end end - it 'correctly saves the type' do - expect(Reshare.from_xml(@xml).root.reload.type).to eq("StatusMessage") + it "correctly saves the type" do + expect(Reshare.from_xml(xml).root.reload.type).to eq("StatusMessage") end - it 'correctly sets the author' do - @original_author = @reshare.root.author - expect(Reshare.from_xml(@xml).root.reload.author.reload).to eq(@original_author) + it "correctly sets the author" do + @original_author = reshare.root.author + expect(Reshare.from_xml(xml).root.reload.author.reload).to eq(@original_author) end - it 'verifies that the author of the post received is the same as the author in the reshare xml' do - @original_author = @reshare.root.author.dup - @xml = @reshare.to_xml.to_s + it "verifies that the author of the post received is the same as the author in the reshare xml" do + @original_author = reshare.root.author.dup + xml = reshare.to_xml.to_s different_person = FactoryGirl.build(:person) expect(Person).to receive(:find_or_fetch_by_identifier).and_return(different_person) allow(different_person).to receive(:url).and_return(@original_author.url) - expect{ - Reshare.from_xml(@xml) + expect { + Reshare.from_xml(xml) }.to raise_error /^Diaspora ID \(.+\) in the root does not match the Diaspora ID \(.+\) specified in the reshare!$/ end end end end end + + describe ".coordinates" do + let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } + let(:reshare) { create(:reshare, root: status_message) } + + context "with location" do + let(:location) { build(:location) } + + it "should deliver coordinates" do + status_message.location = location + expect(reshare.coordinates).to include(lat: location.lat, lng: location.lng) + end + end + + context "without location" do + it "should deliver empty coordinates" do + expect(reshare.coordinates[:lat]).to be_nil + expect(reshare.coordinates[:lng]).to be_nil + end + end + end end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 0f37390a4..6b1523bce 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -2,56 +2,54 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe StatusMessage, :type => :model do +describe StatusMessage, type: :model do include PeopleHelper - before do - @user = alice - @aspect = @user.aspects.first - end + let!(:user) { alice } + let!(:aspect) { user.aspects.first } + let(:status) { build(:status_message) } - describe 'scopes' do - describe '.where_person_is_mentioned' do - it 'returns status messages where the given person is mentioned' do - @bo = bob.person - @test_string = "@{Daniel; #{@bo.diaspora_handle}} can mention people like Raph" + describe "scopes" do + describe ".where_person_is_mentioned" do + it "returns status messages where the given person is mentioned" do + @bob = bob.person + @test_string = "@{Daniel; #{@bob.diaspora_handle}} can mention people like Raph" + FactoryGirl.create(:status_message, text: @test_string) + FactoryGirl.create(:status_message, text: @test_string) + FactoryGirl.create(:status_message) - FactoryGirl.create(:status_message, :text => @test_string ) - FactoryGirl.create(:status_message, :text => @test_string ) - FactoryGirl.create(:status_message) - - expect(StatusMessage.where_person_is_mentioned(@bo).count).to eq(2) + expect(StatusMessage.where_person_is_mentioned(bob).count).to eq(2) end end context "tag_streams" do before do - @sm1 = FactoryGirl.create(:status_message, :text => "#hashtag" , :public => true) - @sm2 = FactoryGirl.create(:status_message, :text => "#hashtag" ) - @sm3 = FactoryGirl.create(:status_message, :text => "hashtags are #awesome", :public => true ) - @sm4 = FactoryGirl.create(:status_message, :text => "hashtags are #awesome" ) + @status_message_1 = FactoryGirl.create(:status_message, text: "#hashtag", public: true) + @status_message_2 = FactoryGirl.create(:status_message, text: "#hashtag") + @status_message_3 = FactoryGirl.create(:status_message, text: "hashtags are #awesome", public: true) + @status_message_4 = FactoryGirl.create(:status_message, text: "hashtags are #awesome") - @tag_id = ActsAsTaggableOn::Tag.where(:name => "hashtag").first.id + @tag_id = ActsAsTaggableOn::Tag.where(name: "hashtag").first.id end - describe '.tag_steam' do - it 'returns status messages tagged with the tag' do + describe ".tag_steam" do + it "returns status messages tagged with the tag" do tag_stream = StatusMessage.send(:tag_stream, [@tag_id]) - expect(tag_stream).to include @sm1 - expect(tag_stream).to include @sm2 + expect(tag_stream).to include @status_message_1 + expect(tag_stream).to include @status_message_2 end end - describe '.public_tag_stream' do - it 'returns public status messages tagged with the tag' do - expect(StatusMessage.public_tag_stream([@tag_id])).to eq([@sm1]) + describe ".public_tag_stream" do + it "returns public status messages tagged with the tag" do + expect(StatusMessage.public_tag_stream([@tag_id])).to eq([@status_message_1]) end end - describe '.user_tag_stream' do - it 'returns tag stream thats owned or visible by' do + describe ".user_tag_stream" do + it "returns tag stream thats owned or visible by" do relation = double expect(StatusMessage).to receive(:owned_or_visible_by_user).with(bob).and_return(relation) expect(relation).to receive(:tag_stream).with([@tag_id]) @@ -63,48 +61,45 @@ describe StatusMessage, :type => :model do end describe ".guids_for_author" do - it 'returns an array of the status_message guids' do - sm1 = FactoryGirl.create(:status_message, :author => alice.person) - sm2 = FactoryGirl.create(:status_message, :author => bob.person) + it "returns an array of the status_message guids" do + status_message_1 = FactoryGirl.create(:status_message, author: alice.person) + status_message_2 = FactoryGirl.create(:status_message, author: bob.person) guids = StatusMessage.guids_for_author(alice.person) - expect(guids).to eq([sm1.guid]) + expect(guids).to eq([status_message_1.guid]) end end - describe '.before_validation' do - it 'calls build_tags' do - status = FactoryGirl.build(:status_message) + describe ".before_validation" do + it "calls build_tags" do expect(status).to receive(:build_tags) status.save end end - describe '.before_create' do - it 'calls build_tags' do - status = FactoryGirl.build(:status_message) + describe ".before_create" do + it "calls build_tags" do expect(status).to receive(:build_tags) status.save end - it 'calls filter_mentions' do - status = FactoryGirl.build(:status_message) + it "calls filter_mentions" do expect(status).to receive(:filter_mentions) status.save end end - describe '.after_create' do - it 'calls create_mentions' do + describe ".after_create" do + it "calls create_mentions" do status = FactoryGirl.build(:status_message, text: "text @{Test; #{alice.diaspora_handle}}") expect(status).to receive(:create_mentions).and_call_original status.save end end - describe '#diaspora_handle=' do - it 'sets #author' do + describe "#diaspora_handle=" do + it "sets #author" do person = FactoryGirl.create(:person) - post = FactoryGirl.build(:status_message, :author => @user.person) + post = FactoryGirl.build(:status_message, author: user.person) post.diaspora_handle = person.diaspora_handle expect(post.author).to eq(person) end @@ -112,105 +107,104 @@ describe StatusMessage, :type => :model do context "emptyness" do it "needs either a message or at least one photo" do - n = @user.build_post(:status_message, :text => nil) - expect(n).not_to be_valid + post = user.build_post(:status_message, text: nil) + expect(post).not_to be_valid - n.text = "" - expect(n).not_to be_valid + post.text = "" + expect(post).not_to be_valid - n.text = "wales" - expect(n).to be_valid - n.text = nil + post.text = "wales" + expect(post).to be_valid + post.text = nil - photo = @user.build_post(:photo, :user_file => uploaded_photo, :to => @aspect.id) + photo = user.build_post(:photo, user_file: uploaded_photo, to: aspect.id) photo.save! - n.photos << photo - expect(n).to be_valid - expect(n.errors.full_messages).to eq([]) + post.photos << photo + expect(post).to be_valid + expect(post.errors.full_messages).to eq([]) end it "doesn't check for content when author is remote (federation...)" do - p = FactoryGirl.build(:status_message, text: nil) - expect(p).to be_valid + post = FactoryGirl.build(:status_message, text: nil) + expect(post).to be_valid end end - it 'should be postable through the user' do + it "should be postable through the user" do message = "Users do things" - status = @user.post(:status_message, :text => message, :to => @aspect.id) + status = user.post(:status_message, text: message, to: aspect.id) db_status = StatusMessage.find(status.id) expect(db_status.text).to eq(message) end - it 'should require status messages not be more than 65535 characters long' do - message = 'a' * (65535+1) - status_message = FactoryGirl.build(:status_message, :text => message) + it "should require status messages not be more than 65535 characters long" do + message = "a" * (65_535 + 1) + status_message = FactoryGirl.build(:status_message, text: message) expect(status_message).not_to be_valid end - describe 'mentions' do - before do - @people = [alice, bob, eve].map{|u| u.person} - @test_string = <<-STR -@{Raphael; #{@people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{@people[1].diaspora_handle}} -can mention people like Raphaellike Raphael @{Daniel; #{@people[2].diaspora_handle}} can mention people like Raph -STR - @sm = FactoryGirl.create(:status_message, :text => @test_string ) - end + describe "mentions" do + let(:people) { [alice, bob, eve].map(&:person) } + let(:test_string) { + "@{Raphael; #{people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{people[1].diaspora_handle}} + can mention people like Raphaellike Raphael @{Daniel; #{people[2].diaspora_handle}} can mention people like Raph" + } + let(:status_message) { create(:status_message, text: test_string) } - describe '#create_mentions' do - it 'creates a mention for everyone mentioned in the message' do - expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(@people) - @sm.mentions.delete_all - @sm.create_mentions - expect(@sm.mentions(true).map{|m| m.person}.to_set).to eq(@people.to_set) + describe "#create_mentions" do + it "creates a mention for everyone mentioned in the message" do + status_message + expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(people) + status_message.mentions.delete_all + status_message.create_mentions + expect(status_message.mentions(true).map(&:person).to_set).to eq(people.to_set) end - it 'does not barf if it gets called twice' do - @sm.create_mentions + it "does not barf if it gets called twice" do + status_message.create_mentions - expect{ - @sm.create_mentions + expect { + status_message.create_mentions }.to_not raise_error end end - describe '#mentioned_people' do - it 'calls create_mentions if there are no mentions in the db' do - @sm.mentions.delete_all - expect(@sm).to receive(:create_mentions) - @sm.mentioned_people + describe "#mentioned_people" do + it "calls create_mentions if there are no mentions in the db" do + status_message.mentions.delete_all + expect(status_message).to receive(:create_mentions) + status_message.mentioned_people end - it 'returns the mentioned people' do - @sm.mentions.delete_all - expect(@sm.mentioned_people.to_set).to eq(@people.to_set) + it "returns the mentioned people" do + status_message.mentions.delete_all + expect(status_message.mentioned_people.to_set).to eq(people.to_set) end - it 'does not call create_mentions if there are mentions in the db' do - expect(@sm).not_to receive(:create_mentions) - @sm.mentioned_people + it "does not call create_mentions if there are mentions in the db" do + expect(status_message).not_to receive(:create_mentions) + status_message.mentioned_people end end describe "#mentions?" do - it 'returns true if the person was mentioned' do - expect(@sm.mentions?(@people[0])).to be true + it "returns true if the person was mentioned" do + expect(status_message.mentions?(people[0])).to be true end - it 'returns false if the person was not mentioned' do - expect(@sm.mentions?(FactoryGirl.build(:person))).to be false + it "returns false if the person was not mentioned" do + expect(status_message.mentions?(FactoryGirl.build(:person))).to be false end end describe "#notify_person" do - it 'notifies the person mentioned' do + it "notifies the person mentioned" do expect(Notification).to receive(:notify).with(alice, anything, anything) - @sm.notify_person(alice.person) + status_message.notify_person(alice.person) end end describe "#filter_mentions" do - it 'calls Diaspora::Mentionable#filter_for_aspects' do + it "calls Diaspora::Mentionable#filter_for_aspects" do msg = FactoryGirl.build(:status_message_in_aspect) msg_txt = msg.raw_message @@ -233,222 +227,240 @@ STR end describe "#nsfw" do - it 'returns MatchObject (true) if the post contains #nsfw (however capitalised)' do - status = FactoryGirl.build(:status_message, :text => "This message is #nSFw") + it "returns MatchObject (true) if the post contains #nsfw (however capitalised)" do + status = FactoryGirl.build(:status_message, text: "This message is #nSFw") expect(status.nsfw).to be_truthy end - it 'returns nil (false) if the post does not contain #nsfw' do - status = FactoryGirl.build(:status_message, :text => "This message is #sFW") + it "returns nil (false) if the post does not contain #nsfw" do + status = FactoryGirl.build(:status_message, text: "This message is #sFW") expect(status.nsfw).to be false end end - describe 'tags' do + describe "tags" do before do @object = FactoryGirl.build(:status_message) end - it_should_behave_like 'it is taggable' + it_should_behave_like "it is taggable" - it 'associates different-case tags to the same tag entry' do + it "associates different-case tags to the same tag entry" do assert_equal ActsAsTaggableOn.force_lowercase, true - msg_lc = FactoryGirl.build(:status_message, :text => '#newhere') - msg_uc = FactoryGirl.build(:status_message, :text => '#NewHere') - msg_cp = FactoryGirl.build(:status_message, :text => '#NEWHERE') + msg_lc = FactoryGirl.build(:status_message, text: "#newhere") + msg_uc = FactoryGirl.build(:status_message, text: "#NewHere") + msg_cp = FactoryGirl.build(:status_message, text: "#NEWHERE") - msg_lc.save; msg_uc.save; msg_cp.save + msg_lc.save + msg_uc.save + msg_cp.save tag_array = msg_lc.tags expect(msg_uc.tags).to match_array(tag_array) expect(msg_cp.tags).to match_array(tag_array) end - it 'should require tag name not be more than 255 characters long' do - message = "##{'a' * (255+1)}" - status_message = FactoryGirl.build(:status_message, :text => message) + it "should require tag name not be more than 255 characters long" do + message = "##{'a' * (255 + 1)}" + status_message = FactoryGirl.build(:status_message, text: message) expect(status_message).not_to be_valid end end describe "XML" do - let(:message) { FactoryGirl.build(:status_message, text: "I hate WALRUSES!", author: @user.person) } + let(:message) { FactoryGirl.build(:status_message, text: "I hate WALRUSES!", author: user.person) } let(:xml) { message.to_xml.to_s } let(:marshalled) { StatusMessage.from_xml(xml) } - it 'serializes the escaped, unprocessed message' do + it "serializes the escaped, unprocessed message" do text = "[url](http://example.org)" message.text = text expect(xml).to include Builder::XChar.encode(text) end - it 'serializes the message' do + it "serializes the message" do expect(xml).to include "I hate WALRUSES!" end - it 'serializes the author address' do - expect(xml).to include(@user.person.diaspora_handle) + it "serializes the author address" do + expect(xml).to include(user.person.diaspora_handle) end - describe '.from_xml' do - it 'marshals the message' do + describe ".from_xml" do + it "marshals the message" do expect(marshalled.text).to eq("I hate WALRUSES!") end - it 'marshals the guid' do + it "marshals the guid" do expect(marshalled.guid).to eq(message.guid) end - it 'marshals the author' do + it "marshals the author" do expect(marshalled.author).to eq(message.author) end - it 'marshals the diaspora_handle' do + it "marshals the diaspora_handle" do expect(marshalled.diaspora_handle).to eq(message.diaspora_handle) end end - context 'with some photos' do + context "with some photos" do before do message.photos << FactoryGirl.build(:photo) message.photos << FactoryGirl.build(:photo) end - it 'serializes the photos' do + it "serializes the photos" do expect(xml).to include "photo" expect(xml).to include message.photos.first.remote_photo_path end - describe '.from_xml' do - it 'marshals the photos' do + describe ".from_xml" do + it "marshals the photos" do expect(marshalled.photos.size).to eq(2) end - it 'handles existing photos' do + it "handles existing photos" do message.photos.each(&:save!) expect(marshalled).to be_valid end end end - context 'with a location' do + context "with a location" do before do message.location = FactoryGirl.build(:location) end - it 'serializes the location' do + it "serializes the location" do expect(xml).to include "location" expect(xml).to include "lat" expect(xml).to include "lng" end describe ".from_xml" do - it 'marshals the location' do + it "marshals the location" do expect(marshalled.location).to be_present end end end - context 'with a poll' do + context "with a poll" do before do message.poll = FactoryGirl.build(:poll) end - it 'serializes the poll' do + it "serializes the poll" do expect(xml).to include "poll" expect(xml).to include "question" expect(xml).to include "poll_answer" end describe ".from_xml" do - it 'marshals the poll' do + it "marshals the poll" do expect(marshalled.poll).to be_present end - it 'marshals the poll answers' do + it "marshals the poll answers" do expect(marshalled.poll.poll_answers.size).to eq(2) end end end end - describe '#after_dispatch' do + describe "#after_dispatch" do before do - @photos = [alice.build_post(:photo, :pending => true, :user_file=> File.open(photo_fixture_name)), - alice.build_post(:photo, :pending => true, :user_file=> File.open(photo_fixture_name))] - + @photos = [alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name)), + alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name))] @photos.each(&:save!) - - @status_message = alice.build_post(:status_message, :text => "the best pebble.") - @status_message.photos << @photos - + @status_message = alice.build_post(:status_message, text: "the best pebble.") + @status_message.photos << @photos @status_message.save! alice.add_to_streams(@status_message, alice.aspects) end - it 'sets pending to false on any attached photos' do + + it "sets pending to false on any attached photos" do @status_message.after_dispatch(alice) - expect(@photos.all?{|p| p.reload.pending}).to be false + expect(@photos.all? {|p| p.reload.pending }).to be false end - it 'dispatches any attached photos' do + + it "dispatches any attached photos" do expect(alice).to receive(:dispatch_post).twice @status_message.after_dispatch(alice) end end - describe 'oembed' do - before do - @youtube_url = "https://www.youtube.com/watch?v=3PtFwlKfvHI" - @message_text = "#{@youtube_url} is so cool. so is this link -> https://joindiaspora.com" - end + describe "oembed" do + let(:youtube_url) { "https://www.youtube.com/watch?v=3PtFwlKfvHI" } + let(:message_text) { "#{youtube_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:status_message) { FactoryGirl.build(:status_message, text: message_text) } - it 'should queue a GatherOembedData if it includes a link' do - sm = FactoryGirl.build(:status_message, :text => @message_text) + it "should queue a GatherOembedData if it includes a link" do + status_message expect(Workers::GatherOEmbedData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) - sm.save + status_message.save end - describe '#contains_oembed_url_in_text?' do - it 'returns the oembed urls found in the raw message' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(sm.contains_oembed_url_in_text?).not_to be_nil - expect(sm.oembed_url).to eq(@youtube_url) + describe "#contains_oembed_url_in_text?" do + it "returns the oembed urls found in the raw message" do + expect(status_message.contains_oembed_url_in_text?).not_to be_nil + expect(status_message.oembed_url).to eq(youtube_url) end end end - describe 'opengraph' do - before do - @ninegag_url = "http://9gag.com/gag/a1AMW16" - @youtube_url = "https://www.youtube.com/watch?v=3PtFwlKfvHI" - @message_text = "#{@ninegag_url} is so cool. so is this link -> https://joindiaspora.com" - @oemessage_text = "#{@youtube_url} is so cool. so is this link -> https://joindiaspora.com" - end + describe "opengraph" do + let(:ninegag_url) { "http://9gag.com/gag/a1AMW16" } + let(:youtube_url) { "https://www.youtube.com/watch?v=3PtFwlKfvHI" } + let(:message_text) { "#{ninegag_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:oemessage_text) { "#{youtube_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:status_message) { build(:status_message, text: message_text) } - it 'should queue a GatherOpenGraphData if it includes a link' do - sm = FactoryGirl.build(:status_message, :text => @message_text) + it "should queue a GatherOpenGraphData if it includes a link" do + status_message expect(Workers::GatherOpenGraphData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) - sm.save + status_message.save end - describe '#contains_open_graph_url_in_text?' do - it 'returns the opengraph urls found in the raw message' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(sm.contains_open_graph_url_in_text?).not_to be_nil - expect(sm.open_graph_url).to eq(@ninegag_url) + describe "#contains_open_graph_url_in_text?" do + it "returns the opengraph urls found in the raw message" do + expect(status_message.contains_open_graph_url_in_text?).not_to be_nil + expect(status_message.open_graph_url).to eq(ninegag_url) end - it 'returns nil if the link is from trusted oembed provider' do - sm = FactoryGirl.build(:status_message, :text => @oemessage_text) - expect(sm.contains_open_graph_url_in_text?).to be_nil - expect(sm.open_graph_url).to be_nil + it "returns nil if the link is from trusted oembed provider" do + status_message = FactoryGirl.build(:status_message, text: oemessage_text) + expect(status_message.contains_open_graph_url_in_text?).to be_nil + expect(status_message.open_graph_url).to be_nil end end end describe "validation" do + let(:status_message) { build(:status_message, text: @message_text) } + it "should not be valid if the author is missing" do - sm = FactoryGirl.build(:status_message, text: @message_text) - sm.author = nil - expect(sm).not_to be_valid + status_message.author = nil + expect(status_message).not_to be_valid + end + end + + describe ".coordinates" do + let(:status_message) { build(:status_message, text: @message_text) } + + context "with location" do + let(:location) { build(:location) } + + it "should deliver coordinates" do + status_message.location = location + expect(status_message.coordinates).to include(lat: location.lat, lng: location.lng) + end + end + + context "without location" do + it "should deliver empty coordinates" do + expect(status_message.coordinates[:lat]).to be_nil + expect(status_message.coordinates[:lng]).to be_nil + end end end end From f92a2ee0dd25950837c0cf5d938e7a6ec77d920f Mon Sep 17 00:00:00 2001 From: zaziemo Date: Tue, 4 Aug 2015 11:55:45 +0200 Subject: [PATCH 02/11] merge address & coordinates in one location object to provide a clear arrangement of all location data - add 'L' to predefs for pronto because it is part of the leaflet library - fix: show address template only with an address present with merging the location objects into one, only the objects within the location object can be empty (#5813) --- app/assets/javascripts/app/views/content_view.js | 4 ++-- app/assets/javascripts/app/views/location_map.js | 8 ++++---- .../templates/status-message-location_tpl.jst.hbs | 4 ++-- app/assets/templates/status-message-map_tpl.jst.hbs | 2 +- app/models/reshare.rb | 12 ++++++------ app/models/status_message.rb | 12 ++++++------ config/.jshint.json | 2 +- spec/models/reshare_spec.rb | 13 +++++++------ spec/models/status_message_spec.rb | 13 +++++++------ 9 files changed, 36 insertions(+), 34 deletions(-) diff --git a/app/assets/javascripts/app/views/content_view.js b/app/assets/javascripts/app/views/content_view.js index 20ddadb0d..d462dd067 100644 --- a/app/assets/javascripts/app/views/content_view.js +++ b/app/assets/javascripts/app/views/content_view.js @@ -39,8 +39,8 @@ app.views.Content = app.views.Base.extend({ }, location: function(){ - var address = this.model.get('address')? this.model.get('address') : ''; - return address; + var location = this.model.get("location")? this.model.get("location") : ""; + return location; }, collapseOversized : function() { diff --git a/app/assets/javascripts/app/views/location_map.js b/app/assets/javascripts/app/views/location_map.js index e499e2371..59949ae16 100644 --- a/app/assets/javascripts/app/views/location_map.js +++ b/app/assets/javascripts/app/views/location_map.js @@ -4,12 +4,12 @@ app.views.LocationMap = app.views.Content.extend({ templateName: "status-message-map", map: function() { - var coordinates = this.model.get("coordinates"); + var location = this.model.get("location"); // if (coordinates != "" && tileserver.enable) { // for when the tileserver is set via the diaspora.yml - if (coordinates.lat) { + if (location.lat) { var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; - var map = L.map("map").setView([coordinates.lat, coordinates.lng], 16); + var map = L.map("map").setView([location.lat, location.lng], 16); var attribution = "Map data © OpenStreetMap contributors, " + "CC-BY-SA, " + "Imagery © Mapbox"; @@ -21,7 +21,7 @@ app.views.LocationMap = app.views.Content.extend({ accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" }).addTo(map); - var markerOnMap = L.marker(coordinates).addTo(map); + var markerOnMap = L.marker(location).addTo(map); return map; } diff --git a/app/assets/templates/status-message-location_tpl.jst.hbs b/app/assets/templates/status-message-location_tpl.jst.hbs index 0d648125c..0f97e3d7a 100644 --- a/app/assets/templates/status-message-location_tpl.jst.hbs +++ b/app/assets/templates/status-message-location_tpl.jst.hbs @@ -1,5 +1,5 @@ -{{#if location}} +{{#if location.address}} {{/if}} diff --git a/app/assets/templates/status-message-map_tpl.jst.hbs b/app/assets/templates/status-message-map_tpl.jst.hbs index 87207d39c..6b344c792 100644 --- a/app/assets/templates/status-message-map_tpl.jst.hbs +++ b/app/assets/templates/status-message-map_tpl.jst.hbs @@ -1,4 +1,4 @@ -{{#if location}} +{{#if location.lat}}
{{/if}} diff --git a/app/models/reshare.rb b/app/models/reshare.rb index f3cbdb2ed..456d12866 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -44,12 +44,12 @@ class Reshare < Post absolute_root.try(:photos) || super end - def address - absolute_root.try(:location).try(:address) - end - - def coordinates - {lat: absolute_root.try(:location).try(:lat), lng: absolute_root.try(:location).try(:lng)} + def post_location + { + address: absolute_root.try(:location).try(:address), + lat: absolute_root.try(:location).try(:lat), + lng: absolute_root.try(:location).try(:lng) + } end def poll diff --git a/app/models/status_message.rb b/app/models/status_message.rb index b69a682d6..3e6605866 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -158,12 +158,12 @@ class StatusMessage < Post self.open_graph_url = self.message.urls[0] end - def address - location.try(:address) - end - - def coordinates - {lat: location.try(:lat), lng: location.try(:lng)} + def post_location + { + address: location.try(:address), + lat: location.try(:lat), + lng: location.try(:lng) + } end protected diff --git a/config/.jshint.json b/config/.jshint.json index 15675a257..c56365620 100644 --- a/config/.jshint.json +++ b/config/.jshint.json @@ -53,7 +53,7 @@ "punycode", "qq", "blueimp", - + "L", "loginAs", "logout", "spec", diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index 3661bae94..0e13aacd4 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -291,23 +291,24 @@ describe Reshare, type: :model do end end - describe ".coordinates" do + describe "#post_location" do let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } let(:reshare) { create(:reshare, root: status_message) } context "with location" do let(:location) { build(:location) } - it "should deliver coordinates" do + it "should deliver address and coordinates" do status_message.location = location - expect(reshare.coordinates).to include(lat: location.lat, lng: location.lng) + expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) end end context "without location" do - it "should deliver empty coordinates" do - expect(reshare.coordinates[:lat]).to be_nil - expect(reshare.coordinates[:lng]).to be_nil + it "should deliver empty address and coordinates" do + expect(reshare.post_location[:address]).to be_nil + expect(reshare.post_location[:lat]).to be_nil + expect(reshare.post_location[:lng]).to be_nil end end end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 6b1523bce..d17a103fa 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -444,22 +444,23 @@ describe StatusMessage, type: :model do end end - describe ".coordinates" do + describe "#coordinates" do let(:status_message) { build(:status_message, text: @message_text) } context "with location" do let(:location) { build(:location) } - it "should deliver coordinates" do + it "should deliver address and coordinates" do status_message.location = location - expect(status_message.coordinates).to include(lat: location.lat, lng: location.lng) + expect(status_message.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) end end context "without location" do - it "should deliver empty coordinates" do - expect(status_message.coordinates[:lat]).to be_nil - expect(status_message.coordinates[:lng]).to be_nil + it "should deliver empty address and coordinates" do + expect(status_message.post_location[:address]).to be_nil + expect(status_message.post_location[:lat]).to be_nil + expect(status_message.post_location[:lng]).to be_nil end end end From c0f909d22863d0d63a005369d72d8ca1d7d6576b Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 5 Aug 2015 18:13:23 +0200 Subject: [PATCH 03/11] add map to header and add toggle map function to show and load map only when user is clicking on address (#5813) --- .../javascripts/app/views/location_map.js | 34 ---------------- .../javascripts/app/views/location_stream.js | 40 ++++++++++++++++++- .../single_post_content_view.js | 2 - app/assets/stylesheets/map.scss | 8 +++- app/assets/stylesheets/single-post-view.scss | 6 ++- app/assets/stylesheets/stream_element.scss | 2 +- .../single-post-content_tpl.jst.hbs | 5 ++- .../status-message-location_tpl.jst.hbs | 5 ++- .../templates/status-message-map_tpl.jst.hbs | 4 -- .../app/views/content_view_spec.js | 9 ++--- .../app/views/location_stream_spec.js | 39 ++++++++++++++++++ spec/javascripts/helpers/factory.js | 8 ++++ 12 files changed, 108 insertions(+), 54 deletions(-) delete mode 100644 app/assets/javascripts/app/views/location_map.js delete mode 100644 app/assets/templates/status-message-map_tpl.jst.hbs create mode 100644 spec/javascripts/app/views/location_stream_spec.js diff --git a/app/assets/javascripts/app/views/location_map.js b/app/assets/javascripts/app/views/location_map.js deleted file mode 100644 index 59949ae16..000000000 --- a/app/assets/javascripts/app/views/location_map.js +++ /dev/null @@ -1,34 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -app.views.LocationMap = app.views.Content.extend({ - templateName: "status-message-map", - - map: function() { - var location = this.model.get("location"); - - // if (coordinates != "" && tileserver.enable) { // for when the tileserver is set via the diaspora.yml - if (location.lat) { - var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; - var map = L.map("map").setView([location.lat, location.lng], 16); - var attribution = "Map data © OpenStreetMap contributors, " + - "CC-BY-SA, " + - "Imagery © Mapbox"; - - L.tileLayer(tileLayerSource, { - attribution: attribution, - maxZoom: 18, - id: "zaziemo.mpn66kn8", - accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" - }).addTo(map); - - var markerOnMap = L.marker(location).addTo(map); - - return map; - } - }, - - postRenderTemplate : function(){ - _.defer(_.bind(this.map, this)); - } -}); -// @license-end diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index fd6fae946..591a88bdb 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -1,7 +1,43 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.LocationStream = app.views.Content.extend({ - templateName: "status-message-location" + events: { + "click .near-from": "toggleMap" + }, + templateName: "status-message-location", + + toggleMap: function () { + var mapContainer = this.$el.find(".mapContainer"); + + if (mapContainer.hasClass("empty")) { + var location = this.model.get("location"); + mapContainer.css("height", "150px"); + + if (location.lat) { + var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 16); + var attribution = "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox"; + + L.tileLayer(tileLayerSource, { + attribution: attribution, + maxZoom: 18, + id: "zaziemo.mpn66kn8", + accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" + }).addTo(map); + + var markerOnMap = L.marker(location).addTo(map); + mapContainer.removeClass("empty"); + return map; + } + } else { + if (mapContainer.css("display") === "none") { + mapContainer.css("display", "block"); + } else { + mapContainer.css("display", "none"); + } + } + } }); // @license-end - diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 92e5cb29e..463986151 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -11,7 +11,6 @@ app.views.SinglePostContent = app.views.Base.extend({ ".oembed" : "oEmbedView", ".opengraph" : "openGraphView", ".status-message-location" : "postLocationStreamView", - ".map" : "postMapView", '.poll': 'pollView', }, @@ -21,7 +20,6 @@ app.views.SinglePostContent = app.views.Base.extend({ this.oEmbedView = new app.views.OEmbed({model : this.model}); this.openGraphView = new app.views.SPVOpenGraph({model : this.model}); this.postContentView = new app.views.ExpandedStatusMessage({model: this.model}); - this.postMapView = new app.views.LocationMap({model: this.model}); this.pollView = new app.views.Poll({ model: this.model }); }, diff --git a/app/assets/stylesheets/map.scss b/app/assets/stylesheets/map.scss index f210f8dbb..6729448cb 100644 --- a/app/assets/stylesheets/map.scss +++ b/app/assets/stylesheets/map.scss @@ -1,9 +1,13 @@ -#map { - height: 180px; +.map { position: relative; overflow: hidden; } +.near-from:hover { + cursor: pointer; + text-decoration: underline; +} + .leaflet-bottom .leaflet-control { margin-bottom: 0; } diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss index 71ca37235..2706c8608 100644 --- a/app/assets/stylesheets/single-post-view.scss +++ b/app/assets/stylesheets/single-post-view.scss @@ -13,7 +13,6 @@ color: lighten($text-grey,10%); font-size: 12px; .post-time a { color: $text-grey; } - .near-from a { color: $text-grey; } .post_scope { margin-right: 5px; } .status-message-location { padding-top: 2px; @@ -24,6 +23,11 @@ padding-left: 10px; } } + .status-message-location { + color: $text-grey; + font-size: 12px; + margin: 10px 20px 0px 15px; + } .row.reshare { border-top: 1px solid lighten($border-grey,5%); padding-top: 10px; diff --git a/app/assets/stylesheets/stream_element.scss b/app/assets/stylesheets/stream_element.scss index 1cf764c64..46ed66c96 100644 --- a/app/assets/stylesheets/stream_element.scss +++ b/app/assets/stylesheets/stream_element.scss @@ -83,7 +83,7 @@ float: left; margin-top: 6px; } - .status-message-location .near-from a { + .status-message-location { font-size: $font-size-small; color: $text-grey; } diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs index 4da6a3ead..3f55e580a 100644 --- a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs @@ -57,7 +57,6 @@ {{t "stream.via" provider=provider_display_name}} {{/if}} {{/if}} -
{{#unless root}}
@@ -68,6 +67,9 @@
{{/unless}}
+
+
+
{{#if root}}
@@ -99,5 +101,4 @@
-
diff --git a/app/assets/templates/status-message-location_tpl.jst.hbs b/app/assets/templates/status-message-location_tpl.jst.hbs index 0f97e3d7a..1cb8bda65 100644 --- a/app/assets/templates/status-message-location_tpl.jst.hbs +++ b/app/assets/templates/status-message-location_tpl.jst.hbs @@ -1,5 +1,8 @@ {{#if location.address}}
- {{ t "publisher.near_from" location=location.address}} + {{t "publisher.near_from" location=location.address}} +
+
+
{{/if}} diff --git a/app/assets/templates/status-message-map_tpl.jst.hbs b/app/assets/templates/status-message-map_tpl.jst.hbs deleted file mode 100644 index 6b344c792..000000000 --- a/app/assets/templates/status-message-map_tpl.jst.hbs +++ /dev/null @@ -1,4 +0,0 @@ -{{#if location.lat}} -
-
-{{/if}} diff --git a/spec/javascripts/app/views/content_view_spec.js b/spec/javascripts/app/views/content_view_spec.js index 218bc4e0f..90fa3c4af 100644 --- a/spec/javascripts/app/views/content_view_spec.js +++ b/spec/javascripts/app/views/content_view_spec.js @@ -25,10 +25,9 @@ describe("app.views.Content", function(){ expect(this.view.presenter().isReshare).toBeTruthy(); }); - // it("provides coordinates", function(){ - // this.post.location; - // console.log(this.view.presenter()); - // console.log(this.post.location); - // }); + it("provides location", function(){ + this.post.set({location : factory.location()}); + expect(this.view.presenter().location).toEqual(factory.location()); + }); }); }); diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js new file mode 100644 index 000000000..25a01b642 --- /dev/null +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -0,0 +1,39 @@ +describe("app.views.LocationMap", function() { + beforeEach(function(){ + this.post = factory.post(); + this.view = new app.views.LocationStream({model : this.post}); + }); + + describe("toggleMap", function() { + context("with location provided", function() { + beforeEach(function(){ + this.post.set({location : factory.location()}); // set location + this.view.render(); + console.log(this.view.$el.find(".mapContainer")[0]); + }); + + it("should contain a map container", function() { + expect(this.view.$el[0]).toContainElement(".mapContainer"); + }); + + it("should initialize map", function() { + expect(this.view.$el.find(".mapContainer")[0]).toHaveClass("empty"); + this.view.toggleMap(); + expect(this.view.$el.find(".mapContainer")[0]).not.toHaveClass("empty"); + }); + /* + * does not work .. not sure why + it("should change display status on every click", function() { + expect(this.view.$el.find(".mapContainer")[0]).toHaveCss({display: "block"}); + this.view.toggleMap(); + expect(this.view.$el.find(".mapContainer")[0]).toHaveCss({display: "none"}); + }); + */ + }), + context("without location provided", function() { + it("should not initialize the map", function() { + expect(this.view.$el[0]).not.toContainElement(".mapContainer"); + }); + }); + }); +}); diff --git a/spec/javascripts/helpers/factory.js b/spec/javascripts/helpers/factory.js index 40aeaf39f..f8a40b874 100644 --- a/spec/javascripts/helpers/factory.js +++ b/spec/javascripts/helpers/factory.js @@ -148,6 +148,14 @@ var factory = { }, overrides); }, + location : function() { + return { + address: "Starco Mart, Mission Street, West SoMa, San Francisco, San Francisco City and County, Kalifornien, 94103, Vereinigte Staaten von Amerika", + lat: 37.78, + lng: -122.41 + }; + }, + post : function(overrides) { var defaultAttrs = _.extend(factory.postAttrs(), {"author" : this.author()}); return new app.models.Post(_.extend(defaultAttrs, overrides)); From dc25c01bcdd0013d2929b957c7c505521c71c047 Mon Sep 17 00:00:00 2001 From: zaziemo Date: Wed, 19 Aug 2015 16:32:17 +0200 Subject: [PATCH 04/11] add a different map representation to the SPV so a small map is rendered in the SPV and a location is provided via toggling the map gets bigger (#5813) --- .../single_post_content_view.js | 54 +++++++++++++++++-- app/assets/stylesheets/map.scss | 6 ++- app/assets/stylesheets/single-post-view.scss | 3 +- .../single-post-content_tpl.jst.hbs | 7 ++- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 463986151..bb3a28feb 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -1,7 +1,11 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.SinglePostContent = app.views.Base.extend({ - templateName: "single-post-viewer/single-post-content", + events: { + "click .near-from": "toggleMap" + }, + + templateName: 'single-post-viewer/single-post-content', tooltipSelector: "time, .post_scope", subviews : { @@ -10,7 +14,6 @@ app.views.SinglePostContent = app.views.Base.extend({ "#real-post-content" : "postContentView", ".oembed" : "oEmbedView", ".opengraph" : "openGraphView", - ".status-message-location" : "postLocationStreamView", '.poll': 'pollView', }, @@ -23,8 +26,47 @@ app.views.SinglePostContent = app.views.Base.extend({ this.pollView = new app.views.Poll({ model: this.model }); }, - postLocationStreamView : function(){ - return new app.views.LocationStream({ model : this.model}); + map : function(){ + if (this.$el.find(".mapContainer")){ + + // find and set height of mapContainer to max size of the container + // which is necessary to have all necessary tiles prerendered + var mapContainer = this.$el.find(".mapContainer"); + mapContainer.css("height", "200px"); + + // get location data and render map + var location = this.model.get("location"); + var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); + var attribution = "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox"; + + L.tileLayer(tileLayerSource, { + attribution: attribution, + maxZoom: 18, + id: "zaziemo.mpn66kn8", + accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" + }).addTo(map); + + // set mapContainer size to a smaller preview size + mapContainer.css("height", "75px"); + map.invalidateSize(); + + // put marker on map + var markerOnMap = L.marker(location).addTo(map); + return map; + }; + }, + + toggleMap: function () { + if (this.$el.find(".mapContainer").css("height") === "75px") { + this.$el.find(".mapContainer").css("height", "200px"); + this.$el.find(".leaflet-control-zoom").css("display", "block"); + } else { + this.$el.find(".mapContainer").css("height", "75px"); + this.$el.find(".leaflet-control-zoom").css("display", "none"); + } }, presenter : function() { @@ -37,6 +79,10 @@ app.views.SinglePostContent = app.views.Base.extend({ showPost : function() { return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw"); + }, + + postRenderTemplate : function(){ + _.defer(_.bind(this.map, this)); } }); // @license-end diff --git a/app/assets/stylesheets/map.scss b/app/assets/stylesheets/map.scss index 6729448cb..f304d135b 100644 --- a/app/assets/stylesheets/map.scss +++ b/app/assets/stylesheets/map.scss @@ -1,4 +1,4 @@ -.map { +.mapContainer { position: relative; overflow: hidden; } @@ -8,6 +8,10 @@ text-decoration: underline; } +.leaflet-control-zoom { + display: none; +} + .leaflet-bottom .leaflet-control { margin-bottom: 0; } diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss index 2706c8608..cf2298821 100644 --- a/app/assets/stylesheets/single-post-view.scss +++ b/app/assets/stylesheets/single-post-view.scss @@ -23,11 +23,12 @@ padding-left: 10px; } } - .status-message-location { + .near-from { color: $text-grey; font-size: 12px; margin: 10px 20px 0px 15px; } + .row.reshare { border-top: 1px solid lighten($border-grey,5%); padding-top: 10px; diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs index 3f55e580a..c8dcd63f1 100644 --- a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs @@ -67,9 +67,14 @@
{{/unless}}
+ {{#if location.lat}}
-
+
+ {{t "publisher.near_from" location=location.address}} +
+
+ {{/if}} {{#if root}}
From 6716b4c1757412728864fc6f39c05d2dc172000a Mon Sep 17 00:00:00 2001 From: realtin Date: Wed, 19 Aug 2015 16:51:57 +0200 Subject: [PATCH 05/11] rename location_view to locator because it is confusing with the other location files --- app/assets/javascripts/app/views/{location_view.js => locator.js} | 0 .../app/views/{location_view_spec.js => locator_spec.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename app/assets/javascripts/app/views/{location_view.js => locator.js} (100%) rename spec/javascripts/app/views/{location_view_spec.js => locator_spec.js} (100%) diff --git a/app/assets/javascripts/app/views/location_view.js b/app/assets/javascripts/app/views/locator.js similarity index 100% rename from app/assets/javascripts/app/views/location_view.js rename to app/assets/javascripts/app/views/locator.js diff --git a/spec/javascripts/app/views/location_view_spec.js b/spec/javascripts/app/views/locator_spec.js similarity index 100% rename from spec/javascripts/app/views/location_view_spec.js rename to spec/javascripts/app/views/locator_spec.js From e5cc8dff0e488f628703609de2938d723f0ecd38 Mon Sep 17 00:00:00 2001 From: zaziemo Date: Thu, 20 Aug 2015 12:00:21 +0200 Subject: [PATCH 06/11] outsource map credentials and allow podmin to enable and disable the feature (#5813) --- .../javascripts/app/views/location_stream.js | 52 ++++++++++--------- .../single_post_content_view.js | 22 ++++---- app/controllers/application_controller.rb | 3 +- config/defaults.yml | 5 ++ config/diaspora.yml.example | 11 ++++ 5 files changed, 57 insertions(+), 36 deletions(-) diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index 591a88bdb..446a9765f 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -7,35 +7,37 @@ app.views.LocationStream = app.views.Content.extend({ templateName: "status-message-location", toggleMap: function () { - var mapContainer = this.$el.find(".mapContainer"); + if (gon.appConfig.map.enabled){ + var mapContainer = this.$el.find(".mapContainer"); - if (mapContainer.hasClass("empty")) { - var location = this.model.get("location"); - mapContainer.css("height", "150px"); + if (mapContainer.hasClass("empty")) { + var location = this.model.get("location"); + mapContainer.css("height", "150px"); - if (location.lat) { - var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; - var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 16); - var attribution = "Map data © OpenStreetMap contributors, " + - "CC-BY-SA, " + - "Imagery © Mapbox"; + if (location.lat) { + var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 16); + var attribution = "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox"; - L.tileLayer(tileLayerSource, { - attribution: attribution, - maxZoom: 18, - id: "zaziemo.mpn66kn8", - accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" - }).addTo(map); + L.tileLayer(tileLayerSource, { + attribution: attribution, + maxZoom: 18, + id: gon.appConfig.map.mapbox.id, + accessToken: gon.appConfig.map.mapbox.accessToken + }).addTo(map); - var markerOnMap = L.marker(location).addTo(map); - mapContainer.removeClass("empty"); - return map; - } - } else { - if (mapContainer.css("display") === "none") { - mapContainer.css("display", "block"); - } else { - mapContainer.css("display", "none"); + var markerOnMap = L.marker(location).addTo(map); + mapContainer.removeClass("empty"); + return map; + } + } else { + if (mapContainer.css("display") === "none") { + mapContainer.css("display", "block"); + } else { + mapContainer.css("display", "none"); + } } } } diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index bb3a28feb..d1f3dcfd6 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -27,7 +27,7 @@ app.views.SinglePostContent = app.views.Base.extend({ }, map : function(){ - if (this.$el.find(".mapContainer")){ + if (this.$el.find(".mapContainer")&&gon.appConfig.map.enabled){ // find and set height of mapContainer to max size of the container // which is necessary to have all necessary tiles prerendered @@ -45,8 +45,8 @@ app.views.SinglePostContent = app.views.Base.extend({ L.tileLayer(tileLayerSource, { attribution: attribution, maxZoom: 18, - id: "zaziemo.mpn66kn8", - accessToken: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" + id: gon.appConfig.map.mapbox.id, + accessToken: gon.appConfig.map.mapbox.accessToken }).addTo(map); // set mapContainer size to a smaller preview size @@ -56,16 +56,18 @@ app.views.SinglePostContent = app.views.Base.extend({ // put marker on map var markerOnMap = L.marker(location).addTo(map); return map; - }; + }; }, toggleMap: function () { - if (this.$el.find(".mapContainer").css("height") === "75px") { - this.$el.find(".mapContainer").css("height", "200px"); - this.$el.find(".leaflet-control-zoom").css("display", "block"); - } else { - this.$el.find(".mapContainer").css("height", "75px"); - this.$el.find(".leaflet-control-zoom").css("display", "none"); + if (gon.appConfig.map.enabled){ + if (this.$el.find(".mapContainer").css("height") === "75px") { + this.$el.find(".mapContainer").css("height", "200px"); + this.$el.find(".leaflet-control-zoom").css("display", "block"); + } else { + this.$el.find(".mapContainer").css("height", "75px"); + this.$el.find(".leaflet-control-zoom").css("display", "none"); + } } }, diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index eb06e2f9e..e4e081656 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -145,7 +145,8 @@ class ApplicationController < ActionController::Base def gon_set_appconfig gon.push(appConfig: { chat: {enabled: AppConfig.chat.enabled?}, - settings: {podname: AppConfig.settings.pod_name} + settings: {podname: AppConfig.settings.pod_name}, + map: {enabled: AppConfig.map.enabled?, mapbox: AppConfig.map.mapbox} }) end diff --git a/config/defaults.yml b/config/defaults.yml index 9d4bd0d9c..6f67eeb13 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -75,6 +75,11 @@ defaults: log: file: 'log/vines.log' level: 'info' + map: + enabled: true + mapbox: + id: 'zaziemo.mpn66kn8' + accessToken: 'pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA' privacy: jquery_cdn: false google_analytics_key: diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index cf2e286ce..0f7d8ec52 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -324,6 +324,17 @@ configuration: ## Section ## The debug level logs all XML sent and received by the server. #level: 'info' + ## Displaying location of posts in a map. We are using the map tiles of + ## https://www.mapbox.com. There you have to create a account to get and ID + ## and an access token. If you want to use this feature you can write an email + ## to team@diasporafoundation.org and you'll get an unlimited and free account. + map: ##Section + + # enable: true + # mapbox: + # id: 'your.id' + # accessToken: 'youraccesstoken' + ## Settings potentially affecting the privacy of your users. privacy: ## Section From 57b7c05c4ff6b34aa1c1a55592cdc7f324045b70 Mon Sep 17 00:00:00 2001 From: realtin Date: Mon, 24 Aug 2015 12:15:45 +0200 Subject: [PATCH 07/11] set maptile default to OpenMapSurfer - refactor code for toggle map function - adjust jasmine tests for maps and add tests for SPV - change name of access token in defaults.yml according to naming conventions - add explanation of map use for podmins - add location to post_presenter - fix opening multiple maps inside the stream when clicking on a reshare location (#5813) --- .../javascripts/app/views/location_stream.js | 22 ++++---- .../single_post_content_view.js | 29 ++++++----- app/assets/stylesheets/single-post-view.scss | 4 +- .../single-post-content_tpl.jst.hbs | 2 +- app/presenters/post_presenter.rb | 3 +- config/defaults.yml | 5 +- config/diaspora.yml.example | 17 ++++--- .../app/views/location_stream_spec.js | 28 ++++++----- .../views/single_post_content_view_spec.js | 50 +++++++++++++++++++ spec/models/reshare_spec.rb | 28 +++++------ 10 files changed, 127 insertions(+), 61 deletions(-) create mode 100644 spec/javascripts/app/views/single_post_content_view_spec.js diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index 446a9765f..25687585b 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -15,17 +15,23 @@ app.views.LocationStream = app.views.Content.extend({ mapContainer.css("height", "150px"); if (location.lat) { - var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; - var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 16); + // If the mapbox option is enabled in the defaults the mapbox tiles with the podmin's credentials are used. + // If mapbox is not enabled the OpenMapSurfer tiles are used, which don't need credentials. + var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; + var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" + : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; + var tileAttribution = mapsource ? "Mapbox" + : "OpenMapSurfer"; var attribution = "Map data © OpenStreetMap contributors, " + "CC-BY-SA, " + - "Imagery © Mapbox"; + "Imagery © "+ tileAttribution; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); L.tileLayer(tileLayerSource, { + id: mapsource.id, + accessToken: mapsource.access_token, attribution: attribution, maxZoom: 18, - id: gon.appConfig.map.mapbox.id, - accessToken: gon.appConfig.map.mapbox.accessToken }).addTo(map); var markerOnMap = L.marker(location).addTo(map); @@ -33,11 +39,7 @@ app.views.LocationStream = app.views.Content.extend({ return map; } } else { - if (mapContainer.css("display") === "none") { - mapContainer.css("display", "block"); - } else { - mapContainer.css("display", "none"); - } + mapContainer.toggle(); } } } diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index d1f3dcfd6..7cca84507 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -36,17 +36,24 @@ app.views.SinglePostContent = app.views.Base.extend({ // get location data and render map var location = this.model.get("location"); - var tileLayerSource = "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}"; - var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); + + // If the mapbox option is enabled in the defaults the mapbox tiles with the podmin's credentials are used. + // If mapbox is not enabled the OpenMapSurfer tiles are used, which don't need credentials. + var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; + var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" + : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; + var tileAttribution = mapsource ? "Mapbox" + : "OpenMapSurfer"; var attribution = "Map data © OpenStreetMap contributors, " + "CC-BY-SA, " + - "Imagery © Mapbox"; + "Imagery © "+ tileAttribution; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); L.tileLayer(tileLayerSource, { + id: mapsource.id, + accessToken: mapsource.access_token, attribution: attribution, maxZoom: 18, - id: gon.appConfig.map.mapbox.id, - accessToken: gon.appConfig.map.mapbox.accessToken }).addTo(map); // set mapContainer size to a smaller preview size @@ -56,18 +63,14 @@ app.views.SinglePostContent = app.views.Base.extend({ // put marker on map var markerOnMap = L.marker(location).addTo(map); return map; - }; + } }, toggleMap: function () { if (gon.appConfig.map.enabled){ - if (this.$el.find(".mapContainer").css("height") === "75px") { - this.$el.find(".mapContainer").css("height", "200px"); - this.$el.find(".leaflet-control-zoom").css("display", "block"); - } else { - this.$el.find(".mapContainer").css("height", "75px"); - this.$el.find(".leaflet-control-zoom").css("display", "none"); - } + $(".mapContainer").height($(".small-map")[0] ? 200 : 50); + $(".leaflet-control-zoom").css("display", $(".small-map")[0] ? "block" : "none"); + $(".mapContainer").toggleClass("small-map"); } }, diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss index cf2298821..0166d1802 100644 --- a/app/assets/stylesheets/single-post-view.scss +++ b/app/assets/stylesheets/single-post-view.scss @@ -28,7 +28,9 @@ font-size: 12px; margin: 10px 20px 0px 15px; } - + .mapContainer { + margin: 10px 20px 0px 15px; + } .row.reshare { border-top: 1px solid lighten($border-grey,5%); padding-top: 10px; diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs index c8dcd63f1..9295117eb 100644 --- a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs @@ -71,8 +71,8 @@
{{t "publisher.near_from" location=location.address}} -
+
{{/if}} {{#if root}} diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index ea77b1530..8e95647f4 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -31,8 +31,7 @@ class PostPresenter < BasePresenter photos: build_photos_json, root: root, title: title, - address: @post.address, - coordinates: @post.coordinates, + location: @post.post_location, poll: @post.poll, already_participated_in_poll: already_participated_in_poll, participation: participate?, diff --git a/config/defaults.yml b/config/defaults.yml index 6f67eeb13..3d558d167 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -78,8 +78,9 @@ defaults: map: enabled: true mapbox: - id: 'zaziemo.mpn66kn8' - accessToken: 'pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA' + enabled: false + id: "zaziemo.mpn66kn8" + access_token: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" privacy: jquery_cdn: false google_analytics_key: diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index 0f7d8ec52..fb01cadd1 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -324,16 +324,21 @@ configuration: ## Section ## The debug level logs all XML sent and received by the server. #level: 'info' - ## Displaying location of posts in a map. We are using the map tiles of - ## https://www.mapbox.com. There you have to create a account to get and ID - ## and an access token. If you want to use this feature you can write an email - ## to team@diasporafoundation.org and you'll get an unlimited and free account. + ## Displays the location of a post in a map. Per default we are using the map + ## tiles of OpenMapSurfer (http://korona.geog.uni-heidelberg.de/). + ## If you want to use them you only have to enable the map. You also have the + ## possibility to use the map tiles of https://www.mapbox.com which is probably + ## more reliable. There you have to create a account to get an ID and an access token which is limited. If + ## you want to get an unlimited account you can write an email + ## to team@diasporafoundation.org. Please enable mapbox and fill out your id + ## and access_token. map: ##Section - # enable: true + # enable: false # mapbox: + # enable: false # id: 'your.id' - # accessToken: 'youraccesstoken' + # access_token: 'youraccesstoken' ## Settings potentially affecting the privacy of your users. privacy: ## Section diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js index 25a01b642..fe87ea478 100644 --- a/spec/javascripts/app/views/location_stream_spec.js +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -1,38 +1,42 @@ -describe("app.views.LocationMap", function() { +describe("app.views.LocationStream", function() { beforeEach(function(){ this.post = factory.post(); this.view = new app.views.LocationStream({model : this.post}); + gon.appConfig = { map: {enabled: true, mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken" }} }; }); describe("toggleMap", function() { context("with location provided", function() { beforeEach(function(){ this.post.set({location : factory.location()}); // set location - this.view.render(); - console.log(this.view.$el.find(".mapContainer")[0]); + spec.content().html(this.view.render().el); // loads html element to the page }); it("should contain a map container", function() { - expect(this.view.$el[0]).toContainElement(".mapContainer"); + expect(spec.content()).toContainElement(".mapContainer"); }); it("should initialize map", function() { - expect(this.view.$el.find(".mapContainer")[0]).toHaveClass("empty"); + expect($(".mapContainer")).toHaveClass("empty"); this.view.toggleMap(); - expect(this.view.$el.find(".mapContainer")[0]).not.toHaveClass("empty"); + expect($(".mapContainer")).not.toHaveClass("empty"); }); - /* - * does not work .. not sure why + it("should change display status on every click", function() { - expect(this.view.$el.find(".mapContainer")[0]).toHaveCss({display: "block"}); this.view.toggleMap(); - expect(this.view.$el.find(".mapContainer")[0]).toHaveCss({display: "none"}); + expect($(".mapContainer")).toHaveCss({display: "block"}); + this.view.toggleMap(); + expect($(".mapContainer")).toHaveCss({display: "none"}); }); - */ }), + context("without location provided", function() { + beforeEach(function(){ + spec.content().html(this.view.render().el); + }); + it("should not initialize the map", function() { - expect(this.view.$el[0]).not.toContainElement(".mapContainer"); + expect(spec.content()).not.toContainElement(".mapContainer"); }); }); }); diff --git a/spec/javascripts/app/views/single_post_content_view_spec.js b/spec/javascripts/app/views/single_post_content_view_spec.js new file mode 100644 index 000000000..b38c38b78 --- /dev/null +++ b/spec/javascripts/app/views/single_post_content_view_spec.js @@ -0,0 +1,50 @@ +describe("app.views.SinglePostContent", function() { + beforeEach(function(){ + this.post = factory.post(); + this.view = new app.views.SinglePostContent({model : this.post}); + gon.appConfig = { map: {enabled: true, mapbox: {enabled: true, id: "yourID", accessToken: "yourAccessToken" }} }; + }); + + describe("toggleMap", function() { + context("with location provided", function() { + beforeEach(function(){ + this.post.set({location : factory.location()}); // set location + spec.content().html(this.view.render().el); // loads html element to the page + }); + + it("should contain a map container", function() { + expect(spec.content()).toContainElement(".mapContainer"); + }); + + it("should provide a small map", function() { + expect($(".mapContainer")).toHaveClass("small-map"); + expect($(".mapContainer").height() < 100).toBeTruthy(); + expect($(".mapContainer")).toBeVisible(); + }); + + it("should toggle class small-map on every click", function(){ + this.view.toggleMap(); + expect($(".mapContainer")).not.toHaveClass("small-map"); + this.view.toggleMap(); + expect($(".mapContainer")).toHaveClass("small-map"); + }); + + it("should change height on every click", function() { + this.view.toggleMap(); + expect($(".mapContainer").height() > 100).toBeTruthy(); + this.view.toggleMap(); + expect($(".mapContainer").height() < 100).toBeTruthy(); + }); + }), + + context("without location provided", function() { + beforeEach(function(){ + spec.content().html(this.view.render().el); + }); + + it("should not initialize the map", function() { + expect(spec.content()).not.toContainElement(".mapContainer"); + }); + }); + }); +}); diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index 0e13aacd4..bfaff0dc6 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -292,24 +292,24 @@ describe Reshare, type: :model do end describe "#post_location" do - let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } - let(:reshare) { create(:reshare, root: status_message) } + let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } + let(:reshare) { create(:reshare, root: status_message) } - context "with location" do - let(:location) { build(:location) } + context "with location" do + let(:location) { build(:location) } - it "should deliver address and coordinates" do - status_message.location = location - expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) + it "should deliver address and coordinates" do + status_message.location = location + expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) + end end - end - context "without location" do - it "should deliver empty address and coordinates" do - expect(reshare.post_location[:address]).to be_nil - expect(reshare.post_location[:lat]).to be_nil - expect(reshare.post_location[:lng]).to be_nil + context "without location" do + it "should deliver empty address and coordinates" do + expect(reshare.post_location[:address]).to be_nil + expect(reshare.post_location[:lat]).to be_nil + expect(reshare.post_location[:lng]).to be_nil + end end end end -end From 0f3eff8f883f3f9fd62926f7e9ca10a75753959d Mon Sep 17 00:00:00 2001 From: zaziemo Date: Wed, 9 Sep 2015 15:24:00 +0200 Subject: [PATCH 08/11] add correct attributions for map tiles of Heidelberg University remove personal credentials from mapbox and refactored some code #5813 Signed-off-by: zaziemo --- .../javascripts/app/views/location_stream.js | 14 ++++++---- .../single_post_content_view.js | 17 +++++------ config/defaults.yml | 4 +-- config/diaspora.yml.example | 4 +-- spec/models/reshare_spec.rb | 28 +++++++++---------- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index 25687585b..63f7a6560 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -15,16 +15,18 @@ app.views.LocationStream = app.views.Content.extend({ mapContainer.css("height", "150px"); if (location.lat) { - // If the mapbox option is enabled in the defaults the mapbox tiles with the podmin's credentials are used. - // If mapbox is not enabled the OpenMapSurfer tiles are used, which don't need credentials. + + // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. + // If mapbox is not enabled the Maptiles from the Heidelberg University are used, which don't need credentials. var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; - var tileAttribution = mapsource ? "Mapbox" - : "OpenMapSurfer"; + var tileAttribution = mapsource ? "CC-BY-SA, " + + "Imagery © Mapbox" + : "rendering " + + "GIScience Research Group @ Heidelberg University"; var attribution = "Map data © OpenStreetMap contributors, " + - "CC-BY-SA, " + - "Imagery © "+ tileAttribution; + tileAttribution; var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); L.tileLayer(tileLayerSource, { diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 7cca84507..a5d1c8679 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -5,7 +5,7 @@ app.views.SinglePostContent = app.views.Base.extend({ "click .near-from": "toggleMap" }, - templateName: 'single-post-viewer/single-post-content', + templateName: "single-post-viewer/single-post-content", tooltipSelector: "time, .post_scope", subviews : { @@ -14,7 +14,7 @@ app.views.SinglePostContent = app.views.Base.extend({ "#real-post-content" : "postContentView", ".oembed" : "oEmbedView", ".opengraph" : "openGraphView", - '.poll': 'pollView', + ".poll": "pollView", }, initialize : function() { @@ -37,16 +37,17 @@ app.views.SinglePostContent = app.views.Base.extend({ // get location data and render map var location = this.model.get("location"); - // If the mapbox option is enabled in the defaults the mapbox tiles with the podmin's credentials are used. - // If mapbox is not enabled the OpenMapSurfer tiles are used, which don't need credentials. + // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. + // If mapbox is not enabled the Maptiles from the Heidelberg University are used, which don't need credentials. var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; - var tileAttribution = mapsource ? "Mapbox" - : "OpenMapSurfer"; + var tileAttribution = mapsource ? "CC-BY-SA, " + + "Imagery © Mapbox" + : "rendering " + + "GIScience Research Group @ Heidelberg University"; var attribution = "Map data © OpenStreetMap contributors, " + - "CC-BY-SA, " + - "Imagery © "+ tileAttribution; + tileAttribution; var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); L.tileLayer(tileLayerSource, { diff --git a/config/defaults.yml b/config/defaults.yml index 3d558d167..c876a2fa1 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -79,8 +79,8 @@ defaults: enabled: true mapbox: enabled: false - id: "zaziemo.mpn66kn8" - access_token: "pk.eyJ1IjoiemF6aWVtbyIsImEiOiI3ODVjMzVjNmM2ZTU3YWM3YTE5YWYwMTRhODljM2M1MSJ9.-nVgyS4PLnV4m9YkvMB5wA" + id: + access_token: privacy: jquery_cdn: false google_analytics_key: diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index fb01cadd1..f72fdf370 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -334,9 +334,9 @@ configuration: ## Section ## and access_token. map: ##Section - # enable: false + # enabled: true # mapbox: - # enable: false + # enabled: false # id: 'your.id' # access_token: 'youraccesstoken' diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index bfaff0dc6..0e13aacd4 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -292,24 +292,24 @@ describe Reshare, type: :model do end describe "#post_location" do - let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } - let(:reshare) { create(:reshare, root: status_message) } + let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } + let(:reshare) { create(:reshare, root: status_message) } - context "with location" do - let(:location) { build(:location) } + context "with location" do + let(:location) { build(:location) } - it "should deliver address and coordinates" do - status_message.location = location - expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) - end + it "should deliver address and coordinates" do + status_message.location = location + expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) end + end - context "without location" do - it "should deliver empty address and coordinates" do - expect(reshare.post_location[:address]).to be_nil - expect(reshare.post_location[:lat]).to be_nil - expect(reshare.post_location[:lng]).to be_nil - end + context "without location" do + it "should deliver empty address and coordinates" do + expect(reshare.post_location[:address]).to be_nil + expect(reshare.post_location[:lat]).to be_nil + expect(reshare.post_location[:lng]).to be_nil end end end +end From 263dc6f119344b64c690ab4f85ff94a11c756fe5 Mon Sep 17 00:00:00 2001 From: zaziemo Date: Wed, 9 Sep 2015 17:03:46 +0200 Subject: [PATCH 09/11] refactor code that choses the tile server based on podmin's choice and remove the possibility to disable the map feature. By default the application uses the itles of Heidelberg University that don't need any credentials. If podmins enable the mapbox option in the diaspora.yml and enter their credentials the mapbox tiles are used for the map rendering. --- .../javascripts/app/views/location_stream.js | 65 ++++++++++--------- .../single_post_content_view.js | 42 ++++++------ app/controllers/application_controller.rb | 2 +- config/defaults.yml | 1 - config/diaspora.yml.example | 16 ++--- .../app/views/location_stream_spec.js | 2 +- .../views/single_post_content_view_spec.js | 2 +- 7 files changed, 67 insertions(+), 63 deletions(-) diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index 63f7a6560..eb140f054 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -7,43 +7,46 @@ app.views.LocationStream = app.views.Content.extend({ templateName: "status-message-location", toggleMap: function () { - if (gon.appConfig.map.enabled){ - var mapContainer = this.$el.find(".mapContainer"); + var mapContainer = this.$el.find(".mapContainer"); - if (mapContainer.hasClass("empty")) { - var location = this.model.get("location"); - mapContainer.css("height", "150px"); + if (mapContainer.hasClass("empty")) { + var location = this.model.get("location"); + mapContainer.css("height", "150px"); - if (location.lat) { + if (location.lat) { + // If map function is enabled the maptiles from the Heidelberg University are used by default. - // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. - // If mapbox is not enabled the Maptiles from the Heidelberg University are used, which don't need credentials. - var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; - var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" - : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; - var tileAttribution = mapsource ? "CC-BY-SA, " + - "Imagery © Mapbox" - : "rendering " + - "GIScience Research Group @ Heidelberg University"; - var attribution = "Map data © OpenStreetMap contributors, " + - tileAttribution; + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); - var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); - L.tileLayer(tileLayerSource, { - id: mapsource.id, - accessToken: mapsource.access_token, - attribution: attribution, + var tiles = L.tileLayer("http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", { + attribution: "Map data © OpenStreetMap contributors, " + + "rendering " + + "GIScience Research Group @ Heidelberg University", + maxZoom: 18, + }); + + // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. + if (gon.appConfig.map.mapbox.enabled) { + + tiles = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { + id: gon.appConfig.map.mapbox.id, + accessToken: gon.appConfig.map.mapbox.access_token, + attribution: "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox", maxZoom: 18, - }).addTo(map); + }); + } - var markerOnMap = L.marker(location).addTo(map); - mapContainer.removeClass("empty"); - return map; - } - } else { - mapContainer.toggle(); - } + tiles.addTo(map); + + var markerOnMap = L.marker(location).addTo(map); + mapContainer.removeClass("empty"); + return map; } - } + } else { + mapContainer.toggle(); + } + } }); // @license-end diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index a5d1c8679..6cfbb9528 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -27,7 +27,7 @@ app.views.SinglePostContent = app.views.Base.extend({ }, map : function(){ - if (this.$el.find(".mapContainer")&&gon.appConfig.map.enabled){ + if (this.$el.find(".mapContainer")){ // find and set height of mapContainer to max size of the container // which is necessary to have all necessary tiles prerendered @@ -37,25 +37,31 @@ app.views.SinglePostContent = app.views.Base.extend({ // get location data and render map var location = this.model.get("location"); - // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. - // If mapbox is not enabled the Maptiles from the Heidelberg University are used, which don't need credentials. - var mapsource = gon.appConfig.map.mapbox.enabled ? gon.appConfig.map.mapbox : ""; - var tileLayerSource = mapsource ? "https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}" - : "http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}"; - var tileAttribution = mapsource ? "CC-BY-SA, " + - "Imagery © Mapbox" - : "rendering " + - "GIScience Research Group @ Heidelberg University"; - var attribution = "Map data © OpenStreetMap contributors, " + - tileAttribution; + // If map function is enabled the maptiles from the Heidelberg University are used by default. var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); - L.tileLayer(tileLayerSource, { - id: mapsource.id, - accessToken: mapsource.access_token, - attribution: attribution, + + var tiles = L.tileLayer("http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", { + attribution: "Map data © OpenStreetMap contributors, " + + "rendering " + + "GIScience Research Group @ Heidelberg University", maxZoom: 18, - }).addTo(map); + }); + + // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. + if (gon.appConfig.map.mapbox.enabled) { + + tiles = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { + id: gon.appConfig.map.mapbox.id, + accessToken: gon.appConfig.map.mapbox.access_token, + attribution: "Map data © OpenStreetMap contributors, " + + "CC-BY-SA, " + + "Imagery © Mapbox", + maxZoom: 18, + }); + } + + tiles.addTo(map); // set mapContainer size to a smaller preview size mapContainer.css("height", "75px"); @@ -68,11 +74,9 @@ app.views.SinglePostContent = app.views.Base.extend({ }, toggleMap: function () { - if (gon.appConfig.map.enabled){ $(".mapContainer").height($(".small-map")[0] ? 200 : 50); $(".leaflet-control-zoom").css("display", $(".small-map")[0] ? "block" : "none"); $(".mapContainer").toggleClass("small-map"); - } }, presenter : function() { diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e4e081656..19010ca93 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -146,7 +146,7 @@ class ApplicationController < ActionController::Base gon.push(appConfig: { chat: {enabled: AppConfig.chat.enabled?}, settings: {podname: AppConfig.settings.pod_name}, - map: {enabled: AppConfig.map.enabled?, mapbox: AppConfig.map.mapbox} + map: {mapbox: AppConfig.map.mapbox} }) end diff --git a/config/defaults.yml b/config/defaults.yml index c876a2fa1..2f6382e64 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -76,7 +76,6 @@ defaults: file: 'log/vines.log' level: 'info' map: - enabled: true mapbox: enabled: false id: diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index f72fdf370..3be3478c9 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -325,17 +325,15 @@ configuration: ## Section #level: 'info' ## Displays the location of a post in a map. Per default we are using the map - ## tiles of OpenMapSurfer (http://korona.geog.uni-heidelberg.de/). - ## If you want to use them you only have to enable the map. You also have the - ## possibility to use the map tiles of https://www.mapbox.com which is probably - ## more reliable. There you have to create a account to get an ID and an access token which is limited. If - ## you want to get an unlimited account you can write an email - ## to team@diasporafoundation.org. Please enable mapbox and fill out your id - ## and access_token. + ## tiles of the Heidelberg University (http://giscience.uni-hd.de). + ## You also have the possibility to use the map tiles of https://www.mapbox.com + ## which is probably more reliable. There you have to create an account to get + ## an ID and an access token which is limited. If you want to get an unlimited + ## account you can write an email to team@diasporafoundation.org. + ## Please enable mapbox and fill out your id and access_token. map: ##Section - # enabled: true - # mapbox: + mapbox: # enabled: false # id: 'your.id' # access_token: 'youraccesstoken' diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js index fe87ea478..54513b996 100644 --- a/spec/javascripts/app/views/location_stream_spec.js +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -2,7 +2,7 @@ describe("app.views.LocationStream", function() { beforeEach(function(){ this.post = factory.post(); this.view = new app.views.LocationStream({model : this.post}); - gon.appConfig = { map: {enabled: true, mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken" }} }; + gon.appConfig = {map: { mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken" }}}; }); describe("toggleMap", function() { diff --git a/spec/javascripts/app/views/single_post_content_view_spec.js b/spec/javascripts/app/views/single_post_content_view_spec.js index b38c38b78..688891f96 100644 --- a/spec/javascripts/app/views/single_post_content_view_spec.js +++ b/spec/javascripts/app/views/single_post_content_view_spec.js @@ -2,7 +2,7 @@ describe("app.views.SinglePostContent", function() { beforeEach(function(){ this.post = factory.post(); this.view = new app.views.SinglePostContent({model : this.post}); - gon.appConfig = { map: {enabled: true, mapbox: {enabled: true, id: "yourID", accessToken: "yourAccessToken" }} }; + gon.appConfig = { map: {mapbox: {enabled: true, id: "yourID", accessToken: "yourAccessToken" }}}; }); describe("toggleMap", function() { From 52fac5740e4e8a1192af85e6f4dcef3aaf36679f Mon Sep 17 00:00:00 2001 From: realtin Date: Thu, 10 Sep 2015 14:48:25 +0200 Subject: [PATCH 10/11] fix indentation & jshint predefines according to svbergerem's annotations --- app/assets/javascripts/app/views/location_stream.js | 4 ++-- .../single-post-viewer/single_post_content_view.js | 10 +++++----- config/.jshint.json | 3 ++- spec/javascripts/app/views/location_stream_spec.js | 2 +- .../app/views/single_post_content_view_spec.js | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index eb140f054..d9f727347 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -23,7 +23,7 @@ app.views.LocationStream = app.views.Content.extend({ "rendering " + "GIScience Research Group @ Heidelberg University", maxZoom: 18, - }); + }); // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. if (gon.appConfig.map.mapbox.enabled) { @@ -46,7 +46,7 @@ app.views.LocationStream = app.views.Content.extend({ } } else { mapContainer.toggle(); - } + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 6cfbb9528..0bfb35b2d 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -46,7 +46,7 @@ app.views.SinglePostContent = app.views.Base.extend({ "rendering " + "GIScience Research Group @ Heidelberg University", maxZoom: 18, - }); + }); // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. if (gon.appConfig.map.mapbox.enabled) { @@ -70,13 +70,13 @@ app.views.SinglePostContent = app.views.Base.extend({ // put marker on map var markerOnMap = L.marker(location).addTo(map); return map; - } + } }, toggleMap: function () { - $(".mapContainer").height($(".small-map")[0] ? 200 : 50); - $(".leaflet-control-zoom").css("display", $(".small-map")[0] ? "block" : "none"); - $(".mapContainer").toggleClass("small-map"); + $(".mapContainer").height($(".small-map")[0] ? 200 : 50); + $(".leaflet-control-zoom").css("display", $(".small-map")[0] ? "block" : "none"); + $(".mapContainer").toggleClass("small-map"); }, presenter : function() { diff --git a/config/.jshint.json b/config/.jshint.json index c56365620..cf93d1e6e 100644 --- a/config/.jshint.json +++ b/config/.jshint.json @@ -46,6 +46,7 @@ "HandlebarsTemplates", "ImagePaths", "jsxc", + "L", "MBP", "Routes", "OSM", @@ -53,7 +54,7 @@ "punycode", "qq", "blueimp", - "L", + "loginAs", "logout", "spec", diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js index 54513b996..6f8683b2a 100644 --- a/spec/javascripts/app/views/location_stream_spec.js +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -28,7 +28,7 @@ describe("app.views.LocationStream", function() { this.view.toggleMap(); expect($(".mapContainer")).toHaveCss({display: "none"}); }); - }), + }); context("without location provided", function() { beforeEach(function(){ diff --git a/spec/javascripts/app/views/single_post_content_view_spec.js b/spec/javascripts/app/views/single_post_content_view_spec.js index 688891f96..645e86a31 100644 --- a/spec/javascripts/app/views/single_post_content_view_spec.js +++ b/spec/javascripts/app/views/single_post_content_view_spec.js @@ -35,7 +35,7 @@ describe("app.views.SinglePostContent", function() { this.view.toggleMap(); expect($(".mapContainer").height() < 100).toBeTruthy(); }); - }), + }); context("without location provided", function() { beforeEach(function(){ From 1cdcc50c634ba469ec3db93a4fb687dcbf5f2fd2 Mon Sep 17 00:00:00 2001 From: realtin Date: Fri, 11 Sep 2015 10:06:32 +0200 Subject: [PATCH 11/11] fix all the pronto remarks finally - fix map controls in stream --- app/assets/javascripts/app/views/location_stream.js | 4 +++- .../views/single-post-viewer/single_post_content_view.js | 4 +++- app/assets/stylesheets/stream_element.scss | 3 +++ spec/factories.rb | 7 +++---- spec/javascripts/app/views/location_stream_spec.js | 2 ++ spec/javascripts/app/views/locator_spec.js | 1 - spec/javascripts/helpers/factory.js | 2 +- spec/models/status_message_spec.rb | 2 +- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index d9f727347..1db156dea 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -30,7 +30,9 @@ app.views.LocationStream = app.views.Content.extend({ tiles = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { id: gon.appConfig.map.mapbox.id, + /* jshint camelcase: false */ accessToken: gon.appConfig.map.mapbox.access_token, + /* jshint camelcase: true */ attribution: "Map data © OpenStreetMap contributors, " + "CC-BY-SA, " + "Imagery © Mapbox", @@ -40,7 +42,7 @@ app.views.LocationStream = app.views.Content.extend({ tiles.addTo(map); - var markerOnMap = L.marker(location).addTo(map); + L.marker(location).addTo(map); mapContainer.removeClass("empty"); return map; } diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 0bfb35b2d..b105a74c4 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -53,7 +53,9 @@ app.views.SinglePostContent = app.views.Base.extend({ tiles = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { id: gon.appConfig.map.mapbox.id, + /* jshint camelcase: false */ accessToken: gon.appConfig.map.mapbox.access_token, + /* jshint camelcase: true */ attribution: "Map data © OpenStreetMap contributors, " + "CC-BY-SA, " + "Imagery © Mapbox", @@ -68,7 +70,7 @@ app.views.SinglePostContent = app.views.Base.extend({ map.invalidateSize(); // put marker on map - var markerOnMap = L.marker(location).addTo(map); + L.marker(location).addTo(map); return map; } }, diff --git a/app/assets/stylesheets/stream_element.scss b/app/assets/stylesheets/stream_element.scss index 46ed66c96..cbb826492 100644 --- a/app/assets/stylesheets/stream_element.scss +++ b/app/assets/stylesheets/stream_element.scss @@ -87,6 +87,9 @@ font-size: $font-size-small; color: $text-grey; } + .leaflet-control-zoom { + display: block; + } .grey { color: $text-grey; } .post-content p:last-of-type { margin-bottom: 0; } .nsfw-shield { diff --git a/spec/factories.rb b/spec/factories.rb index a7cddc2b7..056bb1928 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -140,10 +140,9 @@ FactoryGirl.define do end factory(:location) do - address "Starco Mart, Mission Street, West SoMa, San Francisco, San Francisco "\ - "City and County, Kalifornien, 94103, Vereinigte Staaten von Amerika" - lat 37.78 - lng -122.41 + address "Fernsehturm Berlin, Berlin, Germany" + lat 52.520645 + lng 13.409779 end factory(:poll) do diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js index 6f8683b2a..ba0d2e2db 100644 --- a/spec/javascripts/app/views/location_stream_spec.js +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -2,7 +2,9 @@ describe("app.views.LocationStream", function() { beforeEach(function(){ this.post = factory.post(); this.view = new app.views.LocationStream({model : this.post}); + /* jshint camelcase: false */ gon.appConfig = {map: { mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken" }}}; + /* jshint camelcase: true */ }); describe("toggleMap", function() { diff --git a/spec/javascripts/app/views/locator_spec.js b/spec/javascripts/app/views/locator_spec.js index 42e04741c..f600de8b9 100644 --- a/spec/javascripts/app/views/locator_spec.js +++ b/spec/javascripts/app/views/locator_spec.js @@ -1,6 +1,5 @@ describe("app.views.Location", function(){ beforeEach(function(){ - OSM = {}; OSM.Locator = function(){return { getAddress:function(){}}}; this.view = new app.views.Location(); diff --git a/spec/javascripts/helpers/factory.js b/spec/javascripts/helpers/factory.js index f8a40b874..856e8301a 100644 --- a/spec/javascripts/helpers/factory.js +++ b/spec/javascripts/helpers/factory.js @@ -150,7 +150,7 @@ var factory = { location : function() { return { - address: "Starco Mart, Mission Street, West SoMa, San Francisco, San Francisco City and County, Kalifornien, 94103, Vereinigte Staaten von Amerika", + address: "Starco Mart, Mission Street, San Francisco, Kalifornien, 94103, Vereinigte Staaten von Amerika", lat: 37.78, lng: -122.41 }; diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index d17a103fa..7172ae590 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -63,7 +63,7 @@ describe StatusMessage, type: :model do describe ".guids_for_author" do it "returns an array of the status_message guids" do status_message_1 = FactoryGirl.create(:status_message, author: alice.person) - status_message_2 = FactoryGirl.create(:status_message, author: bob.person) + FactoryGirl.create(:status_message, author: bob.person) guids = StatusMessage.guids_for_author(alice.person) expect(guids).to eq([status_message_1.guid]) end