diff --git a/app/assets/javascripts/app/pages/composer.js b/app/assets/javascripts/app/pages/composer.js index 1eaea7105..ac6804f05 100644 --- a/app/assets/javascripts/app/pages/composer.js +++ b/app/assets/javascripts/app/pages/composer.js @@ -11,9 +11,7 @@ app.pages.Composer = app.views.Base.extend({ }, formAttrs : { - "textarea#text_with_markup" : "text", - "input.aspect_ids" : "aspect_ids[]", - "input.services" : "services[]" + "textarea#text_with_markup" : "text" }, initialize : function(){ @@ -45,34 +43,13 @@ app.pages.Composer = app.views.Base.extend({ }, setModelAttributes : function(overrides){ - var form = this.$el; - this.model.set(_.inject(this.formAttrs, setValueFromField, {})) + this.setFormAttrs() this.model.photos = this.postForm.pictureForm.photos this.model.set({"photos": this.model.photos.toJSON() }) this.model.set(overrides) - - - function setValueFromField(memo, attribute, selector){ - if(attribute.slice("-2") === "[]") { - memo[attribute.slice(0, attribute.length - 2)] = _.pluck(form.find(selector).serializeArray(), "value") - } else { - memo[attribute] = form.find(selector).val(); - } - return memo - } } }); app.views.ComposerControls = app.views.Base.extend({ - templateName : 'composer-controls', - - subviews : { - ".aspect-selector" : "aspectsDropdown", - ".service-selector" : "servicesSelector" - }, - - initialize : function() { - this.aspectsDropdown = new app.views.AspectsDropdown({model : this.model}); - this.servicesSelector = new app.views.ServicesSelector({model : this.model}); - } + templateName : 'composer-controls' }) diff --git a/app/assets/javascripts/app/pages/framer.js b/app/assets/javascripts/app/pages/framer.js index 01a3ca21c..68f9b3c38 100644 --- a/app/assets/javascripts/app/pages/framer.js +++ b/app/assets/javascripts/app/pages/framer.js @@ -10,9 +10,10 @@ app.pages.Framer = app.views.Base.extend({ initialize : function(){ this.model = app.frame - this.model.authorIsCurrentUser = function(){ return true } + if(!this.model.get("frame_name")) this.model.setFrameName() - this.model.bind("change", this.render, this) + this.model.authorIsCurrentUser = function(){ return true } + this.model.bind("change:frame_name", this.render, this) this.model.bind("sync", this.navigateNext, this) this.framerControls = new app.views.framerControls({model : this.model}) @@ -49,19 +50,43 @@ app.views.framerControls = app.views.Base.extend({ events : { "click button.done" : "saveFrame", - "click button.back" : "editFrame" + "click button.back" : "editFrame", + "change input" : "setFormAttrs" }, - subviews : { - ".template-picker" : 'templatePicker' + subviews:{ + ".template-picker":'templatePicker', + ".aspect-selector":"aspectsDropdown", + ".service-selector":"servicesSelector" + }, + + formAttrs : { + "input.mood:checked" : "frame_name", + "input.aspect_ids" : "aspect_ids[]", + "input.services" : "services[]" }, initialize : function(){ - this.templatePicker = new app.views.TemplatePicker({model: this.model}) + this.aspectsDropdown = new app.views.AspectsDropdown({model:this.model}); + this.servicesSelector = new app.views.ServicesSelector({model:this.model}); + }, + + presenter : function() { + var selectedFrame = this.model.get("frame_name") + , templates =_.union(app.models.Post.frameMoods, _.without(app.models.Post.legacyTemplateNames, ["status", "status-with-photo-backdrop", "photo-backdrop", "activity-streams-photo", "note"])) //subtract re-implemented templates + return _.extend(this.defaultPresenter(), { + templates :_.map(templates, function(template) { + return { + name : template, + checked : selectedFrame === template + } + }) + }) }, saveFrame : function(){ this.$('button').prop('disabled', 'disabled').addClass('disabled') + this.setFormAttrs() this.model.save() }, diff --git a/app/assets/javascripts/app/views.js b/app/assets/javascripts/app/views.js index 503b0d431..03f6f9ad9 100644 --- a/app/assets/javascripts/app/views.js +++ b/app/assets/javascripts/app/views.js @@ -71,6 +71,20 @@ app.views.Base = Backbone.View.extend({ removeTooltips : function() { $(".tooltip").remove(); + }, + + setFormAttrs : function(){ + this.model.set(_.inject(this.formAttrs, _.bind(setValueFromField, this), {})) + console.log("set from form", this.model.attributes) + + function setValueFromField(memo, attribute, selector){ + if(attribute.slice("-2") === "[]") { + memo[attribute.slice(0, attribute.length - 2)] = _.pluck(this.$el.find(selector).serializeArray(), "value") + } else { + memo[attribute] = this.$el.find(selector).val(); + } + return memo + } } }); diff --git a/app/assets/javascripts/app/views/aspects_dropdown_view.js b/app/assets/javascripts/app/views/aspects_dropdown_view.js index 5925b0ea2..406532cfa 100644 --- a/app/assets/javascripts/app/views/aspects_dropdown_view.js +++ b/app/assets/javascripts/app/views/aspects_dropdown_view.js @@ -57,4 +57,4 @@ app.views.AspectsDropdown = app.views.Base.extend({ $.trim(this.$(".dropdown-toggle .text").text(text)) } -}) +}); diff --git a/app/assets/javascripts/app/views/template_picker_view.js b/app/assets/javascripts/app/views/template_picker_view.js deleted file mode 100644 index c2f768071..000000000 --- a/app/assets/javascripts/app/views/template_picker_view.js +++ /dev/null @@ -1,33 +0,0 @@ -app.views.TemplatePicker = app.views.Base.extend({ - templateName : "template-picker", - - events : { - "click .mood" : "setModelTemplate" - }, - - initialize : function(){ - if(!this.model.get('frame_name')) this.model.setFrameName() - }, - - postRenderTemplate : function(){ - this.setSelectedMoodAttribute() - }, - - setModelTemplate : function(evt){ - evt.preventDefault(); - var selectedMood = $(evt.target); - this.model.set({"frame_name": selectedMood.data("mood")}) - this.setSelectedMoodAttribute() - }, - - setSelectedMoodAttribute : function(){ - this.$("#selected_mood").removeAttr("id") - this.$(".mood[data-mood=" + this.model.get("frame_name") + "]").attr("id", "selected_mood") - }, - - presenter : function() { - return _.extend(this.defaultPresenter(), { - templates : _.union(app.models.Post.frameMoods, _.without(app.models.Post.legacyTemplateNames, ["status", "status-with-photo-backdrop", "photo-backdrop", "activity-streams-photo", "note"])) //subtract re-implemented templates - }) - } -}) \ No newline at end of file diff --git a/app/assets/stylesheets/new_styles/_composer.scss b/app/assets/stylesheets/new_styles/_composer.scss index 5799e6675..41ae25cfa 100644 --- a/app/assets/stylesheets/new_styles/_composer.scss +++ b/app/assets/stylesheets/new_styles/_composer.scss @@ -53,6 +53,10 @@ .aspect-selector { float: left; + form { + margin: 0 + } + i, input { display: none; } @@ -65,6 +69,13 @@ } label { + margin : 0; + padding : 5px 0; + + &:hover { + background-color : #eee; + } + span:not(.caret) { padding-left: 21px; } @@ -80,23 +91,37 @@ text-align: left; } - a.mood { - @include border-radius(); - margin-right: 11px; - padding: 7px; - color: #999; - font-size: 14px; - line-height: 2em; + .template-picker { + margin-bottom : 1em; - &#selected_mood { - background-color: #222; + input { + display : none; } - &:hover { + label { + @include transition(background-color); + @include border-radius(); + + cursor : pointer; + + display: inline; + margin-right: 11px; + padding: 7px; + color: #999; + font-size: 14px; + line-height: 2em; + + &:hover { + background-color: #222; + text-decoration: none; + } + } + + input:checked + label { background-color: #222; - text-decoration: none; } } + } // this is about the service toggle icons, there is a jasmine test that tests this in service_selector spec diff --git a/app/assets/templates/composer-controls.jst.hbs b/app/assets/templates/composer-controls.jst.hbs index e60cb19f7..e947ed3f2 100644 --- a/app/assets/templates/composer-controls.jst.hbs +++ b/app/assets/templates/composer-controls.jst.hbs @@ -1,5 +1,3 @@
-
-
\ No newline at end of file diff --git a/app/assets/templates/framer-controls.jst.hbs b/app/assets/templates/framer-controls.jst.hbs index a4c59b94f..d711977d6 100644 --- a/app/assets/templates/framer-controls.jst.hbs +++ b/app/assets/templates/framer-controls.jst.hbs @@ -1,5 +1,12 @@
-
+
+ {{#each templates}} + + + {{/each}} +
+
+
\ No newline at end of file diff --git a/app/assets/templates/template-picker.jst.hbs b/app/assets/templates/template-picker.jst.hbs deleted file mode 100644 index 9c17319f0..000000000 --- a/app/assets/templates/template-picker.jst.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{#each templates}} - {{.}} -{{/each}} diff --git a/features/not_safe_for_work.feature b/features/not_safe_for_work.feature index 4b538b8d8..55a671804 100644 --- a/features/not_safe_for_work.feature +++ b/features/not_safe_for_work.feature @@ -54,5 +54,6 @@ Scenario: Resharing an nsfw post And I wait for 2 seconds And I wait for the ajax to finish And I go to the home page + #if this is failing on travis throw a random wait in here :/ Then I should not see "Sexy Senators Gone Wild!" And I should have 2 nsfw posts diff --git a/features/step_definitions/trumpeter_steps.rb b/features/step_definitions/trumpeter_steps.rb index e3125b45d..b7a0519f7 100644 --- a/features/step_definitions/trumpeter_steps.rb +++ b/features/step_definitions/trumpeter_steps.rb @@ -118,7 +118,7 @@ Then /^I should see "([^"]*)" in the framer preview$/ do |post_text| end When /^I select the mood "([^"]*)"$/ do |mood| - click_link mood + find("label:contains('#{mood}')").click end Then /^the post's (?:default |)mood should (?:still |)be "([^"]*)"$/ do |mood| diff --git a/features/trumpeter.feature b/features/trumpeter.feature index 52fa7911c..9dbe06aa5 100644 --- a/features/trumpeter.feature +++ b/features/trumpeter.feature @@ -7,9 +7,10 @@ Feature: Creating a new post Scenario: Posting a public message with a photo And I write "I love RMS" - When I select "Public" in my aspects dropdown And I upload a fixture picture with filename "button.gif" - When I go through the default composer + When I start the framing process + When I select "Public" in my aspects dropdown + And I finalize my frame When I go to "/stream" Then I should see "I love RMS" as the first post in my stream And "I love RMS" should be a public post in my stream @@ -17,8 +18,9 @@ Feature: Creating a new post Scenario: Posting to Aspects And I write "This is super skrunkle" + And I start the framing process When I select "All Aspects" in my aspects dropdown - And I go through the default composer + And I finalize my frame When I go to "/stream" Then I should see "This is super skrunkle" as the first post in my stream Then "This is super skrunkle" should be a limited post in my stream diff --git a/spec/javascripts/app/pages/composer_spec.js b/spec/javascripts/app/pages/composer_spec.js index c1b59eca7..9992033eb 100644 --- a/spec/javascripts/app/pages/composer_spec.js +++ b/spec/javascripts/app/pages/composer_spec.js @@ -21,17 +21,12 @@ describe("app.pages.Composer", function(){ describe(" setting the model's attributes from the various form fields", function(){ beforeEach(function(){ this.page.$("form .text").val("Oh My") - this.page.$("input.aspect_ids").val("public") - this.page.$("input.services[value=facebook]").attr("checked", "checked") - this.page.$("input.services[value=twitter]").attr("checked", "checked") }) it("instantiates a post on form submit", function(){ this.page.$("button.next").click() waitsFor(function(){ return this.navigateSpy.wasCalled }) runs(function(){ - expect(this.page.model.get("aspect_ids")).toEqual(["public"]) - expect(this.page.model.get("services")).toEqual(["facebook", "twitter"]) expect(this.page.model.get("text")).toBe("Oh My") }) }) diff --git a/spec/javascripts/app/pages/framer_spec.js b/spec/javascripts/app/pages/framer_spec.js index 6d2ee4381..c288b640b 100644 --- a/spec/javascripts/app/pages/framer_spec.js +++ b/spec/javascripts/app/pages/framer_spec.js @@ -1,8 +1,11 @@ describe("app.pages.Framer", function(){ beforeEach(function(){ loginAs(factory.user()) - app.frame = new factory.statusMessage(); + app.frame = new factory.statusMessage({frame_name: undefined}); + this.page = new app.pages.Framer(); + this.model = this.page.model + expect(this.model).toBe(app.frame) //uses global state of app.frame :/ }); it("passes the model down to the post view", function(){ @@ -19,6 +22,20 @@ describe("app.pages.Framer", function(){ // want a spec here for the bookmarklet case }) + describe("initialization", function(){ + it("calls setFrameName on the model when there is no frame_name", function(){ + spyOn(this.model, 'setFrameName') + this.model.unset("frame_name") + new app.pages.Framer() + expect(this.model.setFrameName).toHaveBeenCalled() + }) + + it("sets the frame_name of the model to 'Day' by default", function(){ //jasmine integration test, arguably unnecessary + expect(this.model.get("frame_name")).toBe("Day") + }) + }) + + describe("rendering", function(){ beforeEach(function(){ this.page.render(); @@ -30,10 +47,28 @@ describe("app.pages.Framer", function(){ expect(app.frame.save).toHaveBeenCalled(); }); - it("makes and renders a new smallFrame when the template is changed", function(){ - expect(app.frame.get("frame_name")).not.toBe("night") //pre conditions, yo - this.page.$("a.mood[data-mood=Night]").click() - expect(app.frame.get("frame_name")).toBe("Night") - }) + describe("setting the model's attributes from the various form fields", function(){ + beforeEach(function(){ + this.page.$("input.mood").attr("checked", false) //radio button hax + expect(app.frame.get("frame_name")).not.toBe("Night") + this.page.$("input.aspect_ids").val("public") + this.page.$("input[value='Night']").attr("checked", "checked") + this.page.$("input.services[value=facebook]").attr("checked", "checked") + this.page.$("input.services[value=twitter]").attr("checked", "checked") + }) + + it("instantiates a post on form submit", function(){ + this.page.$("input").trigger("change") //runs setFormAttrs + waitsFor(function(){ + return this.page.model.get("frame_name") == "Night" + }) + + runs(function(){ + expect(this.page.model.get("aspect_ids")).toEqual(["public"]) + expect(this.page.model.get("services")).toEqual(["facebook", "twitter"]) + expect(this.page.model.get("frame_name")).toBe("Night") + }) + }) + }); }); }); diff --git a/spec/javascripts/app/views/template_picker_view_spec.js b/spec/javascripts/app/views/template_picker_view_spec.js deleted file mode 100644 index fe015d216..000000000 --- a/spec/javascripts/app/views/template_picker_view_spec.js +++ /dev/null @@ -1,36 +0,0 @@ -describe("app.views.TemplatePicker", function(){ - beforeEach(function(){ - this.model = factory.statusMessage({frame_name: undefined}) - this.view = new app.views.TemplatePicker({model:this.model }) - }) - - describe("initialization", function(){ - it("calls setFrameName on the model when there is no frame_name", function(){ - spyOn(this.model, 'setFrameName') - this.model.unset("frame_name") - new app.views.TemplatePicker({model:this.model}) - expect(this.model.setFrameName).toHaveBeenCalled() - }) - - it("sets the frame_name of the model to 'Day' by default", function(){ //jasmine integration test, arguably unnecessary - expect(this.model.get("frame_name")).toBe("Day") - }) - }) - - describe("rendering", function(){ - beforeEach(function(){ - this.model.set({frame_name : 'Wallpaper'}) - this.view.render() - }) - - it("selects the model's frame_name from the dropdown", function(){ - expect(this.view.$(".mood#selected_mood").data("mood")).toBe("Wallpaper") - }) - - it("changes the frame_name on the model when is is selected", function(){ - this.view.$(".mood[data-mood=Night]").click() - expect(this.view.$(".mood#selected_mood").data("mood")).toBe("Night") - expect(this.model.get("frame_name")).toBe('Night') - }) - }) -}) \ No newline at end of file