diff --git a/client/coral-admin/src/containers/Configure/TechSettings.js b/client/coral-admin/src/containers/Configure/TechSettings.js
index c50a7d507..6fbc302a0 100644
--- a/client/coral-admin/src/containers/Configure/TechSettings.js
+++ b/client/coral-admin/src/containers/Configure/TechSettings.js
@@ -14,19 +14,20 @@ const updateCustomCssUrl = (updateSettings) => (event) => {
const TechSettings = ({settings, onChangeDomainlist, updateSettings}) => {
return (
-
+
- {lang.t('configure.custom-css-url')}
- {lang.t('configure.custom-css-url-desc')}
-
-
+
+
{lang.t('configure.custom-css-url')}
+
{lang.t('configure.custom-css-url-desc')}
+
+
);
diff --git a/client/coral-admin/src/containers/Configure/Wordlist.js b/client/coral-admin/src/containers/Configure/Wordlist.js
index aa79cb8ae..8eb010b79 100644
--- a/client/coral-admin/src/containers/Configure/Wordlist.js
+++ b/client/coral-admin/src/containers/Configure/Wordlist.js
@@ -8,25 +8,29 @@ import {Card} from 'coral-ui';
const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => (
- {lang.t('configure.banned-words-title')}
+ {lang.t('configure.banned-words-title')}
{lang.t('configure.banned-word-text')}
- data.split(',').map(d => d.trim())}
- onChange={tags => onChangeWordlist('banned', tags)}
- />
+
+ data.split(',').map(d => d.trim())}
+ onChange={tags => onChangeWordlist('banned', tags)}
+ />
+
- {lang.t('configure.suspect-words-title')}
+ {lang.t('configure.suspect-words-title')}
{lang.t('configure.suspect-word-text')}
- data.split(',').map(d => d.trim())}
- onChange={tags => onChangeWordlist('suspect', tags)} />
+
+ data.split(',').map(d => d.trim())}
+ onChange={tags => onChangeWordlist('suspect', tags)} />
+
);
diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json
index cebc499ca..ac9131685 100644
--- a/client/coral-admin/src/translations.json
+++ b/client/coral-admin/src/translations.json
@@ -53,6 +53,7 @@
"copy": "Copy to Clipboard"
},
"configure": {
+ "closed-stream-settings": "Closed Stream Message",
"stream-settings": "Stream Settings",
"moderation-settings": "Moderation Settings",
"tech-settings": "Tech Settings",
@@ -63,9 +64,11 @@
"enable-pre-moderation-text": "Moderators must approve any comment before it is published.",
"require-email-verification": "Require Email Verification",
"require-email-verification-text": "New Users must verify their email before commenting",
- "include-comment-stream": "Include Comment Stream Description for Readers.",
+ "include-comment-stream": "Include Comment Stream Description for Readers",
"include-comment-stream-desc": "Write a message to be added to the top of your comment stream. Pose a topic, include community guidelines, etc.",
"include-text": "Include your text here.",
+ "enable-premod-links": "Pre-Moderate Comments Containing Links",
+ "enable-premod-links-text": "Moderators must approve any comment containing a link before its published.",
"comment-settings": "Settings",
"embed-comment-stream": "Embed Stream",
"banned-word-text": "Comments which contain these words or phrases (not case-sensitive) will be automatically removed from the comment stream. Type a word and press Enter or Tab to add. Optionally paste a comma-separated list.",
@@ -79,7 +82,7 @@
"configure": "Configure",
"community": "Community",
"streams": "Streams",
- "closed-comments-desc": "Write a message for closed threads",
+ "closed-comments-desc": "Write a message to be displayed when when your comment stream is closed and no longer accepting comments.",
"closed-comments-label": "Write a message...",
"hours": "Hours",
"days": "Days",
@@ -87,7 +90,7 @@
"close-after": "Close comments after",
"comment-count-header": "Limit Comment Length",
"comment-count-text-pre": "Comments will be limited to ",
- "comment-count-text-post": " characters.",
+ "comment-count-text-post": " characters",
"comment-count-error": "Please enter a valid number.",
"domain-list-title": "Permitted Domains",
"domain-list-text": "Enter the domains you would like to permit for Talk, e.g. your local, staging and production environments (ex. localhost:3000, staging.domain.com, domain.com)."
@@ -178,6 +181,7 @@
"username_flags": ""
},
"configure": {
+ "closed-stream-settings": "Mensaje cuando los comentarios están cerrados en el artículo",
"stream-settings": "Configuración de Comentarios",
"moderation-settings": "Configuración de Moderación",
"tech-settings": "Configuración Technical",
@@ -193,6 +197,8 @@
"include-text": "Incluir tu texto aqui.",
"comment-settings": "Configuración de Comentarios",
"embed-comment-stream": "Colocar Hilo de Comentarios",
+ "enable-premod-links": "Pre-Moderar Commentarios que contienen Links",
+ "enable-premod-links-text": "Los y las Moderadoras deben probar cualquier comentario que contengan links antes de su publicación.",
"wordlist": "Palabras Suspendidas y Suspechosas",
"banned-word-text": "Comentarios que contengan estas palabras o frases, no separadas por comas y en mayusculas o minusuculas, serán automaticamente separadas de los comentarios publicados.",
"suspect-word-text": "Comments which contain these words or phrases (not case-sensitive) will be highlighted in the comment stream. Type a word and press Enter or Tab to add. Optionally paste a comma-separated list.",
@@ -204,7 +210,7 @@
"configure": "Configurar",
"community": "Comunidad",
"streams": "Streams",
- "closed-comments-desc": "Escribe un mensaje para cuando los comentarios se encuentran cerrados",
+ "closed-comments-desc": "Escribe un mensaje que será mostrado cuando los comentarios estén cerrados y no se acepten más comentarios.",
"closed-comments-label": "Escribe un mensaje...",
"never": "Nunca",
"hours": "Horas",
diff --git a/client/coral-configure/components/ConfigureCommentStream.js b/client/coral-configure/components/ConfigureCommentStream.js
index d80e487de..348d26f53 100644
--- a/client/coral-configure/components/ConfigureCommentStream.js
+++ b/client/coral-configure/components/ConfigureCommentStream.js
@@ -34,6 +34,18 @@ export default ({handleChange, handleApply, changed, updateQuestionBoxContent, .
description: lang.t('configureCommentStream.enablePremodDescription')
}} />
+
+
+
@@ -88,11 +88,11 @@ class ConfigureStreamContainer extends Component {
handleChange={this.handleChange}
handleApply={this.handleApply}
changed={this.state.changed}
- premodLinks={false}
+ premodLinks={settings.premodLinks}
premod={premod}
updateQuestionBoxContent={this.updateQuestionBoxContent}
- questionBoxEnable={questionBoxEnable}
- questionBoxContent={questionBoxContent}
+ questionBoxEnable={settings.questionBoxEnable}
+ questionBoxContent={settings.questionBoxContent}
/>
{status === 'open' ? 'Close' : 'Open'} Comment Stream
diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css
index f888b8fa6..009246963 100644
--- a/client/coral-embed-stream/style/default.css
+++ b/client/coral-embed-stream/style/default.css
@@ -80,6 +80,7 @@ hr {
padding: 10px;
margin-bottom: 10px;
display: block;
+ box-sizing: border-box;
}
/* Question Box Styles */
@@ -220,7 +221,7 @@ hr {
.comment__action-container .material-icons {
font-size: 12px;
- margin-left: 3px;
+ margin-left: 3px;
}
button.comment__action-button,
diff --git a/client/coral-framework/graphql/mutations/index.js b/client/coral-framework/graphql/mutations/index.js
index a874f8f0c..7dd8bf12b 100644
--- a/client/coral-framework/graphql/mutations/index.js
+++ b/client/coral-framework/graphql/mutations/index.js
@@ -42,7 +42,7 @@ export const postComment = graphql(POST_COMMENT, {
updateQueries: {
AssetQuery: (oldData, {mutationResult:{data:{createComment:{comment}}}}) => {
- if (oldData.asset.settings.moderation === 'PRE') {
+ if (oldData.asset.settings.moderation === 'PRE' || comment.status === 'PREMOD' || comment.status === 'REJECTED') {
return oldData;
}
diff --git a/client/coral-ui/components/TextArea.css b/client/coral-ui/components/TextArea.css
new file mode 100644
index 000000000..794064cf1
--- /dev/null
+++ b/client/coral-ui/components/TextArea.css
@@ -0,0 +1,15 @@
+.textArea {
+ textarea {
+ width: 100%;
+ display: block;
+ outline: none;
+ border: 1px solid rgba(0,0,0,.12);
+ padding: 6px;
+ box-sizing: border-box;
+ border-radius: 2px;
+ margin: 5px auto;
+ min-height: 175px;
+ font-size: 14px;
+ resize: none;
+ }
+}
diff --git a/client/coral-ui/components/TextArea.js b/client/coral-ui/components/TextArea.js
new file mode 100644
index 000000000..fedc7914b
--- /dev/null
+++ b/client/coral-ui/components/TextArea.js
@@ -0,0 +1,14 @@
+import React, {PropTypes} from 'react';
+import styles from './TextArea.css';
+
+const TextArea = ({className, value = '', ...props}) => (
+
+
+
+);
+
+TextArea.propTypes = {
+ onChange: PropTypes.func,
+};
+
+export default TextArea;
diff --git a/client/coral-ui/index.js b/client/coral-ui/index.js
index b3498c3e0..148da0383 100644
--- a/client/coral-ui/index.js
+++ b/client/coral-ui/index.js
@@ -22,3 +22,4 @@ export {default as WizardNav} from './components/WizardNav';
export {default as Select} from './components/Select';
export {default as Option} from './components/Option';
export {default as SnackBar} from './components/SnackBar';
+export {default as TextArea} from './components/TextArea';
diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js
index 553c3f44c..bcab347d7 100644
--- a/graph/mutators/comment.js
+++ b/graph/mutators/comment.js
@@ -3,6 +3,7 @@ const errors = require('../../errors');
const AssetsService = require('../../services/assets');
const ActionsService = require('../../services/actions');
const CommentsService = require('../../services/comments');
+const linkify = require('linkify-it')();
const Wordlist = require('../../services/wordlist');
@@ -54,13 +55,16 @@ const createComment = ({user, loaders: {Comments}}, {body, asset_id, parent_id =
* @param {String} body body of a comment
* @return {Object} resolves to the wordlist results
*/
-const filterNewComment = (context, {body}) => {
+const filterNewComment = (context, {body, asset_id}) => {
// Create a new instance of the Wordlist.
const wl = new Wordlist();
// Load the wordlist and filter the comment content.
- return wl.load().then(() => wl.scan('body', body));
+ return Promise.all([
+ wl.load().then(() => wl.scan('body', body)),
+ AssetsService.rectifySettings(AssetsService.findById(asset_id))
+ ]);
};
/**
@@ -72,7 +76,7 @@ const filterNewComment = (context, {body}) => {
* @param {Object} [wordlist={}] the results of the wordlist scan
* @return {Promise} resolves to the comment's status
*/
-const resolveNewCommentStatus = (context, {asset_id, body}, wordlist = {}) => {
+const resolveNewCommentStatus = (context, {asset_id, body}, wordlist = {}, settings) => {
// Decide the status based on whether or not the current asset/settings
// has pre-mod enabled or not. If the comment was rejected based on the
@@ -82,6 +86,8 @@ const resolveNewCommentStatus = (context, {asset_id, body}, wordlist = {}) => {
if (wordlist.banned) {
status = Promise.resolve('REJECTED');
+ } else if (settings.premodLinksEnable && linkify.test(body)) {
+ status = Promise.resolve('PREMOD');
} else {
status = AssetsService
.rectifySettings(AssetsService.findById(asset_id).then((asset) => {
@@ -131,13 +137,13 @@ const createPublicComment = (context, commentInput) => {
// We then take the wordlist and the comment into consideration when
// considering what status to assign the new comment, and resolve the new
// status to set the comment to.
- .then((wordlist) => resolveNewCommentStatus(context, commentInput, wordlist)
+ .then(([wordlist, settings]) => resolveNewCommentStatus(context, commentInput, wordlist, settings)
// Then we actually create the comment with the new status.
.then((status) => createComment(context, commentInput, status))
.then((comment) => {
- // If the comment was flagged as being suspect, we need to add a
+ // If the comment has a suspect word or a link, we need to add a
// flag to it to indicate that it needs to be looked at.
// Otherwise just return the new comment.
diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql
index daf9edafa..6cb4cb046 100644
--- a/graph/typeDefs.graphql
+++ b/graph/typeDefs.graphql
@@ -370,6 +370,7 @@ type Settings {
infoBoxEnable: Boolean
infoBoxContent: String
+ premodLinksEnable: Boolean
questionBoxEnable: Boolean
questionBoxContent: String
closeTimeout: Int
diff --git a/models/setting.js b/models/setting.js
index 993384ff1..ac54584a4 100644
--- a/models/setting.js
+++ b/models/setting.js
@@ -40,6 +40,10 @@ const SettingSchema = new Schema({
type: String,
default: ''
},
+ premodLinksEnable: {
+ type: Boolean,
+ default: false
+ },
organizationName: {
type: String
},
diff --git a/package.json b/package.json
index f67a36908..92442efd2 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,7 @@
"inquirer": "^3.0.1",
"jsonwebtoken": "^7.1.9",
"kue": "^0.11.5",
+ "linkify-it": "^2.0.3",
"lodash": "^4.16.6",
"metascraper": "^1.0.6",
"minimist": "^1.2.0",
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100755
index 000000000..be75408cd
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/img/android-icon-144x144.png b/public/img/android-icon-144x144.png
new file mode 100755
index 000000000..c18ebc610
Binary files /dev/null and b/public/img/android-icon-144x144.png differ
diff --git a/public/img/android-icon-192x192.png b/public/img/android-icon-192x192.png
new file mode 100755
index 000000000..613792d40
Binary files /dev/null and b/public/img/android-icon-192x192.png differ
diff --git a/public/img/android-icon-36x36.png b/public/img/android-icon-36x36.png
new file mode 100755
index 000000000..b08960fea
Binary files /dev/null and b/public/img/android-icon-36x36.png differ
diff --git a/public/img/android-icon-48x48.png b/public/img/android-icon-48x48.png
new file mode 100755
index 000000000..3dcfcaeaf
Binary files /dev/null and b/public/img/android-icon-48x48.png differ
diff --git a/public/img/android-icon-72x72.png b/public/img/android-icon-72x72.png
new file mode 100755
index 000000000..9e3c0b654
Binary files /dev/null and b/public/img/android-icon-72x72.png differ
diff --git a/public/img/android-icon-96x96.png b/public/img/android-icon-96x96.png
new file mode 100755
index 000000000..1d7bcc163
Binary files /dev/null and b/public/img/android-icon-96x96.png differ
diff --git a/public/img/apple-icon-114x114.png b/public/img/apple-icon-114x114.png
new file mode 100755
index 000000000..1575be1ce
Binary files /dev/null and b/public/img/apple-icon-114x114.png differ
diff --git a/public/img/apple-icon-120x120.png b/public/img/apple-icon-120x120.png
new file mode 100755
index 000000000..e16fa5495
Binary files /dev/null and b/public/img/apple-icon-120x120.png differ
diff --git a/public/img/apple-icon-144x144.png b/public/img/apple-icon-144x144.png
new file mode 100755
index 000000000..c18ebc610
Binary files /dev/null and b/public/img/apple-icon-144x144.png differ
diff --git a/public/img/apple-icon-152x152.png b/public/img/apple-icon-152x152.png
new file mode 100755
index 000000000..1855b9f44
Binary files /dev/null and b/public/img/apple-icon-152x152.png differ
diff --git a/public/img/apple-icon-180x180.png b/public/img/apple-icon-180x180.png
new file mode 100755
index 000000000..677a61bba
Binary files /dev/null and b/public/img/apple-icon-180x180.png differ
diff --git a/public/img/apple-icon-57x57.png b/public/img/apple-icon-57x57.png
new file mode 100755
index 000000000..f777aa003
Binary files /dev/null and b/public/img/apple-icon-57x57.png differ
diff --git a/public/img/apple-icon-60x60.png b/public/img/apple-icon-60x60.png
new file mode 100755
index 000000000..df7ee450a
Binary files /dev/null and b/public/img/apple-icon-60x60.png differ
diff --git a/public/img/apple-icon-72x72.png b/public/img/apple-icon-72x72.png
new file mode 100755
index 000000000..9e3c0b654
Binary files /dev/null and b/public/img/apple-icon-72x72.png differ
diff --git a/public/img/apple-icon-76x76.png b/public/img/apple-icon-76x76.png
new file mode 100755
index 000000000..3cef6c189
Binary files /dev/null and b/public/img/apple-icon-76x76.png differ
diff --git a/public/img/apple-icon-precomposed.png b/public/img/apple-icon-precomposed.png
new file mode 100755
index 000000000..805d88945
Binary files /dev/null and b/public/img/apple-icon-precomposed.png differ
diff --git a/public/img/apple-icon.png b/public/img/apple-icon.png
new file mode 100755
index 000000000..805d88945
Binary files /dev/null and b/public/img/apple-icon.png differ
diff --git a/public/img/coralWordMark-color.png b/public/img/coralWordMark-color.png
new file mode 100755
index 000000000..9c9044148
Binary files /dev/null and b/public/img/coralWordMark-color.png differ
diff --git a/public/img/favicon-16x16.png b/public/img/favicon-16x16.png
new file mode 100755
index 000000000..20b075359
Binary files /dev/null and b/public/img/favicon-16x16.png differ
diff --git a/public/img/favicon-32x32.png b/public/img/favicon-32x32.png
new file mode 100755
index 000000000..ee1d75621
Binary files /dev/null and b/public/img/favicon-32x32.png differ
diff --git a/public/img/favicon-96x96.png b/public/img/favicon-96x96.png
new file mode 100755
index 000000000..1d7bcc163
Binary files /dev/null and b/public/img/favicon-96x96.png differ
diff --git a/public/img/logo_white.png b/public/img/logo_white.png
new file mode 100755
index 000000000..02b3f53f3
Binary files /dev/null and b/public/img/logo_white.png differ
diff --git a/public/img/logomark_512x512.svg b/public/img/logomark_512x512.svg
new file mode 100755
index 000000000..3c6a62250
--- /dev/null
+++ b/public/img/logomark_512x512.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/img/ms-icon-144x144.png b/public/img/ms-icon-144x144.png
new file mode 100755
index 000000000..c18ebc610
Binary files /dev/null and b/public/img/ms-icon-144x144.png differ
diff --git a/public/img/ms-icon-150x150.png b/public/img/ms-icon-150x150.png
new file mode 100755
index 000000000..f522f9aa7
Binary files /dev/null and b/public/img/ms-icon-150x150.png differ
diff --git a/public/img/ms-icon-310x310.png b/public/img/ms-icon-310x310.png
new file mode 100755
index 000000000..166949a37
Binary files /dev/null and b/public/img/ms-icon-310x310.png differ
diff --git a/public/img/ms-icon-70x70.png b/public/img/ms-icon-70x70.png
new file mode 100755
index 000000000..83b246409
Binary files /dev/null and b/public/img/ms-icon-70x70.png differ
diff --git a/public/img/user_portrait_placeholder.png b/public/img/user_portrait_placeholder.png
new file mode 100755
index 000000000..562891c12
Binary files /dev/null and b/public/img/user_portrait_placeholder.png differ
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100755
index 000000000..97d1632d6
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,41 @@
+{
+ "name": "App",
+ "icons": [
+ {
+ "src": "\/img\/android-icon-36x36.png",
+ "sizes": "36x36",
+ "type": "image\/png",
+ "density": "0.75"
+ },
+ {
+ "src": "\/img\/android-icon-48x48.png",
+ "sizes": "48x48",
+ "type": "image\/png",
+ "density": "1.0"
+ },
+ {
+ "src": "\/img\/android-icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+ {
+ "src": "\/img\/android-icon-96x96.png",
+ "sizes": "96x96",
+ "type": "image\/png",
+ "density": "2.0"
+ },
+ {
+ "src": "\/img\/android-icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image\/png",
+ "density": "3.0"
+ },
+ {
+ "src": "\/img\/android-icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image\/png",
+ "density": "4.0"
+ }
+ ]
+}
diff --git a/views/admin.ejs b/views/admin.ejs
index 32d38734a..dafd5e3cc 100644
--- a/views/admin.ejs
+++ b/views/admin.ejs
@@ -5,6 +5,20 @@
Talk - Coral Admin
+
+
+
+
+
+
+
+
+
+
+
+
+
+