Merge pull request #300 from coralproject/story-137818425-tag-staff

Tag comments made by Staff with 'STAFF' tag automatically.
This commit is contained in:
Gabriela Rodríguez Berón
2017-02-10 13:48:41 -08:00
committed by GitHub
10 changed files with 151 additions and 5 deletions
+12 -2
View File
@@ -10,6 +10,8 @@ import React, {PropTypes} from 'react';
import PermalinkButton from 'coral-plugin-permalinks/PermalinkButton';
import AuthorName from 'coral-plugin-author-name/AuthorName';
import TagLabel from 'coral-plugin-tag-label/TagLabel';
import Content from 'coral-plugin-commentcontent/CommentContent';
import PubDate from 'coral-plugin-pubdate/PubDate';
import {ReplyBox, ReplyButton} from 'coral-plugin-replies';
@@ -20,6 +22,7 @@ import styles from './Comment.css';
const getActionSummary = (type, comment) => comment.action_summaries
.filter((a) => a.__typename === type)[0];
const isStaff = (tags) => !tags.every((t) => t.name !== 'STAFF') ;
class Comment extends React.Component {
@@ -56,12 +59,16 @@ class Comment extends React.Component {
action_summaries: PropTypes.array.isRequired,
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
tags: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string
})
),
replies: PropTypes.arrayOf(
PropTypes.shape({
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired
})
),
})),
user: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired
@@ -98,6 +105,9 @@ class Comment extends React.Component {
<hr aria-hidden={true} />
<AuthorName
author={comment.user}/>
{ isStaff(comment.tags)
? <TagLabel isStaff={true}/>
: null }
<PubDate created_at={comment.created_at} />
<Content body={comment.body} />
<div className="commentActionsLeft">
@@ -5,6 +5,9 @@ fragment commentView on Comment {
body
created_at
status
tags {
name
}
user {
id
name: displayName
+3
View File
@@ -58,6 +58,9 @@ const StreamQuery = gql`fragment commentView on Comment {
user {
name: displayName
}
tags {
name
}
actions {
type: action_type
count
@@ -0,0 +1,9 @@
import React from 'react';
import styles from './styles.css';
const TagLabel = ({isStaff}) => <div className={`${styles.staff}`}>
{isStaff ? 'Staff' : ''}
</div>;
export default TagLabel;
+7
View File
@@ -0,0 +1,7 @@
.staff {
background-color: #4C1066;
color: white;
display: inline-block;
margin: 10px 10px;
padding: 5px 5px;
}
+6
View File
@@ -36,6 +36,12 @@ const createComment = ({user, loaders: {Comments}}, {body, asset_id, parent_id =
}
}
if (user.hasRoles('ADMIN')) {
return CommentsService
.addTag(comment.id, 'STAFF', user.id)
.then(() => comment);
}
return comment;
});
};
+19 -1
View File
@@ -5,6 +5,7 @@
# Date represented as an ISO8601 string.
scalar Date
################################################################################
## Users
################################################################################
@@ -45,6 +46,17 @@ type User {
comments(query: CommentsQuery): [Comment]
}
type Tag {
# the actual tag for the comment.
name: String!
# the user that assigned the tag. If NULL then the system automatically tagged it.
assigned_by: String
# the time when the tag was assigned.
created_at: Date!
}
################################################################################
## Comments
################################################################################
@@ -96,6 +108,9 @@ input CommentsQuery {
# skip results from the last created_at timestamp.
cursor: Date
# filter by a specific tag name.
tag: [String]
# sort the results by created_at.
sort: SORT_ORDER = REVERSE_CHRONOLOGICAL
}
@@ -109,7 +124,10 @@ type Comment {
# The actual comment data.
body: String!
# The user who authored the comment.
# the tags on the comment
tags: [Tag]
# the user who authored the comment.
user: User
# the recent replies made against this comment.
+19
View File
@@ -30,6 +30,24 @@ const StatusSchema = new Schema({
_id: false
});
/**
* The Mongo schema for a Comment Tag.
* @type {Schema}
*/
const TagSchema = new Schema({
name: String,
// The User ID of the user that assigned the status.
assigned_by: {
type: String,
default: null
},
created_at: Date
}, {
_id: false
});
/**
* The Mongo schema for a Comment.
* @type {Schema}
@@ -49,6 +67,7 @@ const CommentSchema = new Schema({
author_id: String,
status_history: [StatusSchema],
status: {type: String, default: null},
tags: [TagSchema],
parent_id: String
}, {
timestamps: {
+32
View File
@@ -3,6 +3,10 @@ const CommentModel = require('../models/comment');
const ActionModel = require('../models/action');
const ActionsService = require('./actions');
const ALLOWED_TAGS = [
{name: 'STAFF'}
];
module.exports = class CommentsService {
/**
@@ -33,6 +37,7 @@ module.exports = class CommentsService {
type: status,
created_at: new Date()
}] : [],
tags: [],
status,
author_id
});
@@ -40,6 +45,33 @@ module.exports = class CommentsService {
return comment.save();
}
/**
* Adds a tag if it doesn't already exist on the comment.
*/
static addTag(id, name, assigned_by) {
if (ALLOWED_TAGS.find((t) => t.name === name) == null) {
return Promise.reject(new Error('tag not allowed'));
}
return CommentModel.update({
id,
tags: {
$ne: {
name
}
}
}, {
$push: {
tags: {
name,
assigned_by,
created_at: new Date()
}
}
});
}
/**
* Finds a comment by the id.
* @param {String} id identifier of comment (uuid)
+41 -2
View File
@@ -70,11 +70,14 @@ describe('services.CommentsService', () => {
const users = [{
email: 'stampi@gmail.com',
displayName: 'Stampi',
password: '1Coral!!'
password: '1Coral!!',
roles: ['ADMIN'],
_id: '1'
}, {
email: 'sockmonster@gmail.com',
displayName: 'Sockmonster',
password: '2Coral!!'
password: '2Coral!!',
_id : '2'
}];
const actions = [{
@@ -256,4 +259,40 @@ describe('services.CommentsService', () => {
});
});
describe('#tagByStaff()', () => {
it('creates a new comment by admin', () => {
return UsersService.findLocalUser('stampi@gmail.com', '1Coral!!').then((user) => {
return UsersService.addRoleToUser(user.id, 'ADMIN').then(() => {
UsersService.findById(user.id).then((u) => {
return CommentsService
.publicCreate({
body: 'This is a comment!',
status: 'ACCEPTED',
author_id: u.id
}).then((c) => {
expect(c).to.not.be.null;
expect(c.tags).to.not.have.length(0);
expect(c.tags[0].name).to.be.equal('STAFF');
});
});
});
});
});
it('creates a new comment by non admin', () => {
return UsersService.findLocalUser('sockmonster@gmail.com', '2Coral!!').then((user) => {
return CommentsService
.publicCreate({
body: 'This is a comment!',
status: 'ACCEPTED',
author_id: user.id
}).then((c) => {
expect(c).to.not.be.null;
expect(c.tags).to.have.length(0);
});
});
});
});
});