diff --git a/.eslintrc.json b/.eslintrc.json
index 5df3444a6..23bdea410 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -55,6 +55,7 @@
"no-var": [2],
"no-lonely-if": [2],
"curly": [2],
+ "no-unused-vars": ["error", { "argsIgnorePattern": "next" }],
"no-multiple-empty-lines": [
"error",
{"max": 1}
diff --git a/Dockerfile b/Dockerfile
index 985e55159..3be5916a8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,15 +11,9 @@ EXPOSE 5000
# Install app dependencies
COPY package.json /usr/src/app/
-RUN npm install
+RUN npm install --production
# Bundle app source
COPY . /usr/src/app
-# Compile static assets
-RUN npm run build
-
-# Prune development dependancies
-RUN npm prune --production
-
CMD [ "npm", "start" ]
diff --git a/README.md b/README.md
index d295ef326..f4d8b31de 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,12 @@
# Talk [](https://circleci.com/gh/coralproject/talk)
A commenting platform from The Coral Project. [https://coralproject.net](https://coralproject.net)
+## Contributing to Talk
+
+### Local Dependencies
+Node
+Mongo
+
### Getting Started
`npm install`
Run it once to install the dependencies.
@@ -8,16 +14,22 @@ Run it once to install the dependencies.
`npm start`
Runs Talk.
+### Running with Docker
+Make sure you have Docker running first and then run `docker-compose up -d`
+
### Testing
`npm test`
### Lint
`npm run lint`
+### Helpful URLs
+Bare comment stream: http://localhost:5000/client/coral-embed-stream/
+Comment stream embedded on sample article: http://localhost:5000/client/coral-embed-stream/samplearticle.html
+Moderator view: http://localhost:5000/admin/
+
### Docs
`swagger.yaml`
-### Mantainers
-
### License
**Apache-2.0**
diff --git a/TERMINOLOGY.md b/TERMINOLOGY.md
new file mode 100644
index 000000000..5c1e9aaa8
--- /dev/null
+++ b/TERMINOLOGY.md
@@ -0,0 +1,66 @@
+# Product's Terminology
+
+This is a guide to have a common language to talk about "Talk".
+
+## Definitions
+
+* Site - a top level site, aka nytimes.com
+* Section - the section of a site, aka, Politics.
+* Subsection - the section of a site, aka, Politics.
+* Asset - An article/video/etc identified by URL.
+
+* Embed - Things we put on a asset: comment box, ToS, Stream, etc…
+* Stream - All the activity on a certain asset. Container for Comments, actions, user
+* Thread - defined by a parent and everything below. All replies to a comment and their replies, etc…
+* Comment - a kind of user-generated content submitted by a comment author
+ * A parent comment has replies to it
+ * A child comments is a reply to another comment
+ * A comment can be both a parent comment and a child of another comment
+ * A top-level comment is a comment that is not a reply to any other comment
+ * A nth-level comment refers to the number of replies away from the top-level comment
+
+* User - an item to represent a person using Talk. It could be a moderator, reader, etc.
+* User Roles:
+ * Active: some who takes action (logged in or not)
+ * Passive: some who just reads, no actions performed
+ * Comment Author: The user who wrote the comment
+ * Staff Member: someone who works for an organization (tagged for leverage in trust)
+ * Moderator: someone with the ability to access the moderation queue and perform moderation actions
+ * Administrator: has the ability to change the setup of their coral space
+* Public Profile: information about users shown in public
+* Private Profile: information about users shown only to user about themselves
+* Protected Profile: information about users that only moderators and admins can see
+
+* Queue - Group of items based on a query, aka - moderation queue
+* Target - The item/s on which an action is performed..
+
+## Actions
+
+Actions are performed by users on items. Actions themselves are items. This requires two relationships: action on item, and user performs action.
+
+### Flag
+* A Flagger(user) performs a Flag
+* A Flag is performed on a Comment or a username or profile content
+
+
+## Moderation Actions and Status
+
+Comments contain a field `status`. As moderation actions are peformed, the status changes.
+
+* Initial status is empty.
+* When a moderator Approves, the status is set to 'approved'.
+* When a moderator Rejects, the status is set to 'reject'.
+
+### Pre and post moderation
+
+Comments can be set to be premoderated or postmoderated.
+
+Premoderation means that moderation has to occur _before_ a comment is shown on the site:
+
+* New comments are shown in the moderator queues immediately.
+* The are not shown to users until (aka in streams) until they are approved by a moderator.
+
+Postmoderation means that comments appear on the site _before_ any moderation action is taken.
+
+* New comments appear in comment streams immediately.
+* New comments do not appear in moderation queues unless they are flagged by other users.
diff --git a/app.js b/app.js
index 838819e35..29817c970 100644
--- a/app.js
+++ b/app.js
@@ -8,11 +8,60 @@ const app = express();
// Middleware declarations.
app.use(morgan('dev'));
app.use(bodyParser.json());
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'ejs');
-// API Routes.
+// Routes.
app.use('/api/v1', require('./routes/api'));
+app.use('/client', express.static(path.join(__dirname, 'dist')));
+app.use('/admin', require('./routes/admin'));
-// Static Routes.
-app.use('/client/', express.static(path.join(__dirname, 'dist')));
+//==============================================================================
+// ERROR HANDLING
+//==============================================================================
+
+const ErrNotFound = new Error('Not Found');
+ErrNotFound.status = 404;
+
+// Catch 404 and forward to error handler.
+app.use((req, res, next) => {
+ next(ErrNotFound);
+});
+
+// General error handler. Respond with the message and error if we have it while
+// returning a status code that makes sense.
+if (app.get('env') === 'development') {
+ app.use('/api', (err, req, res, next) => {
+ res.status(err.status || 500);
+ res.json({
+ message: err.message,
+ error: err
+ });
+ });
+
+ app.use('/', (err, req, res, next) => {
+ res.status(err.status || 500);
+ res.render('error', {
+ message: err.message,
+ error: err
+ });
+ });
+}
+
+app.use('/api', (err, req, res, next) => {
+ res.status(err.status || 500);
+ res.json({
+ message: err.message,
+ error: {}
+ });
+});
+
+app.use('/', (err, req, res, next) => {
+ res.status(err.status || 500);
+ res.render('error', {
+ message: err.message,
+ error: {}
+ });
+});
module.exports = app;
diff --git a/circle.yml b/circle.yml
index 9de9eae4c..b9cea6fed 100644
--- a/circle.yml
+++ b/circle.yml
@@ -8,6 +8,7 @@ test:
override:
- MOCHA_FILE=$CIRCLE_TEST_REPORTS/junit/test-results.xml ./node_modules/.bin/mocha tests --reporter mocha-junit-reporter
- npm run lint
+ - npm run build
deployment:
release:
diff --git a/client/coral-admin/.gitignore b/client/coral-admin/.gitignore
deleted file mode 100644
index c9c7cb580..000000000
--- a/client/coral-admin/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules
-public/bundle.js
-public/embed/comment-stream
-.DS_Store
-npm-debug.log
-config.json
-yarn.lock
diff --git a/client/coral-admin/config.json b/client/coral-admin/config.json
new file mode 100644
index 000000000..156740de5
--- /dev/null
+++ b/client/coral-admin/config.json
@@ -0,0 +1,3 @@
+{
+ "basePath": "admin"
+}
diff --git a/client/coral-admin/config.sample.json b/client/coral-admin/config.sample.json
deleted file mode 100644
index 55d39db05..000000000
--- a/client/coral-admin/config.sample.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "basePath": "client/coral-admin"
-}
diff --git a/client/coral-admin/package.json b/client/coral-admin/package.json
deleted file mode 100644
index 048359526..000000000
--- a/client/coral-admin/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "name": "coral-admin",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "build": "./node_modules/.bin/webpack --config webpack.config.js",
- "start": "./node_modules/.bin/webpack-dev-server --config webpack.config.dev.js --inline --hot --content-base public --port 3142"
- },
- "keywords": [],
- "author": "",
- "license": "ISC",
- "dependencies": {
- "hammerjs": "2.0.8",
- "immutable": "3.8.1",
- "keymaster": "1.6.2",
- "material-design-lite": "1.2.1",
- "react": "^15.3.2",
- "react-dom": "^15.3.2",
- "react-mdl": "^1.7.2",
- "react-redux": "^4.4.5",
- "react-router": "^3.0.0",
- "redux": "3.6.0",
- "redux-thunk": "2.1.0",
- "timeago.js": "2.0.2"
- },
- "devDependencies": {
- "autoprefixer": "6.5.0",
- "babel-core": "^6.18.2",
- "babel-loader": "^6.2.7",
- "copy-webpack-plugin": "3.0.1",
- "css-loader": "0.25.0",
- "json-loader": "0.5.4",
- "postcss-loader": "0.13.0",
- "postcss-modules": "0.5.2",
- "precss": "1.4.0",
- "standard": "8.2.0",
- "style-loader": "0.13.1",
- "webpack": "^1.13.3",
- "webpack-dev-server": "1.16.1"
- }
-}
diff --git a/client/coral-admin/src/AppRouter.js b/client/coral-admin/src/AppRouter.js
new file mode 100644
index 000000000..40465bd19
--- /dev/null
+++ b/client/coral-admin/src/AppRouter.js
@@ -0,0 +1,23 @@
+import React from 'react'
+import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'
+
+import ModerationQueue from 'containers/ModerationQueue'
+import CommentStream from 'containers/CommentStream'
+import EmbedLink from 'components/EmbedLink'
+import Configure from 'containers/Configure'
+import CommunityContainer from 'containers/CommunityContainer'
+import LayoutContainer from 'containers/LayoutContainer'
+
+const routes = (
+
+
+
+
+
+
+
+)
+
+const AppRouter = () =>
+
+export default AppRouter
diff --git a/client/coral-admin/src/components/App.js b/client/coral-admin/src/components/App.js
index 4b7c01e84..1fbbe1448 100644
--- a/client/coral-admin/src/components/App.js
+++ b/client/coral-admin/src/components/App.js
@@ -1,25 +1,16 @@
-
import React from 'react'
import { Provider } from 'react-redux'
import 'material-design-lite'
-import { Router, Route, browserHistory } from 'react-router'
-import ModerationQueue from 'containers/ModerationQueue'
+import { Layout } from 'react-mdl'
import store from 'services/store'
-import CommentStream from 'containers/CommentStream'
-import EmbedLink from 'components/EmbedLink'
-import Configure from 'containers/Configure'
-import config from 'services/config'
+
+import AppRouter from '../AppRouter'
export default class App extends React.Component {
render (props) {
return (
-
-
-
-
-
-
+
)
}
diff --git a/client/coral-admin/src/components/Header.js b/client/coral-admin/src/components/Header.js
deleted file mode 100644
index 0e52686d8..000000000
--- a/client/coral-admin/src/components/Header.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react'
-import { Layout, Navigation, Drawer, Header } from 'react-mdl'
-import { Link } from 'react-router'
-import styles from './Header.css'
-import config from 'services/config'
-
-// App header. If we add a navbar it should be here
-export default (props) => (
-
-
-
- Moderate
- Configure
-
-
-
-
- Moderate
- Configure
-
-
- {props.children}
-
-)
diff --git a/client/coral-admin/src/components/Page.js b/client/coral-admin/src/components/Page.js
deleted file mode 100644
index 733cec677..000000000
--- a/client/coral-admin/src/components/Page.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react'
-import {Layout} from 'react-mdl'
-import 'material-design-lite'
-import Header from 'components/Header'
-
-export default (props) => (
-
-
- {props.children}
-
-
-)
diff --git a/client/coral-admin/src/components/ui/Drawer.js b/client/coral-admin/src/components/ui/Drawer.js
new file mode 100644
index 000000000..b1c87baaf
--- /dev/null
+++ b/client/coral-admin/src/components/ui/Drawer.js
@@ -0,0 +1,14 @@
+import React from 'react'
+import { Navigation, Drawer } from 'react-mdl'
+import { Link } from 'react-router'
+import styles from './Header.css'
+
+export default () => (
+
+
+ Moderate
+ Community
+ Configure
+
+
+)
diff --git a/client/coral-admin/src/components/Header.css b/client/coral-admin/src/components/ui/Header.css
similarity index 100%
rename from client/coral-admin/src/components/Header.css
rename to client/coral-admin/src/components/ui/Header.css
diff --git a/client/coral-admin/src/components/ui/Header.js b/client/coral-admin/src/components/ui/Header.js
new file mode 100644
index 000000000..1455721d8
--- /dev/null
+++ b/client/coral-admin/src/components/ui/Header.js
@@ -0,0 +1,14 @@
+import React from 'react'
+import { Navigation, Header } from 'react-mdl'
+import { Link } from 'react-router'
+import styles from './Header.css'
+
+export default () => (
+
+
+ Moderate
+ Community
+ Configure
+
+
+)
diff --git a/client/coral-admin/src/components/ui/Layout.js b/client/coral-admin/src/components/ui/Layout.js
new file mode 100644
index 000000000..fd963b667
--- /dev/null
+++ b/client/coral-admin/src/components/ui/Layout.js
@@ -0,0 +1,12 @@
+import React from 'react'
+import { Layout as LayoutMDL} from 'react-mdl'
+import Header from './Header'
+import Drawer from './Drawer'
+
+export const Layout = ({ children }) => (
+
+
+
+ {children}
+
+)
\ No newline at end of file
diff --git a/client/coral-admin/src/containers/CommentStream.js b/client/coral-admin/src/containers/CommentStream.js
index 4f0a03698..33963f422 100644
--- a/client/coral-admin/src/containers/CommentStream.js
+++ b/client/coral-admin/src/containers/CommentStream.js
@@ -6,7 +6,6 @@ import { connect } from 'react-redux'
import { createComment, flagComment } from 'actions/comments'
import CommentList from 'components/CommentList'
import CommentBox from 'components/CommentBox'
-import Page from 'components/Page'
/**
* Renders a comment stream using a CommentList component
@@ -44,19 +43,17 @@ class CommentStream extends React.Component {
// Render the comment box along with the CommentList
render ({ comments }, { snackbar, snackbarMsg }) {
return (
-
-
-
-
- {snackbarMsg}
-
-
+
+
+
+ {snackbarMsg}
+
)
}
}
diff --git a/client/coral-admin/src/containers/CommunityContainer.js b/client/coral-admin/src/containers/CommunityContainer.js
new file mode 100644
index 000000000..bd13ca04b
--- /dev/null
+++ b/client/coral-admin/src/containers/CommunityContainer.js
@@ -0,0 +1,14 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import I18n from 'coral-framework/i18n/i18n'
+import translations from '../translations'
+
+export default class CommunityContainer extends Component {
+ render() {
+ return (
+
+
Community
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/client/coral-admin/src/containers/Configure.js b/client/coral-admin/src/containers/Configure.js
index 4a36e56e7..5c86019c8 100644
--- a/client/coral-admin/src/containers/Configure.js
+++ b/client/coral-admin/src/containers/Configure.js
@@ -10,8 +10,9 @@ import {
Button,
Icon
} from 'react-mdl'
-import Page from 'components/Page'
import styles from './Configure.css'
+import I18n from 'coral-framework/i18n/i18n'
+import translations from '../translations'
class Configure extends React.Component {
constructor (props) {
@@ -40,12 +41,28 @@ class Configure extends React.Component {
}
+ copyToClipBoard (event) {
+ const copyTextarea = document.querySelector('.' + styles.embedInput)
+ copyTextarea.select()
+
+ try {
+ document.execCommand('copy')
+ } catch (err) {
+ console.error('Unable to copy')
+ }
+ }
+
getEmbed () {
+ const embedText =
+ ``
+
return
Copy and paste code below into your CMS to embed your comment box in your articles