Merge branch 'master' into view-char-count
@@ -3,10 +3,10 @@ const bodyParser = require('body-parser');
|
||||
const morgan = require('morgan');
|
||||
const path = require('path');
|
||||
const helmet = require('helmet');
|
||||
const passport = require('./passport');
|
||||
const passport = require('./services/passport');
|
||||
const session = require('express-session');
|
||||
const RedisStore = require('connect-redis')(session);
|
||||
const redis = require('./redis');
|
||||
const redis = require('./services/redis');
|
||||
|
||||
const app = express();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const pkg = require('../package.json');
|
||||
const parseDuration = require('parse-duration');
|
||||
const Table = require('cli-table');
|
||||
const Asset = require('../models/asset');
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const scraper = require('../services/scraper');
|
||||
const util = require('../util');
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ process.env.DEBUG = process.env.TALK_DEBUG;
|
||||
const program = require('commander');
|
||||
const scraper = require('../services/scraper');
|
||||
const util = require('../util');
|
||||
const mongoose = require('../mongoose');
|
||||
const kue = require('../kue');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const kue = require('../services/kue');
|
||||
|
||||
util.onshutdown([
|
||||
() => mongoose.disconnect()
|
||||
|
||||
@@ -11,7 +11,7 @@ const debug = require('debug')('talk:server');
|
||||
const http = require('http');
|
||||
const init = require('../init');
|
||||
const scraper = require('../services/scraper');
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const util = require('../util');
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ process.env.DEBUG = process.env.TALK_DEBUG;
|
||||
*/
|
||||
|
||||
const program = require('commander');
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const Setting = require('../models/setting');
|
||||
const util = require('../util');
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const program = require('commander');
|
||||
const pkg = require('../package.json');
|
||||
const prompt = require('prompt');
|
||||
const User = require('../models/user');
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const util = require('../util');
|
||||
const Table = require('cli-table');
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"configureCommentStream": {
|
||||
"apply": "Apply",
|
||||
"title": "Configure Comment Stream",
|
||||
"description": "As an admin you may customize the settings for the comment stream for this article",
|
||||
"description": "As an admin you may customize the settings for the comment stream for this asset",
|
||||
"enablePremod": "Enable Premoderation",
|
||||
"enablePremodDescription": "Moderators must approve any comment before its published.",
|
||||
"enablePremodLinks": "Pre-Moderate Comments Containing Links",
|
||||
|
||||
@@ -6,14 +6,6 @@ import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from './../translations';
|
||||
const lang = new I18n(translations);
|
||||
|
||||
export const updateOpenStatus = status => (dispatch, getState) => {
|
||||
const assetId = getState().items.get('assets')
|
||||
.keySeq()
|
||||
.toArray()[0];
|
||||
return coralApi(`/asset/${assetId}/status?status=${status}`, {method: 'PUT'})
|
||||
.then(() => dispatch({type: status === 'open' ? actions.OPEN_COMMENTS : actions.CLOSE_COMMENTS}));
|
||||
};
|
||||
|
||||
const updateConfigRequest = () => ({type: actions.UPDATE_CONFIG_REQUEST});
|
||||
const updateConfigSuccess = config => ({type: actions.UPDATE_CONFIG_SUCCESS, config});
|
||||
const updateConfigFailure = () => ({type: actions.UPDATE_CONFIG_FAILURE});
|
||||
@@ -31,3 +23,31 @@ export const updateConfiguration = newConfig => (dispatch, getState) => {
|
||||
})
|
||||
.catch(error => dispatch(updateConfigFailure(error)));
|
||||
};
|
||||
|
||||
export const updateOpenStream = closedBody => (dispatch, getState) => {
|
||||
const assetId = getState().items.get('assets')
|
||||
.keySeq()
|
||||
.toArray()[0];
|
||||
|
||||
dispatch(updateConfigRequest());
|
||||
|
||||
coralApi(`/asset/${assetId}/status`, {method: 'PUT', body: closedBody})
|
||||
.then(() => {
|
||||
dispatch(addNotification('success', lang.t('successUpdateSettings')));
|
||||
dispatch(updateConfigSuccess(closedBody));
|
||||
})
|
||||
.catch(error => dispatch(updateConfigFailure(error)));
|
||||
};
|
||||
|
||||
const openStream = () => ({type: actions.OPEN_COMMENTS});
|
||||
const closeStream = () => ({type: actions.CLOSE_COMMENTS});
|
||||
|
||||
export const updateOpenStatus = status => dispatch => {
|
||||
if (status === 'open') {
|
||||
dispatch(openStream());
|
||||
dispatch(updateOpenStream({closedAt: null}));
|
||||
} else {
|
||||
dispatch(closeStream());
|
||||
dispatch(updateOpenStream({closedAt: new Date().getTime()}));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ export default (state = initialState, action) => {
|
||||
return state
|
||||
.set('status', 'closed');
|
||||
case actions.ADD_ITEM:
|
||||
return action.item_type === 'assets' ? state.set('status', action.item.status) : state;
|
||||
return action.item_type === 'assets' ? state.set('status', (action.item && action.item.closedAt && new Date(action.item.closedAt).getTime() <= new Date().getTime()) ? 'closed' : 'open') : state;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const uuid = require('uuid');
|
||||
const _ = require('lodash');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const Setting = require('./setting');
|
||||
@@ -19,7 +19,7 @@ const AssetSchema = new Schema({
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'article'
|
||||
default: 'assets'
|
||||
},
|
||||
scraped: {
|
||||
type: Date,
|
||||
@@ -64,13 +64,6 @@ AssetSchema.index({
|
||||
background: true
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns true if the asset is closed, false else.
|
||||
*/
|
||||
AssetSchema.virtual('isClosed').get(function() {
|
||||
return this.closedAt && this.closedAt.getTime() <= new Date().getTime();
|
||||
});
|
||||
|
||||
/**
|
||||
* Finds an asset by its id.
|
||||
* @param {String} id identifier of the asset (uuid).
|
||||
@@ -83,6 +76,13 @@ AssetSchema.statics.findById = (id) => Asset.findOne({id});
|
||||
*/
|
||||
AssetSchema.statics.findByUrl = (url) => Asset.findOne({url});
|
||||
|
||||
/**
|
||||
* Returns true if the asset is closed, false else.
|
||||
*/
|
||||
AssetSchema.virtual('isClosed').get(function() {
|
||||
return this.closedAt && this.closedAt.getTime() <= new Date().getTime();
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieves the settings given an asset query and rectifies it against the
|
||||
* global settings.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
const _ = require('lodash');
|
||||
const uuid = require('uuid');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
const _ = require('lodash');
|
||||
const cache = require('../cache');
|
||||
const cache = require('../services/cache');
|
||||
|
||||
/**
|
||||
* SettingSchema manages application settings that get used on front and backend.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const uuid = require('uuid');
|
||||
const _ = require('lodash');
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
@@ -5,21 +5,26 @@
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"start": "./bin/cli serve --jobs",
|
||||
"build": "NODE_ENV=production webpack --config webpack.config.js --bail",
|
||||
"build-watch": "NODE_ENV=development webpack --config webpack.config.dev.js --watch",
|
||||
"lint": "eslint bin/* .",
|
||||
"lint-fix": "eslint . --fix",
|
||||
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --recursive tests",
|
||||
"test-watch": "NODE_ENV=test mocha --compilers js:babel-core/register --recursive -w tests",
|
||||
"pree2e": "NODE_ENV=test ./pree2e.sh",
|
||||
"e2e": "NODE_ENV=test node_modules/.bin/nightwatch",
|
||||
"build": "NODE_ENV=production ./node_modules/.bin/webpack --config webpack.config.js --bail",
|
||||
"build-watch": "NODE_ENV=development ./node_modules/.bin/webpack --config webpack.config.dev.js --watch",
|
||||
"lint": "./node_modules/.bin/eslint bin/* .",
|
||||
"lint-fix": "./node_modules/.bin/eslint bin/* . --fix",
|
||||
"test": "NODE_ENV=test ./node_modules/.bin/mocha --compilers js:babel-core/register --recursive tests",
|
||||
"test-watch": "NODE_ENV=test ./node_modules/.bin/mocha --compilers js:babel-core/register --recursive -w tests",
|
||||
"pree2e": "NODE_ENV=test ./scripts/pree2e.sh",
|
||||
"e2e": "NODE_ENV=test ./node_modules/.bin/nightwatch",
|
||||
"embed-start": "NODE_ENV=development npm run build && ./bin/cli serve --jobs"
|
||||
},
|
||||
"config": {
|
||||
"pre-git": {
|
||||
"commit-msg": [],
|
||||
"pre-commit": ["npm run lint", "npm test"],
|
||||
"pre-push": ["npm test"],
|
||||
"pre-commit": [
|
||||
"npm run lint",
|
||||
"npm test"
|
||||
],
|
||||
"pre-push": [
|
||||
"npm test"
|
||||
],
|
||||
"post-commit": [],
|
||||
"post-merge": []
|
||||
}
|
||||
@@ -28,7 +33,12 @@
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/coralproject/talk.git"
|
||||
},
|
||||
"keywords": ["talk", "coral", "coralproject", "ask"],
|
||||
"keywords": [
|
||||
"talk",
|
||||
"coral",
|
||||
"coralproject",
|
||||
"ask"
|
||||
],
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
@@ -59,7 +69,6 @@
|
||||
"passport-facebook": "^2.1.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"react-linkify": "^0.1.3",
|
||||
"redis": "^2.6.3",
|
||||
"uuid": "^2.0.3"
|
||||
},
|
||||
@@ -84,9 +93,10 @@
|
||||
"copy-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^0.25.0",
|
||||
"dialog-polyfill": "^0.4.4",
|
||||
"eslint": "^3.9.1",
|
||||
"eslint": "^3.12.1",
|
||||
"eslint-config-postcss": "^2.0.2",
|
||||
"eslint-config-standard": "^6.2.1",
|
||||
"eslint-module-utils": "^2.0.0",
|
||||
"eslint-plugin-flowtype": "^2.25.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-mocha": "^4.7.0",
|
||||
@@ -113,6 +123,7 @@
|
||||
"pym.js": "^1.1.1",
|
||||
"react": "15.3.2",
|
||||
"react-dom": "15.3.2",
|
||||
"react-linkify": "^0.1.3",
|
||||
"react-mdl": "^1.7.2",
|
||||
"react-mdl-selectfield": "^0.2.0",
|
||||
"react-onclickoutside": "^5.7.1",
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules/selenium-standalone/bin/selenium-standalone install
|
||||
npm start &
|
||||
@@ -90,11 +90,28 @@ router.put('/:asset_id/settings', (req, res, next) => {
|
||||
});
|
||||
|
||||
router.put('/:asset_id/status', (req, res, next) => {
|
||||
// Update the asset status
|
||||
|
||||
const id = req.params.asset_id;
|
||||
|
||||
const {
|
||||
closedAt,
|
||||
closedMessage
|
||||
} = req.body;
|
||||
|
||||
Asset
|
||||
.update({id: req.params.asset_id}, {status: req.query.status})
|
||||
.then(() => res.status(204).end())
|
||||
.catch((err) => next(err));
|
||||
.update({id}, {
|
||||
$set: {
|
||||
closedAt,
|
||||
closedMessage
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
res.status(204).json();
|
||||
})
|
||||
.catch((err) => {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const express = require('express');
|
||||
const passport = require('../../../passport');
|
||||
const passport = require('../../../services/passport');
|
||||
const authorization = require('../../../middleware/authorization');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -87,7 +87,6 @@ router.post('/', wordlist.filter('body'), (req, res, next) => {
|
||||
|
||||
// Check to see if the asset has closed commenting...
|
||||
if (asset.isClosed) {
|
||||
|
||||
// They have, ensure that we send back an error.
|
||||
return Promise.reject(new Error(`asset has commenting closed because: ${asset.closedMessage}`));
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ router.use('/stream', require('./stream'));
|
||||
router.use('/users', require('./users'));
|
||||
|
||||
// Bind the kue handler to the /kue path.
|
||||
router.use('/kue', authorization.needed('admin'), require('../../kue').kue.app);
|
||||
router.use('/kue', authorization.needed('admin'), require('../../services/kue').kue.app);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install selenium
|
||||
../node_modules/selenium-standalone/bin/selenium-standalone install
|
||||
|
||||
# start the app server
|
||||
npm start &
|
||||
@@ -1,5 +1,5 @@
|
||||
const passport = require('passport');
|
||||
const User = require('./models/user');
|
||||
const User = require('../models/user');
|
||||
const LocalStrategy = require('passport-local').Strategy;
|
||||
const FacebookStrategy = require('passport-facebook').Strategy;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const kue = require('../kue');
|
||||
const kue = require('./kue');
|
||||
const debug = require('debug')('talk:services:scraper');
|
||||
const Asset = require('../models/asset');
|
||||
const JOB_NAME = 'scraper';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../mongoose');
|
||||
const mongoose = require('../services/mongoose');
|
||||
|
||||
beforeEach(function (done) {
|
||||
function clearDB() {
|
||||
|
||||
@@ -17,7 +17,8 @@ describe('/api/v1/assets', () => {
|
||||
{
|
||||
url: 'https://coralproject.net/news/asset1',
|
||||
title: 'Asset 1',
|
||||
description: 'term1'
|
||||
description: 'term1',
|
||||
id: '1'
|
||||
},
|
||||
{
|
||||
url: 'https://coralproject.net/news/asset2',
|
||||
@@ -82,4 +83,32 @@ describe('/api/v1/assets', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('#put', () => {
|
||||
it('should close the asset', function() {
|
||||
|
||||
const today = Date.now();
|
||||
|
||||
return Asset.findOrCreateByUrl('http://test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('isClosed', null);
|
||||
expect(asset).to.have.property('closedAt', null);
|
||||
|
||||
return chai.request(app)
|
||||
.put(`/api/v1/asset/${asset.id}/status`)
|
||||
.set(passport.inject({roles: ['admin']}))
|
||||
.send({closedAt: today});
|
||||
})
|
||||
.then((res) => {
|
||||
|
||||
expect(res).to.have.status(204);
|
||||
|
||||
return Asset.findByUrl('http://test.com');
|
||||
})
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('isClosed', true);
|
||||
expect(asset).to.have.property('closedAt').and.to.not.equal(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('../../mongoose');
|
||||
const mongoose = require('../../services/mongoose');
|
||||
|
||||
// Ensure the NODE_ENV is set to 'test',
|
||||
// this is helpful when you would like to change behavior when testing.
|
||||
|
||||