From 5a7bd05b37d76d6573ffe112cda9eccd87ae4243 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:14:41 +0900 Subject: [PATCH 1/7] Change the path of CommentDetail API --- backend/api/tests/api/test_comment.py | 2 +- backend/api/urls.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/api/tests/api/test_comment.py b/backend/api/tests/api/test_comment.py index d24f6902..a3622287 100644 --- a/backend/api/tests/api/test_comment.py +++ b/backend/api/tests/api/test_comment.py @@ -87,7 +87,7 @@ class TestCommentDetailAPI(CRUDMixin): doc = make_doc(self.project.item) comment = make_comment(doc, self.project.users[0]) self.data = {'text': 'example'} - self.url = reverse(viewname='comment_detail', args=[self.project.item.id, doc.id, comment.id]) + self.url = reverse(viewname='comment_detail', args=[self.project.item.id, comment.id]) def test_allows_comment_owner_to_get_comment(self): # Todo: Allows project member to get comment. diff --git a/backend/api/urls.py b/backend/api/urls.py index ba3ed0c5..be55ea77 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -126,7 +126,7 @@ urlpatterns_project = [ name='comment_list_project' ), path( - route='examples//comments/', + route='comments/', view=comment.CommentDetail.as_view(), name='comment_detail' ), From 6eb65e63a124c70fbe29b9f948caf23775a950dd Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:17:07 +0900 Subject: [PATCH 2/7] Change the view name of CommentListProject API --- backend/api/tests/api/test_comment.py | 2 +- backend/api/urls.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/api/tests/api/test_comment.py b/backend/api/tests/api/test_comment.py index a3622287..ad793776 100644 --- a/backend/api/tests/api/test_comment.py +++ b/backend/api/tests/api/test_comment.py @@ -45,7 +45,7 @@ class TestCommentListProjectAPI(CRUDMixin): self.non_member = make_user() self.doc = make_doc(self.project.item) make_comment(self.doc, self.project.users[0]) - self.url = reverse(viewname='comment_list_project', args=[self.project.item.id]) + self.url = reverse(viewname='comment_list', args=[self.project.item.id]) def test_allows_project_member_to_list_comments(self): for member in self.project.users: diff --git a/backend/api/urls.py b/backend/api/urls.py index be55ea77..dbf1e904 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -123,7 +123,7 @@ urlpatterns_project = [ path( route='comments', view=comment.CommentListProject.as_view(), - name='comment_list_project' + name='comment_list' ), path( route='comments/', From c9206e614d6d0a51d727660b2a877118708564d0 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:31:36 +0900 Subject: [PATCH 3/7] Allow CommentList API to filter comments by example id --- backend/api/tests/api/test_comment.py | 11 +++++++---- backend/api/urls.py | 2 +- backend/api/views/comment.py | 14 ++++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/api/tests/api/test_comment.py b/backend/api/tests/api/test_comment.py index ad793776..aca84d3f 100644 --- a/backend/api/tests/api/test_comment.py +++ b/backend/api/tests/api/test_comment.py @@ -11,15 +11,18 @@ class TestCommentListDocAPI(CRUDMixin): def setUpTestData(cls): cls.project = prepare_project() cls.non_member = make_user() - doc = make_doc(cls.project.item) - make_comment(doc, cls.project.users[0]) + doc1 = make_doc(cls.project.item) + doc2 = make_doc(cls.project.item) + make_comment(doc1, cls.project.users[0]) + make_comment(doc2, cls.project.users[0]) cls.data = {'text': 'example'} - cls.url = reverse(viewname='comment_list_doc', args=[cls.project.item.id, doc.id]) + cls.url = reverse(viewname='comment_list', args=[cls.project.item.id]) + cls.url += f'?example={doc1.id}' def test_allows_project_member_to_list_comments(self): for member in self.project.users: response = self.assert_fetch(member, status.HTTP_200_OK) - self.assertEqual(len(response.data), 1) + self.assertEqual(response.data['count'], 1) def test_denies_non_project_member_to_list_comments(self): self.assert_fetch(self.non_member, status.HTTP_403_FORBIDDEN) diff --git a/backend/api/urls.py b/backend/api/urls.py index dbf1e904..79885d28 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -122,7 +122,7 @@ urlpatterns_project = [ ), path( route='comments', - view=comment.CommentListProject.as_view(), + view=comment.CommentList.as_view(), name='comment_list' ), path( diff --git a/backend/api/views/comment.py b/backend/api/views/comment.py index 2871349d..168da5b7 100644 --- a/backend/api/views/comment.py +++ b/backend/api/views/comment.py @@ -27,22 +27,28 @@ class CommentListDoc(generics.ListCreateAPIView): serializer.save(example_id=self.kwargs['example_id'], user=self.request.user) -class CommentListProject(generics.ListAPIView): +class CommentList(generics.ListCreateAPIView): permission_classes = [IsAuthenticated & IsInProjectOrAdmin] serializer_class = CommentSerializer filter_backends = (DjangoFilterBackend, filters.SearchFilter) + filterset_fields = ['example'] search_fields = ('text',) - model = Comment def get_queryset(self): - queryset = self.model.objects.filter( + queryset = Comment.objects.filter( example__project_id=self.kwargs['project_id'] ) return queryset + def perform_create(self, serializer): + serializer.save( + example_id=self.request.query_params.get('example'), + user=self.request.user + ) + def delete(self, request, *args, **kwargs): delete_ids = request.data['ids'] - self.model.objects.filter(user=request.user, pk__in=delete_ids).delete() + Comment.objects.filter(user=request.user, pk__in=delete_ids).delete() return Response(status=status.HTTP_204_NO_CONTENT) From 9bd8758643a54214853bc984532dfb4e62bee811 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:33:41 +0900 Subject: [PATCH 4/7] Remove unused CommentListDoc API --- backend/api/urls.py | 5 ----- backend/api/views/comment.py | 17 ----------------- 2 files changed, 22 deletions(-) diff --git a/backend/api/urls.py b/backend/api/urls.py index 79885d28..b1fac0e1 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -115,11 +115,6 @@ urlpatterns_project = [ view=tag.TagDetail.as_view(), name='tag_detail' ), - path( - route='examples//comments', - view=comment.CommentListDoc.as_view(), - name='comment_list_doc' - ), path( route='comments', view=comment.CommentList.as_view(), diff --git a/backend/api/views/comment.py b/backend/api/views/comment.py index 168da5b7..727637e4 100644 --- a/backend/api/views/comment.py +++ b/backend/api/views/comment.py @@ -10,23 +10,6 @@ from ..permissions import IsOwnComment from ..serializers import CommentSerializer -class CommentListDoc(generics.ListCreateAPIView): - pagination_class = None - permission_classes = [IsAuthenticated & IsInProjectOrAdmin] - serializer_class = CommentSerializer - model = Comment - - def get_queryset(self): - queryset = self.model.objects.filter( - example__project_id=self.kwargs['project_id'], - example=self.kwargs['example_id'] - ) - return queryset - - def perform_create(self, serializer): - serializer.save(example_id=self.kwargs['example_id'], user=self.request.user) - - class CommentList(generics.ListCreateAPIView): permission_classes = [IsAuthenticated & IsInProjectOrAdmin] serializer_class = CommentSerializer From 50b70fdd12147b9fc04942cba81f79e465222e8c Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:42:51 +0900 Subject: [PATCH 5/7] Fix the url of comment repository --- frontend/repositories/comment/apiCommentRepository.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/repositories/comment/apiCommentRepository.ts b/frontend/repositories/comment/apiCommentRepository.ts index 2ac96b3b..e48a919f 100644 --- a/frontend/repositories/comment/apiCommentRepository.ts +++ b/frontend/repositories/comment/apiCommentRepository.ts @@ -16,25 +16,25 @@ export class APICommentRepository implements CommentRepository { } async list(projectId: string, exampleId: number): Promise { - const url = `/projects/${projectId}/examples/${exampleId}/comments` + const url = `/projects/${projectId}/comments?example=${exampleId}&limit=100` const response = await this.request.get(url) - return response.data.map((item: any) => plainToInstance(CommentItem, item)) + return response.data.results.map((item: any) => plainToInstance(CommentItem, item)) } async create(projectId: string, exampleId: number, text: string): Promise { - const url = `/projects/${projectId}/examples/${exampleId}/comments` + const url = `/projects/${projectId}/comments?example=${exampleId}` const response = await this.request.post(url, { projectId, exampleId, text }) return plainToInstance(CommentItem, response.data) } async update(projectId: string, exampleId: number, item: CommentItem): Promise { - const url = `/projects/${projectId}/examples/${exampleId}/comments/${item.id}` + const url = `/projects/${projectId}/comments/${item.id}` const response = await this.request.put(url, item.toObject()) return plainToInstance(CommentItem, response.data) } async delete(projectId: string, exampleId: number, commentId: number): Promise { - const url = `/projects/${projectId}/examples/${exampleId}/comments/${commentId}` + const url = `/projects/${projectId}/comments/${commentId}` const response = await this.request.delete(url) } From c5da8ec3a73e9b89fea8212160dbf75ef83c7eb5 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:49:23 +0900 Subject: [PATCH 6/7] Change the signature of CommentRepository --- frontend/components/tasks/toolbar/forms/FormComment.vue | 4 ++-- frontend/domain/models/comment/commentRepository.ts | 4 ++-- frontend/repositories/comment/apiCommentRepository.ts | 4 ++-- .../application/comment/commentApplicationService.ts | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/components/tasks/toolbar/forms/FormComment.vue b/frontend/components/tasks/toolbar/forms/FormComment.vue index 53925a50..bfdf0aed 100644 --- a/frontend/components/tasks/toolbar/forms/FormComment.vue +++ b/frontend/components/tasks/toolbar/forms/FormComment.vue @@ -73,11 +73,11 @@ export default Vue.extend({ this.list() }, async remove(item: CommentReadDTO) { - await this.$services.comment.delete(this.$route.params.id, this.docId, item) + await this.$services.comment.delete(this.$route.params.id, item) this.list() }, async maybeUpdate(item: CommentReadDTO) { - await this.$services.comment.update(this.$route.params.id, this.docId, item) + await this.$services.comment.update(this.$route.params.id, item) this.list() } } diff --git a/frontend/domain/models/comment/commentRepository.ts b/frontend/domain/models/comment/commentRepository.ts index bc8e931d..a5a02529 100644 --- a/frontend/domain/models/comment/commentRepository.ts +++ b/frontend/domain/models/comment/commentRepository.ts @@ -9,9 +9,9 @@ export interface CommentRepository { create(projectId: string, docId: number, text: string): Promise - update(projectId: string, docId: number, item: CommentItem): Promise + update(projectId: string, item: CommentItem): Promise - delete(projectId: string, docId: number, commentId: number): Promise + delete(projectId: string, commentId: number): Promise deleteBulk(projectId: string, items: number[]): Promise } diff --git a/frontend/repositories/comment/apiCommentRepository.ts b/frontend/repositories/comment/apiCommentRepository.ts index e48a919f..b6a08eb3 100644 --- a/frontend/repositories/comment/apiCommentRepository.ts +++ b/frontend/repositories/comment/apiCommentRepository.ts @@ -27,13 +27,13 @@ export class APICommentRepository implements CommentRepository { return plainToInstance(CommentItem, response.data) } - async update(projectId: string, exampleId: number, item: CommentItem): Promise { + async update(projectId: string, item: CommentItem): Promise { const url = `/projects/${projectId}/comments/${item.id}` const response = await this.request.put(url, item.toObject()) return plainToInstance(CommentItem, response.data) } - async delete(projectId: string, exampleId: number, commentId: number): Promise { + async delete(projectId: string, commentId: number): Promise { const url = `/projects/${projectId}/comments/${commentId}` const response = await this.request.delete(url) } diff --git a/frontend/services/application/comment/commentApplicationService.ts b/frontend/services/application/comment/commentApplicationService.ts index 621bb451..985228bb 100644 --- a/frontend/services/application/comment/commentApplicationService.ts +++ b/frontend/services/application/comment/commentApplicationService.ts @@ -22,13 +22,13 @@ export class CommentApplicationService { return this.repository.create(projectId, docId, text) } - public update(projectId: string, docId: number, item: CommentReadDTO): Promise { + public update(projectId: string, item: CommentReadDTO): Promise { const comment = plainToInstance(CommentItem, item) - return this.repository.update(projectId, docId, comment) + return this.repository.update(projectId, comment) } - public delete(projectId: string, docId: number, item: CommentReadDTO): Promise { - return this.repository.delete(projectId, docId, item.id) + public delete(projectId: string, item: CommentReadDTO): Promise { + return this.repository.delete(projectId, item.id) } public deleteBulk(projectId: string, items: CommentReadDTO[]): Promise { From 8eb7c87243d123343cc8b8f9738828dbfb761017 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Mon, 24 Jan 2022 08:56:35 +0900 Subject: [PATCH 7/7] Rename a prop name from docId to exampleId --- .../components/tasks/toolbar/ToolbarLaptop.vue | 2 +- .../tasks/toolbar/forms/FormComment.vue | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/components/tasks/toolbar/ToolbarLaptop.vue b/frontend/components/tasks/toolbar/ToolbarLaptop.vue index ebd76775..cdc8a42d 100644 --- a/frontend/components/tasks/toolbar/ToolbarLaptop.vue +++ b/frontend/components/tasks/toolbar/ToolbarLaptop.vue @@ -31,7 +31,7 @@ /> diff --git a/frontend/components/tasks/toolbar/forms/FormComment.vue b/frontend/components/tasks/toolbar/forms/FormComment.vue index bfdf0aed..3abb79e5 100644 --- a/frontend/components/tasks/toolbar/forms/FormComment.vue +++ b/frontend/components/tasks/toolbar/forms/FormComment.vue @@ -4,7 +4,7 @@ :cancel-text="$t('generic.close')" @cancel="$emit('click:cancel')" > -