Skip to content

Commit

Permalink
Add Profile picture selection + denormalization
Browse files Browse the repository at this point in the history
  • Loading branch information
eprochasson committed Jul 10, 2013
1 parent e9ed8b3 commit bb73e6c
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 67 deletions.
2 changes: 2 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ Add a messaging system (instant chat)

Activities: what did one do, what can of activity can the others see.
Upload pictures

Check picture security, make sure users can't change their picture URL
22 changes: 20 additions & 2 deletions client/views/profile/profile_pictures.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
<template name="profile_pictures">
{{#each pictures}}
{{#if thumbnail50x50}}
<img src="{{thumbnail50x50}}">
<a href="#modalImage" class="showImage" data-toggle="modal"><img src="{{thumbnail50x50}}"></a>
<a href="#" class="setAsProfilePicture">Set as main profile picture</a>
{{else}}
No Thumbnail available.
{{/if}}
{{else}}
You haven't upload any picture
{{/each}}
</template>

{{> modalImage}}
</template>

<template name="modalImage">
<div id="modalImage" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<p><img id="previewImage" src=""/></p>
<div id="description"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
</template>
45 changes: 44 additions & 1 deletion client/views/profile/profile_pictures.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Template.profile_pictures.helpers({
pictures: function(){
return Pictures.find({owner: Meteor.userId()}, {sort: {sortorder: -1}});
var user = Session.get('currentUserProfile') || Meteor.userId();
return Pictures.find({owner: user}, {sort: {main: -1, sortorder: -1}});
},
original: function(){
if(this.fileHandler && this.fileHandler.save){
Expand All @@ -15,5 +16,47 @@ Template.profile_pictures.helpers({
} else {
return null;
}
},thumbnail150x150: function(){
if(this.fileHandler && this.fileHandler.thumbnail150x150){
return this.fileHandler.thumbnail150x150.url;
} else {
return null;
}
}
});

Template.profile_pictures.events({
'click .setAsProfilePicture': function(e){
e.preventDefault();
// Remove that property on other pictures.
var pictures = Pictures.find({owner: Meteor.userId()});
pictures.forEach(function(pic){
Pictures.update(pic._id, {$set: {main: 0}});
});

// Set it on the chosen one
Pictures.update(this._id, {$set: {main:1}});

var urls = {};
var files = Pictures.findOne(this._id).fileHandler;
_.each(files, function(f,n){
urls[n] = f.url;
});

Meteor.call('denormalizeProfilePicture', urls, function(err, res){
if(err){
console.log(err);
} else {
console.log(res);
}
})

}
});

Template.profile_pictures.events({
'click .showImage': function(e){
e.preventDefault();
$('#previewImage').attr('src', this.fileHandler.save.url);
}
});
14 changes: 9 additions & 5 deletions client/views/widgets/online_friends.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<template name="online_friends">

{{#if count}}
You have {{count}} friend(s) online
<ul>
{{#each friends}}
{{> online_friend}}
{{#each friends}}
{{> online_friend}}
{{/each}}
</ul>
{{else}}
No friend online
{{/each}}
</ul>
{{/if}}
</template>

<template name="online_friend">
<li>Name: {{profile.name}} is online</li>
<li><img src="{{profile.picture.thumbnail50x50}}" /><a href="{{profilePath}}/{{_id}}">{{profile.name}}</a> is online (<a class="startChat" href="#">chat</a>)</a></li>
</template>
8 changes: 7 additions & 1 deletion client/views/widgets/online_friends.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@ Template.online_friends.helpers({
friends: function(){
var friends = Meteor.user().friends || [];
return Meteor.users.find({'profile.online': 1, visible: 1, _id: {$in: friends}});
},
count: function(){
var friends = Meteor.user().friends || [];
return Meteor.users.find({'profile.online': 1, visible: 1, _id: {$in: friends}}).count();
}
});
});


20 changes: 16 additions & 4 deletions collections/pictures.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ Pictures.allow({
insert: function(userId, myFile) {
return isValidImage(myFile.contentType) && myFile.length < 1024*1024 && Pictures.find({owner: userId}).count() < 8 && userId && myFile.owner === userId;
},
update: function(userId, files, fields, modifier) {
return _.all(files, function (myFile) {
return (userId == myFile.owner);
});
update: function(userId, file, fields, modifier) {
return file.owner === userId;
},
remove: function(userId, files) { return false; }
});
Expand All @@ -36,5 +34,19 @@ Pictures.fileHandlers({
} else {
return null;
}
},
thumbnail150x150: function(options){
if (isValidImage(options.fileRecord.contentType)){
var destination = options.destination();
Imagemagick.resize({
srcData: options.blob,
dstPath: destination.serverFilename,
width: 150,
height: 150
});
return destination.fileData;
} else {
return null;
}
}
});
58 changes: 4 additions & 54 deletions server/publications.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Meteor.publish("myData", function () {
);
});

Meteor.publish("", function (){

});

// Also maintains user online/offline status
Meteor.publish("myOnlineFriends", function(){
var friends = Meteor.users.findOne(this.userId).friends || [];
Expand Down Expand Up @@ -46,60 +50,6 @@ Meteor.publish("userProfile", function(userId){
});


Meteor.publish("oneUserProfile", function(userId){

// Send over the picture attached to a user depending on permission.
var source = Meteor.users.findOne(this.userId);
var target = Meteor.users.findOne({_id: userId, 'visible': 1});

var self = this;
var profileHandle = null, picturesHandles = [];
var profileType = 'public'; // Default: can only see default information.
var fields = {
'profile.name': 1,
'profile.gender': 1
};

if(target && target.friends && _.contains(target.friends, source._id)){
profileType = 'private'; // If the target is friend (or wants to be friend) with you, get the full profile.
fields = {
'profile': 1
};
}

function publishProfilePictures(profile){
var limit = {limit: 2, sort: {sortorder: -1}};
if(profileType == 'private'){
limit = {limit: 0, sort: {sortorder: -1}};
}
var pictures = Pictures.find({ type: 'profile', owner: userId}, limit);
picturesHandles[profile._id] = pictures.observe({
added: function(id, picture){
self.added('pictures', id, pictures);
}
})
}

profileHandle = Meteor.users.find({_id: userId, visible: 1}, { fields: fields }).observe({
added: function(profile){
publishProfilePictures(profile);
self.added('users', profile._id, profile);
},
removed: function(id){
//stop observing changes on the profile;
picturesHandles[id] && picturesHandles[id].stop();
// Delete the profile
self.removed('users')
}
});

self.ready();

self.onStop(function(){
profileHandle.stop();
});
});

Meteor.publish('oneUserPictures', function(userId){
if(userId){
// Send over the picture attached to a user depending on permission.
Expand Down
9 changes: 9 additions & 0 deletions server/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ Meteor.methods({
});
}
})
},
denormalizeProfilePicture: function(pixHandler){
if(pixHandler){
Meteor.users.update(Meteor.userId(), {$set: {'profile.picture': pixHandler}});
return true;
} else {
throw new Meteor.Error(500, 'Internal Error');
}

}
});

0 comments on commit bb73e6c

Please sign in to comment.