Merge branch 'master' of github.com:coralproject/talk

This commit is contained in:
gaba
2016-11-08 15:28:22 -08:00
23 changed files with 217 additions and 387 deletions
+1 -7
View File
@@ -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" ]
+66
View File
@@ -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.
+1
View File
@@ -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:
-6
View File
@@ -1,6 +0,0 @@
node_modules
public/bundle.js
public/embed/comment-stream
.DS_Store
npm-debug.log
yarn.lock
+1 -3
View File
@@ -1,5 +1,3 @@
{
"basePath": "admin",
"talkHost": "http://localhost:16180",
"xeniaHost": "http://localhost:16180"
"basePath": "admin"
}
-3
View File
@@ -1,3 +0,0 @@
{
"basePath": "client/coral-admin"
}
-42
View File
@@ -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"
}
}
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
plugins: [
require('postcss-smart-import')({ /* ...options */ }),
require('precss')({ /* ...options */ }),
require('autoprefixer')({ /* ...options */ })
]
}
-22
View File
@@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Talk - Coral Admin</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<style media="screen">
body, #root {
width: 100%;
height: 100%;
margin: 0;
background: #fff;
}
</style>
</head>
<body>
<div id="root"></div>
<script src="client/coral-admin/bundle.js" charset="utf-8"></script>
</body>
</html>
+22 -2
View File
@@ -12,6 +12,8 @@ import {
} 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 +42,28 @@ class Configure extends React.Component {
</List>
}
copyToClipBoard (event) {
const copyTextarea = document.querySelector('.' + styles.embedInput)
copyTextarea.select()
try {
document.execCommand('copy')
} catch (err) {
console.error('Unable to copy')
}
}
getEmbed () {
const embedText =
`<div id='coralStreamEmbed'></div><script type='text/javascript' src='https://pym.nprapps.org/pym.v1.min.js'></script><script>var pymParent = new pym.Parent('coralStreamEmbed', '${window.location.protocol}//${window.location.host}/client/coral-embed-stream/', {title: 'comments'});</script>`
return <List>
<ListItem className={styles.configSettingEmbed}>
<p>Copy and paste code below into your CMS to embed your comment box in your articles</p>
<input type='text' className={styles.embedInput} />
<Button raised colored>Copy</Button>
<textarea type='text' className={styles.embedInput}>
{embedText}
</textarea>
<Button raised colored>{lang.t('embedlink.copy')}</Button>
</ListItem>
</List>
}
@@ -94,3 +112,5 @@ class Configure extends React.Component {
}
export default connect(x => x)(Configure)
const lang = new I18n(translations)
-32
View File
@@ -1,32 +0,0 @@
const path = require('path')
const autoprefixer = require('autoprefixer')
const precss = require('precss')
module.exports = {
entry: {
'bundle': path.join(__dirname, 'src', 'index')
},
output: {
path: path.join(__dirname, '..', '..', 'dist', 'coral-admin'),
filename: '[name].js'
},
module: {
loaders: [
{ test: /.js$/, loader: 'babel', include: path.join(__dirname, 'src'), exclude: /node_modules/ },
{ test: /\.json$/, loaders: 'json', include: __dirname, exclude: /node_modules/ },
{ test: /.css$/, loaders: ['style-loader', 'css-loader?modules&localIdentName=[name]__[local]___[hash:base64:5]', 'postcss-loader'] }
]
},
plugins: [ autoprefixer, precss ],
resolve: {
root: [
path.resolve('./src'),
path.resolve('../')
]
},
devServer: {
historyApiFallback: {
index: '/'
}
}
}
-23
View File
@@ -1,23 +0,0 @@
const path = require('path')
const devConfig = require('./webpack.config.dev')
const autoprefixer = require('autoprefixer')
const precss = require('precss')
const Copy = require('copy-webpack-plugin')
module.exports = Object.assign({}, devConfig, {
module: {
context: __dirname,
loaders: [
{ test: /.js$/, loader: 'babel', include: [path.join(__dirname, 'src'), path.join(__dirname, '../', 'coral-framework')], exclude: /node_modules/ },
{ test: /.json$/, loader: 'json', include: __dirname, exclude: /node_modules/ },
{ test: /.css$/, loaders: ['style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', 'postcss-loader'] }
]
},
plugins: [
new Copy([{
from: path.join(__dirname, '..', 'coral-embed-stream', 'dist'),
to: './embed/comment-stream'
}]),
autoprefixer, precss
]
})
-41
View File
@@ -1,41 +0,0 @@
var path = require('path')
var express = require('express')
var http = require('http')
var webpack = require('webpack')
var config = require('./webpack.config.dev')
var Dashboard = require('webpack-dashboard')
var DashboardPlugin = require('webpack-dashboard/plugin')
var app = express()
var server = http.Server(app)
var compiler = webpack(config)
var dashboard = new Dashboard()
compiler.apply(new DashboardPlugin(dashboard.setData))
app.use(express.static('public'))
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
quiet: true,
publicPath: config.output.publicPath
}))
app.use(require('webpack-hot-middleware')(compiler, {log: () => {}}))
app.get('/default.css', function (req, res) {
res.sendFile(path.join(__dirname, '/style/default.css'))
})
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'))
})
server.listen(6182, 'localhost', function (err) {
if (err) {
console.log(err)
return
}
console.log('Listening at http://localhost:6182')
})
-13
View File
@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="default.css">
<link href="https://fonts.googleapis.com/css?family=Lato|Open+Sans" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
</head>
<body>
<div id="coralStream"/>
<script src="./bundle.js"></script>
</body>
</html>
@@ -1,70 +0,0 @@
var path = require('path')
var webpack = require('webpack')
const Copy = require('copy-webpack-plugin')
module.exports = {
devtool: 'eval',
entry: [
'babel-polyfill',
'webpack-hot-middleware/client',
path.join(__dirname, 'src', 'app')
],
output: {
path: path.join(__dirname, '..', '..','dist', 'coral-embed-stream'),
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
root: [
path.resolve(__dirname, 'src'),
path.resolve(__dirname, '..')
],
extensions: ['', '.js', '.jsx']
},
plugins: [
new Copy([{
from: path.join(__dirname, 'index.html')
},
{
from: path.join(__dirname, 'style', 'default.css')
},
{
from: path.join(__dirname, 'public'),
to: './'
}]),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.ProvidePlugin({
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
}),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [{
test: /\.(js|jsx)$/,
loaders: ['babel'],
exclude: /node_modules/,
include: path.join(__dirname, '../')
}, {
test: /\.css$/,
loader: 'style-loader!css-loader'
}, {
test: /\.png$/,
loader: 'url-loader?limit=100000'
}, {
test: /\.(jpg|png|gif|svg)$/,
loader: 'file-loader'
}, {
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.woff$/,
loader: 'url?limit=100000'
}]
}
}
@@ -1,73 +0,0 @@
const path = require('path')
const webpack = require('webpack')
const Copy = require('copy-webpack-plugin')
//Keeping this file for reference, it should move to a global webpack.
module.exports = {
devtool: 'source-map',
entry: [
'babel-polyfill',
path.join(__dirname, 'src', 'app')
],
output: {
path: path.join(__dirname, '..', '..','dist', 'coral-embed-stream'),
filename: 'bundle.js',
publicPath: '/dist/'
},
resolve: {
root: [
path.resolve(__dirname, 'src')
],
extensions: ['', '.js', '.jsx']
},
plugins: [
new Copy([{
from: path.join(__dirname, 'index.html')
},
{
from: path.join(__dirname, 'style', 'default.css')
},
{
from: path.join(__dirname, 'public'),
to: './'
},
{
from: path.resolve(__dirname, '..', 'coral-framework', 'i18n', 'translations'),
to: './translations'
}]),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.ProvidePlugin({
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
}),
new webpack.ExtendedAPIPlugin()
],
module: {
loaders: [{
test: /\.(js|jsx)$/,
loaders: ['babel'],
exclude: /node_modules/,
include: path.join(__dirname, '../')
}, {
test: /\.css$/,
loader: 'style-loader!css-loader'
}, {
test: /\.png$/,
loader: 'url-loader?limit=100000'
}, {
test: /\.jpg$/,
loader: 'file-loader'
}, {
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.woff$/,
loader: 'url?limit=100000'
}]
}
}
-23
View File
@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Talk - Coral Admin</title>
<base href="/client/coral-admin/" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<style media="screen">
body, #root {
width: 100%;
height: 100%;
margin: 0;
background: #fff;
}
</style>
</head>
<body>
<div id="root"></div>
<script src="bundle.js" charset="utf-8"></script>
</body>
</html>
-12
View File
@@ -1,12 +0,0 @@
{
"short_name": "Talk",
"name": "Talk",
"icons": [
{
"src": "https://coralproject.net/images/icon-coral-white.svg",
"sizes": "150x150"
}
],
"start_url": "./",
"display": "standalone"
}
+14 -8
View File
@@ -5,12 +5,13 @@
"main": "app.js",
"scripts": {
"start": "./bin/www",
"build": "./node_modules/webpack/bin/webpack.js --config ./client/coral-embed-stream/webpack.config.js && cd client/coral-admin && npm install && npm run build",
"build": "webpack --config webpack.config.js --bail",
"build-watch": "webpack --config webpack.config.dev.js --watch",
"lint": "eslint .",
"pretest": "npm install",
"test": "mocha tests --recursive",
"test-watch": "mocha tests --recursive -w",
"embed-start": "./node_modules/webpack/bin/webpack.js --config ./client/coral-embed-stream/webpack.config.dev.js && ./bin/www"
"embed-start": "npm run build && ./bin/www"
},
"config": {
"pre-git": {
@@ -53,9 +54,9 @@
},
"devDependencies": {
"autoprefixer": "6.5.0",
"babel-core": "6.14.0",
"babel-core": "^6.14.0",
"babel-jest": "^15.0.0",
"babel-loader": "6.2.5",
"babel-loader": "^6.2.5",
"babel-plugin-transform-async-to-generator": "^6.8.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-object-assign": "^6.8.0",
@@ -67,26 +68,31 @@
"chai": "^3.5.0",
"chai-http": "^3.0.0",
"copy-webpack-plugin": "^3.0.1",
"css-loader": "0.25.0",
"css-loader": "^0.25.0",
"eslint": "^3.9.1",
"exports-loader": "^0.6.3",
"hammerjs": "^2.0.8",
"immutable": "^3.8.1",
"imports-loader": "^0.6.5",
"json-loader": "^0.5.4",
"keymaster": "^1.6.2",
"material-design-lite": "^1.2.1",
"mocha": "^3.1.2",
"mocha-junit-reporter": "^1.12.1",
"postcss-loader": "0.13.0",
"postcss-loader": "^0.13.0",
"postcss-modules": "0.5.2",
"precss": "1.4.0",
"pre-git": "^3.10.0",
"precss": "^1.4.0",
"pym.js": "^1.1.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",
"regenerator": "^0.8.46",
"style-loader": "0.13.1",
"style-loader": "^0.13.1",
"supertest": "^2.0.1",
"timeago.js": "^2.0.3",
"webpack": "^1.13.2",
+90
View File
@@ -0,0 +1,90 @@
const path = require('path');
const autoprefixer = require('autoprefixer');
const precss = require('precss');
const Copy = require('copy-webpack-plugin');
const webpack = require('webpack');
// Edit the build targets and embeds below.
const buildTargets = [
'coral-admin'
];
const buildEmbeds = [
'stream'
];
module.exports = {
devtool: 'inline-source-map',
entry: buildTargets.reduce((entry, target) => {
// Add the entry for the bundle.
entry[`${target}/bundle`] = [
'babel-polyfill',
path.join(__dirname, 'client/', target, '/src/index')
];
return entry;
}, buildEmbeds.reduce((entry, embed) => {
// Add the entry for the bundle.
entry[`embed/${embed}/bundle`] = [
'babel-polyfill',
path.join(__dirname, 'client/', `coral-embed-${embed}`, '/src/index')
];
return entry;
}, {})),
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
loaders: [
{
loader: 'babel',
exclude: /node_modules/,
test: /\.js$/
},
{
loader: 'json',
test: /\.json$/,
exclude: /node_modules/
},
{
loaders: ['style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', 'postcss-loader'],
test: /.css$/,
},
{
loader: 'url-loader?limit=100000',
test: /\.png$/
},
{
loader: 'file-loader',
test: /\.(jpg|png|gif|svg)$/
},
{
loader: 'url?limit=100000',
test: /\.woff$/
}
]
},
plugins: [
new Copy(buildEmbeds.map(embed => ({
from: path.join(__dirname, 'client', `coral-embed-${embed}`, 'style'),
to: path.join(__dirname, 'dist', 'embed', embed)
}))),
autoprefixer,
precss,
new webpack.ProvidePlugin({
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
],
resolve: {
root: [
path.join(__dirname, 'client'),
...buildTargets.map(target => path.join(__dirname, 'client', target, 'src')),
...buildEmbeds.map(embed => path.join(__dirname, 'client', `coral-embed-${embed}`, 'src'))
]
}
};
+22
View File
@@ -0,0 +1,22 @@
const webpack = require('webpack');
const devConfig = require('./webpack.config.dev');
// Disable source maps.
devConfig.devtool = null;
devConfig.plugins = devConfig.plugins.concat([
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin()
]);
module.exports = devConfig;