Add initial comments setup
This commit is contained in:
parent
6ee5077c88
commit
10e5775bf4
102
packages/client/src/comments/CommentActions.ts
Normal file
102
packages/client/src/comments/CommentActions.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import {IHTTPClient} from '../http'
|
||||
import {IComment, IAPIDef} from '@rondo/common'
|
||||
|
||||
export enum ICommentActionTypes {
|
||||
VOTE_UP = 'VOTE_UP',
|
||||
VOTE_DOWN = 'VOTE_DOWN',
|
||||
COMMENTS_RETRIEVE = 'COMMENTS_RETRIEVE',
|
||||
COMMENT_ADD = 'COMMENT_ADD',
|
||||
COMMENT_EDIT = 'COMMENT_EDIT',
|
||||
COMMENT_REMOVE = 'COMMENT_DELETE',
|
||||
|
||||
SPAM_MARK = 'SPAM_MARK',
|
||||
SPAM_UNMARK = 'SPAM_UNMARK',
|
||||
}
|
||||
|
||||
export class CommentActions {
|
||||
constructor(protected readonly http: IHTTPClient<IAPIDef>) {}
|
||||
|
||||
voteUp(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.post('/comments/:commentId/vote', null, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.VOTE_UP,
|
||||
}
|
||||
}
|
||||
|
||||
voteDown(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.delete('/comments/:commentId/vote', null, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.VOTE_DOWN,
|
||||
}
|
||||
}
|
||||
|
||||
getComments(storyId: number) {
|
||||
return {
|
||||
payload: this.http.get('/story/:storyId/comments', null, {
|
||||
storyId,
|
||||
}),
|
||||
type: ICommentActionTypes.COMMENTS_RETRIEVE,
|
||||
}
|
||||
}
|
||||
|
||||
addComment(comment: IComment) {
|
||||
if (!comment.parentId) {
|
||||
// root comment
|
||||
return {
|
||||
payload: this.http.post('/story/:storyId/comments', comment, {
|
||||
storyId: comment.storyId,
|
||||
}),
|
||||
type: ICommentActionTypes.COMMENT_ADD,
|
||||
}
|
||||
}
|
||||
|
||||
// nested comment
|
||||
return {
|
||||
payload: this.http.post('/comments/:parentId', comment, {
|
||||
parentId: comment.parentId,
|
||||
}),
|
||||
type: ICommentActionTypes.COMMENT_ADD,
|
||||
}
|
||||
}
|
||||
|
||||
editComment(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.put('/comments/:commentId', comment, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.COMMENT_EDIT,
|
||||
}
|
||||
}
|
||||
|
||||
removeComment(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.delete('/comments/:commentId', null, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.COMMENT_REMOVE,
|
||||
}
|
||||
}
|
||||
|
||||
markAsSpam(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.post('/comments/:commentId/spam', comment, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.SPAM_MARK,
|
||||
}
|
||||
}
|
||||
|
||||
unmarkAsSpam(comment: IComment) {
|
||||
return {
|
||||
payload: this.http.delete('/comments/:commentId/spam', null, {
|
||||
commentId: comment.id,
|
||||
}),
|
||||
type: ICommentActionTypes.SPAM_UNMARK,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
49
packages/client/src/comments/Comments.tsx
Normal file
49
packages/client/src/comments/Comments.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import React from 'react'
|
||||
import {IComment} from '@rondo/common'
|
||||
|
||||
export interface ICommentProps {
|
||||
comment: IComment
|
||||
}
|
||||
|
||||
export class CommentVote extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class CommentButtons extends React.PureComponent {
|
||||
render() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class Comment extends React.PureComponent<ICommentProps> {
|
||||
render() {
|
||||
const {comment} = this.props
|
||||
return (
|
||||
<div className='comment'>
|
||||
<span className='score'>{comment.score}</span>
|
||||
<p>{comment.message}</p>
|
||||
|
||||
<Comments comments={comment.children} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export interface ICommentsProps {
|
||||
comments: IComment[]
|
||||
}
|
||||
|
||||
export class Comments extends React.PureComponent<ICommentsProps> {
|
||||
render() {
|
||||
const {comments} = this.props
|
||||
return (
|
||||
<div className='comments'>
|
||||
{comments.map(comment => <Comment comment={comment} />)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,2 +1,6 @@
|
||||
export * from './HTTPClient'
|
||||
export * from './IHTTPClient'
|
||||
export * from './IHeader'
|
||||
export * from './IRequest'
|
||||
export * from './IResponse'
|
||||
export * from './ITypedRequestParams'
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {ICredentials} from './ICredentials'
|
||||
import {IComment} from './IComment'
|
||||
import {IUser} from './IUser'
|
||||
|
||||
export interface IAPIDef {
|
||||
@ -15,7 +16,7 @@ export interface IAPIDef {
|
||||
}
|
||||
'/auth/logout': {
|
||||
'get': {}
|
||||
},
|
||||
}
|
||||
'/users/password': {
|
||||
'post': {
|
||||
body: {
|
||||
@ -31,4 +32,65 @@ export interface IAPIDef {
|
||||
}
|
||||
}
|
||||
}
|
||||
'/story/:storyId/comments': {
|
||||
'get': {
|
||||
response: IComment[],
|
||||
params: {
|
||||
storyId: number // TODO might have to change to string (url)
|
||||
}
|
||||
}
|
||||
'post': {
|
||||
response: IComment,
|
||||
params: {
|
||||
storyId: number
|
||||
}
|
||||
}
|
||||
}
|
||||
'/comments/:parentId': {
|
||||
'post': {
|
||||
response: IComment,
|
||||
params: {
|
||||
parentId: number
|
||||
},
|
||||
body: IComment,
|
||||
}
|
||||
}
|
||||
'/comments/:commentId': {
|
||||
'put': {
|
||||
response: IComment,
|
||||
body: IComment,
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
'delete': {
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
}
|
||||
'/comments/:commentId/vote': {
|
||||
'post': {
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
'delete': {
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
}
|
||||
'/comments/:commentId/spam': {
|
||||
'post': {
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
'delete': {
|
||||
params: {
|
||||
commentId: number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
packages/common/src/IComment.ts
Normal file
8
packages/common/src/IComment.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface IComment {
|
||||
id: number
|
||||
storyId: number
|
||||
message: string
|
||||
score: number
|
||||
parentId: number
|
||||
children: IComment[]
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
export * from './IAPIDef'
|
||||
export * from './IComment'
|
||||
export * from './ICredentials'
|
||||
export * from './IRoutes'
|
||||
export * from './IUser'
|
||||
|
||||
0
packages/server/src/entities/Comment.ts
Normal file
0
packages/server/src/entities/Comment.ts
Normal file
0
packages/server/src/entities/Site.ts
Normal file
0
packages/server/src/entities/Site.ts
Normal file
0
packages/server/src/entities/Story.ts
Normal file
0
packages/server/src/entities/Story.ts
Normal file
0
packages/server/src/entities/Team.ts
Normal file
0
packages/server/src/entities/Team.ts
Normal file
0
packages/server/src/entities/TeamUser.ts
Normal file
0
packages/server/src/entities/TeamUser.ts
Normal file
68
packages/server/src/routes/CommentRoutes.ts
Normal file
68
packages/server/src/routes/CommentRoutes.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {AsyncRouter} from '../router'
|
||||
import {BaseRoute} from './BaseRoute'
|
||||
import {IAPIDef} from '@rondo/common'
|
||||
import {ensureLoggedInApi} from '../middleware'
|
||||
|
||||
export class CommentRoutes extends BaseRoute<IAPIDef> {
|
||||
constructor(
|
||||
protected readonly commentService: ICommentService,
|
||||
protected readonly t: AsyncRouter<IAPIDef>,
|
||||
) {
|
||||
super(t)
|
||||
}
|
||||
|
||||
setup(t: AsyncRouter<IAPIDef>) {
|
||||
|
||||
t.get('/story/:storyId/comments', async req => {
|
||||
const {storyId} = req.params
|
||||
// TODO retrieve comments from story
|
||||
return []
|
||||
})
|
||||
|
||||
t.use(ensureLoggedInApi)
|
||||
|
||||
t.post('/story/:storyId/comments', async req => {
|
||||
const comment = req.body
|
||||
// TODO save a comment
|
||||
return comment
|
||||
})
|
||||
|
||||
t.post('/comments/:parentId', async req => {
|
||||
const comment = req.body
|
||||
// TODO save a comment
|
||||
return comment
|
||||
})
|
||||
|
||||
t.put('/comments/:commentId', async req => {
|
||||
const comment = req.body
|
||||
// TODO edit a comment
|
||||
return comment
|
||||
})
|
||||
|
||||
t.delete('/comments/:commentId', async req => {
|
||||
const {commentId} = req.params
|
||||
// TODO delete a comment
|
||||
})
|
||||
|
||||
t.post('/comments/:commentId/vote', async req => {
|
||||
const {commentId} = req.params
|
||||
// TODO upvote a comment
|
||||
})
|
||||
|
||||
t.delete('/comments/:commentId/vote', async req => {
|
||||
const {commentId} = req.params
|
||||
// TODO delete a vote
|
||||
})
|
||||
|
||||
t.post('/comments/:commentId/spam', async req => {
|
||||
const {commentId} = req.params
|
||||
// TODO report comment as spam
|
||||
})
|
||||
|
||||
t.delete('/comments/:commentId/spam', async req => {
|
||||
const {commentId} = req.params
|
||||
// TODO delete spam report
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,7 @@ export class LoginRoutes extends BaseRoute<IAPIDef> {
|
||||
}
|
||||
await req.logInPromise(user)
|
||||
res.redirect(req.baseUrl)
|
||||
// TODO return user
|
||||
})
|
||||
|
||||
t.get('/auth/logout', async (req, res) => {
|
||||
|
||||
34
packages/server/src/services/CommentService.ts
Normal file
34
packages/server/src/services/CommentService.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import {BaseService} from './BaseService'
|
||||
import {IComment} from '@rondo/common'
|
||||
import {ICommentService} from'./ICommentService'
|
||||
|
||||
export class CommentService extends BaseService implements ICommentService {
|
||||
|
||||
async find(storyId: number) {
|
||||
}
|
||||
|
||||
async saveRoot(comment: IComment, userId: number) {
|
||||
}
|
||||
|
||||
async save(comment: IComment, userId: number) {
|
||||
}
|
||||
|
||||
async edit(comment: IComment, userId: number) {
|
||||
}
|
||||
|
||||
async delete(comment: IComment, userId: number) {
|
||||
}
|
||||
|
||||
async upVote(commentId: number, userId: number) {
|
||||
}
|
||||
|
||||
async deleteVote(commentId: number, userId: number) {
|
||||
}
|
||||
|
||||
async markAsSpam(commentId: number, userId: number) {
|
||||
}
|
||||
|
||||
async unmarkAsSpam(commentId: number, userId: number) {
|
||||
}
|
||||
|
||||
}
|
||||
21
packages/server/src/services/ICommentService.ts
Normal file
21
packages/server/src/services/ICommentService.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import {IComment} from '@rondo/common'
|
||||
|
||||
export interface ICommentService {
|
||||
find(storyId: number): Promise<IComment>
|
||||
|
||||
saveRoot(comment: IComment, userId: number): Promise<IComment>
|
||||
|
||||
save(comment: IComment, userId: number): Promise<IComment>
|
||||
|
||||
edit(comment: IComment, userId: number): Promise<IComment>
|
||||
|
||||
delete(comment: IComment, userId: number): Promise<IComment>
|
||||
|
||||
upVote(commentId: number, userId: number): Promise<void>
|
||||
|
||||
deleteVote(commentId: number, userId: number): Promise<void>
|
||||
|
||||
markAsSpam(commentId: number, userId: number): Promise<void>
|
||||
|
||||
unmarkAsSpam(commentId: number, userId: number): Promise<void>
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user