mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 18:41:31 +08:00
Merge pull request #300 from coralproject/story-137818425-tag-staff
Tag comments made by Staff with 'STAFF' tag automatically.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,7 @@
|
||||
.staff {
|
||||
background-color: #4C1066;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
margin: 10px 10px;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user