Skip to content

Instantly share code, notes, and snippets.

@sailsinaction
Last active June 14, 2016 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sailsinaction/4aa62ec9b504d570c475449fdba193de to your computer and use it in GitHub Desktop.
Save sailsinaction/4aa62ec9b504d570c475449fdba193de to your computer and use it in GitHub Desktop.
Chapter 13 - Gists
.d8888b. 888 888 d888 .d8888b. .d8888b. d8b 888
d88P Y88b 888 888 d8888 d88P Y88b d88P Y88b Y8P 888
888 888 888 888 888 .d88P 888 888 888
888 88888b. 8888b. 88888b. 888888 .d88b. 888d888 888 8888" 888 888 .d8888b 888888 .d8888b
888 888 "88b "88b 888 "88b 888 d8P Y8b 888P" 888 "Y8b. 888 88888 888 88K 888 88K
888 888 888 888 .d888888 888 888 888 88888888 888 888 888 888 888888 888 888 888 "Y8888b. 888 "Y8888b.
Y88b d88P 888 888 888 888 888 d88P Y88b. Y8b. 888 888 Y88b d88P Y88b d88P 888 X88 Y88b. X88
"Y8888P" 888 888 "Y888888 88888P" "Y888 "Y8888 888 8888888 "Y8888P" "Y8888P88 888 88888P' "Y888 88888P'
888
888
888
tutorialDetail: function(req, res) {
// Find the tutorial that will be displayed
Tutorial.findOne({
id: req.param('id')
})
.populate('owner')
.populate('videos')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find all ratings made by the currently authenticated user agent
Rating.find({
byUser: req.session.userId
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the user agent hasn't made any ratings, assign myRating to null
if (foundRating.length === 0) {
foundTutorial.myRating = null;
} else {
// Iterate through ratings to determine whether the rating matches
// the id of the tutorial to be displayed.
_.each(foundRating, function(rating){
if (foundTutorial.id === rating.byTutorial) {
foundTutorial.myRating = rating.stars;
return;
}
});
}
// If the tutorial has no ratings assign averageRating to null.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
var sumfoundTutorialRatings = 0;
// Iterate through each rating and add up the sum of all ratings
_.each(foundTutorial.ratings, function(rating){
sumfoundTutorialRatings = sumfoundTutorialRatings + rating.stars;
});
// Calculate the average rating
foundTutorial.averageRating = sumfoundTutorialRatings / foundTutorial.ratings.length;
}
// limit the owner attribute to the users name
foundTutorial.owner = foundTutorial.owner.username;
// Transform createdAt in time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
// Transform updatedAt in time ago format
foundTutorial.updated = DatetimeService.getTimeAgo({date: foundTutorial.updatedAt});
// If not logged in set `me` property to `null` and pass the tutorial to the view
if (!req.session.userId) {
return res.view('tutorials-detail', {
me: null,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
User.findOne(req.session.userId)
.exec(function(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('tutorials-detail', {
me: null
});
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
};
if (user.username === foundTutorial.owner) {
me.isMe = true;
return res.view('tutorials-detail', {
me: me,
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
} else {
return res.view('tutorials-detail', {
me: {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
});
});
});
},
tutorialDetail: function(req, res) {
// Find the tutorial that will be displayed
Tutorial.findOne({
id: req.param('id')
})
.populate('owner')
.populate('videos')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find all ratings made by the currently authenticated user agent
Rating.find({
byUser: req.session.userId
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the user agent hasn't made any ratings, assign myRating to null
if (foundRating.length === 0) {
foundTutorial.myRating = null;
} else {
// Iterate through ratings to determine whether the rating matches
// the id of the tutorial to be displayed.
_.each(foundRating, function(rating){
if (foundTutorial.id === rating.byTutorial) {
foundTutorial.myRating = rating.stars;
return;
}
});
}
// If the tutorial has no ratings assign averageRating to null.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
var sumfoundTutorialRatings = 0;
// Iterate through each rating and add up the sum of all ratings
_.each(foundTutorial.ratings, function(rating){
sumfoundTutorialRatings = sumfoundTutorialRatings + rating.stars;
});
// Calculate the average rating
foundTutorial.averageRating = sumfoundTutorialRatings / foundTutorial.ratings.length;
}
// limit the owner attribute to the users name
foundTutorial.owner = foundTutorial.owner.username;
// Transform createdAt in time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
// Transform updatedAt in time ago format
foundTutorial.updated = DatetimeService.getTimeAgo({date: foundTutorial.updatedAt});
// If not logged in set `me` property to `null` and pass the tutorial to the view
if (!req.session.userId) {
return res.view('tutorials-detail', {
me: null,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
User.findOne(req.session.userId)
.exec(function(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('tutorials-detail', {
me: null
});
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
};
if (user.username === foundTutorial.owner) {
me.isMe = true;
return res.view('tutorials-detail', {
me: me,
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
} else {
return res.view('tutorials-detail', {
me: {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
});
});
});
},
rateTutorial: function(req, res) {
// Find the currently authenticated user
User.findOne({
id: req.session.userId
})
.exec(function(err, currentUser){
if (err) return res.negotiate(err);
if (!currentUser) return res.notFound();
// Find the tutorial being rated
Tutorial.findOne({
id: +req.param('id')
})
.populate('owner')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Assure that the owner of the tutorial cannot rate their own tutorial.
// Note that this is a back-up to the front-end which already prevents the UI from being displayed.
if (currentUser.id === foundTutorial.owner.id) {
return res.forbidden();
}
// Find the rating, if any, of the tutorial from the currently logged in user.
Rating.findOne({
byUser: currentUser.id,
byTutorial: foundTutorial.id
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the currently authenticated user-agent (user) has previously rated this
// tutorial update it with the new rating.
if (foundRating) {
Rating.update({
id: foundRating.id
}).set({
stars: req.param('stars')
}).exec(function(err, updatedRating){
if (err) return res.negotiate(err);
if (!updatedRating) return res.notFound();
// Re-find the tutorial whose being rated to get the latest
Tutorial.findOne({
id: req.param('id')
})
.populate('ratings')
.exec(function(err, foundTutorialAfterUpdate){
if (err) return res.negotiate(err);
if (!foundTutorialAfterUpdate) return res.notFound();
var sumTutorialRatings = 0;
_.each(foundTutorialAfterUpdate.ratings, function(rating){
sumTutorialRatings = sumTutorialRatings + rating.stars;
});
foundTutorialAfterUpdate.averageRating = Math.floor(sumTutorialRatings / foundTutorialAfterUpdate.ratings.length);
return res.json({
averageRating: foundTutorialAfterUpdate.averageRating
});
});
});
// If the currently authenticated user-agent (user) has not already rated this
// tutorial create it with the new rating.
} else {
Rating.create({
stars: req.param('stars'),
byUser: currentUser.id,
byTutorial: foundTutorial.id
}).exec(function(err, createdRating){
if (err) return res.negotiate(err);
if (!createdRating) return res.notFound();
// Re-Find the tutorial whose being rated to get the latest
Tutorial.findOne({
id: req.param('id')
})
.populate('ratings')
.exec(function(err, foundTutorialAfterUpdate){
if (err) return res.negotiate(err);
if (!foundTutorialAfterUpdate) return res.notFound();
var sumTutorialRatings = 0;
_.each(foundTutorialAfterUpdate.ratings, function(rating){
sumTutorialRatings = sumTutorialRatings + rating.stars;
});
foundTutorialAfterUpdate.averageRating = Math.floor(sumTutorialRatings / foundTutorialAfterUpdate.ratings.length);
return res.json({
averageRating: foundTutorialAfterUpdate.averageRating
});
});
});
}
});
});
});
},
rateTutorial: function(req, res) {
// Find the currently authenticated user
User.findOne({
id: req.session.userId
})
.exec(function(err, currentUser){
if (err) return res.negotiate(err);
if (!currentUser) return res.notFound();
// Find the tutorial being rated
Tutorial.findOne({
id: +req.param('id')
})
.populate('owner')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Assure that the owner of the tutorial cannot rate their own tutorial.
// Note that this is a back-up to the front-end which already prevents the UI from being displayed.
if (currentUser.id === foundTutorial.owner.id) {
return res.forbidden();
}
// Find the rating, if any, of the tutorial from the currently logged in user.
Rating.findOne({
byUser: currentUser.id,
byTutorial: foundTutorial.id
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the currently authenticated user-agent (user) has previously rated this
// tutorial update it with the new rating.
if (foundRating) {
Rating.update({
id: foundRating.id
}).set({
stars: req.param('stars')
}).exec(function(err, updatedRating){
if (err) return res.negotiate(err);
if (!updatedRating) return res.notFound();
// Re-find the tutorial whose being rated to get the latest
Tutorial.findOne({
id: req.param('id')
})
.populate('ratings')
.exec(function(err, foundTutorialAfterUpdate){
if (err) return res.negotiate(err);
if (!foundTutorialAfterUpdate) return res.notFound();
return res.json({
averageRating: MathService.calculateAverage({ratings: foundTutorialAfterUpdate.ratings})
});
});
});
// If the currently authenticated user-agent (user) has not already rated this
// tutorial create it with the new rating.
} else {
Rating.create({
stars: req.param('stars'),
byUser: currentUser.id,
byTutorial: foundTutorial.id
}).exec(function(err, createdRating){
if (err) return res.negotiate(err);
if (!createdRating) return res.notFound();
// Re-Find the tutorial whose being rated to get the latest
Tutorial.findOne({
id: req.param('id')
})
.populate('ratings')
.exec(function(err, foundTutorialAfterUpdate){
if (err) return res.negotiate(err);
if (!foundTutorialAfterUpdate) return res.notFound();
return res.json({
averageRating: MathService.calculateAverage({ratings: foundTutorialAfterUpdate.ratings})
});
});
});
}
});
});
});
},
tutorialDetail: function(req, res) {
// Find the tutorial that will be displayed
Tutorial.findOne({
id: req.param('id')
})
.populate('owner')
.populate('videos')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find all ratings made by the currently authenticated user agent
Rating.find({
byUser: req.session.userId
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the user agent hasn't made any ratings, assign myRating to null
if (foundRating.length === 0) {
foundTutorial.myRating = null;
} else {
// Iterate through ratings to determine whether the rating matches
// the id of the tutorial to be displayed.
_.each(foundRating, function(rating){
if (foundTutorial.id === rating.byTutorial) {
foundTutorial.myRating = rating.stars;
return;
}
});
}
// If the tutorial has no ratings assign averageRating to null.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
// Calculate the average rating
// Assign the average to foundTutorial.averageRating
foundTutorial.averageRating = MathService.calculateAverage({ratings: foundTutorial.ratings});
}
// limit the owner attribute to the users name
foundTutorial.owner = foundTutorial.owner.username;
// Transform createdAt in time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
// Transform updatedAt in time ago format
foundTutorial.updated = DatetimeService.getTimeAgo({date: foundTutorial.updatedAt});
// If not logged in set `me` property to `null` and pass the tutorial to the view
if (!req.session.userId) {
return res.view('tutorials-detail', {
me: null,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
User.findOne(req.session.userId)
.exec(function(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('tutorials-detail', {
me: null
});
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
};
if (user.username === foundTutorial.owner) {
me.isMe = true;
return res.view('tutorials-detail', {
me: me,
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
} else {
return res.view('tutorials-detail', {
me: {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
});
});
});
},
newVideo: function(req, res) {
// Find the tutorial that will contain the added video
Tutorial.findOne({
id: +req.param('id')
})
.populate('owner')
.populate('ratings')
.populate('videos')
.exec(function (err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find the currently authenticated user
User.findOne({
id: req.session.userId
}).exec(function (err, foundUser) {
if (err) {
return res.negotiate(err);
}
if (!foundUser) {
sails.log.verbose('Session refers to a user who no longer exists.');
return res.redirect('/');
}
// TODO: Probably should be a policy
if (foundUser.username !== foundTutorial.owner.username) {
return res.redirect('/tutorials/'+foundTutorial.id);
}
/*
_____ __
|_ _| __ __ _ _ __ ___ / _| ___ _ __ _ __ ___
| || '__/ _` | '_ \/ __| |_ / _ \| '__| '_ ` _ \
| || | | (_| | | | \__ \ _| (_) | | | | | | | |
|_||_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|
*/
// Transform the `created` attribute into time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
/**********************************************************************************
Calculate the averge rating
**********************************************************************************/
// Calculate the average of all existing ratings.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
// Assign the average to foundTutorial.stars
foundTutorial.stars = MathService.calculateAverage({ratings: foundTutorial.ratings});
}
/************************************
Tutorial & Video Length Formatting
*************************************/
// Format the total time for each video and for the tutorial as a whole.
var totalSeconds = 0;
_.each(foundTutorial.videos, function(video){
// Total the number of seconds for all videos for tutorial total time
totalSeconds = totalSeconds + video.lengthInSeconds;
// Format the total time for the tutorial
foundTutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
return res.view('tutorials-detail-video-new', {
me: {
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
admin: foundUser.admin
},
tutorial: {
id: foundTutorial.id,
title: foundTutorial.title,
description: foundTutorial.description,
owner: foundTutorial.owner.username,
created: foundTutorial.created,
totalTime: foundTutorial.totalTime,
stars: foundTutorial.stars
}
});
});
});
},
newVideo: function(req, res) {
// Find the tutorial that will contain the added video
Tutorial.findOne({
id: +req.param('id')
})
.populate('owner')
.populate('ratings')
.populate('videos')
.exec(function (err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find the currently authenticated user
User.findOne({
id: req.session.userId
}).exec(function (err, foundUser) {
if (err) {
return res.negotiate(err);
}
if (!foundUser) {
sails.log.verbose('Session refers to a user who no longer exists.');
return res.redirect('/');
}
// TODO: Probably should be a policy
if (foundUser.username !== foundTutorial.owner.username) {
return res.redirect('/tutorials/'+foundTutorial.id);
}
/*
_____ __
|_ _| __ __ _ _ __ ___ / _| ___ _ __ _ __ ___
| || '__/ _` | '_ \/ __| |_ / _ \| '__| '_ ` _ \
| || | | (_| | | | \__ \ _| (_) | | | | | | | |
|_||_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|
*/
// Transform the `created` attribute into time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
/**********************************************************************************
Calculate the averge rating
**********************************************************************************/
// Calculate the average of all existing ratings.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
// Assign the average to foundTutorial.stars
foundTutorial.stars = MathService.calculateAverage({ratings: foundTutorial.ratings});
}
/************************************
Tutorial & Video Length Formatting
*************************************/
// Format the total time for each video and for the tutorial as a whole.
var totalSeconds = 0;
_.each(foundTutorial.videos, function(video){
// Total the number of seconds for all videos for tutorial total time
totalSeconds = totalSeconds + video.lengthInSeconds;
// Format the total time for the tutorial
foundTutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
return res.view('tutorials-detail-video-new', {
me: {
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
admin: foundUser.admin
},
tutorial: {
id: foundTutorial.id,
title: foundTutorial.title,
description: foundTutorial.description,
owner: foundTutorial.owner.username,
created: foundTutorial.created,
totalTime: foundTutorial.totalTime,
stars: foundTutorial.stars
}
});
});
});
},
tutorialDetail: function(req, res) {
// Find the tutorial that will be displayed
Tutorial.findOne({
id: req.param('id')
})
.populate('owner')
.populate('videos')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find all ratings made by the currently authenticated user agent
Rating.find({
byUser: req.session.userId
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the user agent hasn't made any ratings, assign myRating to null
if (foundRating.length === 0) {
foundTutorial.myRating = null;
} else {
// Iterate through ratings to determine whether the rating matches
// the id of the tutorial to be displayed.
_.each(foundRating, function(rating){
if (foundTutorial.id === rating.byTutorial) {
foundTutorial.myRating = rating.stars;
return;
}
});
}
// If the tutorial has no ratings assign averageRating to null.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
// Calculate the average rating
// Assign the average to foundTutorial.averageRating
foundTutorial.averageRating = MathService.calculateAverage({ratings: foundTutorial.ratings});
}
var totalSeconds = 0;
_.each(foundTutorial.videos, function(video){
totalSeconds = totalSeconds + video.lengthInSeconds;
video.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: video.lengthInSeconds}).hoursMinutesSeconds;
foundTutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
// limit the owner attribute to the users name
foundTutorial.owner = foundTutorial.owner.username;
// Transform createdAt in time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
// Transform updatedAt in time ago format
foundTutorial.updated = DatetimeService.getTimeAgo({date: foundTutorial.updatedAt});
// If not logged in set `me` property to `null` and pass the tutorial to the view
if (!req.session.userId) {
return res.view('tutorials-detail', {
me: null,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
User.findOne(req.session.userId)
.exec(function(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('tutorials-detail', {
me: null
});
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
};
if (user.username === foundTutorial.owner) {
me.isMe = true;
return res.view('tutorials-detail', {
me: me,
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
} else {
return res.view('tutorials-detail', {
me: {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
});
});
});
},
addVideo: function(req, res) {
if (!_.isNumber(req.param('hours')) || !_.isNumber(req.param('minutes')) || !_.isNumber(req.param('seconds'))) {
return res.badRequest();
}
if (!_.isString(req.param('src')) || !_.isString(req.param('title'))) {
return res.badRequest();
}
Tutorial.findOne({
id: +req.param('tutorialId')
})
.populate('owner')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
if (foundTutorial.owner.id !== req.session.userId) {
return res.forbidden();
}
Video.create({
tutorialAssoc: foundTutorial.id,
title: req.param('title'),
src: req.param('src'),
lengthInSeconds: req.param('hours') * 60 * 60 + req.param('minutes') * 60 + req.param('seconds')
}).exec(function (err, createdVideo) {
if (err) return res.negotiate(err);
return res.ok();
});
});
},
editVideo: function(req, res) {
Tutorial.findOne({
id: +req.param('tutorialId')
})
.populate('videos')
.populate('owner')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
User.findOne({
id: req.session.userId
}).exec(function (err, foundUser) {
if (err) {
return res.negotiate(err);
}
if (!foundUser) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.redirect('/');
}
if (foundUser.username !== foundTutorial.owner.username) {
return res.redirect('/tutorials/'+foundTutorial.id);
}
/*
_____ __
|_ _| __ __ _ _ __ ___ / _| ___ _ __ _ __ ___
| || '__/ _` | '_ \/ __| |_ / _ \| '__| '_ ` _ \
| || | | (_| | | | \__ \ _| (_) | | | | | | | |
|_||_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|
*/
// Transform the `created` attribute into time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
/**********************************************************************************
Calculate the averge rating
**********************************************************************************/
// Perform Average Ratings calculation if there are ratings
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
var sumTutorialRatings = 0;
// Total the number of ratings for the Tutorial
_.each(foundTutorial.ratings, function(rating){
sumTutorialRatings = sumTutorialRatings + rating.stars;
});
// Assign the average to the tutorial
foundTutorial.averageRating = sumTutorialRatings / foundTutorial.ratings.length;
}
/************************************
Tutorial & Video Length Formatting
*************************************/
var totalSeconds = 0;
_.each(foundTutorial.videos, function(video){
totalSeconds = totalSeconds + video.lengthInSeconds;
foundTutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
var videoToUpdate = _.find(foundTutorial.videos, function(video){
return video.id === +req.param('id');
});
/*
_____
| __ \
| |__) |___ ___ _ __ ___ _ __ ___ ___
| _ // _ \/ __| '_ \ / _ \| '_ \/ __|/ _ \
| | \ \ __/\__ \ |_) | (_) | | | \__ \ __/
|_| \_\___||___/ .__/ \___/|_| |_|___/\___|
| |
|_|
*/
return res.view('tutorials-detail-video-edit', {
me: {
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
admin: foundUser.admin
},
tutorial: {
id: foundTutorial.id,
title: foundTutorial.title,
description: foundTutorial.description,
owner: foundTutorial.owner.username,
created: foundTutorial.created,
totalTime: foundTutorial.totalTime,
averageRating: foundTutorial.averageRating,
video: {
id: videoToUpdate.id,
title: videoToUpdate.title,
src: videoToUpdate.src,
hours: DatetimeService.getHoursMinutesSeconds({totalSeconds: videoToUpdate.lengthInSeconds}).hours,
minutes: DatetimeService.getHoursMinutesSeconds({totalSeconds: videoToUpdate.lengthInSeconds}).minutes,
seconds: DatetimeService.getHoursMinutesSeconds({totalSeconds: videoToUpdate.lengthInSeconds}).seconds
}
}
});
});
});
},
updateVideo: function(req, res) {
/*
__ __ _ _ _ _ _
\ \ / /_ _| (_)__| |__ _| |_(_)___ _ _
\ V / _` | | / _` / _` | _| / _ \ ' \
\_/\__,_|_|_\__,_\__,_|\__|_\___/_||_|
*/
if (!_.isString(req.param('title'))) {
return res.badRequest();
}
if (!_.isString(req.param('src'))) {
return res.badRequest();
}
if (!_.isNumber(req.param('hours')) || !_.isNumber(req.param('minutes')) || !_.isNumber(req.param('seconds'))) {
return res.badRequest();
}
// Coerce the hours, minutes, seconds parameter to integers
var hours = +req.param('hours');
var minutes = +req.param('minutes');
var seconds = +req.param('seconds');
// Calculate the total seconds of the video and store that value as lengthInSeconds
var convertedToSeconds = hours * 60 * 60 + minutes * 60 + seconds;
Video.findOne({
id: +req.param('id')
})
.populate('tutorialAssoc')
.exec(function (err, foundVideo){
if (err) return res.negotiate (err);
if (!foundVideo) return res.notFound();
// Assure that the currently logged in user is the owner of the tutorial
if (req.session.userId !== foundVideo.tutorialAssoc.owner) {
return res.forbidden();
}
// Update the video
Video.update({
id: +req.param('id')
}, {
title: req.param('title'),
src: req.param('src'),
lengthInSeconds: convertedToSeconds
}).exec(function (err, updatedUser){
if (err) return res.negotiate(err);
if (!updatedUser) return res.notFound();
return res.ok();
});
});
},
createTutorial: function(req, res) {
/*
__ __ _ _ _ _ _
\ \ / /_ _| (_)__| |__ _| |_(_)___ _ _
\ V / _` | | / _` / _` | _| / _ \ ' \
\_/\__,_|_|_\__,_\__,_|\__|_\___/_||_|
*/
if (!_.isString(req.param('title'))) {
return res.badRequest();
}
if (!_.isString(req.param('description'))) {
return res.badRequest();
}
// Find the user that's adding a tutorial
User.findOne({
id: req.session.userId
}).exec(function(err, foundUser){
if (err) return res.negotiate;
if (!foundUser) return res.notFound();
Tutorial.create({
title: req.param('title'),
description: req.param('description'),
owner: foundUser.id,
videoOrder: []
})
.exec(function(err, createdTutorial){
if (err) return res.negotiate(err);
return res.json({id: createdTutorial.id});
});
});
},
addVideo: function(req, res) {
if (!_.isNumber(req.param('hours')) || !_.isNumber(req.param('minutes')) || !_.isNumber(req.param('seconds'))) {
return res.badRequest();
}
if (!_.isString(req.param('src')) || !_.isString(req.param('title'))) {
return res.badRequest();
}
Tutorial.findOne({
id: +req.param('tutorialId')
})
.populate('owner')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
if (foundTutorial.owner.id !== req.session.userId) {
return res.forbidden();
}
Video.create({
tutorialAssoc: foundTutorial.id,
title: req.param('title'),
src: req.param('src'),
lengthInSeconds: req.param('hours') * 60 * 60 + req.param('minutes') * 60 + req.param('seconds')
}).exec(function (err, createdVideo) {
if (err) return res.negotiate(err);
// Add this video to the `videoOrder` array embedded in our tutorial .
// (We always add new videos to the bottom of the list)
foundTutorial.videoOrder.push(createdVideo.id);
return res.ok();
});
});
},
tutorialDetail: function(req, res) {
// Find the tutorial that will be displayed
Tutorial.findOne({
id: req.param('id')
})
.populate('owner')
.populate('videos')
.populate('ratings')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Find all ratings made by the currently authenticated user agent
Rating.find({
byUser: req.session.userId
}).exec(function(err, foundRating){
if (err) return res.negotiate(err);
// If the user agent hasn't made any ratings, assign myRating to null
if (foundRating.length === 0) {
foundTutorial.myRating = null;
} else {
// Iterate through ratings to determine whether the rating matches
// the id of the tutorial to be displayed.
_.each(foundRating, function(rating){
if (foundTutorial.id === rating.byTutorial) {
foundTutorial.myRating = rating.stars;
return;
}
});
}
// If the tutorial has no ratings assign averageRating to null.
if (foundTutorial.ratings.length === 0) {
foundTutorial.averageRating = null;
} else {
// Calculate the average rating
// Assign the average to foundTutorial.averageRating
foundTutorial.averageRating = MathService.calculateAverage({ratings: foundTutorial.ratings});
}
var totalSeconds = 0;
_.each(foundTutorial.videos, function(video){
totalSeconds = totalSeconds + video.lengthInSeconds;
video.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: video.lengthInSeconds}).hoursMinutesSeconds;
foundTutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
// limit the owner attribute to the users name
foundTutorial.owner = foundTutorial.owner.username;
// Transform createdAt in time ago format
foundTutorial.created = DatetimeService.getTimeAgo({date: foundTutorial.createdAt});
// Transform updatedAt in time ago format
foundTutorial.updated = DatetimeService.getTimeAgo({date: foundTutorial.updatedAt});
/**************
Video Order
***************/
// Use the embedded `videoOrder` array to apply the manual sort order
// to our videos.
foundTutorial.videos = _.sortBy(foundTutorial.videos, function getRank (video) {
// We use the index of this video id within the `videoOrder` array as our sort rank.
// Because that array is in the proper order, if we use the index of this video id as
// the rank, then the newly sorted `tutorial.videos` array will be in the same order.
return _.indexOf(foundTutorial.videoOrder,video.id);
});
// Given (e.g.):
// tutorial.videoOrder= [3, 4, 5]
// tutorial.videos = [{id: 5}, {id: 4}, {id: 3}]
//
// Yields (e.g.):
// tutorial.videos <== [{id: 3}, {id: 4}, {id: 5}]
// If not logged in set `me` property to `null` and pass the tutorial to the view
if (!req.session.userId) {
return res.view('tutorials-detail', {
me: null,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
User.findOne(req.session.userId)
.exec(function(err, user) {
if (err) return res.negotiate(err);
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('tutorials-detail', {
me: null
});
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
};
if (user.username === foundTutorial.owner) {
me.isMe = true;
return res.view('tutorials-detail', {
me: me,
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
} else {
return res.view('tutorials-detail', {
me: {
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true,
stars: foundTutorial.stars,
tutorial: foundTutorial
});
}
});
});
});
},
reorderVideoUp: function(req, res) {
// Look up the video with the specified id
// (and populate the tutorial it belongs to)
Video.findOne({
id: +req.param('id')
})
.populate('tutorialAssoc') // consider renaming this association to `partOfTutorial`
.exec(function (err, foundVideo){
if (err) return res.negotiate(err);
if (!foundVideo) return res.notFound();
// Assure that the owner of the tutorial cannot rate their own tutorial.
// Note that this is a back-up to the front-end which already prevents the UI from being displayed.
if (req.session.userId !== foundVideo.tutorialAssoc.owner) {
return res.forbidden();
}
// Modify the tutorial's `videoOrder` to move the video with the
// specified id up in the list.
// Find the index of the video id within the array.
var indexOfVideo = _.indexOf(foundVideo.tutorialAssoc.videoOrder, +req.param('id'));
// If this is already the first video in the list, consider this a bad request.
// (this should have been prevented on the front-end already, but we're just being safe)
if (indexOfVideo === 0) {
return res.badRequest('This video is already at the top of the list.');
}
// Remove the video id from its current position in the array
foundVideo.tutorialAssoc.videoOrder.splice(indexOfVideo, 1);
// Insert the video id at the new position within the array
foundVideo.tutorialAssoc.videoOrder.splice(indexOfVideo-1, 0, +req.param('id'));
// Persist the tutorial record back to the database.
foundVideo.tutorialAssoc.save(function (err) {
if (err) return res.negotiate(err);
return res.ok();
});
});
},
reorderVideoDown: function(req, res) {
// Look up the video with the specified id
// (and populate the tutorial it belongs to)
Video.findOne({
id: +req.param('id')
})
.populate('tutorialAssoc') // consider renaming this association to `partOfTutorial`
.exec(function (err, foundVideo){
if (err) return res.negotiate(err);
if (!foundVideo) return res.notFound();
// Assure that the owner of the tutorial cannot rate their own tutorial.
// Note that this is a back-up to the front-end which already prevents the UI from being displayed.
if (req.session.userId !== foundVideo.tutorialAssoc.owner) {
return res.forbidden();
}
// Modify the tutorial's `videoOrder` to move the video with the
// specified id up in the list.
// Find the index of the video id within the array.
var indexOfVideo = _.indexOf(foundVideo.tutorialAssoc.videoOrder, +req.param('id'));
var numberOfTutorials = foundVideo.tutorialAssoc.videoOrder.length;
// If this is already the last video in the list, consider this a bad request.
// (this should have been prevented on the front-end already, but we're just being safe)
if (indexOfVideo === numberOfTutorials) {
return res.badRequest('This video is already at the bottom of the list.');
}
// Remove the video id from its current position in the array
foundVideo.tutorialAssoc.videoOrder.splice(indexOfVideo, 1);
// Insert the video id at the new position within the array
foundVideo.tutorialAssoc.videoOrder.splice(indexOfVideo+1, 0, +req.param('id'));
// Persist the tutorial record back to the database.
foundVideo.tutorialAssoc.save(function (err) {
if (err) return res.negotiate(err);
return res.ok();
});
});
},
showVideo: function(req, res) {
// Simulating a found video
var video = {
id: 34,
title: 'Crockford on JavaScript - Volume 1: The Early Years',
src: 'https://www.youtube.com/embed/JxAXlJEmNMg'
};
FAKE_CHAT = [{
username: 'sailsinaction',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/ef3eac6c71fdf24b13db12d8ff8d1264'
}, {
username: 'nikolatesla',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/c06112bbecd8a290a00441bf181a24d3?'
}, {
username: 'sailsinaction',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/ef3eac6c71fdf24b13db12d8ff8d1264'
}, {
username: 'nikolatesla',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/c06112bbecd8a290a00441bf181a24d3?'
}, {
username: 'sailsinaction',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/ef3eac6c71fdf24b13db12d8ff8d1264'
}, {
username: 'nikolatesla',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/c06112bbecd8a290a00441bf181a24d3?'
}, {
username: 'sailsinaction',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/ef3eac6c71fdf24b13db12d8ff8d1264'
}, {
username: 'nikolatesla',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/c06112bbecd8a290a00441bf181a24d3?'
}, {
username: 'sailsinaction',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum ornare.',
created: '2 minutes ago',
gravatarURL: 'http://www.gravatar.com/avatar/ef3eac6c71fdf24b13db12d8ff8d1264'
}];
// If not logged in
if (!req.session.userId) {
return res.view('show-video', {
me: null,
video: video,
tutorialId: req.param('tutorialId'),
chats: FAKE_CHAT
});
}
// If logged in...
User.findOne({
id: +req.session.userId
}).exec(function (err, foundUser) {
if (err) {
return res.negotiate(err);
}
if (!foundUser) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
}
return res.view('show-video', {
me: {
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
admin: foundUser.admin
},
video: video,
tutorialId: req.param('tutorialId'),
chats: FAKE_CHAT
});
});
},
deleteTutorial: function(req, res) {
// Find the currently logged in user and her tutorials
User.findOne({
id: req.session.userId
}).exec(function (err, foundUser){
if (err) return res.negotiate(err);
if (!foundUser) return res.notFound();
Tutorial.findOne({
id: +req.param('id')
})
.populate('owner')
.populate ('ratings')
.populate('videos')
.exec(function(err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Check ownership
if (foundUser.id != foundTutorial.owner.id) {
return res.forbidden();
}
// Destroy the tutorial
Tutorial.destroy({
id: req.param('id')
}).exec(function(err){
if (err) return res.negotiate(err);
// Destroy videos
Video.destroy({
id: _.pluck(foundTutorial.videos, 'id')
}).exec(function (err){
if (err) return res.negotiate(err);
// Destroy ratings
Rating.destroy({
id: _.pluck(foundTutorial.ratings, 'id')
}).exec(function (err){
if (err) return res.negotiate(err);
// Return the username of the user using the userId of the session.
return res.json({username: foundUser.username});
});
});
});
});
});
},
removeVideo: function(req, res) {
Tutorial.findOne({
id: +req.param('tutorialId')
})
.exec(function (err, foundTutorial){
if (err) return res.negotiate(err);
if (!foundTutorial) return res.notFound();
// Check ownership
if (req.session.userId !== foundTutorial.owner) {
return res.forbidden();
}
// Remove the reference to this video from our tutorial record.
foundTutorial.videos.remove(+req.param('id'));
// Remove this video id from the `videoOrder` array
foundTutorial.videoOrder = _.without(foundTutorial.videoOrder, +req.param('id'));
// Persist our tutorial back to the database.
foundTutorial.save(function (err){
if (err) return res.negotiate(err);
Video.destroy({
id: +req.param('id')
}).exec(function(err){
if (err) return res.negotiate(err);
return res.ok();
});
});
});
},
profile: function(req, res) {
User.findOne({
username: req.param('username')
})
.populate("followers")
.populate("following")
.exec(function (err, foundUser){
if (err) return res.negotiate(err);
if (!foundUser) return res.notFound();
Tutorial.find({where: {
owner: foundUser.id
}, sort: 'title ASC'})
.populate('ratings')
.populate('videos')
.exec(function (err, foundTutorials){
if (err) return res.negotiate(err);
if (!foundTutorials) return res.notFound();
/*
_____ __
|_ _| __ __ _ _ __ ___ / _| ___ _ __ _ __ ___
| || '__/ _` | '_ \/ __| |_ / _ \| '__| '_ ` _ \
| || | | (_| | | | \__ \ _| (_) | | | | | | | |
|_||_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|
*/
_.each(foundTutorials, function(tutorial){
// sync owner
tutorial.owner = foundUser.username;
// Format the createdAt attributes and assign them to the tutorial
tutorial.created = DatetimeService.getTimeAgo({date: tutorial.createdAt});
// Format Videos
var totalSeconds = 0;
_.each(tutorial.videos, function(video){
// Total the number of seconds for all videos for tutorial total time
totalSeconds = totalSeconds + video.lengthInSeconds;
tutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
});
// Format average ratings
var totalRating = 0;
_.each(tutorial.ratings, function(rating){
totalRating = totalRating + rating.stars;
});
var averageRating = 0;
if (tutorial.ratings.length < 1) {
averageRating = 0;
} else {
averageRating = totalRating / tutorial.ratings.length;
}
tutorial.averageRating = averageRating;
});
// The logged out case
if (!req.session.userId) {
return res.view('profile', {
// This is for the navigation bar
me: null,
// This is for profile body
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundTutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length
},
// This is for the list of tutorials
tutorials: foundTutorials
});
}
// Otherwise the user-agent IS logged in.
// Look up the logged-in user from the database.
User.findOne({
id: req.session.userId
})
.exec(function (err, loggedInUser){
if (err) {
return res.negotiate(err);
}
if (!loggedInUser) {
return res.serverError('User record from logged in user is missing?');
}
// Is the logged in user is currently following the owner of this tutorial?
var cachedFollower = _.find(foundUser.followers, function(follower){
return follower.id === loggedInUser.id;
});
var followedByLoggedInUser = false;
if (cachedFollower) {
followedByLoggedInUser = true;
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
username: loggedInUser.username,
email: loggedInUser.email,
gravatarURL: loggedInUser.gravatarURL,
admin: loggedInUser.admin
};
// We'll provide the `isMe` flag to the profile page view
// if the logged-in user is the same as the user whose profile we looked up earlier.
if (req.session.userId === foundUser.id) {
me.isMe = true;
} else {
me.isMe = false;
}
// Return me property for the nav and the remaining properties for the profile page.
return res.view('profile', {
me: me,
showAddTutorialButton: true,
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundTutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length,
followedByLoggedInUser: followedByLoggedInUser
},
tutorials: foundTutorials
});
}); //</ User.findOne({id: req.session.userId})
});
});
},
profileFollower: function(req, res) {
User.findOne({
username: req.param('username')
})
.populate("followers")
.populate("following")
.populate("tutorials")
.exec(function (err, foundUser){
if (err) return res.negotiate(err);
if (!foundUser) return res.notFound();
// The logged out case
if (!req.session.userId) {
return res.view('profile-followers', {
// This is for the navigation bar
me: null,
// This is for profile body
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundUser.tutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length,
followers: foundUser.followers
},
// This is for the list of followers
followers: foundUser.followers
});
}
// Otherwise the user-agent IS logged in.
// Look up the logged-in user from the database.
User.findOne({
id: req.session.userId
})
.populate('following')
.exec(function (err, loggedInUser){
if (err) {
return res.negotiate(err);
}
if (!loggedInUser) {
return res.serverError('User record from logged in user is missing?');
}
// Is the logged in user currently following the owner of this tutorial?
var cachedFollower = _.find(foundUser.followers, function(follower){
return follower.id === loggedInUser.id;
});
// Set the display toggle (followedByLoggedInUser) based upon whether
// the currently logged in user is following the owner of the tutorial.
var followedByLoggedInUser = false;
if (cachedFollower) {
followedByLoggedInUser = true;
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
username: loggedInUser.username,
email: loggedInUser.email,
gravatarURL: loggedInUser.gravatarURL,
admin: loggedInUser.admin
};
// We'll provide the `isMe` flag to the profile page view
// if the logged-in user is the same as the user whose profile we looked up earlier.
if (req.session.userId === foundUser.id) {
me.isMe = true;
} else {
me.isMe = false;
}
// Return me property for the nav and the remaining properties for the profile page.
return res.view('profile-followers', {
me: me,
showAddTutorialButton: true,
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundUser.tutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length,
followedByLoggedInUser: followedByLoggedInUser,
followers: foundUser.followers
},
followers: foundUser.followers
});
}); //</ User.findOne({id: req.session.userId})
});
},
profileFollowing: function(req, res) {
User.findOne({
username: req.param('username')
})
.populate("followers")
.populate("following")
.populate("tutorials")
.exec(function (err, foundUser){
if (err) return res.negotiate(err);
if (!foundUser) return res.notFound();
// The logged out case
if (!req.session.userId) {
return res.view('profile-following', {
// This is for the navigation bar
me: null,
// This is for profile body
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundUser.tutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length,
following: foundUser.following
},
// This is for the list of following
following: foundUser.following
});
}
// Otherwise the user-agent IS logged in.
// Look up the logged-in user from the database.
User.findOne({
id: req.session.userId
})
.populate('following')
.exec(function (err, loggedInUser){
if (err) {
return res.negotiate(err);
}
if (!loggedInUser) {
return res.serverError('User record from logged in user is missing?');
}
// Is the logged in user currently following the owner of this tutorial?
var cachedFollower = _.find(foundUser.followers, function(follower){
return follower.id === loggedInUser.id;
});
// Set the display toggle (followedByLoggedInUser) based upon whether
// the currently logged in user is following the owner of the tutorial.
var followedByLoggedInUser = false;
if (cachedFollower) {
followedByLoggedInUser = true;
}
// We'll provide `me` as a local to the profile page view.
// (this is so we can render the logged-in navbar state, etc.)
var me = {
username: loggedInUser.username,
email: loggedInUser.email,
gravatarURL: loggedInUser.gravatarURL,
admin: loggedInUser.admin
};
// We'll provide the `isMe` flag to the profile page view
// if the logged-in user is the same as the user whose profile we looked up earlier.
if (req.session.userId === foundUser.id) {
me.isMe = true;
} else {
me.isMe = false;
}
// Return me property for the nav and the remaining properties for the profile page.
return res.view('profile-following', {
me: me,
showAddTutorialButton: true,
username: foundUser.username,
gravatarURL: foundUser.gravatarURL,
frontEnd: {
numOfTutorials: foundUser.tutorials.length,
numOfFollowers: foundUser.followers.length,
numOfFollowing: foundUser.following.length,
followedByLoggedInUser: followedByLoggedInUser,
following: foundUser.following
},
following: foundUser.following
});
}); //</ User.findOne({id: req.session.userId})
});
},
searchTutorials: function(req, res) {
Tutorial.count().exec(function(err, found){
if (err) return res.negotiate(err);
if (!found) return res.notFound();
Tutorial.find({
or : [
{
title: {
'contains': req.param('searchCriteria')
},
},
{
description: {
'contains': req.param('searchCriteria')
}
}
],
limit: 10,
skip: req.param('skip')
})
.populate('owner')
.populate('ratings')
.populate('videos')
.exec(function(err, tutorials){
// Iterate through tutorials to format the owner and created attributes
_.each(tutorials, function(tutorial){
tutorial.owner = tutorial.owner.username;
tutorial.created = DatetimeService.getTimeAgo({date: tutorial.createdAt});
// Determine the total seconds for all videos and each video
var totalSeconds = 0;
_.each(tutorial.videos, function(video){
// Total the number of seconds for all videos for tutorial total time
totalSeconds = totalSeconds + video.lengthInSeconds;
tutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
// Format average ratings
var totalRating = 0;
_.each(tutorial.ratings, function(rating){
totalRating = totalRating + rating.stars;
});
var averageRating = 0;
if (tutorial.ratings.length < 1) {
averageRating = 0;
} else {
averageRating = totalRating / tutorial.ratings.length;
}
tutorial.averageRating = averageRating;
});
});
return res.json({
options: {
totalTutorials: found,
updatedTutorials: tutorials
}
});
});
});
},
browseTutorials: function(req, res) {
Tutorial.count().exec(function (err, numberOfTutorials){
if (err) return res.negotiate(err);
if (!numberOfTutorials) return res.notFound();
Tutorial.find({
limit: 10,
skip: req.param('skip')
})
.populate('owner')
.populate('ratings')
.populate('videos')
.exec(function(err, foundTutorials){
_.each(foundTutorials, function(tutorial){
tutorial.owner = tutorial.owner.username;
tutorial.created = DatetimeService.getTimeAgo({date: tutorial.createdAt});
var totalSeconds = 0;
_.each(tutorial.videos, function(video){
// Total the number of seconds for all videos for tutorial total time
totalSeconds = totalSeconds + video.lengthInSeconds;
tutorial.totalTime = DatetimeService.getHoursMinutesSeconds({totalSeconds: totalSeconds}).hoursMinutesSeconds;
// Format average ratings
var totalRating = 0;
_.each(tutorial.ratings, function(rating){
totalRating = totalRating + rating.stars;
});
var averageRating = 0;
if (tutorial.ratings.length < 1) {
averageRating = 0;
} else {
averageRating = totalRating / tutorial.ratings.length;
}
tutorial.averageRating = averageRating;
});
});
return res.json({
options: {
totalTutorials: numberOfTutorials,
updatedTutorials: foundTutorials
}
});
});
});
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment