Merge branch 'Raven24-user-photos'
Conflicts: public/javascripts/app/router.js public/stylesheets/sass/application.sass
This commit is contained in:
commit
7aba1ce1f7
12 changed files with 264 additions and 5 deletions
|
|
@ -29,9 +29,12 @@ class PhotosController < ApplicationController
|
||||||
@contacts_of_contact_count = 0
|
@contacts_of_contact_count = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
@posts = current_user.photos_from(@person).paginate(:page => params[:page])
|
@posts = current_user.photos_from(@person)
|
||||||
|
|
||||||
render 'people/show'
|
respond_to do |format|
|
||||||
|
format.all { render 'people/show' }
|
||||||
|
format.json{ render_for_api :backbone, :json => @posts, :root => :photos }
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
flash[:error] = I18n.t 'people.show.does_not_exist'
|
flash[:error] = I18n.t 'people.show.does_not_exist'
|
||||||
|
|
|
||||||
12
public/javascripts/app/collections/photos.js
Normal file
12
public/javascripts/app/collections/photos.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
app.collections.Photos = Backbone.Collection.extend({
|
||||||
|
url : "/photos",
|
||||||
|
|
||||||
|
model: function(attrs, options) {
|
||||||
|
var modelClass = app.models.Photo
|
||||||
|
return new modelClass(attrs, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
parse: function(resp){
|
||||||
|
return resp.photos;
|
||||||
|
}
|
||||||
|
});
|
||||||
14
public/javascripts/app/models/photo.js
Normal file
14
public/javascripts/app/models/photo.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
app.models.Photo = Backbone.Model.extend({
|
||||||
|
urlRoot : "/photos",
|
||||||
|
|
||||||
|
initialize : function() {},
|
||||||
|
|
||||||
|
createdAt : function() {
|
||||||
|
return this.timeOf("created_at");
|
||||||
|
},
|
||||||
|
|
||||||
|
timeOf: function(field) {
|
||||||
|
return new Date(this.get(field)) /1000;
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
69
public/javascripts/app/models/photos.js
Normal file
69
public/javascripts/app/models/photos.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
app.models.Photos = Backbone.Model.extend({
|
||||||
|
initialize : function(){
|
||||||
|
this.photos = new app.collections.Photos([], this.photoOptions());
|
||||||
|
},
|
||||||
|
|
||||||
|
photoOptions :function(){
|
||||||
|
var order = this.sortOrder();
|
||||||
|
return {
|
||||||
|
comparator : function(photo) { return -photo[order](); }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
url : function() {
|
||||||
|
return _.any(this.photos.models) ? this.timeFilteredPath() : this.basePath()
|
||||||
|
},
|
||||||
|
|
||||||
|
_fetching : false,
|
||||||
|
|
||||||
|
fetch : function(){
|
||||||
|
if(this._fetching) { return false; }
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// we're fetching the collection... there is probably a better way to do this
|
||||||
|
self._fetching = true;
|
||||||
|
|
||||||
|
this.photos
|
||||||
|
.fetch({
|
||||||
|
add : true,
|
||||||
|
url : self.url()
|
||||||
|
})
|
||||||
|
.done(
|
||||||
|
function(resp){
|
||||||
|
// we're done fetching... there is probably a better way to handle this
|
||||||
|
self._fetching = false;
|
||||||
|
|
||||||
|
self.trigger("fetched", self);
|
||||||
|
|
||||||
|
// all loaded?
|
||||||
|
if(resp.photos && resp.photos.length == 0) {
|
||||||
|
self.trigger("allPostsLoaded", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
basePath : function(){
|
||||||
|
return document.location.pathname;
|
||||||
|
},
|
||||||
|
|
||||||
|
timeFilteredPath : function(){
|
||||||
|
return this.basePath() + "?max_time=" + this.maxTime();
|
||||||
|
},
|
||||||
|
|
||||||
|
maxTime: function(){
|
||||||
|
var lastPost = _.last(this.photos.models);
|
||||||
|
return lastPost[this.sortOrder()]()
|
||||||
|
},
|
||||||
|
|
||||||
|
sortOrder : function() {
|
||||||
|
return "createdAt";
|
||||||
|
},
|
||||||
|
|
||||||
|
add : function(models){
|
||||||
|
this.photos.add(models)
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -11,7 +11,8 @@ app.Router = Backbone.Router.extend({
|
||||||
"liked": "stream",
|
"liked": "stream",
|
||||||
"mentions": "stream",
|
"mentions": "stream",
|
||||||
"people/:id": "stream",
|
"people/:id": "stream",
|
||||||
"u/:name": "stream",
|
"people/:id/photos": "photos",
|
||||||
|
"u/:name": "stream",
|
||||||
"followed_tags": "stream",
|
"followed_tags": "stream",
|
||||||
"tags/:name": "stream",
|
"tags/:name": "stream",
|
||||||
"posts/:id": "singlePost",
|
"posts/:id": "singlePost",
|
||||||
|
|
@ -19,7 +20,7 @@ app.Router = Backbone.Router.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
stream : function() {
|
stream : function() {
|
||||||
app.stream = new app.models.Stream()
|
app.stream = new app.models.Stream();
|
||||||
app.page = new app.views.Stream({model : app.stream}).render();
|
app.page = new app.views.Stream({model : app.stream}).render();
|
||||||
app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.posts});
|
app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.posts});
|
||||||
|
|
||||||
|
|
@ -29,6 +30,13 @@ app.Router = Backbone.Router.extend({
|
||||||
$('#selected_aspect_contacts .content').html(streamFacesView.el);
|
$('#selected_aspect_contacts .content').html(streamFacesView.el);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
photos : function() {
|
||||||
|
app.photos = new app.models.Photos();
|
||||||
|
app.page = new app.views.Photos({model : app.photos}).render();
|
||||||
|
|
||||||
|
$("#main_stream").html(app.page.el);
|
||||||
|
},
|
||||||
|
|
||||||
singlePost : function(id) {
|
singlePost : function(id) {
|
||||||
new app.models.Post({id : id}).fetch({success : function(resp){
|
new app.models.Post({id : id}).fetch({success : function(resp){
|
||||||
var postAttrs = resp.get("posts");
|
var postAttrs = resp.get("posts");
|
||||||
|
|
|
||||||
3
public/javascripts/app/templates/photo.handlebars
Normal file
3
public/javascripts/app/templates/photo.handlebars
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<a href="#" class="photo-link">
|
||||||
|
<img src="{{sizes.large}}" class="photo big_photo" data-small-photo="{{sizes.small}}" data-full-photo="{{sizes.large}}" rel="lightbox">
|
||||||
|
</a>
|
||||||
13
public/javascripts/app/views/photo_view.js
Normal file
13
public/javascripts/app/views/photo_view.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
app.views.Photo = app.views.StreamObject.extend({
|
||||||
|
|
||||||
|
templateName: "photo",
|
||||||
|
|
||||||
|
className : "photo loaded",
|
||||||
|
|
||||||
|
initialize : function() {
|
||||||
|
$(this.el).attr("id", this.model.get("guid"));
|
||||||
|
this.model.bind('remove', this.remove, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
56
public/javascripts/app/views/photos_view.js
Normal file
56
public/javascripts/app/views/photos_view.js
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
app.views.Photos = Backbone.View.extend({
|
||||||
|
|
||||||
|
events : {},
|
||||||
|
|
||||||
|
initialize : function(options) {
|
||||||
|
this.photos = this.model;
|
||||||
|
this.collection = this.model.photos;
|
||||||
|
|
||||||
|
this.setupEvents();
|
||||||
|
//this.setupLightbox(); ERROR: "imageThumb is undefined" ...
|
||||||
|
},
|
||||||
|
|
||||||
|
setupEvents : function(){
|
||||||
|
this.photos.bind("fetched", this.removeLoader, this)
|
||||||
|
this.collection.bind("add", this.addPhoto, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
addPhoto : function(photo) {
|
||||||
|
var photoView = new app.views.Photo({ model: photo });
|
||||||
|
|
||||||
|
$(this.el)[
|
||||||
|
(this.collection.at(0).id == photo.id)
|
||||||
|
? "prepend"
|
||||||
|
: "append"
|
||||||
|
](photoView.render().el);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
render : function(evt) {
|
||||||
|
if(evt) {evt.preventDefault(); }
|
||||||
|
|
||||||
|
if(this.model.fetch()) {
|
||||||
|
this.appendLoader();
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
appendLoader: function(){
|
||||||
|
$("#paginate").html($("<img>", {
|
||||||
|
src : "/images/static-loader.png",
|
||||||
|
"class" : "loader"
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
removeLoader: function() {
|
||||||
|
$("#paginate").empty();
|
||||||
|
},
|
||||||
|
|
||||||
|
setupLightbox : function(){
|
||||||
|
this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox");
|
||||||
|
$(this.el).delegate("a.photo-link", "click", this.lightbox.lightboxImageClicked);
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -2821,3 +2821,4 @@ a.toggle_selector
|
||||||
:color #999
|
:color #999
|
||||||
a
|
a
|
||||||
:color #666
|
:color #666
|
||||||
|
:color #666
|
||||||
|
|
@ -80,6 +80,14 @@ describe PhotosController do
|
||||||
assigns[:person].should == bob.person
|
assigns[:person].should == bob.person
|
||||||
assigns[:posts].should == [@bobs_photo]
|
assigns[:posts].should == [@bobs_photo]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns json when requested" do
|
||||||
|
request.env['HTTP_ACCEPT'] = 'application/json'
|
||||||
|
get :index, :person_id => alice.person.guid.to_s
|
||||||
|
|
||||||
|
response.headers['Content-Type'].should match 'application/json.*'
|
||||||
|
save_fixture(response.body, "photos_json")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#show' do
|
describe '#show' do
|
||||||
|
|
|
||||||
27
spec/javascripts/app/models/photo_spec.js
Normal file
27
spec/javascripts/app/models/photo_spec.js
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
describe("app.models.Photo", function() {
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
this.photo = new app.models.Photo();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("url", function(){
|
||||||
|
it("should be /photos when it doesn't have an id", function(){
|
||||||
|
expect(new app.models.Photo().url()).toBe("/photos");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be /photos/id when it has an id", function(){
|
||||||
|
expect(new app.models.Photo({id: 5}).url()).toBe("/photos/5");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("createdAt", function() {
|
||||||
|
it("returns the photo's created_at as an integer", function() {
|
||||||
|
var date = new Date;
|
||||||
|
this.photo.set({ created_at: +date * 1000 });
|
||||||
|
|
||||||
|
expect(typeof this.photo.createdAt()).toEqual("number");
|
||||||
|
expect(this.photo.createdAt()).toEqual(+date);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
45
spec/javascripts/app/views/photos_view_spec.js
Normal file
45
spec/javascripts/app/views/photos_view_spec.js
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
describe("app.views.Photos", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}});
|
||||||
|
|
||||||
|
this._photos = $.parseJSON(spec.readFixture("photos_json"))["photos"];
|
||||||
|
|
||||||
|
this.photos = new app.models.Photos();
|
||||||
|
this.photos.add(this._photos);
|
||||||
|
|
||||||
|
this.view = new app.views.Photos({model : this.photos});
|
||||||
|
|
||||||
|
// do this manually because we've moved loadMore into render??
|
||||||
|
this.view.render();
|
||||||
|
_.each(this.view.collection.models, function(photo) {
|
||||||
|
this.view.addPhoto(photo);
|
||||||
|
}, this);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("initialize", function() {
|
||||||
|
// nothing there yet
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#render", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.photo = this.photos.photos.models[0];
|
||||||
|
this.photoElement = $(this.view.$("#" + this.photo.get("guid")));
|
||||||
|
});
|
||||||
|
|
||||||
|
context("when rendering a photo message", function() {
|
||||||
|
it("shows the photo in the content area", function() {
|
||||||
|
expect(this.photoElement.length).toBeGreaterThan(0); //markdown'ed
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("removeLoader", function() {
|
||||||
|
it("emptys the pagination div when the stream is fetched", function() {
|
||||||
|
$("#jasmine_content").append($('<div id="paginate">OMG</div>'));
|
||||||
|
expect($("#paginate").text()).toBe("OMG");
|
||||||
|
this.view.photos.trigger("fetched");
|
||||||
|
expect($("#paginate")).toBeEmpty();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue