From 32170e90d276b4d10c240df2a5ed54ba6ea409dd Mon Sep 17 00:00:00 2001 From: ireic Date: Wed, 18 Dec 2019 20:44:05 +0100 Subject: [PATCH] Implemented issue comments --- api/src/controllers/comments.ts | 33 +++ api/src/controllers/issues.ts | 2 +- api/src/entities/Comment.ts | 6 +- api/src/index.ts | 6 +- .../IssueDetails/Comments/BodyForm/Styles.js | 12 + .../IssueDetails/Comments/BodyForm/index.jsx | 54 ++++ .../IssueDetails/Comments/Comment/Styles.js | 66 +++++ .../IssueDetails/Comments/Comment/index.jsx | 83 ++++++ .../IssueDetails/Comments/Create/Style.js | 55 ++++ .../IssueDetails/Comments/Create/index.jsx | 62 ++++ .../Board/IssueDetails/Comments/Styles.js | 12 + .../Board/IssueDetails/Comments/index.jsx | 27 ++ .../Board/IssueDetails/Description/Styles.js | 2 +- .../Board/IssueDetails/Description/index.jsx | 4 +- .../Board/IssueDetails/Priority/Styles.js | 22 ++ .../Board/IssueDetails/Priority/index.jsx | 45 +++ .../Board/IssueDetails/RightActions/Styles.js | 146 ---------- .../Board/IssueDetails/RightActions/index.jsx | 267 ------------------ .../Board/IssueDetails/Status/Styles.js | 16 ++ .../Board/IssueDetails/Status/index.jsx | 40 +++ .../Project/Board/IssueDetails/Styles.js | 12 +- .../Board/IssueDetails/Title/Styles.js | 5 +- .../Board/IssueDetails/TopActions/index.jsx | 2 +- .../Board/IssueDetails/Tracking/Styles.js | 73 +++++ .../Board/IssueDetails/Tracking/index.jsx | 134 +++++++++ .../Board/IssueDetails/Users/Styles.js | 30 ++ .../Board/IssueDetails/Users/index.jsx | 85 ++++++ .../Project/Board/IssueDetails/index.jsx | 16 +- .../shared/components/ConfirmModal/Styles.js | 2 +- .../shared/components/ConfirmModal/index.jsx | 6 +- .../src/shared/components/Textarea/Styles.js | 2 +- .../src/shared/components/Textarea/index.jsx | 2 +- client/src/shared/hooks/deepCompareMemoize.js | 4 +- client/src/shared/utils/dateTime.js | 8 +- 34 files changed, 902 insertions(+), 439 deletions(-) create mode 100644 api/src/controllers/comments.ts create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/BodyForm/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/BodyForm/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/Comment/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/Comment/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/Create/Style.js create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/Create/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Comments/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Priority/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Priority/index.jsx delete mode 100644 client/src/components/Project/Board/IssueDetails/RightActions/Styles.js delete mode 100644 client/src/components/Project/Board/IssueDetails/RightActions/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Status/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Status/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Tracking/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Tracking/index.jsx create mode 100644 client/src/components/Project/Board/IssueDetails/Users/Styles.js create mode 100644 client/src/components/Project/Board/IssueDetails/Users/index.jsx diff --git a/api/src/controllers/comments.ts b/api/src/controllers/comments.ts new file mode 100644 index 0000000..3b4087c --- /dev/null +++ b/api/src/controllers/comments.ts @@ -0,0 +1,33 @@ +import express from 'express'; + +import { Comment } from 'entities'; +import { catchErrors } from 'errors'; +import { updateEntity, deleteEntity, createEntity } from 'utils/typeorm'; + +const router = express.Router(); + +router.post( + '/comments', + catchErrors(async (req, res) => { + const comment = await createEntity(Comment, req.body); + res.respond({ comment }); + }), +); + +router.put( + '/comments/:commentId', + catchErrors(async (req, res) => { + const comment = await updateEntity(Comment, req.params.commentId, req.body); + res.respond({ comment }); + }), +); + +router.delete( + '/comments/:commentId', + catchErrors(async (req, res) => { + const comment = await deleteEntity(Comment, req.params.commentId); + res.respond({ comment }); + }), +); + +export default router; diff --git a/api/src/controllers/issues.ts b/api/src/controllers/issues.ts index bab172f..cd7d12b 100644 --- a/api/src/controllers/issues.ts +++ b/api/src/controllers/issues.ts @@ -10,7 +10,7 @@ router.get( '/issues/:issueId', catchErrors(async (req, res) => { const issue = await findEntityOrThrow(Issue, req.params.issueId, { - relations: ['users', 'comments'], + relations: ['users', 'comments', 'comments.user'], }); res.respond({ issue }); }), diff --git a/api/src/entities/Comment.ts b/api/src/entities/Comment.ts index a96d193..f77f4a0 100644 --- a/api/src/entities/Comment.ts +++ b/api/src/entities/Comment.ts @@ -6,7 +6,6 @@ import { CreateDateColumn, UpdateDateColumn, ManyToOne, - RelationId, } from 'typeorm'; import is from 'utils/validation'; @@ -36,7 +35,7 @@ class Comment extends BaseEntity { ) user: User; - @RelationId((comment: Comment) => comment.user) + @Column('integer') userId: number; @ManyToOne( @@ -45,6 +44,9 @@ class Comment extends BaseEntity { { onDelete: 'CASCADE' }, ) issue: Issue; + + @Column('integer') + issueId: number; } export default Comment; diff --git a/api/src/index.ts b/api/src/index.ts index a38bb9a..4184769 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -7,8 +7,9 @@ import cors from 'cors'; import createDatabaseConnection from 'database/connection'; import { authenticateUser } from 'middleware/authentication'; import authenticationRoutes from 'controllers/authentication'; -import projectsRoutes from 'controllers/projects'; +import commentsRoutes from 'controllers/comments'; import issuesRoutes from 'controllers/issues'; +import projectsRoutes from 'controllers/projects'; import usersRoutes from 'controllers/users'; import { RouteNotFoundError } from 'errors'; import { errorHandler } from 'errors/errorHandler'; @@ -40,8 +41,9 @@ const initializeExpress = (): void => { app.use('/', authenticateUser); - app.use('/', projectsRoutes); + app.use('/', commentsRoutes); app.use('/', issuesRoutes); + app.use('/', projectsRoutes); app.use('/', usersRoutes); app.use((req, _res, next) => next(new RouteNotFoundError(req.originalUrl))); diff --git a/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/Styles.js b/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/Styles.js new file mode 100644 index 0000000..c25a3d6 --- /dev/null +++ b/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/Styles.js @@ -0,0 +1,12 @@ +import styled from 'styled-components'; + +import { Button } from 'shared/components'; + +export const Actions = styled.div` + display: flex; + padding-top: 10px; +`; + +export const FormButton = styled(Button)` + margin-right: 6px; +`; diff --git a/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/index.jsx b/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/index.jsx new file mode 100644 index 0000000..d96a728 --- /dev/null +++ b/client/src/components/Project/Board/IssueDetails/Comments/BodyForm/index.jsx @@ -0,0 +1,54 @@ +import React, { useRef } from 'react'; +import PropTypes from 'prop-types'; + +import { Textarea } from 'shared/components'; +import { Actions, FormButton } from './Styles'; + +const propTypes = { + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + isWorking: PropTypes.bool.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired, +}; + +const ProjectBoardIssueDetailsCommentsBodyForm = ({ + value, + onChange, + isWorking, + onSubmit, + onCancel, +}) => { + const $textareaRef = useRef(); + return ( + <> +