DG DC uploading a photo shows up in the stream
This commit is contained in:
parent
1ec2b73d59
commit
426f0278f9
12 changed files with 162 additions and 71 deletions
|
|
@ -44,18 +44,16 @@ class PhotosController < ApplicationController
|
||||||
rescuing_photo_errors do
|
rescuing_photo_errors do
|
||||||
if remotipart_submitted?
|
if remotipart_submitted?
|
||||||
@photo = current_user.build_post(:photo, params[:photo])
|
@photo = current_user.build_post(:photo, params[:photo])
|
||||||
else
|
|
||||||
legacy_create
|
|
||||||
end
|
|
||||||
|
|
||||||
if @photo.save
|
if @photo.save
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )}
|
format.json { render :json => {"success" => true, "data" => @photo.as_api_response(:backbone)} }
|
||||||
format.html{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )}
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
respond_with @photo, :location => photos_path, :error => message
|
respond_with @photo, :location => photos_path, :error => message
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
legacy_create
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -192,6 +190,13 @@ class PhotosController < ApplicationController
|
||||||
:image_url_small => @photo.url(:thumb_small)}
|
:image_url_small => @photo.url(:thumb_small)}
|
||||||
current_user.update_profile(profile_params)
|
current_user.update_profile(profile_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.json{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )}
|
||||||
|
format.html{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_with @photo, :location => photos_path, :error => message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ class Photo < ActiveRecord::Base
|
||||||
include Diaspora::Commentable
|
include Diaspora::Commentable
|
||||||
include Diaspora::Shareable
|
include Diaspora::Shareable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE API V1 to be extracted
|
# NOTE API V1 to be extracted
|
||||||
acts_as_api
|
acts_as_api
|
||||||
api_accessible :backbone do |t|
|
api_accessible :backbone do |t|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,7 @@
|
||||||
When /^I trumpet$/ do
|
|
||||||
visit new_post_path
|
|
||||||
end
|
|
||||||
|
|
||||||
When /^I write "([^"]*)"$/ do |text|
|
|
||||||
fill_in :text, :with => text
|
|
||||||
end
|
|
||||||
|
|
||||||
Then /I mention "([^"]*)"$/ do |text|
|
|
||||||
fill_in_autocomplete('textarea.text', '@a')
|
|
||||||
sleep(5)
|
|
||||||
find("li.active").click
|
|
||||||
end
|
|
||||||
|
|
||||||
def fill_in_autocomplete(selector, value)
|
def fill_in_autocomplete(selector, value)
|
||||||
page.execute_script %Q{$('#{selector}').val('#{value}').keyup()}
|
page.execute_script %Q{$('#{selector}').val('#{value}').keyup()}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def aspects_dropdown
|
def aspects_dropdown
|
||||||
find(".dropdown-toggle")
|
find(".dropdown-toggle")
|
||||||
end
|
end
|
||||||
|
|
@ -31,11 +16,39 @@ def select_from_dropdown(option_text, dropdown)
|
||||||
#assert dropdown text is link
|
#assert dropdown text is link
|
||||||
end
|
end
|
||||||
|
|
||||||
|
When /^I trumpet$/ do
|
||||||
|
visit new_post_path
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I write "([^"]*)"$/ do |text|
|
||||||
|
fill_in :text, :with => text
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /I mention "([^"]*)"$/ do |text|
|
||||||
|
fill_in_autocomplete('textarea.text', '@a')
|
||||||
|
sleep(5)
|
||||||
|
find("li.active").click
|
||||||
|
end
|
||||||
|
|
||||||
When /^I select "([^"]*)" in my aspects dropdown$/ do |title|
|
When /^I select "([^"]*)" in my aspects dropdown$/ do |title|
|
||||||
within ".aspect_selector" do
|
within ".aspect_selector" do
|
||||||
select_from_dropdown(title, aspects_dropdown)
|
select_from_dropdown(title, aspects_dropdown)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^"([^"]*)" should be a (limited|public) post in my stream$/ do |post_text, scope|
|
Then /^"([^"]*)" should be a (limited|public) post in my stream$/ do |post_text, scope|
|
||||||
find_post_by_text(post_text).find(".post_scope").text.should =~ /#{scope}/i
|
find_post_by_text(post_text).find(".post_scope").text.should =~ /#{scope}/i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
When /^I upload a fixture picture with filename "([^"]*)"$/ do |file_name|
|
||||||
|
within ".new_photo" do
|
||||||
|
attach_file "photo[user_file]", Rails.root.join("spec", "fixtures", file_name)
|
||||||
|
click_button :submit
|
||||||
|
end
|
||||||
|
|
||||||
|
@image_source = find(".photos img")["src"]
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^"([^"]*)" should have my photo$/ do |status_text|
|
||||||
|
find_post_by_text(status_text).find(".photo_attachments img")["src"].should == @image_source
|
||||||
|
end
|
||||||
|
|
@ -29,3 +29,9 @@ Feature: Creating a new post
|
||||||
And I go to "/stream"
|
And I go to "/stream"
|
||||||
Then I follow "Alice Smith"
|
Then I follow "Alice Smith"
|
||||||
|
|
||||||
|
Scenario: Uploading a photo
|
||||||
|
When I write "check out this picture"
|
||||||
|
And I upload a fixture picture with filename "button.gif"
|
||||||
|
And I press "Share"
|
||||||
|
And I go to "/stream"
|
||||||
|
Then "check out this picture" should have my photo
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,14 @@
|
||||||
app.forms.Base = app.views.Base.extend({
|
app.forms.Base = app.views.Base.extend({
|
||||||
events :{
|
formSelector : "form",
|
||||||
'submit form' : 'setModelAttributes'
|
|
||||||
|
initialize : function() {
|
||||||
|
this.setupFormEvents()
|
||||||
},
|
},
|
||||||
|
|
||||||
setModelAttributes : function(evt){
|
setupFormEvents : function(){
|
||||||
if(evt){ evt.preventDefault(); }
|
this.events = {}
|
||||||
|
this.events['submit ' + this.formSelector] = 'setModelAttributes';
|
||||||
|
this.delegateEvents();
|
||||||
|
},
|
||||||
|
|
||||||
var form = this.$("form");
|
|
||||||
|
|
||||||
function setValueFromField(memo, attribute, selector){
|
|
||||||
var selectors = form.find(selector);
|
|
||||||
|
|
||||||
if(selectors.length > 1) {
|
|
||||||
memo[attribute] = _.map(selectors, function(selector){
|
|
||||||
return $(selector).val()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
memo[attribute] = selectors.val();
|
|
||||||
}
|
|
||||||
|
|
||||||
return memo
|
|
||||||
}
|
|
||||||
|
|
||||||
this.model.set(_.inject(this.formAttrs, setValueFromField, {}))
|
|
||||||
this.model.trigger("setFromForm")
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,31 @@ app.forms.Picture = app.forms.Base.extend({
|
||||||
'ajax:complete .new_photo' : "photoUploaded"
|
'ajax:complete .new_photo' : "photoUploaded"
|
||||||
},
|
},
|
||||||
|
|
||||||
postRenderTemplate : function(){
|
initialize : function() {
|
||||||
this.$("input[name=authenticity_token]").val($("meta[name=csrf-token]").attr("content"))
|
this.photos = new Backbone.Collection()
|
||||||
|
this.photos.bind("add", this.render, this)
|
||||||
},
|
},
|
||||||
|
|
||||||
photoUploaded : function(evt, xhr) {
|
photoUploaded : function(evt, xhr) {
|
||||||
resp = JSON.parse(xhr.responseText)
|
resp = JSON.parse(xhr.responseText)
|
||||||
if(resp.success) {
|
if(resp.success) {
|
||||||
console.log(new Backbone.Model(resp.data.photo));
|
this.photos.add(new Backbone.Model(resp.data))
|
||||||
} else {
|
} else {
|
||||||
console.log(resp.error);
|
alert("Upload failed! Please try again. " + resp.error);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
|
||||||
|
postRenderTemplate : function(){
|
||||||
|
this.$("input[name=authenticity_token]").val($("meta[name=csrf-token]").attr("content"))
|
||||||
|
this.$("input[name=photo_ids]").val(this.photos.pluck("id"))
|
||||||
|
this.renderPhotos();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderPhotos : function(){
|
||||||
|
var photoContainer = this.$(".photos")
|
||||||
|
this.photos.each(function(photo){
|
||||||
|
var photoView = new app.views.Photo({model : photo}).render().el
|
||||||
|
photoContainer.append(photoView)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
app.forms.Post = app.forms.Base.extend({
|
app.forms.Post = app.forms.Base.extend({
|
||||||
templateName : "post-form",
|
templateName : "post-form",
|
||||||
|
formSelector : ".new-post",
|
||||||
|
|
||||||
subviews : {
|
subviews : {
|
||||||
".aspect_selector" : "aspectsDropdown",
|
".aspect_selector" : "aspectsDropdown",
|
||||||
|
|
@ -10,13 +11,37 @@ app.forms.Post = app.forms.Base.extend({
|
||||||
formAttrs : {
|
formAttrs : {
|
||||||
"textarea#text_with_markup" : "text",
|
"textarea#text_with_markup" : "text",
|
||||||
"input.aspect_ids" : "aspect_ids",
|
"input.aspect_ids" : "aspect_ids",
|
||||||
'input.service:checked' : 'services'
|
"input.service:checked" : "services"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize : function() {
|
initialize : function() {
|
||||||
this.aspectsDropdown = new app.views.AspectsDropdown();
|
this.aspectsDropdown = new app.views.AspectsDropdown();
|
||||||
this.servicesSelector = new app.views.ServicesSelector();
|
this.servicesSelector = new app.views.ServicesSelector();
|
||||||
this.pictureForm = new app.forms.Picture();
|
this.pictureForm = new app.forms.Picture();
|
||||||
|
|
||||||
|
this.setupFormEvents();
|
||||||
|
},
|
||||||
|
|
||||||
|
setModelAttributes : function(evt){
|
||||||
|
if(evt){ evt.preventDefault(); }
|
||||||
|
var form = this.$(this.formSelector);
|
||||||
|
|
||||||
|
this.model.set(_.inject(this.formAttrs, setValueFromField, {}))
|
||||||
|
//pass collections across
|
||||||
|
this.model.photos = this.pictureForm.photos
|
||||||
|
this.model.trigger("setFromForm")
|
||||||
|
|
||||||
|
function setValueFromField(memo, attribute, selector){
|
||||||
|
var selectors = form.find(selector);
|
||||||
|
if(selectors.length > 1) {
|
||||||
|
memo[attribute] = _.map(selectors, function(selector){
|
||||||
|
return $(selector).val()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
memo[attribute] = selectors.val();
|
||||||
|
}
|
||||||
|
return memo
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
postRenderTemplate : function() {
|
postRenderTemplate : function() {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ app.models.StatusMessage = app.models.Post.extend({
|
||||||
var mungedAttrs = {
|
var mungedAttrs = {
|
||||||
status_message : _.clone(this.attributes),
|
status_message : _.clone(this.attributes),
|
||||||
'aspect_ids[]' : this.get("aspect_ids"),
|
'aspect_ids[]' : this.get("aspect_ids"),
|
||||||
|
photos : this.photos.pluck("id"),
|
||||||
services : mungeServices(this.get("services"))
|
services : mungeServices(this.get("services"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<div style="margin:0;padding:0;display:inline">
|
<div style="margin:0;padding:0;display:inline">
|
||||||
<input name="utf8" type="hidden" value="✓"/>
|
<input name="utf8" type="hidden" value="✓"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="photos"></div>
|
||||||
<input name="photo[user_file]" type="file"/>
|
<input name="photo[user_file]" type="file"/>
|
||||||
<input name="commit" type="submit" value="Create Photo"/>
|
<input name="commit" type="submit" class="btn" value="Create Photo"/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,6 @@
|
||||||
return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
|
return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
|
||||||
},
|
},
|
||||||
success: function(data, status, xhr) {
|
success: function(data, status, xhr) {
|
||||||
alert("hella boner jamz")
|
|
||||||
element.trigger('ajax:success', [data, status, xhr]);
|
element.trigger('ajax:success', [data, status, xhr]);
|
||||||
},
|
},
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
|
|
|
||||||
43
spec/javascripts/app/forms/picture_form_spec.js
Normal file
43
spec/javascripts/app/forms/picture_form_spec.js
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
describe("app.forms.Picture", function(){
|
||||||
|
beforeEach(function(){
|
||||||
|
$("<meta/>", {
|
||||||
|
"name" : "csrf-token",
|
||||||
|
"content" : "supersecrettokenlol"
|
||||||
|
}).prependTo("head")
|
||||||
|
|
||||||
|
this.form = new app.forms.Picture().render()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the authenticity token from the meta tag", function(){
|
||||||
|
expect(this.form.$("input[name='authenticity_token']").val()).toBe("supersecrettokenlol")
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when a photo is suceessfully submitted", function(){
|
||||||
|
beforeEach(function(){
|
||||||
|
this.photoAttrs = { name : "Obama rides a bicycle" }
|
||||||
|
this.respond = function() {
|
||||||
|
this.form.$(".new_photo").trigger("ajax:complete", {
|
||||||
|
responseText : JSON.stringify({success : true, data : this.photoAttrs})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds a new model to the photos", function(){
|
||||||
|
expect(this.form.$(".photos div").length).toBe(0);
|
||||||
|
this.respond()
|
||||||
|
expect(this.form.$(".photos div").length).toBeGreaterThan(0);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when a photo is unsuccessfully submitted", function(){
|
||||||
|
beforeEach(function(){
|
||||||
|
this.response = {responseText : JSON.stringify({success : false, message : "I like to eat basketballs"}) }
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds a new model to the photos", function(){
|
||||||
|
spyOn(window, "alert")
|
||||||
|
this.form.$(".new_photo").trigger("ajax:complete", this.response)
|
||||||
|
expect(window.alert).toHaveBeenCalled();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
@ -15,14 +15,14 @@ describe("app.forms.Post", function(){
|
||||||
this.view.$("form .aspect_ids").val("public")
|
this.view.$("form .aspect_ids").val("public")
|
||||||
|
|
||||||
/* appending checkboxes */
|
/* appending checkboxes */
|
||||||
this.view.$("form").append($("<input/>", {
|
this.view.$(".new-post").append($("<input/>", {
|
||||||
value : "fakeBook",
|
value : "fakeBook",
|
||||||
checked : "checked",
|
checked : "checked",
|
||||||
"class" : "service",
|
"class" : "service",
|
||||||
"type" : "checkbox"
|
"type" : "checkbox"
|
||||||
}))
|
}))
|
||||||
|
|
||||||
this.view.$("form").append($("<input/>", {
|
this.view.$(".new-post").append($("<input/>", {
|
||||||
value : "twitter",
|
value : "twitter",
|
||||||
checked : "checked",
|
checked : "checked",
|
||||||
"class" : "service",
|
"class" : "service",
|
||||||
|
|
@ -31,7 +31,7 @@ describe("app.forms.Post", function(){
|
||||||
})
|
})
|
||||||
|
|
||||||
it("instantiates a post on form submit", function(){
|
it("instantiates a post on form submit", function(){
|
||||||
this.view.$("form").submit()
|
this.view.$(".new-post").submit()
|
||||||
expect(this.view.model.get("text")).toBe("Oh My")
|
expect(this.view.model.get("text")).toBe("Oh My")
|
||||||
expect(this.view.model.get("aspect_ids")).toBe("public")
|
expect(this.view.model.get("aspect_ids")).toBe("public")
|
||||||
expect(this.view.model.get("services").length).toBe(2)
|
expect(this.view.model.get("services").length).toBe(2)
|
||||||
|
|
@ -40,7 +40,7 @@ describe("app.forms.Post", function(){
|
||||||
it("triggers a 'setFromForm' event", function(){
|
it("triggers a 'setFromForm' event", function(){
|
||||||
var spy = jasmine.createSpy();
|
var spy = jasmine.createSpy();
|
||||||
this.view.model.bind("setFromForm", spy);
|
this.view.model.bind("setFromForm", spy);
|
||||||
this.view.$("form").submit();
|
this.view.$(".new-post").submit();
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue