diff --git a/.env.SAMPLE b/.env.SAMPLE index 8ff6652..01d4fe5 100644 --- a/.env.SAMPLE +++ b/.env.SAMPLE @@ -19,3 +19,15 @@ STAGE=prod # A Slack webhook to send notifications to (optional) #SLACK=https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ +# Require author email address - string is error message to display. +#REQEMAIL='Email is required.' + +# Require author name - string is error message to display. +#REQNAME='Name is required.' + +# Size limit of post in bytes +#SIZELIMIT=4096 + +# Disallow empty content (spaces only, etc.) - string is error message to display. +#DISALLOW_EMPTY='You need to actually use words.' + diff --git a/README.md b/README.md index 1e14d66..5ca3ff0 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,12 @@ STAGE=prod # A Slack webhook to send notifications to (optional) #SLACK=https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ -``` + +# Require author email address - string is error message to display. +#REQEMAIL='Email is required.' + +# Require author name - string is error message to display. +#REQNAME='Name is required.' We use [dotenv](https://github.com/motdotla/dotenv) so it is also possible to configure the project by setting environment variables. diff --git a/deploy/apex/webpack.config.es6.js b/deploy/apex/webpack.config.es6.js index eeebdcb..e15c49a 100644 --- a/deploy/apex/webpack.config.es6.js +++ b/deploy/apex/webpack.config.es6.js @@ -37,6 +37,22 @@ if (process.env.SLACK) { defines['process.env.SLACK'] = `'${process.env.SLACK}'` } +if (process.env.REQEMAIL) { + defines['process.env.REQEMAIL'] = `'${process.env.REQEMAIL}'` +} + +if (process.env.REQNAME) { + defines['process.env.REQNAME'] = `'${process.env.REQNAME}'` +} + +if (process.env.SIZELIMIT) { + defines['process.env.SIZELIMIT'] = `'${process.env.SIZELIMIT}'` +} + +if (process.env.DISALLOW_EMPTY) { + defines['process.env.DISALLOW_EMPTY'] = `'${process.env.DISALLOW_EMPTY}'` +} + export default { entry: { [lambdaDirNames['QueueComment']]: [ diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 9ae8f78..3c19525 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -78,6 +78,7 @@ "react-measure": "0.3.5", "react-motion": "0.4.2", "react-project": "0.0.30", + "react-redux": "4.4.5", "react-router": "2.0.0", "react-router-redux": "4.0.2", "react-spinner": "0.2.6", diff --git a/packages/frontend/src/actions/comments.js b/packages/frontend/src/actions/comments.js index 823cbc3..94822ac 100644 --- a/packages/frontend/src/actions/comments.js +++ b/packages/frontend/src/actions/comments.js @@ -25,6 +25,10 @@ export const FORM_FIELDS = [ const websiteUrl = __CONFIG__.websiteUrl const apiUrl = __CONFIG__.apiUrl const apiKey = __CONFIG__.apiKey +const authorNameRequired = __CONFIG__.authorNameRequired +const authorEmailRequired = __CONFIG__.authorEmailRequired +const contentSizeLimit = __CONFIG__.contentSizeLimit +const disallowEmptyContent = __CONFIG__.disallowEmptyContent class ValidationError extends Error { constructor (data) { diff --git a/packages/frontend/src/ui/comments.css b/packages/frontend/src/ui/comments.css index 26f9e24..5663dbb 100644 --- a/packages/frontend/src/ui/comments.css +++ b/packages/frontend/src/ui/comments.css @@ -97,6 +97,13 @@ } } +.commentCounter { + font-size: 13px; + color: gray; + text-decoration: none; + padding-left: 10px; +} + .previewWrapper { overflow-y: hidden; } diff --git a/packages/frontend/src/ui/postCommentForm.js b/packages/frontend/src/ui/postCommentForm.js index d6b636b..3e838c9 100644 --- a/packages/frontend/src/ui/postCommentForm.js +++ b/packages/frontend/src/ui/postCommentForm.js @@ -16,6 +16,7 @@ import { errorMessage, postCommentFormHeader, markdownNote, + commentCounter, previewWrapper, preview, spinnerButton, @@ -27,15 +28,34 @@ import { } from './comments.css' import { FORM_NAME, FORM_FIELDS } from '../actions/comments' +const authorNameRequired = __CONFIG__.authorNameRequired +const authorEmailRequired = __CONFIG__.authorEmailRequired +const contentSizeLimit = __CONFIG__.contentSizeLimit +const disallowEmptyContent = __CONFIG__.disallowEmptyContent + +let contentRegex = /\w+/ + function validate (values) { const errors = {} - const { commentContent, authorEmail, authorUrl } = values + const { commentContent, authorName, authorEmail, authorUrl } = values if (!commentContent) { errors.commentContent = 'Required' } if (commentContent && commentContent.length < 3) { errors.commentContent = 'Must be at least 3 characters' } + if (commentContent && contentSizeLimit && (commentContent.length > parseInt(contentSizeLimit))) { + errors.commentContent = 'Comment has exceeded content length of: ' + parseInt(contentSizeLimit) + ' characters.' + } + if (commentContent && disallowEmptyContent && !commentContent.match(contentRegex)) { + errors.commentContent = disallowEmptyContent + } + if (authorNameRequired && !authorName) { + errors.authorName = authorNameRequired + } + if (authorEmailRequired && !authorEmail) { + errors.authorEmail = authorEmailRequired + } if (authorEmail && !isEmail(authorEmail)) { errors.authorEmail = 'Email format not valid' } @@ -138,6 +158,7 @@ export default class PostCommentForm extends Component { date: new Date(), commentContent: commentContent.value, } + const length = commentContent.value ? commentContent.value.length : 0 return (