Merge branch 'staging' of github.com:FreeCodeCamp/freecodecamp into staging
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "bonfire",
|
||||
"base": "PersistedModel",
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"unique": true
|
||||
},
|
||||
"difficulty": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "array"
|
||||
},
|
||||
"tests": {
|
||||
"type": "array"
|
||||
},
|
||||
"challengeSeed": {
|
||||
"type": "array"
|
||||
},
|
||||
"MDNlinks": {
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"validations": [],
|
||||
"relations": {},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "DENY"
|
||||
},
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
],
|
||||
"methods": []
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"name": "comment",
|
||||
"base": "PersistedModel",
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"associatedPost": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"originalStoryLink": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"originalStoryAuthorEmail": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"rank": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"upvotes": {
|
||||
"type": "array",
|
||||
"default": []
|
||||
},
|
||||
"author": {
|
||||
"type": {},
|
||||
"default": {}
|
||||
},
|
||||
"comments": {
|
||||
"type": "array",
|
||||
"default": []
|
||||
},
|
||||
"commentOn": {
|
||||
"type": "number",
|
||||
"defaultFn": "now"
|
||||
}
|
||||
},
|
||||
"validations": [],
|
||||
"relations": {},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "DENY"
|
||||
},
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW",
|
||||
"property": "create"
|
||||
}
|
||||
],
|
||||
"methods": []
|
||||
}
|
@@ -44,10 +44,6 @@
|
||||
"author": {
|
||||
"type": {}
|
||||
},
|
||||
"comments": {
|
||||
"type": "array",
|
||||
"default": []
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
|
@@ -126,7 +126,7 @@ gulp.task('serve', function(cb) {
|
||||
script: paths.server,
|
||||
ext: '.js .json',
|
||||
ignore: paths.serverIgnore,
|
||||
exec: './node_modules/.bin/babel-node',
|
||||
exec: path.join(__dirname, 'node_modules/.bin/babel-node'),
|
||||
env: {
|
||||
'NODE_ENV': 'development',
|
||||
'DEBUG': process.env.DEBUG || 'freecc:*'
|
||||
|
@@ -277,34 +277,32 @@ $(document).ready(function() {
|
||||
$('#long-instructions').hide();
|
||||
});
|
||||
|
||||
var upvoteHandler = function () {
|
||||
var id = storyId;
|
||||
$('#upvote').unbind('click');
|
||||
function upvoteHandler(e) {
|
||||
e.preventDefault();
|
||||
var upvoteBtn = this;
|
||||
var id = upvoteBtn.id;
|
||||
var upVotes = $(upvoteBtn).data().upVotes;
|
||||
var username = typeof username !== 'undefined' ? username : '';
|
||||
var alreadyUpvoted = false;
|
||||
for (var i = 0; i < upVotes.length; i++) {
|
||||
if (upVotes[i].upVotedBy === B3BA669EC5C1DD70FB478221E067A7E1B686929C569F5E73561B69C8F42129B) {
|
||||
if (upVotes[i].upVotedBy === username) {
|
||||
alreadyUpvoted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyUpvoted) {
|
||||
$.post('/stories/upvote',
|
||||
{
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
$.post('/stories/upvote', { id: id })
|
||||
.fail(function(xhr, textStatus, errorThrown) {
|
||||
$(upvoteBtn).bind('click', upvoteHandler);
|
||||
})
|
||||
.fail(function (xhr, textStatus, errorThrown) {
|
||||
$('#upvote').bind('click', upvoteHandler);
|
||||
})
|
||||
.done(function (data, textStatus, xhr) {
|
||||
$('#upvote').text('Upvoted!').addClass('disabled');
|
||||
.done(function(data, textStatus, xhr) {
|
||||
$(upvoteBtn).text('Upvoted!').addClass('disabled');
|
||||
|
||||
$('#storyRank').text(data.rank + " points");
|
||||
});
|
||||
}
|
||||
};
|
||||
$('#upvote').on('click', upvoteHandler);
|
||||
$('#story-list').on('click', 'button.btn-upvote', upvoteHandler);
|
||||
|
||||
var storySubmitButtonHandler = function storySubmitButtonHandler() {
|
||||
|
||||
@@ -322,7 +320,6 @@ $(document).ready(function() {
|
||||
description: description,
|
||||
storyMetaDescription: storyMetaDescription,
|
||||
rank: 1,
|
||||
comments: [],
|
||||
image: storyImage
|
||||
}
|
||||
})
|
||||
@@ -336,29 +333,6 @@ $(document).ready(function() {
|
||||
|
||||
$('#story-submit').on('click', storySubmitButtonHandler);
|
||||
|
||||
var commentSubmitButtonHandler = function commentSubmitButtonHandler() {
|
||||
$('#comment-button').unbind('click');
|
||||
var data = $('#comment-box').val();
|
||||
|
||||
$('#comment-button').attr('disabled', 'disabled');
|
||||
$.post('/stories/comment/',
|
||||
{
|
||||
data: {
|
||||
associatedPost: storyId,
|
||||
originalStoryLink: originalStoryLink,
|
||||
originalStoryAuthorEmail: originalStoryAuthorEmail,
|
||||
body: data
|
||||
}
|
||||
})
|
||||
.fail(function (xhr, textStatus, errorThrown) {
|
||||
$('#comment-button').attr('disabled', false);
|
||||
$('#comment-button').bind('click', commentSubmitButtonHandler);
|
||||
})
|
||||
.done(function (data, textStatus, xhr) {
|
||||
window.location.reload();
|
||||
});
|
||||
};
|
||||
|
||||
//fakeiphone positioning hotfix
|
||||
if($('.iphone-position').html() !==undefined || $('.iphone').html() !== undefined){
|
||||
var startIphonePosition = parseInt($('.iphone-position').css('top').replace('px', ''));
|
||||
@@ -405,9 +379,7 @@ $(document).ready(function() {
|
||||
lockTop(initOff);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#comment-button').on('click', commentSubmitButtonHandler);
|
||||
}
|
||||
});
|
||||
|
||||
var profileValidation = angular.module('profileValidation',
|
||||
|
@@ -448,7 +448,7 @@
|
||||
"Let's now go create a nested array called <code>myArray</code>"
|
||||
],
|
||||
"tests":[
|
||||
"assert((function(){if(typeof(myArray) !== 'undefined' && typeof(myArray) === 'object' && typeof(myArray[0]) !== 'undefined' && typeof(myArray) === 'object'){return(true);}else{return(false);}})(), 'myArray should contain at least one array');"
|
||||
"assert((function(){if(typeof(myArray) !== 'undefined' && typeof(myArray) === 'object' && typeof(myArray[0]) !== 'undefined' && typeof(myArray[0]) === 'object' && editor.getValue().match(/[[]]/g).length >= 1){return(true);}else{return(false);}})(), 'myArray should contain at least one array');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"var myArray = [];",
|
||||
@@ -548,7 +548,7 @@
|
||||
"//console.log(removed); //Gives 3",
|
||||
"",
|
||||
"var myArray = ['John', 23, ['cat', 2]];",
|
||||
"var removed = _;//This should be ['cat', 2] and myArray should now be ['John', 23]",
|
||||
"var removed = myArray;//This should be ['cat', 2] and myArray should now be ['John', 23]",
|
||||
"",
|
||||
"",
|
||||
"(function(y, z){return('myArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z));})(myArray, removed);"
|
||||
@@ -566,7 +566,7 @@
|
||||
"Let's take the code we had last time and <code> push </code> this value to the end: <code> ['dog', 3] </code>"
|
||||
],
|
||||
"tests": [
|
||||
"assert((function(d){if(d[2] != undefined && d[0] == 'John' && d[1] == 23 && d[2][0] == 'dog' && d[2][1] == 3){return(true);}else{return(false);}})(myArray), 'myArray should only have the first two values left([\"John\", 23, [\"dog\", 3]])');"
|
||||
"assert((function(d){if(d[2] != undefined && d[0] == 'John' && d[1] == 23 && d[2][0] == 'dog' && d[2][1] == 3 && d[2].length == 2){return(true);}else{return(false);}})(myArray), 'myArray should only have the first two values left([\"John\", 23, [\"dog\", 3]])');"
|
||||
],
|
||||
"challengeSeed": [
|
||||
"var myArray = ['John', 23, ['cat', 2]];",
|
||||
@@ -595,7 +595,7 @@
|
||||
],
|
||||
"challengeSeed": [
|
||||
"var myArray = ['John', 23, ['dog', 3]];",
|
||||
"var removed = _;//This should be ['John'] and myArray should now be ['John', 23]",
|
||||
"var removed = myArray;//This should be ['John'] and myArray should now be ['John', 23]",
|
||||
"",
|
||||
"",
|
||||
"(function(y, z){return('myArray = ' + JSON.stringify(y) + ' & removed = ' + JSON.stringify(z));})(myArray, removed);"
|
||||
@@ -644,7 +644,7 @@
|
||||
"Let's try creating and calling a function now called <code>myFunction</code>"
|
||||
],
|
||||
"tests":[
|
||||
"assert((function(){if(typeof(f) !== 'undefined' && typeof(f) === 'number' && f === 9){return(true);}else{return(false);}})(), 'Your function should return the value of a + b');"
|
||||
"assert((function(){if(typeof(f) !== 'undefined' && typeof(f) === 'number' && f === a + b && editor.getValue().match(RegExp('return\\\\(a\\\\+b\\\\)', 'g')).length >= 1){return(true);}else{return(false);}})(), 'Your function should return the value of a + b');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"var a = 4;",
|
||||
@@ -726,7 +726,7 @@
|
||||
""
|
||||
],
|
||||
"tests":[
|
||||
"assert(myDog.bark != undefined, 'The property tails should have been deleted');",
|
||||
"assert(myDog.bark != undefined, 'You should have added the property bark to myDog');",
|
||||
"assert(myDog.tails == undefined, 'The property tails should have been deleted');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
@@ -740,9 +740,9 @@
|
||||
"//Re-create myDog",
|
||||
"",
|
||||
"var myDog = {",
|
||||
" \"name\": _,",
|
||||
" \"legs\": _,",
|
||||
" \"tails\": _,",
|
||||
" \"name\": 'Camper',",
|
||||
" \"legs\": 4,",
|
||||
" \"tails\": 1,",
|
||||
" \"friends\": []",
|
||||
"};",
|
||||
"",
|
||||
@@ -1021,7 +1021,7 @@
|
||||
],
|
||||
"tests":[
|
||||
"assert(test === 2, 'Your RegEx should have found two numbers in the testString');",
|
||||
"assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'You should be using the following expression /\\d+/gi to find the numbers in the testString');"
|
||||
"assert(editorValue.match(/\\/\\\\d\\+\\//gi), 'You should be using the following expression /\\d+/gi to find the numbers in the testString');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"var test = (function(){",
|
||||
@@ -1052,7 +1052,7 @@
|
||||
],
|
||||
"tests":[
|
||||
"assert(test === 7, 'Your RegEx should have found seven spaces in the testString');",
|
||||
"assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'You should be using the following expression /\\s+/gi to find the spaces in the testString');"
|
||||
"assert(editorValue.match(/\\/\\\\s\\+\\//gi), 'You should be using the following expression /\\s+/gi to find the spaces in the testString');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"var test = (function(){",
|
||||
@@ -1083,14 +1083,14 @@
|
||||
"<code> Math.floor(Math.random() * (5 - 1 + 1)) + 1; </code>"
|
||||
],
|
||||
"tests":[
|
||||
"assert(typeof(runSlots($(''))[0]) == 'number', 'SlotOne should be a random number');",
|
||||
"assert(typeof(runSlots($(''))[1]) == 'number', 'SlotTwo should be a random number');",
|
||||
"assert(typeof(runSlots($(''))[2]) == 'number', 'SlotThree should be a random number');",
|
||||
"assert(editor.getValue().match(/Math.floor\\(Math.random\\(\\) \\* \\(5 \\- 1 \\+ 1\\)\\) \\+ 1/g).length === 3);"
|
||||
"assert(typeof(runSlots($('.slot'))[0]) == 'number', 'SlotOne should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[1]) == 'number', 'SlotTwo should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[2]) == 'number', 'SlotThree should be a random number');",
|
||||
"assert(editorValue.match(/Math.floor\\(Math.random\\(\\) \\* \\(5 \\- 1 \\+ 1\\)\\) \\+ 1/g).length === 3);"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"fccss",
|
||||
" function runSlots(slots){",
|
||||
" function runSlots(){",
|
||||
" var slotOne;",
|
||||
" var slotTwo;",
|
||||
" var slotThree;",
|
||||
@@ -1111,7 +1111,7 @@
|
||||
"",
|
||||
" $(document).ready(function(){",
|
||||
" $('.go').click(function(){",
|
||||
" runSlots(slots);",
|
||||
" runSlots();",
|
||||
" });",
|
||||
" });",
|
||||
"fcces",
|
||||
|
@@ -254,9 +254,8 @@
|
||||
"Click \"News\" in the upper right hand corner.",
|
||||
"You'll see a variety of links that have been submitted. Click on the \"Discuss\" button under one of them.",
|
||||
"You can upvote links. This will push the link up the rankings of hot links.",
|
||||
"You can also comment on a link. If someone responds to your comment, you'll get an email notification so you can come back and respond to them.",
|
||||
"You can also submit links. You can modify the link's headline and also leave an initial comment about the link.",
|
||||
"You can view the portfolio pages of any camper who has posted links or comments on Camper News. Just click on their photo.",
|
||||
"You can also submit links.",
|
||||
"You can view the portfolio pages of any camper who has posted links on Camper News. Just click on their photo.",
|
||||
"When you submit a link, you'll get a point. You will also get a point each time someone upvotes your link.",
|
||||
"Now that you've learned how to use Camper News, let's move on to your next challenge."
|
||||
],
|
||||
|
@@ -18,7 +18,7 @@
|
||||
"<span class='text-info'>User Story:</span> As a user, I can click on a post to be taken to the story's original URL.",
|
||||
"<span class='text-info'>User Story:</span> As a user, I can click a link to go directly to the post's discussion page.",
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I can see how many upvotes each story has.",
|
||||
"<span class='text-info'>Hint:</span> Here's the Camper News Hot Stories API endpoint: <code>http://www.freecodecamp.com/stories/hotStories</code>.",
|
||||
"<span class='text-info'>Hint:</span> Here's the Camper News Hot Stories API endpoint: <code>http://www.freecodecamp.com/news/hot</code>.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
|
@@ -1,5 +1,4 @@
|
||||
var Rx = require('rx'),
|
||||
nodemailer = require('nodemailer'),
|
||||
assign = require('object.assign'),
|
||||
sanitizeHtml = require('sanitize-html'),
|
||||
moment = require('moment'),
|
||||
@@ -19,23 +18,6 @@ var unDasherize = utils.unDasherize;
|
||||
var dasherize = utils.dasherize;
|
||||
var getURLTitle = utils.getURLTitle;
|
||||
|
||||
var transporter = nodemailer.createTransport({
|
||||
service: 'Mandrill',
|
||||
auth: {
|
||||
user: secrets.mandrill.user,
|
||||
pass: secrets.mandrill.password
|
||||
}
|
||||
});
|
||||
|
||||
function sendMailWhillyNilly(mailOptions) {
|
||||
transporter.sendMail(mailOptions, function(err) {
|
||||
if (err) {
|
||||
console.log('err sending mail whilly nilly', err);
|
||||
console.log('logging err but not carring');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function hotRank(timeValue, rank) {
|
||||
/*
|
||||
* Hotness ranking algorithm: http://amix.dk/blog/post/19588
|
||||
@@ -69,7 +51,6 @@ module.exports = function(app) {
|
||||
var router = app.loopback.Router();
|
||||
var User = app.models.User;
|
||||
var findUserById = observeMethod(User, 'findById');
|
||||
var findOneUser = observeMethod(User, 'findOne');
|
||||
|
||||
var Story = app.models.Story;
|
||||
var findStory = observeMethod(Story, 'find');
|
||||
@@ -77,14 +58,8 @@ module.exports = function(app) {
|
||||
var findStoryById = observeMethod(Story, 'findById');
|
||||
var countStories = observeMethod(Story, 'count');
|
||||
|
||||
var Comment = app.models.Comment;
|
||||
var findCommentById = observeMethod(Comment, 'findById');
|
||||
|
||||
router.get('/news/hot', hotJSON);
|
||||
router.get('/stories/hotStories', hotJSON);
|
||||
router.get('/stories/comments/:id', comments);
|
||||
router.post('/stories/comment/', commentSubmit);
|
||||
router.post('/stories/comment/:id/comment', commentOnCommentSubmit);
|
||||
router.put('/stories/comment/:id/edit', commentEdit);
|
||||
router.get('/stories/submit', submitNew);
|
||||
router.get('/stories/submit/new-story', preSubmit);
|
||||
router.post('/stories/preliminary', newStory);
|
||||
@@ -194,7 +169,6 @@ module.exports = function(app) {
|
||||
description: story.description,
|
||||
rank: story.upVotes.length,
|
||||
upVotes: story.upVotes,
|
||||
comments: story.comments,
|
||||
id: story.id,
|
||||
timeAgo: moment(story.timePosted).fromNow(),
|
||||
image: story.image,
|
||||
@@ -224,7 +198,6 @@ module.exports = function(app) {
|
||||
rank: 1,
|
||||
upVotes: 1,
|
||||
author: 1,
|
||||
comments: 1,
|
||||
image: 1,
|
||||
storyLink: 1,
|
||||
metaDescription: 1,
|
||||
@@ -250,7 +223,7 @@ module.exports = function(app) {
|
||||
}
|
||||
|
||||
function upvote(req, res, next) {
|
||||
var id = req.body.data.id;
|
||||
const { id } = req.body;
|
||||
var story$ = findStoryById(id).shareReplay();
|
||||
|
||||
story$.flatMap(function(story) {
|
||||
@@ -284,16 +257,6 @@ module.exports = function(app) {
|
||||
);
|
||||
}
|
||||
|
||||
function comments(req, res, next) {
|
||||
var id = req.params.id;
|
||||
findCommentById(id).subscribe(
|
||||
function(comment) {
|
||||
res.send(comment);
|
||||
},
|
||||
next
|
||||
);
|
||||
}
|
||||
|
||||
function newStory(req, res, next) {
|
||||
if (!req.user) {
|
||||
return next(new Error('Must be logged in'));
|
||||
@@ -407,7 +370,6 @@ module.exports = function(app) {
|
||||
username: req.user.username,
|
||||
email: req.user.email
|
||||
},
|
||||
comments: [],
|
||||
image: data.image,
|
||||
storyLink: storyLink,
|
||||
metaDescription: data.storyMetaDescription,
|
||||
@@ -428,174 +390,4 @@ module.exports = function(app) {
|
||||
next
|
||||
);
|
||||
}
|
||||
|
||||
function commentSubmit(req, res, next) {
|
||||
var data = req.body.data;
|
||||
if (!req.user) {
|
||||
return next(new Error('Not authorized'));
|
||||
}
|
||||
var sanitizedBody = cleanData(data.body);
|
||||
|
||||
if (data.body !== sanitizedBody) {
|
||||
req.flash('errors', {
|
||||
msg: 'HTML is not allowed'
|
||||
});
|
||||
return res.send(true);
|
||||
}
|
||||
var comment = new Comment({
|
||||
associatedPost: data.associatedPost,
|
||||
originalStoryLink: data.originalStoryLink,
|
||||
originalStoryAuthorEmail: data.originalStoryAuthorEmail,
|
||||
body: sanitizedBody,
|
||||
rank: 0,
|
||||
upvotes: 0,
|
||||
author: {
|
||||
picture: req.user.picture,
|
||||
userId: req.user.id,
|
||||
username: req.user.username,
|
||||
email: req.user.email
|
||||
},
|
||||
comments: [],
|
||||
topLevel: true,
|
||||
commentOn: Date.now()
|
||||
});
|
||||
|
||||
commentSave(comment, findStoryById).subscribe(
|
||||
function() {},
|
||||
next,
|
||||
function() {
|
||||
res.send(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function commentOnCommentSubmit(req, res, next) {
|
||||
var data = req.body.data;
|
||||
if (!req.user) {
|
||||
return next(new Error('Not authorized'));
|
||||
}
|
||||
|
||||
var sanitizedBody = cleanData(data.body);
|
||||
|
||||
if (data.body !== sanitizedBody) {
|
||||
req.flash('errors', {
|
||||
msg: 'HTML is not allowed'
|
||||
});
|
||||
return res.send(true);
|
||||
}
|
||||
|
||||
var comment = new Comment({
|
||||
associatedPost: data.associatedPost,
|
||||
body: sanitizedBody,
|
||||
rank: 0,
|
||||
upvotes: 0,
|
||||
originalStoryLink: data.originalStoryLink,
|
||||
originalStoryAuthorEmail: data.originalStoryAuthorEmail,
|
||||
author: {
|
||||
picture: req.user.picture,
|
||||
userId: req.user.id,
|
||||
username: req.user.username,
|
||||
email: req.user.email
|
||||
},
|
||||
comments: [],
|
||||
topLevel: false,
|
||||
commentOn: Date.now()
|
||||
});
|
||||
commentSave(comment, findCommentById).subscribe(
|
||||
function() {},
|
||||
next,
|
||||
function() {
|
||||
res.send(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function commentEdit(req, res, next) {
|
||||
findCommentById(req.params.id)
|
||||
.doOnNext(function(comment) {
|
||||
if (!req.user && comment.author.userId !== req.user.id) {
|
||||
throw new Error('Not authorized');
|
||||
}
|
||||
})
|
||||
.flatMap(function(comment) {
|
||||
var sanitizedBody = cleanData(req.body.body);
|
||||
if (req.body.body !== sanitizedBody) {
|
||||
req.flash('errors', {
|
||||
msg: 'HTML is not allowed'
|
||||
});
|
||||
}
|
||||
comment.body = sanitizedBody;
|
||||
comment.commentOn = Date.now();
|
||||
return saveInstance(comment);
|
||||
})
|
||||
.subscribe(
|
||||
function() {
|
||||
res.send(true);
|
||||
},
|
||||
next
|
||||
);
|
||||
}
|
||||
|
||||
function commentSave(comment, findContextById) {
|
||||
return saveInstance(comment)
|
||||
.flatMap(function(comment) {
|
||||
// Based on the context retrieve the parent
|
||||
// object of the comment (Story/Comment)
|
||||
return findContextById(comment.associatedPost);
|
||||
})
|
||||
.flatMap(function(associatedContext) {
|
||||
if (associatedContext) {
|
||||
associatedContext.comments.push(comment.id);
|
||||
}
|
||||
// NOTE(berks): saveInstance is safe
|
||||
// it will automatically call onNext with null and onCompleted if
|
||||
// argument is falsey or has no method save
|
||||
return saveInstance(associatedContext);
|
||||
})
|
||||
.flatMap(function(associatedContext) {
|
||||
// Find the author of the parent object
|
||||
// if no username
|
||||
var username = associatedContext && associatedContext.author ?
|
||||
associatedContext.author.username :
|
||||
null;
|
||||
|
||||
var query = { where: { username: username } };
|
||||
return findOneUser(query);
|
||||
})
|
||||
// if no user is found we don't want to hit the doOnNext
|
||||
// filter here will call onCompleted without running through the following
|
||||
// steps
|
||||
.filter(function(user) {
|
||||
return !!user;
|
||||
})
|
||||
// if this is called user is guarenteed to exits
|
||||
// this is a side effect, hence we use do/tap observable methods
|
||||
.doOnNext(function(user) {
|
||||
// If the emails of both authors differ,
|
||||
// only then proceed with email notification
|
||||
if (
|
||||
comment.author &&
|
||||
comment.author.email &&
|
||||
user.email &&
|
||||
(comment.author.email !== user.email)
|
||||
) {
|
||||
sendMailWhillyNilly({
|
||||
to: user.email,
|
||||
from: 'Team@freecodecamp.com',
|
||||
subject: comment.author.username +
|
||||
' replied to your post on Camper News',
|
||||
text: [
|
||||
'Just a quick heads-up: ',
|
||||
comment.author.username,
|
||||
' replied to you on Camper News.',
|
||||
'You can keep this conversation going.',
|
||||
'Just head back to the discussion here: ',
|
||||
'http://freecodecamp.com/stories/',
|
||||
comment.originalStoryLink,
|
||||
'- the Free Code Camp Volunteer Team'
|
||||
].join('\n')
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@@ -12,7 +12,6 @@ module.exports = function(app) {
|
||||
var router = app.loopback.Router();
|
||||
var User = app.models.User;
|
||||
var Story = app.models.Story;
|
||||
var Comment = app.models.Comment;
|
||||
|
||||
router.get('/login', function(req, res) {
|
||||
res.redirect(301, '/signin');
|
||||
@@ -623,55 +622,23 @@ module.exports = function(app) {
|
||||
}
|
||||
|
||||
function updateUserStoryPictures(userId, picture, username, cb) {
|
||||
|
||||
var counter = 0,
|
||||
foundStories,
|
||||
foundComments;
|
||||
|
||||
Story.find({ 'author.userId': userId }, function(err, stories) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
foundStories = stories;
|
||||
counter++;
|
||||
saveStoriesAndComments();
|
||||
});
|
||||
if (err) { return cb(err); }
|
||||
|
||||
Comment.find({ 'author.userId': userId }, function(err, comments) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
foundComments = comments;
|
||||
counter++;
|
||||
saveStoriesAndComments();
|
||||
});
|
||||
|
||||
function saveStoriesAndComments() {
|
||||
if (counter !== 2) {
|
||||
return;
|
||||
}
|
||||
var tasks = [];
|
||||
R.forEach(function(comment) {
|
||||
comment.author.picture = picture;
|
||||
comment.author.username = username;
|
||||
tasks.push(function(cb) {
|
||||
comment.save(cb);
|
||||
});
|
||||
}, foundComments);
|
||||
|
||||
R.forEach(function(story) {
|
||||
const tasks = [];
|
||||
stories.forEach(function(story) {
|
||||
story.author.picture = picture;
|
||||
story.author.username = username;
|
||||
tasks.push(function(cb) {
|
||||
story.save(cb);
|
||||
});
|
||||
}, foundStories);
|
||||
});
|
||||
async.parallel(tasks, function(err) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@@ -31,18 +31,10 @@
|
||||
"dataSource": "mail",
|
||||
"public": false
|
||||
},
|
||||
"bonfire": {
|
||||
"dataSource": "db",
|
||||
"public": true
|
||||
},
|
||||
"challenge": {
|
||||
"dataSource": "db",
|
||||
"public": true
|
||||
},
|
||||
"comment": {
|
||||
"dataSource": "db",
|
||||
"public": true
|
||||
},
|
||||
"fieldGuide": {
|
||||
"dataSource": "db",
|
||||
"public": true
|
||||
|
@@ -208,7 +208,7 @@ app.use(function(req, res, next) {
|
||||
var path = req.path.split('/')[1];
|
||||
if (/auth|login|logout|signin|signup|fonts|favicon/i.test(path)) {
|
||||
return next();
|
||||
} else if (/\/stories\/comments\/\w+/i.test(req.path)) {
|
||||
} else if (/\/stories\/\w+/i.test(req.path)) {
|
||||
return next();
|
||||
}
|
||||
req.session.returnTo = req.path;
|
||||
|
@@ -1,164 +0,0 @@
|
||||
.text-left
|
||||
div#comment-list
|
||||
|
||||
script(src="https://cdn.jsdelivr.net/ramda/0.10.0/ramda.min.js")
|
||||
script(src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js")
|
||||
script.
|
||||
var sentinel = 0;
|
||||
var renderComments = function renderComments(comments, containerSelector, level) {
|
||||
var commentDetails;
|
||||
R.forEach(function displayComments(comment) {
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/stories/comments/' + comment,
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
commentDetails = {
|
||||
error: true,
|
||||
body: 'There seems to be a problem fetching this comment.'
|
||||
}
|
||||
},
|
||||
success: function (data, textStatus, xhr) {
|
||||
commentDetails = data;
|
||||
var div = document.createElement('div');
|
||||
var editButton = "";
|
||||
// todo
|
||||
if (commentDetails.author.username === DF105CFA89562196E702912B3818C6A5B46E80D262442FDF29976621E5AF0D23) {
|
||||
if ((Date.now() - commentDetails.commentOn) < 600000){
|
||||
editButton = "<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost edit-btn' id='" + commentDetails.id + "'>Edit</a> · ";
|
||||
}
|
||||
}
|
||||
$(div)
|
||||
.html(
|
||||
'<div class="media media-news">' +
|
||||
'<div class="media-left">' +
|
||||
"<a href='/" + commentDetails.author.username + "'>" +
|
||||
'<img class="media-object img-news" src="' + commentDetails.author.picture +'" alt="' + commentDetails.author.username + '">' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
'<div class="media-body comment_' + commentDetails.id + '">' +
|
||||
'<div class="media-body-wrapper">' +
|
||||
'<p>' + commentDetails.body + '</p>' +
|
||||
'<h6>' +
|
||||
'<div class="clearfix comment-a-comment negative-15">' +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' id='" + commentDetails.id + "'>Reply</a> · " +
|
||||
editButton +
|
||||
"commented " + moment(commentDetails.commentOn).fromNow() + " by " +
|
||||
"<a href='/" + commentDetails.author.username + "'>@" + commentDetails.author.username + "</a>" +
|
||||
'</div>' +
|
||||
'</h6>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)
|
||||
.addClass('comment-wrapper positive-10')
|
||||
.appendTo($(containerSelector));
|
||||
|
||||
sentinel += commentDetails.comments.length;
|
||||
|
||||
renderComments(commentDetails.comments, '.comment_' + commentDetails.id, ++level);
|
||||
|
||||
},
|
||||
complete: function () {
|
||||
sentinel--;
|
||||
if (!sentinel) {
|
||||
$('.comment-a-comment').on('click', 'a', function() {
|
||||
var editOrComment = 'comment';
|
||||
if ($(this).hasClass("edit-btn")){
|
||||
editOrComment = 'edit';
|
||||
}
|
||||
if (!isLoggedIn) {
|
||||
window.location.href = '/signin';
|
||||
return;
|
||||
}
|
||||
$(this).unbind('click');
|
||||
$('.comment-to-comment-formgroup').empty();
|
||||
$('#initial-comment-submit').addClass('hidden-element');
|
||||
var div = document.createElement('div');
|
||||
var commentId = $(this).attr('id');
|
||||
$(div).html(
|
||||
"<div class='formgroup comment-to-comment-formgroup control-label-story-submission'>" +
|
||||
'<div class="col-xs-12">' +
|
||||
"<div class='input-group'>" +
|
||||
"<input class='form-control big-text-field field-responsive' id='comment-to-comment-textinput' type='text' maxlength='140' autofocus />" +
|
||||
"<span class='input-group-btn'>" +
|
||||
"<button id='submit-comment-to-" + editOrComment + "' class='btn btn-big btn-primary btn-responsive'>Send</button>" +
|
||||
"</span>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div id='textarea-comment-feedback'></div>" +
|
||||
"</div>"
|
||||
)
|
||||
.addClass('row')
|
||||
.appendTo($(this).closest('.media-body-wrapper'));
|
||||
var text_max = 140;
|
||||
$('#textarea-comment-feedback').html(text_max + ' characters remaining');
|
||||
$('#comment-to-comment-textinput').keyup(function (e) {
|
||||
if (e.which === 13 || e === 13) {
|
||||
$('#submit-comment-to-comment').click();
|
||||
$('#submit-comment-to-edit').click();
|
||||
}
|
||||
var text_length = $('#comment-to-comment-textinput').val().length;
|
||||
var text_remaining = text_max - text_length;
|
||||
$('#textarea-comment-feedback').html(text_remaining + ' characters remaining');
|
||||
});
|
||||
var submitCommentToCommentHandler = function submitCommentToCommentHandler() {
|
||||
$('#submit-comment-to-comment').unbind('click');
|
||||
$.post('/stories/comment/' + commentId + '/comment',
|
||||
{
|
||||
data: {
|
||||
associatedPost: commentId,
|
||||
originalStoryLink: originalStoryLink,
|
||||
originalStoryAuthorEmail: originalStoryAuthorEmail,
|
||||
body: $('#comment-to-comment-textinput').val(),
|
||||
}
|
||||
})
|
||||
.fail(function (xhr, textStatus, errorThrown) {
|
||||
$('#submit-comment-to-comment').bind('click', submitCommentToCommentHandler);
|
||||
})
|
||||
.done(function (data, textStatus, xhr) {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
};
|
||||
// todo
|
||||
var submitCommentForEditToCommentHandler = function submitCommentForEditToCommentHandler() {
|
||||
$('#submit-comment-to-edit').unbind('click');
|
||||
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: '/stories/comment/' + commentId + '/edit',
|
||||
data: {
|
||||
associatedPost: commentId,
|
||||
originalStoryLink: originalStoryLink,
|
||||
body: $('#comment-to-comment-textinput').val()
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (msg) {
|
||||
window.location.reload();
|
||||
},
|
||||
error: function (err){
|
||||
$('#submit-comment-to-edit').bind('click', submitCommentForEditToCommentHandler);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#submit-comment-to-edit').on('click', submitCommentForEditToCommentHandler)
|
||||
$('#submit-comment-to-comment').on('click', submitCommentToCommentHandler);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}, comments);
|
||||
}
|
||||
sentinel += comments.length;
|
||||
|
||||
|
||||
renderComments(comments, $('#comment-list'), 0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
return name.trim().toLowerCase().replace(/\s/g, '-');
|
||||
}
|
||||
$.ajax({
|
||||
url: '/stories/hotStories',
|
||||
url: '/news/hot',
|
||||
type: 'GET'
|
||||
})
|
||||
.success(
|
||||
@@ -18,6 +18,12 @@
|
||||
var div = document.createElement('div');
|
||||
var linkedName = getLinkedName(data[i].storyLink);
|
||||
var rank = data[i].rank;
|
||||
var alreadyUpvoted = false;
|
||||
if (typeof username !== 'undefined') {
|
||||
alreadyUpvoted = data[i].upVotes.some(function(vote) {
|
||||
return vote.upVotedByUsername === username
|
||||
});
|
||||
}
|
||||
|
||||
$(div)
|
||||
.html(
|
||||
@@ -38,7 +44,11 @@
|
||||
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + "</a> " +
|
||||
"</div>" +
|
||||
"<div class='col-xs-12'>" +
|
||||
"<br><a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/stories/" + linkedName + "'>discuss</a>" +
|
||||
"<br>" +
|
||||
(typeof username !== 'undefined' ?
|
||||
"<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</button>" :
|
||||
"<a href='/signup' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</a>") +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/news/" + linkedName + "'>more info...</a>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='hidden-xs row media-stories'>" +
|
||||
@@ -56,7 +66,10 @@
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
"<div class='story-byline col-xs-12 wrappable'>" +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/stories/" + linkedName + "'>discuss</a> · " +
|
||||
(typeof username !== 'undefined' ?
|
||||
"<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost btn-upvote'>upvote</button>" :
|
||||
"<a href='/signin' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost'>upvote</a>") +
|
||||
" · <a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/news/" + linkedName + "'>more info...</a> · " +
|
||||
rank + (rank > 1 ? " points" : " point") + " · posted " +
|
||||
moment(data[i].timePosted).fromNow() +
|
||||
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + "</a> " +
|
||||
@@ -68,5 +81,13 @@
|
||||
);
|
||||
$(div).addClass('story-list news-box')
|
||||
$(div).appendTo($('#story-list'));
|
||||
$(div).find('.btn-upvote').each(function(idx, btn) {
|
||||
var $btn = $(btn);
|
||||
if (alreadyUpvoted) {
|
||||
$btn.addClass('disabled');
|
||||
$btn.text('upvoted!');
|
||||
}
|
||||
$btn.data('upVotes', data[i].upVotes);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@@ -3,8 +3,8 @@ block content
|
||||
if (user)
|
||||
script.
|
||||
var isLoggedIn = true;
|
||||
var B3BA669EC5C1DD70FB478221E067A7E1B686929C569F5E73561B69C8F42129B = !{JSON.stringify(user.id)};
|
||||
var DF105CFA89562196E702912B3818C6A5B46E80D262442FDF29976621E5AF0D23 = !{JSON.stringify(user.username)};
|
||||
var userId = !{JSON.stringify(user.id)};
|
||||
var username = !{JSON.stringify(user.username)};
|
||||
else
|
||||
script.
|
||||
var isLoggedIn = false;
|
||||
|
@@ -1,55 +0,0 @@
|
||||
.spacer
|
||||
.col-xs-12
|
||||
#story-list.story-list
|
||||
|
||||
script(src="https://cdn.jsdelivr.net/ramda/0.10.0/ramda.min.js")
|
||||
script.
|
||||
|
||||
var getLinkedName = function getLinkedName(name) {
|
||||
return name.trim().toLowerCase().replace(/\s/g, '-');
|
||||
}
|
||||
$.ajax({
|
||||
url: '/stories/recentStories',
|
||||
type: 'GET'
|
||||
})
|
||||
.success(
|
||||
function(data) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var div = document.createElement('div');
|
||||
var linkedName = getLinkedName(data[i].storyLink);
|
||||
var rank = data[i].rank;
|
||||
|
||||
$(div)
|
||||
.html(
|
||||
"<div class='col-xs-12 text-left'>" +
|
||||
"<h2 class='col-xs-1 col-sm-1 positive-5'>" +
|
||||
(i + 1) +
|
||||
"</h2>" +
|
||||
"<div class='col-xs-2 col-sm-1'>" +
|
||||
"<a href='/" + data[i].author.username + "'>" +
|
||||
"<img src='" + data[i].author.picture + "' class='img-news'/>" +
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
"<div class='col-xs-9 col-sm-10'>" +
|
||||
"<div class='row'>" +
|
||||
"<div class='story-headline col-xs-12'>" +
|
||||
"<a href='" + data[i].link + "' target='_blank'>" +
|
||||
data[i].headline +
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
"<div class='col-xs-12'>" +
|
||||
"<span>" +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/stories/" + linkedName + "'>discuss</a> · " +
|
||||
rank + (rank > 1 ? " points" : " point") + " · posted " +
|
||||
moment(data[i].timePosted).fromNow() +
|
||||
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + "</a> " +"</a> " +
|
||||
"</span>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>"
|
||||
);
|
||||
$(div).addClass('story-list')
|
||||
$(div).appendTo($('#story-list'));
|
||||
}
|
||||
});
|
@@ -84,7 +84,7 @@ script.
|
||||
"</div>" +
|
||||
"<div class='col-xs-12'>" +
|
||||
"<br>" +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/news/" + linkedName + "'>discuss</a>" +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/news/" + linkedName + "'>more info...</a>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
@@ -103,7 +103,7 @@ script.
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
"<div class='story-byline col-xs-12 wrappable'>" +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/news/" + linkedName + "'>discuss</a> · " +
|
||||
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/news/" + linkedName + "'>more info.more info...</a> · " +
|
||||
rank + (rank > 1 ? " points" : " point") + " · posted " +
|
||||
moment(data[i].timePosted).fromNow() +
|
||||
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username +
|
||||
|
@@ -2,7 +2,6 @@ script.
|
||||
var storyId = !{JSON.stringify(id)};
|
||||
var originalStoryLink = !{JSON.stringify(originalStoryLink)};
|
||||
var originalStoryAuthorEmail = !{JSON.stringify(originalStoryAuthorEmail)};
|
||||
var comments = !{JSON.stringify(comments)};
|
||||
var upVotes = !{JSON.stringify(upVotes)};
|
||||
var image = !{JSON.stringify(image)};
|
||||
var hasUserVoted = !{JSON.stringify(hasUserVoted)};
|
||||
@@ -26,52 +25,19 @@ h3.row
|
||||
.col-xs-12
|
||||
h4= description
|
||||
.negative-5
|
||||
if !user
|
||||
a#upvote.btn.signup-btn.btn-xs(href='/signin') Sign in to reply or upvote
|
||||
if !hasUserVoted
|
||||
a#upvote.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvote
|
||||
|  · 
|
||||
else
|
||||
a#reply-to-main-post.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Reply
|
||||
|  ·  
|
||||
if !hasUserVoted
|
||||
a#upvote.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvote
|
||||
|  · 
|
||||
else
|
||||
a#upvote.btn.disabled.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvoted!
|
||||
|  · 
|
||||
a#upvote.btn.disabled.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvoted!
|
||||
|  · 
|
||||
span#storyRank= rank + (rank > 1 ? " points" : " point")
|
||||
|  · 
|
||||
span Posted #{timeAgo}
|
||||
span  by 
|
||||
a(href="/" + author.username) @#{author.username}
|
||||
|
||||
if (user !== null)
|
||||
.col-xs-12#reply-area
|
||||
.hidden-element#initial-comment-submit
|
||||
form.form-horizontal.control-label-story-submission
|
||||
.col-xs-12
|
||||
.input-group
|
||||
input#comment-box.big-text-field.field-responsive.form-control(type='text', placeholder='Enter your reply', autofocus)
|
||||
span.input-group-btn
|
||||
button#comment-button.btn.btn-big.btn-primary.btn-responsive(type='button') Send
|
||||
span.spacer.pull-left#textarea_feedback
|
||||
|
||||
script.
|
||||
if (image) {
|
||||
$('#image-display').removeClass('hidden-element')
|
||||
}
|
||||
$('#reply-to-main-post').on('click', function() {
|
||||
$('#initial-comment-submit').removeClass('hidden-element');
|
||||
$(this).unbind('click');
|
||||
$('.comment-to-comment-formgroup').empty();
|
||||
});
|
||||
var text_max = 140;
|
||||
$('#textarea_feedback').html(text_max + ' characters remaining');
|
||||
$('#comment-box').keyup(function (e) {
|
||||
if (e.which === 13 || e === 13) {
|
||||
$('#comment-button').click();
|
||||
}
|
||||
var text_length = $('#comment-box').val().length;
|
||||
var text_remaining = text_max - text_length;
|
||||
$('#textarea_feedback').html(text_remaining + ' characters remaining');
|
||||
});
|
||||
include comments
|
||||
|
@@ -22,11 +22,6 @@
|
||||
alert(type='danger')
|
||||
span.ion-close-circled
|
||||
| A headline is required to submit.
|
||||
.form-group
|
||||
.col-xs-12.col-md-1
|
||||
label.control-label.control-label-story-submission(for='name') Comment
|
||||
.col-xs-12.col-md-11
|
||||
input#description-box.form-control(name="comment-box", placeholder="Kick off the discussion with an optional comment about this link" maxlength='140')
|
||||
.form-group
|
||||
.col-xs-12.col-md-offset-1
|
||||
span.pull-left#textarea_feedback
|
||||
|
Reference in New Issue
Block a user