diff --git a/client/coral-admin/src/actions/community.js b/client/coral-admin/src/actions/community.js
index 06c8ab0f6..7a4112f8b 100644
--- a/client/coral-admin/src/actions/community.js
+++ b/client/coral-admin/src/actions/community.js
@@ -5,7 +5,8 @@ import {
FETCH_COMMENTERS_SUCCESS,
FETCH_COMMENTERS_FAILURE,
SORT_UPDATE,
- COMMENTERS_NEW_PAGE
+ COMMENTERS_NEW_PAGE,
+ SET_ROLE
} from '../constants/community';
import {base, getInit, handleResp} from '../helpers/response';
@@ -40,3 +41,9 @@ export const newPage = () => ({
type: COMMENTERS_NEW_PAGE
});
+export const setRole = (id, role) => dispatch => {
+ return fetch(`${base}/user/${id}/role`, getInit('POST', {role}))
+ .then(() => {
+ return dispatch({type: SET_ROLE, id, role});
+ });
+};
diff --git a/client/coral-admin/src/constants/community.js b/client/coral-admin/src/constants/community.js
index e628a14d6..2ea77ea77 100644
--- a/client/coral-admin/src/constants/community.js
+++ b/client/coral-admin/src/constants/community.js
@@ -3,3 +3,4 @@ export const FETCH_COMMENTERS_SUCCESS = 'FETCH_COMMENTERS_SUCCESS';
export const FETCH_COMMENTERS_FAILURE = 'FETCH_COMMENTERS_FAILURE';
export const SORT_UPDATE = 'SORT_UPDATE';
export const COMMENTERS_NEW_PAGE = 'COMMENTERS_NEW_PAGE';
+export const SET_ROLE = 'SET_ROLE';
diff --git a/client/coral-admin/src/containers/Community/Community.js b/client/coral-admin/src/containers/Community/Community.js
index 1f009429b..fdb542811 100644
--- a/client/coral-admin/src/containers/Community/Community.js
+++ b/client/coral-admin/src/containers/Community/Community.js
@@ -19,6 +19,10 @@ const tableHeaders = [
{
title: lang.t('community.account_creation_date'),
field: 'created_at'
+ },
+ {
+ title: lang.t('community.newsroom_role'),
+ field: 'role'
}
];
diff --git a/client/coral-admin/src/containers/Community/Table.js b/client/coral-admin/src/containers/Community/Table.js
index a15a88723..97848bc9a 100644
--- a/client/coral-admin/src/containers/Community/Table.js
+++ b/client/coral-admin/src/containers/Community/Table.js
@@ -1,34 +1,66 @@
-import React from 'react';
+import React, {Component} from 'react';
+import {connect} from 'react-redux';
+import {SelectField, Option} from 'react-mdl-selectfield';
import styles from './Community.css';
+import I18n from 'coral-framework/i18n/i18n';
+import translations from '../../translations';
+import {setRole} from '../../actions/community';
-const Table = ({headers, data, onHeaderClickHandler}) => (
-
-
-
- {headers.map((header, i) =>(
- | onHeaderClickHandler({field: header.field})}>
- {header.title}
- |
- ))}
-
-
-
- {data.map((row, i)=> (
-
- |
- {row.displayName}
- {row.profiles.map(({id}) => id)}
- |
-
- {row.created_at}
- |
-
- ))}
-
-
-);
+const lang = new I18n(translations);
-export default Table;
+class Table extends Component {
+
+ constructor (props) {
+ super(props);
+ this.onRoleChange = this.onRoleChange.bind(this);
+ }
+
+ onRoleChange (id, role) {
+ this.props.dispatch(setRole(id, role));
+ }
+
+ render () {
+ const {headers, commenters, onHeaderClickHandler} = this.props;
+
+ return (
+
+
+
+ {headers.map((header, i) =>(
+ | onHeaderClickHandler({field: header.field})}>
+ {header.title}
+ |
+ ))}
+
+
+
+ {commenters.map((row, i)=> (
+
+ |
+ {row.displayName}
+ {row.profiles.map(({id}) => id)}
+ |
+
+ {row.created_at}
+ |
+
+ this.onRoleChange(row.id, role)}>
+
+
+
+
+ |
+
+ ))}
+
+
+ );
+ }
+}
+
+export default connect(state => ({commenters: state.community.get('commenters')}))(Table);
diff --git a/client/coral-admin/src/reducers/community.js b/client/coral-admin/src/reducers/community.js
index 8d5dfd2c3..81a09a1cc 100644
--- a/client/coral-admin/src/reducers/community.js
+++ b/client/coral-admin/src/reducers/community.js
@@ -4,7 +4,8 @@ import {
FETCH_COMMENTERS_REQUEST,
FETCH_COMMENTERS_FAILURE,
FETCH_COMMENTERS_SUCCESS,
- SORT_UPDATE
+ SORT_UPDATE,
+ SET_ROLE
} from '../constants/community';
const initialState = Map({
@@ -37,6 +38,13 @@ export default function community (state = initialState, action) {
})
.set('commenters', commenters); // Sets to normal array
}
+ case SET_ROLE : {
+ const commenters = state.get('commenters');
+ const idx = commenters.findIndex(el => el.id === action.id);
+
+ commenters[idx].roles[0] = action.role;
+ return state.set('commenters', commenters.map(id => id));
+ }
case SORT_UPDATE :
return state
.set('field', action.sort.field)
diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json
index 43d0939e0..42b2bce5c 100644
--- a/client/coral-admin/src/translations.json
+++ b/client/coral-admin/src/translations.json
@@ -1,36 +1,44 @@
{
"en": {
- "community": {
- "username_and_email": "Username and Email",
- "account_creation_date": "Account Creation Date"
- },
- "modqueue": {
- "pending": "pending",
- "rejected": "rejected",
- "flagged": "flagged",
- "shortcuts": "Shortcuts",
- "close": "Close",
- "actions": "Actions",
- "navigation": "Navigation",
- "approve": "Approve comment",
- "reject": "Reject comment",
- "nextcomment": "Go to the next comment",
- "prevcomment": "Go to the previous comment",
- "singleview": "Toggle single comment edit view",
- "thismenu": "Open this menu"
- },
- "comment": {
- "flagged": "flagged",
- "anon": "Anonymous"
- },
- "embedlink": {
- "copy": "Copy to Clipboard"
- }
+ "community": {
+ "username_and_email": "Username and Email",
+ "account_creation_date": "Account Creation Date",
+ "newsroom_role": "Newsroom Role",
+ "admin": "Administrator",
+ "moderator": "Moderator",
+ "role": "Select role..."
+ },
+ "modqueue": {
+ "pending": "pending",
+ "rejected": "rejected",
+ "flagged": "flagged",
+ "shortcuts": "Shortcuts",
+ "close": "Close",
+ "actions": "Actions",
+ "navigation": "Navigation",
+ "approve": "Approve comment",
+ "reject": "Reject comment",
+ "nextcomment": "Go to the next comment",
+ "prevcomment": "Go to the previous comment",
+ "singleview": "Toggle single comment edit view",
+ "thismenu": "Open this menu"
+ },
+ "comment": {
+ "flagged": "flagged",
+ "anon": "Anonymous"
+ },
+ "embedlink": {
+ "copy": "Copy to Clipboard"
+ }
},
"es": {
"community": {
"username_and_email": "Usuario y E-mail",
- "account_creation_date": "Fecha de creación de la cuenta"
+ "account_creation_date": "Fecha de creación de la cuenta",
+ "newsroom_role": "Rol en la redacción",
+ "admin": "Administrador",
+ "moderator": "Moderador",
+ "role": "Select role..."
},
"modqueue": {
"pending": "pendiente",
diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js
index d8f5718a7..d3793723b 100644
--- a/client/coral-embed-stream/src/CommentStream.js
+++ b/client/coral-embed-stream/src/CommentStream.js
@@ -15,9 +15,10 @@ import AuthorName from '../../coral-plugin-author-name/AuthorName';
import {ReplyBox, ReplyButton} from '../../coral-plugin-replies';
import Pym from 'pym.js';
import FlagButton from '../../coral-plugin-flags/FlagButton';
+import LikeButton from '../../coral-plugin-likes/LikeButton';
import PermalinkButton from '../../coral-plugin-permalinks/PermalinkButton';
-const {addItem, updateItem, postItem, getStream, postAction, appendItemArray} = itemActions;
+const {addItem, updateItem, postItem, getStream, postAction, deleteAction, appendItemArray} = itemActions;
const {addNotification, clearNotification} = notificationActions;
const {setLoggedInUser} = authActions;
@@ -56,6 +57,9 @@ const mapDispatchToProps = (dispatch) => {
postAction: (item, action, user, itemType) => {
return dispatch(postAction(item, action, user, itemType));
},
+ deleteAction: (item, action, user, itemType) => {
+ return dispatch(deleteAction(item, action, user, itemType));
+ },
appendItemArray: (item, property, value, addToFront, itemType) => {
return dispatch(appendItemArray(item, property, value, addToFront, itemType));
}
@@ -124,21 +128,33 @@ class CommentStream extends Component {
- ;
})
}
diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css
index 9875198cb..793ab0f8c 100644
--- a/client/coral-embed-stream/style/default.css
+++ b/client/coral-embed-stream/style/default.css
@@ -122,16 +122,33 @@ hr {
/* Comment Action Styles */
-.commentActions, .replyActions {
+.commentActionsRight, .replyActionsRight {
display: flex;
justify-content: flex-end;
+ width: 50%;
+}
+.commentActionsLeft, .replyActionsLeft {
+ display: flex;
+ justify-content: flex-start;
+ float: left;
+ width: 50%;
}
-.commentActions .material-icons, .replyActions .material-icons {
+.commentActionsLeft .material-icons,.commentActionsRight .material-icons,
+.replyActionsLeft .material-icons, .replyActionsRight .material-icons {
font-size: 12px;
+ margin-left: 3px;
vertical-align: middle;
}
+.likedButton {
+ color: rgb(0,134,227);
+}
+
+.flaggedIcon {
+ color: #F00;
+}
+
/* Comment count styles */
.coral-plugin-comment-count-text {
margin-bottom: 15px;
diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js
index 07f8e54af..2e7dca70f 100644
--- a/client/coral-framework/store/actions/items.js
+++ b/client/coral-framework/store/actions/items.js
@@ -8,6 +8,23 @@ export const ADD_ITEM = 'ADD_ITEM';
export const UPDATE_ITEM = 'UPDATE_ITEM';
export const APPEND_ITEM_ARRAY = 'APPEND_ITEM_ARRAY';
+const getInit = (method, body) => {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json'
+ };
+
+ const init = {method, headers};
+ if (method.toLowerCase() !== 'get') {
+ init.body = JSON.stringify(body);
+ }
+
+ return init;
+};
+
+const responseHandler = response => {
+ return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`);
+};
/**
* Action creators
*/
@@ -79,12 +96,8 @@ export const appendItemArray = (id, property, value, add_to_front, item_type) =>
*/
export function getStream (assetId) {
return (dispatch) => {
- return fetch(`/api/v1/stream?asset_id=${assetId}`)
- .then(
- response => {
- return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`);
- }
- )
+ return fetch(`/api/v1/stream?asset_id=${assetId}`, getInit('GET'))
+ .then(responseHandler)
.then((json) => {
/* Add items to the store */
@@ -148,13 +161,8 @@ export function getStream (assetId) {
export function getItemsArray (ids) {
return (dispatch) => {
- return fetch(`/v1/item/${ids}`)
- .then(
- response => {
- return response.ok ? response.json()
- : Promise.reject(`${response.status } ${ response.statusText}`);
- }
- )
+ return fetch(`/v1/item/${ids}`, getInit('GET'))
+ .then(responseHandler)
.then((json) => {
for (let i = 0; i < json.items.length; i++) {
dispatch(addItem(json.items[i]));
@@ -183,20 +191,8 @@ export function postItem (item, type, id) {
if (id) {
item.id = id;
}
- let options = {
- method: 'POST',
- body: JSON.stringify(item),
- headers: {
- 'Content-Type':'application/json'
- }
- };
- return fetch(`/api/v1/${type}`, options)
- .then(
- response => {
- return response.ok ? response.json()
- : Promise.reject(`${response.status} ${response.statusText}`);
- }
- )
+ return fetch(`/api/v1/${type}`, getInit('POST', item))
+ .then(responseHandler)
.then((json) => {
dispatch(addItem({...item, id:json.id}, type));
return json.id;
@@ -227,23 +223,35 @@ export function postAction (item_id, action_type, user_id, item_type) {
action_type,
user_id
};
- const options = {
- method: 'POST',
- headers: {
- 'Content-Type':'application/json'
- },
- body: JSON.stringify(action)
- };
- return fetch(`/api/v1/${item_type}/${item_id}/actions`, options)
- .then(
- response => {
- return response.ok ? response.json()
- : Promise.reject(`${response.status} ${response.statusText}`);
- }
- )
- .then((json)=>{
- return json;
- });
+ return fetch(`/api/v1/${item_type}/${item_id}/actions`, getInit('POST', action))
+ .then(responseHandler);
+ };
+}
+
+/*
+* DeleteAction
+* Deletes an action to an item
+*
+* @params
+* id - the id of the item on which the action is taking place
+* action - the name of the action
+* user - the user performing the action
+* host - the coral host
+*
+* @returns
+* A promise resolving to null or an error
+*
+*/
+
+export function deleteAction (item_id, action_type, user_id, item_type) {
+ return () => {
+ const action = {
+ action_type,
+ user_id
+ };
+
+ return fetch(`/api/v1/${item_type}/${item_id}/actions`, getInit('DELETE', action))
+ .then(responseHandler);
};
}
diff --git a/client/coral-plugin-comment-count/CommentCount.js b/client/coral-plugin-comment-count/CommentCount.js
index 47f00ffb5..6786d5c74 100644
--- a/client/coral-plugin-comment-count/CommentCount.js
+++ b/client/coral-plugin-comment-count/CommentCount.js
@@ -5,12 +5,12 @@ const name = 'coral-plugin-comment-count';
const CommentCount = ({items, id}) => {
let count = 0;
- if (items[id]) {
- count += items[id].comments.length;
+ if (items.assets[id]) {
+ count += items.assets[id].comments.length;
}
- const itemKeys = Object.keys(items);
+ const itemKeys = Object.keys(items.comments);
for (let i = 0; i < itemKeys.length; i++) {
- const item = items[itemKeys[i]];
+ const item = items.comments[itemKeys[i]];
if (item.children) {
count += item.children.length;
}
diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js
index 4f90dfb7c..a4869c486 100644
--- a/client/coral-plugin-flags/FlagButton.js
+++ b/client/coral-plugin-flags/FlagButton.js
@@ -4,27 +4,35 @@ import translations from './translations.json';
const name = 'coral-plugin-flags';
-const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification}) => {
+const FlagButton = ({flag, id, postAction, deleteAction, addItem, updateItem, addNotification}) => {
const flagged = flag && flag.current_user;
const onFlagClick = () => {
- postAction(id, 'flag', '123', 'comments')
- .then((action) => {
- addItem({...action, current_user:true}, 'actions');
- updateItem(action.item_id, action.action_type, action.id, 'comments');
- });
- addNotification('success', lang.t('flag-notif'));
+ if (!flagged) {
+ postAction(id, 'flag', '123', 'comments')
+ .then((action) => {
+ addItem({...action, current_user:true}, 'actions');
+ updateItem(action.item_id, action.action_type, action.id, 'comments');
+ });
+ addNotification('success', lang.t('flag-notif'));
+ } else {
+ deleteAction(id, 'flag', '123', 'comments')
+ .then(() => {
+ updateItem(id, 'flag', '', 'comments');
+ });
+ addNotification('success', lang.t('flag-notif-remove'));
+ }
};
- return
-