From 1c135b61fdd9a58f51a0592d9fe84a88455641d6 Mon Sep 17 00:00:00 2001 From: Dennis Collinson Date: Mon, 7 May 2012 15:56:09 -0700 Subject: [PATCH] Jamie Cai DC message in profile when user has no posts --- app/assets/javascripts/app/models/profile.js | 8 + app/assets/javascripts/app/pages/profile.js | 28 ++- .../javascripts/app/views/canvas_view.js | 20 +- .../stylesheets/new_styles/_canvas.scss | 5 + app/assets/templates/canvas.jst.hbs | 173 ------------------ app/controllers/people_controller.rb | 4 +- app/controllers/profiles_controller.rb | 15 +- app/presenters/person_presenter.rb | 34 ++++ spec/controllers/posts_controller_spec.rb | 2 +- spec/javascripts/app/pages/profile_spec.js | 124 +++++++------ 10 files changed, 154 insertions(+), 259 deletions(-) delete mode 100644 app/assets/templates/canvas.jst.hbs create mode 100644 app/presenters/person_presenter.rb diff --git a/app/assets/javascripts/app/models/profile.js b/app/assets/javascripts/app/models/profile.js index cf52af89b..43d04c8c4 100644 --- a/app/assets/javascripts/app/models/profile.js +++ b/app/assets/javascripts/app/models/profile.js @@ -2,6 +2,14 @@ app.models.Profile = Backbone.Model.extend({ urlRoot : "/profiles" }, { + preloadOrFetch : function(id){ + if(app.hasPreload("person")) { + return new app.models.Profile(app.parsePreload("person")) + } else { + return this.findByGuid(id) + } + }, + findByGuid : function(personId){ var person = new app.models.Profile({ id : personId}) person.fetch() diff --git a/app/assets/javascripts/app/pages/profile.js b/app/assets/javascripts/app/pages/profile.js index ae3b97f4c..5f97e329f 100644 --- a/app/assets/javascripts/app/pages/profile.js +++ b/app/assets/javascripts/app/pages/profile.js @@ -2,10 +2,8 @@ //= require ../views/profile_info_view app.pages.Profile = app.views.Base.extend({ - - id : "profile", - templateName : "profile", + id : "profile", subviews : { "#profile-info" : "profileInfo", @@ -23,20 +21,10 @@ app.pages.Profile = app.views.Base.extend({ personGUID : null, editMode : false, - presenter : function(){ - var bio = this.model.get("bio") || '' - - return _.extend(this.defaultPresenter(), - {text : this.model && app.helpers.textFormatter(bio, this.model), - isOwnProfile : this.isOwnProfile(), - showFollowButton : this.showFollowButton() - }) - }, - initialize : function(options) { this.personGUID = options.personId - this.model = new app.models.Profile.findByGuid(options.personId) + this.model = this.model || app.models.Profile.preloadOrFetch(this.personGUID) this.stream = options && options.stream || new app.models.Stream() this.model.bind("change", this.setPageTitleAndBackground, this) @@ -54,6 +42,16 @@ app.pages.Profile = app.views.Base.extend({ this.profileInfo = new app.views.ProfileInfo({ model : this.model.set({isOwnProfile : this.isOwnProfile()}) }) }, + presenter : function(){ + var bio = this.model.get("bio") || '' + + return _.extend(this.defaultPresenter(), + {text : this.model && app.helpers.textFormatter(bio, this.model), + isOwnProfile : this.isOwnProfile(), + showFollowButton : this.showFollowButton() + }) + }, + pulsateNewPostControl : function() { this.$("#composer-button")[ this.stream.items.length == 0 @@ -92,4 +90,4 @@ app.pages.Profile = app.views.Base.extend({ isOwnProfile : function() { return(app.currentUser.get("guid") == this.personGUID) } -}); \ No newline at end of file +}); diff --git a/app/assets/javascripts/app/views/canvas_view.js b/app/assets/javascripts/app/views/canvas_view.js index 709abdeff..b3f28af45 100644 --- a/app/assets/javascripts/app/views/canvas_view.js +++ b/app/assets/javascripts/app/views/canvas_view.js @@ -10,9 +10,23 @@ app.views.Canvas = app.views.Base.extend(_.extend({}, app.views.infiniteScrollMi renderTemplate : function() { this.$el.empty() - this.stream.items.each(_.bind(function(post){ - this.$el.append(this.createPostView(post).render().el); - }, this)) + + if(this.stream.items.isEmpty()){ + var message + , person = app.page.model + if(person.get("is_own_profile")){ + message = "Make something to start the magic." + } else { + var name = person.get("full_name") || "" + message = name + " hasn't posted anything yet." + } + + this.$el.html("

" + message + "

") + } else { + this.stream.items.each(_.bind(function(post){ + this.$el.append(this.createPostView(post).render().el); + }, this)) + } //needs to be deferred so it happens after html rendering finishes _.defer(_.bind(this.mason, this)) diff --git a/app/assets/stylesheets/new_styles/_canvas.scss b/app/assets/stylesheets/new_styles/_canvas.scss index ab80a4e6d..239ac6241 100644 --- a/app/assets/stylesheets/new_styles/_canvas.scss +++ b/app/assets/stylesheets/new_styles/_canvas.scss @@ -3,6 +3,11 @@ min-width : $two-column-width + px; max-width : $two-column-width + px; } +.no-post-message { + text-align: center; + margin-top: 50px; + font-size: 1.2em; +} .canvas-frame { float : left; diff --git a/app/assets/templates/canvas.jst.hbs b/app/assets/templates/canvas.jst.hbs deleted file mode 100644 index eba934a52..000000000 --- a/app/assets/templates/canvas.jst.hbs +++ /dev/null @@ -1,173 +0,0 @@ -
-
- -
-
- Daniel Grippi -
-
- -
-
-

- Here, he discusses how globalisation has exacerbated income inequalities and the control over politics exerted by the rich, citing the Occupy movement which he describes as a 'public relations hazard not a health hazard' -

- -

- Echo park wolf kale chips sunt, dolor scenester deserunt ad cray leggings 3 wolf moon thundercats direct trade. Banksy placeat odd future et, ex gastropub elit whatever. Messenger bag eu fanny pack, pitchfork locavore four loko yr marfa forage. Mcsweeney's hoodie terry richardson exercitation, consectetur commodo banh mi ullamco laboris cliche raw denim salvia selvage in nulla. Lo-fi chambray culpa, dreamcatcher fugiat squid portland nihil high life. Quis VHS blog sunt sint, salvia wes anderson fingerstache portland eiusmod ex consectetur synth enim. Tattooed aliquip proident id, lomo aliqua qui pitchfork hella cosby sweater pariatur vero.

- -
-
- Dennis Collinson -
-
- -
-
- -
-
- Sarah Mei -
-
- - -
-
-

- sometimes, i say things loud. -

-
-
- Sean Tilley -
-
- -
-
-

- this is a longish status but i don't have that much to say. i guess i can keep on typing or something like that or make this a run-on sentance. -

-
-
- Daniel Grippi -
-
- -
-
-

- Echo park wolf kale chips sunt, dolor scenester deserunt ad cray leggings 3 wolf moon thundercats direct trade. Banksy placeat odd future et, ex gastropub elit whatever. Messenger bag eu fanny pack, pitchfork locavore four loko yr marfa forage. Mcsweeney's hoodie terry richardson exercitation, consectetur commodo banh mi ullamco laboris cliche raw denim salvia selvage in nulla. Lo-fi chambray culpa, dreamcatcher fugiat squid portland nihil high life. Quis VHS blog sunt sint, salvia wes anderson fingerstache portland eiusmod ex consectetur synth enim. Tattooed aliquip proident id, lomo aliqua qui pitchfork hella cosby sweater pariatur vero. -

- -
-
- Dennis Collinson -
-
- -
-
- -
-
- Sarah Mei -
-
- - -
-
-

- #weinerjuice -

-
-
- Sean Tilley -
-
- -
-
- -
-
- Rosanna Yau -
-
- -
-
-

- Banksy placeat odd future et, ex gastropub elit whatever. Messenger bag eu fanny pack, pitchfork locavore four loko yr marfa forage. Mcsweeney's hoodie terry richardson exercitation, consectetur commodo banh mi ullamco laboris cliche raw denim salvia selvage - Banksy placeat odd future et, ex gastropub elit whatever. Messenger bag eu fanny pack, pitchfork. -

-
-
- Sarah Mei -
-
- -
-
- -
-
- Daniel Grippi -
-
- - -
-
-

- Banksy placeat odd future et, ex gastropub elit whatever. Messenger bag eu fanny pack, pitchfork locavore four loko yr marfa forage. Mcsweeney's hoodie terry richardson exercitation, consectetur commodo banh mi ullamco laboris cliche raw denim salvia selvage -

-
-
- Daniel Grippi -
-
- - - - -
-
-

- skribblex. -

-
-
- Rosanna Yau -
-
- -
-
- -
-
- Sarah Mei -
-
- -
-
- hey there kids! -
-
- Daniel Grippi -
-
- - -
-
- -
-
- Rosanna Yau -
-
- diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 81a3b2b83..bb0865cc8 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -119,7 +119,9 @@ class PeopleController < ApplicationController format.all do if params[:ex] @page = :experimental - gon.stream = @stream.stream_posts.as_api_response(:backbone).as_json + gon.person = PersonPresenter.new(@person, current_user) + gon.stream = @stream.stream_posts.as_api_response(:backbone) + render :nothing => true, :layout => 'post' else respond_with @person, :locals => {:post_type => :all} diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f9862416c..398843a4d 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -14,20 +14,7 @@ class ProfilesController < ApplicationController @person = Person.find_by_guid!(params[:id]) respond_to do |format| - format.json { - public_json = @person.as_api_response(:backbone) - extra_json = {:wallpaper => @person.profile.wallpaper.url} - - if(current_user && (current_user.person == @person || current_user.contacts.receiving.where(:person_id => @person.id).first)) - extra_json = extra_json.merge({ - :location => @person.profile.location, - :birthday => @person.profile.formatted_birthday, - :bio => @person.profile.bio - }) - end - - render :json => public_json.merge(extra_json) - } + format.json { render :json => PersonPresenter.new(@person, current_user) } end end diff --git a/app/presenters/person_presenter.rb b/app/presenters/person_presenter.rb new file mode 100644 index 000000000..0e3045818 --- /dev/null +++ b/app/presenters/person_presenter.rb @@ -0,0 +1,34 @@ +class PersonPresenter + def initialize(person, current_user = nil) + @person = person + @current_user = current_user + end + + def as_json(options={}) + attrs = @person.as_api_response(:backbone).merge( + { + :wallpaper => @person.profile.wallpaper.url, + :is_own_profile => is_own_profile + }) + + if is_own_profile || person_is_following_current_user + attrs.merge!({ + :location => @person.profile.location, + :birthday => @person.profile.formatted_birthday, + :bio => @person.profile.bio + }) + end + + attrs + end + + def is_own_profile + @current_user.try(:person) == @person + end + + protected + + def person_is_following_current_user + @current_user.contacts.receiving.where(:person_id => @person.id).first + end +end \ No newline at end of file diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index cd58d3563..166f27ee4 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -168,7 +168,7 @@ describe PostsController do end end - describe "next" do + describe "#next" do before do sign_in alice #lets make a class and unit test it, because this is still not working diff --git a/spec/javascripts/app/pages/profile_spec.js b/spec/javascripts/app/pages/profile_spec.js index 1547c18ee..dc8b88a7e 100644 --- a/spec/javascripts/app/pages/profile_spec.js +++ b/spec/javascripts/app/pages/profile_spec.js @@ -1,19 +1,20 @@ describe("app.pages.Profile", function(){ beforeEach(function(){ this.guid = 'abcdefg123' - app.page = this.page = new app.pages.Profile({personId :this.guid }); + this.profile = factory.profile({personId: this.guid}) + app.page = this.page = new app.pages.Profile({model : this.profile }); this.stream = this.page.stream }); it("fetches the profile of the user with the params from the router and assigns it as the model", function(){ - profile = new factory.profile() + var profile = new factory.profile() spyOn(app.models.Profile, 'findByGuid').andReturn(profile) var page = new app.pages.Profile({personId : 'jarjabinkisthebest' }) expect(app.models.Profile.findByGuid).toHaveBeenCalledWith('jarjabinkisthebest') expect(page.model).toBe(profile) }) - it("passes the model down to the post view", function(){ + it("passes the stream down to the canvas view", function(){ expect(this.page.canvasView.model).toBeDefined() expect(this.page.canvasView.model).toBe(this.stream) }); @@ -30,68 +31,87 @@ describe("app.pages.Profile", function(){ }) describe("rendering", function(){ - beforeEach(function(){ - this.post = factory.post() - this.stream.add(this.post) - this.page.toggleEdit() - expect(this.page.editMode).toBeTruthy() - this.page.render() - }); - - context("profile control pane", function(){ - it("shows the edit and create buttons if it's your profile", function() { - spyOn(this.page, "isOwnProfile").andReturn(true) - this.page.render() - expect(this.page.$("#profile-controls .control").length).toBe(2) - }) - - it("shows a follow button if showFollowButton returns true", function() { - spyOn(this.page, "showFollowButton").andReturn(true) - this.page.render() - expect(this.page.$("#follow-button").length).toBe(1) - }) - - it("doesn't show a follow button if showFollowButton returns false", function() { - spyOn(this.page, "showFollowButton").andReturn(false) - this.page.render() - expect(this.page.$("#follow-button").length).toBe(0) - }) - }) - - context("clicking fav", function(){ + context("with no posts", function(){ beforeEach(function(){ - spyOn(this.post, 'toggleFavorite') - spyOn($.fn, "isotope") - this.page.$(".content").click() + this.profile.set({"full_name" : "Alice Waters", person_id : "889"}) }) - it("relayouts the page", function(){ - expect($.fn.isotope).toHaveBeenCalledWith("reLayout") + it("has a message that there are no posts", function(){ + this.page.render() + expect(this.page.$("#canvas").text()).toBe("Alice Waters hasn't posted anything yet.") }) - it("toggles the favorite status on the model", function(){ - expect(this.post.toggleFavorite).toHaveBeenCalled() + it("tells you to post something if it's your profile", function(){ + this.profile.set({is_own_profile : true}) + this.page.render() + expect(this.page.$("#canvas").text()).toBe("Make something to start the magic.") }) }) - context("clicking delete", function(){ - beforeEach(function () { - spyOn(window, "confirm").andReturn(true); + context("with a post", function(){ + beforeEach(function(){ + this.post = factory.post() + this.stream.add(this.post) + this.page.toggleEdit() + expect(this.page.editMode).toBeTruthy() this.page.render() + }); + + context("profile control pane", function(){ + it("shows the edit and create buttons if it's your profile", function() { + spyOn(this.page, "isOwnProfile").andReturn(true) + this.page.render() + expect(this.page.$("#profile-controls .control").length).toBe(2) + }) + + it("shows a follow button if showFollowButton returns true", function() { + spyOn(this.page, "showFollowButton").andReturn(true) + this.page.render() + expect(this.page.$("#follow-button").length).toBe(1) + }) + + it("doesn't show a follow button if showFollowButton returns false", function() { + spyOn(this.page, "showFollowButton").andReturn(false) + this.page.render() + expect(this.page.$("#follow-button").length).toBe(0) + }) }) - it("kills the model", function(){ - spyOn(this.post, "destroy") - this.page.$(".canvas-frame:first a.delete").click() - expect(this.post.destroy).toHaveBeenCalled() + context("clicking fav", function(){ + beforeEach(function(){ + spyOn(this.post, 'toggleFavorite') + spyOn($.fn, "isotope") + this.page.$(".content").click() + }) + + it("relayouts the page", function(){ + expect($.fn.isotope).toHaveBeenCalledWith("reLayout") + }) + + it("toggles the favorite status on the model", function(){ + expect(this.post.toggleFavorite).toHaveBeenCalled() + }) }) - it("removes the frame", function(){ - spyOn($.fn, "remove").andCallThrough() - expect(this.page.$(".canvas-frame").length).toBe(1) - this.page.$(".canvas-frame:first a.delete").click() - waitsFor(function(){ return $.fn.remove.wasCalled }) - runs(function(){ expect(this.page.$(".canvas-frame").length).toBe(0) }) + context("clicking delete", function(){ + beforeEach(function () { + spyOn(window, "confirm").andReturn(true); + this.page.render() + }) + + it("kills the model", function(){ + spyOn(this.post, "destroy") + this.page.$(".canvas-frame:first a.delete").click() + expect(this.post.destroy).toHaveBeenCalled() + }) + + it("removes the frame", function(){ + spyOn($.fn, "remove").andCallThrough() + expect(this.page.$(".canvas-frame").length).toBe(1) + this.page.$(".canvas-frame:first a.delete").click() + waitsFor(function(){ return $.fn.remove.wasCalled }) + runs(function(){ expect(this.page.$(".canvas-frame").length).toBe(0) }) + }) }) }) });