From 6288eff5991087b695937863ca7e0b6823c709e3 Mon Sep 17 00:00:00 2001
From: Dennis Collinson <dennis.collective@gmail.com>
Date: Mon, 26 Mar 2012 17:02:09 -0700
Subject: [PATCH] day mood for a post responds to content

extract creating a post with templates to a static post view method.

Legacy templates extracted, day view

day mood shows photos and has variable text size
---
 features/step_definitions/trumpeter_steps.rb  | 55 ++++++++++++-------
 features/trumpeter.feature                    | 15 +++--
 public/javascripts/app/models/post.js         | 15 +++++
 public/javascripts/app/pages/framer.js        | 18 +-----
 public/javascripts/app/pages/post-viewer.js   |  9 +--
 .../javascripts/app/templates/day.handlebars  |  2 +
 .../app/templates/photo-viewer.handlebars     |  3 +
 public/javascripts/app/views.js               |  4 +-
 public/javascripts/app/views/photo_viewer.js  |  7 +++
 public/javascripts/app/views/post/day_view.js | 16 ++++++
 public/javascripts/app/views/post_view.js     | 31 +++++++++--
 .../app/views/template_picker_view.js         | 10 +---
 public/stylesheets/sass/new-templates.scss    |  4 ++
 spec/javascripts/app/pages/framer_spec.js     |  2 +-
 .../app/views/photo_viewer_spec.js            | 19 +++++++
 .../app/views/post/day_view_spec.js           | 34 ++++++++++++
 spec/javascripts/helpers/factory.js           | 14 +++++
 17 files changed, 193 insertions(+), 65 deletions(-)
 create mode 100644 public/javascripts/app/templates/day.handlebars
 create mode 100644 public/javascripts/app/templates/photo-viewer.handlebars
 create mode 100644 public/javascripts/app/views/photo_viewer.js
 create mode 100644 public/javascripts/app/views/post/day_view.js
 create mode 100644 spec/javascripts/app/views/photo_viewer_spec.js
 create mode 100644 spec/javascripts/app/views/post/day_view_spec.js

diff --git a/features/step_definitions/trumpeter_steps.rb b/features/step_definitions/trumpeter_steps.rb
index b40f2beac8..56d58bc598 100644
--- a/features/step_definitions/trumpeter_steps.rb
+++ b/features/step_definitions/trumpeter_steps.rb
@@ -25,14 +25,29 @@ def finalize_frame
   click_button "done"
 end
 
-def within_frame_preview
-  within find(".post") do
-    yield
-  end
+def assert_post_renders_with(template_name)
+  find(".post")["data-template"].should == template_name.downcase
 end
 
-def assert_post_renders_with(template_name)
-  find(".post")["data-template"].should == template_name
+def find_image_by_filename(filename)
+  find("img[src='#{@image_sources[filename]}']")
+end
+
+def store_image_filename(file_name)
+  @image_sources ||= {}
+  @image_sources[file_name] = all(".photos img").last["src"]
+  @image_sources[file_name].should be_present
+end
+
+def upload_photo(file_name)
+  orig_photo_count = all(".photos img").size
+
+  within ".new_photo" do
+    attach_file "photo[user_file]", Rails.root.join("spec", "fixtures", file_name)
+    wait_until { all(".photos img").size == orig_photo_count + 1 }
+  end
+
+  store_image_filename(file_name)
 end
 
 When /^I trumpet$/ do
@@ -60,21 +75,13 @@ Then /^"([^"]*)" should be a (limited|public) post in my stream$/ do |post_text,
 end
 
 When /^I upload a fixture picture with filename "([^"]*)"$/ do |file_name|
-  orig_photo_count = all(".photos img").size
-
-  within ".new_photo" do
-    attach_file "photo[user_file]", Rails.root.join("spec", "fixtures", file_name)
-    wait_until { all(".photos img").size == orig_photo_count + 1 }
-  end
-
-  @image_sources ||= {}
-  @image_sources[file_name] = all(".photos img").last["src"]
-  @image_sources[file_name].should be_present
+  upload_photo(file_name)
 end
 
 Then /^"([^"]*)" should have the "([^"]*)" picture$/ do |post_text, file_name|
-  image = find_post_by_text(post_text).find(".photo_attachments img[src='#{@image_sources[file_name]}']")
-  image.should be_present
+  within find_post_by_text(post_text) do
+    find_image_by_filename(file_name).should be_present
+  end
 end
 
 When /^I go through the default composer$/ do
@@ -95,13 +102,19 @@ Then /^"([^"]*)" should have (\d+) pictures$/ do |post_text, number_of_pictures|
 end
 
 Then /^I should see "([^"]*)" in the framer preview$/ do |post_text|
-  within_frame_preview { page.should have_content(post_text) }
+  within(find(".post")) { page.should have_content(post_text) }
 end
 
-When /^I select the template "([^"]*)"$/ do |template_name|
+When /^I select the mood "([^"]*)"$/ do |template_name|
   select template_name, :from => 'template'
 end
 
-Then /^the post should (?:still |)be rendered as a "([^"]*)"$/ do |template_name|
+Then /^the post's mood should (?:still |)be "([^"]*)"$/ do |template_name|
   assert_post_renders_with(template_name)
+end
+
+When /^"([^"]*)" should be in the post's picture viewer$/ do |file_name|
+  within(".photo_viewer") do
+    find_image_by_filename(file_name).should be_present
+  end
 end
\ No newline at end of file
diff --git a/features/trumpeter.feature b/features/trumpeter.feature
index 29137f37d5..cbeb8a45cf 100644
--- a/features/trumpeter.feature
+++ b/features/trumpeter.feature
@@ -42,13 +42,18 @@ Feature: Creating a new post
   Scenario: Framing your frame
     When I write "This is hella customized"
     And I upload a fixture picture with filename "button.gif"
+
     And I start the framing process
     Then I should see "This is hella customized" in the framer preview
-#    And I should see the image "button.gif" background
-    When I select the template "note"
-    Then the post should be rendered as a "note"
+  # Then the default mood for the post should be "Wallpaper"
+  # And I should see the image "button.gif" background
+    When I select the mood "Day"
+    Then the post's mood should be "Day"
+    And "button.gif" should be in the post's picture viewer
+    And I should see "This is hella customized" in the framer preview
+
     When I finalize my frame
     And I go to "/stream"
     Then "This is hella customized" should be post 1
-    When I click the show page link for "This is hella customized"
-    Then the post should still be rendered as a "note"
+    And I click the show page link for "This is hella customized"
+    And the post's mood should still be "Day"
diff --git a/public/javascripts/app/models/post.js b/public/javascripts/app/models/post.js
index a5beb5ecd3..efe9c9a8c6 100644
--- a/public/javascripts/app/models/post.js
+++ b/public/javascripts/app/models/post.js
@@ -90,4 +90,19 @@ app.models.Post = Backbone.Model.extend({
       self.trigger('interacted', this)
     }});
   }
+}, {
+
+  frameMoods : [
+    "Day"
+  ],
+
+  legacyTemplateNames : [
+    "status-with-photo-backdrop",
+    "note",
+    "rich-media",
+    "multi-photo",
+    "photo-backdrop",
+    "activity-streams-photo",
+    "status"
+  ]
 });
diff --git a/public/javascripts/app/pages/framer.js b/public/javascripts/app/pages/framer.js
index 3939f832fe..e75f3b1ac1 100644
--- a/public/javascripts/app/pages/framer.js
+++ b/public/javascripts/app/pages/framer.js
@@ -14,28 +14,14 @@ app.pages.Framer = app.views.Base.extend({
 
   initialize : function(){
     this.model = app.frame
+    this.model.authorIsCurrentUser = function(){ return true }
 
     this.model.bind("change", this.render, this)
     this.templatePicker = new app.views.TemplatePicker({ model: this.model })
   },
 
   postView : function(){
-    //we might be leaky like cray cray with this
-
-    var templateType = this.model.get("frame_name")
-
-     this._postView = new app.views.Post({
-      model : this.model,
-      className : templateType + " post loaded",
-      templateName : "post-viewer/content/" + templateType,
-      attributes : {"data-template" : templateType}
-    });
-
-    this._postView.feedbackView = new Backbone.View
-
-    this.model.authorIsCurrentUser = function(){ return true }
-
-    return this._postView
+    return app.views.Post.showFactory(this.model)
   },
 
   saveFrame : function(){
diff --git a/public/javascripts/app/pages/post-viewer.js b/public/javascripts/app/pages/post-viewer.js
index afea0ae7d8..803dbe384f 100644
--- a/public/javascripts/app/pages/post-viewer.js
+++ b/public/javascripts/app/pages/post-viewer.js
@@ -25,14 +25,7 @@ app.pages.PostViewer = app.views.Base.extend({
     this.authorView = new app.views.PostViewerAuthor({ model : this.model });
     this.interactionsView = new app.views.PostViewerInteractions({ model : this.model });
     this.navView = new app.views.PostViewerNav({ model : this.model });
-
-    var frameName = this.model.get("frame_name")
-    this.postView = new app.views.Post({
-      model : this.model,
-      className :  frameName + " post loaded",
-      templateName : "post-viewer/content/" + frameName,
-      attributes : {"data-template" : frameName}
-    });
+    this.postView = app.views.Post.showFactory(this.model)
 
     this.render();
   },
diff --git a/public/javascripts/app/templates/day.handlebars b/public/javascripts/app/templates/day.handlebars
new file mode 100644
index 0000000000..7a9acc3fc7
--- /dev/null
+++ b/public/javascripts/app/templates/day.handlebars
@@ -0,0 +1,2 @@
+<section class="text">{{{text}}}</section>
+<section class="photo_viewer"></section>
diff --git a/public/javascripts/app/templates/photo-viewer.handlebars b/public/javascripts/app/templates/photo-viewer.handlebars
new file mode 100644
index 0000000000..1e83ff5d32
--- /dev/null
+++ b/public/javascripts/app/templates/photo-viewer.handlebars
@@ -0,0 +1,3 @@
+{{#each photos}}
+   <img src="{{sizes.large}}"/>
+{{/each}}
\ No newline at end of file
diff --git a/public/javascripts/app/views.js b/public/javascripts/app/views.js
index 6cd4f336e2..faadd32ce5 100644
--- a/public/javascripts/app/views.js
+++ b/public/javascripts/app/views.js
@@ -40,7 +40,9 @@ app.views.Base = Backbone.View.extend({
   renderTemplate : function(){
     var presenter = _.isFunction(this.presenter) ? this.presenter() : this.presenter
     this.template = JST[this.templateName]
-    $(this.el).html(this.template(presenter));
+    $(this.el)
+      .html(this.template(presenter))
+      .attr("data-template", _.last(this.templateName.split("/")));
     this.postRenderTemplate();
   },
 
diff --git a/public/javascripts/app/views/photo_viewer.js b/public/javascripts/app/views/photo_viewer.js
new file mode 100644
index 0000000000..3f30cfbd46
--- /dev/null
+++ b/public/javascripts/app/views/photo_viewer.js
@@ -0,0 +1,7 @@
+app.views.PhotoViewer = app.views.Base.extend({
+  templateName : "photo-viewer",
+
+  presenter : function(){
+    return { photos : this.model.get("photos") } //json array of attributes, not backbone models, yet.
+  }
+});
\ No newline at end of file
diff --git a/public/javascripts/app/views/post/day_view.js b/public/javascripts/app/views/post/day_view.js
new file mode 100644
index 0000000000..f01bb41a9f
--- /dev/null
+++ b/public/javascripts/app/views/post/day_view.js
@@ -0,0 +1,16 @@
+app.views.Post.Day = app.views.Post.extend({
+  templateName : "day",
+  className : "day post loaded",
+
+  subviews : { "section.photo_viewer" : "photoViewer" },
+
+  photoViewer : function(){
+    return new app.views.PhotoViewer({ model : this.model })
+  },
+
+  postRenderTemplate : function(){
+    if(this.model.get("text").length < 140){
+      this.$('section.text').addClass('headline');
+    }
+  }
+});
\ No newline at end of file
diff --git a/public/javascripts/app/views/post_view.js b/public/javascripts/app/views/post_view.js
index bc6345e505..4f167fd3ae 100644
--- a/public/javascripts/app/views/post_view.js
+++ b/public/javascripts/app/views/post_view.js
@@ -1,8 +1,4 @@
 app.views.Post = app.views.StreamObject.extend({
-  initialize : function(options) {
-    this.templateName = options.templateName
-  },
-
   presenter : function() {
     return _.extend(this.defaultPresenter(), {
       authorIsCurrentUser : this.authorIsCurrentUser(),
@@ -18,4 +14,31 @@ app.views.Post = app.views.StreamObject.extend({
   showPost : function() {
     return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw")
   }
+}, { //static methods below
+
+  showFactory : function(model) {
+    var frameName = model.get("frame_name");
+
+    if(_.include(app.models.Post.legacyTemplateNames, frameName)){
+      return legacyShow(model)
+    } else {
+      return new app.views.Post[frameName]({
+        model : model
+      })
+    }
+
+    function legacyShow(model) {
+      return new app.views.Post.Legacy({
+        model : model,
+        className :   frameName + " post loaded",
+        templateName : "post-viewer/content/" +  frameName
+      });
+    }
+  }
 });
+
+app.views.Post.Legacy = app.views.Post.extend({
+  initialize : function(options) {
+    this.templateName = options.templateName || this.templateName
+  }
+})
\ No newline at end of file
diff --git a/public/javascripts/app/views/template_picker_view.js b/public/javascripts/app/views/template_picker_view.js
index bada253387..834bd72e77 100644
--- a/public/javascripts/app/views/template_picker_view.js
+++ b/public/javascripts/app/views/template_picker_view.js
@@ -19,15 +19,7 @@ app.views.TemplatePicker = app.views.Base.extend({
 
   presenter : function() {
     return _.extend(this.defaultPresenter(), {
-      templates : [
-        "status-with-photo-backdrop",
-        "note",
-        "rich-media",
-        "multi-photo",
-        "photo-backdrop",
-        "activity-streams-photo",
-        "status"
-      ]
+      templates : _.union(app.models.Post.frameMoods, app.models.Post.legacyTemplateNames)
     })
   }
 })
\ No newline at end of file
diff --git a/public/stylesheets/sass/new-templates.scss b/public/stylesheets/sass/new-templates.scss
index 3c7c22d7dd..c8ce383556 100644
--- a/public/stylesheets/sass/new-templates.scss
+++ b/public/stylesheets/sass/new-templates.scss
@@ -805,3 +805,7 @@ text-rendering: optimizelegibility;
     position: absolute;
   }
 }
+
+.headline p{
+  @include media-text();
+}
\ No newline at end of file
diff --git a/spec/javascripts/app/pages/framer_spec.js b/spec/javascripts/app/pages/framer_spec.js
index 951d3a92c3..db9deb0de4 100644
--- a/spec/javascripts/app/pages/framer_spec.js
+++ b/spec/javascripts/app/pages/framer_spec.js
@@ -10,7 +10,7 @@ describe("app.pages.Framer", function(){
   });
 
   it("passes the model down to the post view", function(){
-    expect(this.page._postView.model).toBe(app.frame)
+    expect(this.page.postView().model).toBe(app.frame)
   });
 
   describe("rendering", function(){
diff --git a/spec/javascripts/app/views/photo_viewer_spec.js b/spec/javascripts/app/views/photo_viewer_spec.js
new file mode 100644
index 0000000000..6f25d580b6
--- /dev/null
+++ b/spec/javascripts/app/views/photo_viewer_spec.js
@@ -0,0 +1,19 @@
+describe("app.views.PhotoViewer", function(){
+  beforeEach(function(){
+    this.model = factory.post({
+      photos : [
+        factory.photoAttrs({sizes : {large : "http://tieguy.org/me.jpg"}}),
+        factory.photoAttrs({sizes : {large : "http://whatthefuckiselizabethstarkupto.com/none_knows.gif"}}) //SIC
+      ]
+    })
+    this.view = new app.views.PhotoViewer({model : this.model})
+  })
+
+  describe("rendering", function(){
+    it("should have an image for each photoAttr on the model", function(){
+      this.view.render()
+      expect(this.view.$("img").length).toBe(2)
+      expect(this.view.$("img[src='http://tieguy.org/me.jpg']")).toExist()
+    })
+  })
+})
\ No newline at end of file
diff --git a/spec/javascripts/app/views/post/day_view_spec.js b/spec/javascripts/app/views/post/day_view_spec.js
new file mode 100644
index 0000000000..397ac46151
--- /dev/null
+++ b/spec/javascripts/app/views/post/day_view_spec.js
@@ -0,0 +1,34 @@
+describe("app.views.Post.Day", function(){
+  beforeEach(function(){
+    this.post = factory.post()
+    this.view = new app.views.Post.Day({model : this.post})
+  })
+
+  describe("rendering", function(){
+    it("is happy", function(){
+      this.view.render()
+    })
+
+    describe("when the text is under 140 characters", function(){
+      it("has class headline", function(){
+        this.post.set({text : "Lol this is a short headline"})
+        this.view.render()
+        expect(this.view.$("section.text")).toHaveClass("headline")
+      })
+    })
+
+    describe("when the text is over 140 characters", function(){
+      it("has doesn't have headline", function(){
+        this.post.set({text :"Vegan bushwick tempor labore. Nulla seitan anim, aesthetic ex gluten-free viral" +
+          "thundercats street art. Occaecat carles deserunt lomo messenger bag wes anderson. Narwhal cray selvage " +
+          "dolor. Mixtape wes anderson american apparel, mustache readymade cred nulla squid veniam small batch id " +
+          "cupidatat. Pork belly high life consequat, raw denim sint terry richardson seitan single-origin coffee " +
+          "butcher. Sint yr fugiat cillum."
+        })
+
+        this.view.render()
+        expect(this.view.$("section.text")).not.toHaveClass("headline")
+      })
+    })
+  })
+})
\ No newline at end of file
diff --git a/spec/javascripts/helpers/factory.js b/spec/javascripts/helpers/factory.js
index 9262945e9e..b1ff242729 100644
--- a/spec/javascripts/helpers/factory.js
+++ b/spec/javascripts/helpers/factory.js
@@ -74,6 +74,20 @@ factory = {
     }
   },
 
+  photoAttrs : function(overrides){
+    return _.extend({
+      author: factory.userAttrs(),
+      created_at: "2012-03-27T20:11:52Z",
+      guid: "8b0db16a4c4307b2",
+      id: 117,
+      sizes: {
+          large: "http://localhost:3000/uploads/images/scaled_full_d85410bd19db1016894c.jpg",
+          medium: "http://localhost:3000/uploads/images/thumb_medium_d85410bd19db1016894c.jpg",
+          small: "http://localhost:3000/uploads/images/thumb_small_d85410bd19db1016894c.jpg"
+        }
+    }, overrides)
+  },
+
   post :  function(overrides) {
     defaultAttrs = _.extend(factory.postAttrs(),  {"author" : this.author()})
     return new app.models.Post(_.extend(defaultAttrs, overrides))
-- 
GitLab