Browse Source

Merge pull request #2146 from doccano/enhancement/frontend-comment

Enhancement/frontend-comment
pull/2147/head
Hiroki Nakayama 1 year ago
committed by GitHub
parent
commit
27473ea2ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 36 additions and 131 deletions
  1. 6
      frontend/components/comment/Comment.vue
  2. 6
      frontend/components/comment/CommentList.vue
  3. 16
      frontend/components/tasks/toolbar/forms/FormComment.vue
  4. 9
      frontend/domain/models/comment/comment.ts
  5. 17
      frontend/domain/models/comment/commentRepository.ts
  6. 11
      frontend/pages/projects/_id/comments/index.vue
  7. 3
      frontend/plugins/services.ts
  8. 27
      frontend/repositories/comment/apiCommentRepository.ts
  9. 39
      frontend/services/application/comment/commentApplicationService.ts
  10. 33
      frontend/services/application/comment/commentData.ts

6
frontend/components/comment/Comment.vue

@ -66,10 +66,12 @@
</template>
<script lang="ts">
import Vue from 'vue'
import { mdiAccountCircle, mdiDotsVertical } from '@mdi/js'
import VueFilterDateFormat from '@vuejs-community/vue-filter-date-format'
import VueFilterDateParse from '@vuejs-community/vue-filter-date-parse'
import type { PropType } from 'vue'
import Vue from 'vue'
import { CommentItem } from '~/domain/models/comment/comment'
Vue.use(VueFilterDateFormat)
Vue.use(VueFilterDateParse)
@ -77,7 +79,7 @@ export default Vue.extend({
props: {
comment: {
required: true,
type: Object
type: Object as PropType<CommentItem>
},
userId: {
required: true,

6
frontend/components/comment/CommentList.vue

@ -55,7 +55,7 @@ import VueFilterDateParse from '@vuejs-community/vue-filter-date-parse'
import type { PropType } from 'vue'
import Vue from 'vue'
import { DataOptions } from 'vuetify/types'
import { CommentReadDTO } from '~/services/application/comment/commentData'
import { CommentItem } from '~/domain/models/comment/comment'
Vue.use(VueFilterDateFormat)
Vue.use(VueFilterDateParse)
@ -67,12 +67,12 @@ export default Vue.extend({
required: true
},
items: {
type: Array as PropType<CommentReadDTO[]>,
type: Array as PropType<CommentItem[]>,
default: () => [],
required: true
},
value: {
type: Array as PropType<CommentReadDTO[]>,
type: Array as PropType<CommentItem[]>,
default: () => [],
required: true
},

16
frontend/components/tasks/toolbar/forms/FormComment.vue

@ -23,8 +23,8 @@ import Vue from 'vue'
import Comment from '@/components/comment/Comment.vue'
import FormCreate from '@/components/comment/FormCreate.vue'
import BaseCard from '@/components/utils/BaseCard.vue'
import { CommentItem } from '~/domain/models/comment/comment'
import { UserItem } from '~/domain/models/user/user'
import { CommentReadDTO } from '~/services/application/comment/commentData'
export default Vue.extend({
components: {
@ -43,7 +43,7 @@ export default Vue.extend({
data() {
return {
user: {} as UserItem,
comments: [] as CommentReadDTO[]
comments: [] as CommentItem[]
}
},
@ -65,18 +65,18 @@ export default Vue.extend({
methods: {
async list() {
this.comments = await this.$services.comment.list(this.$route.params.id, this.exampleId)
this.comments = await this.$repositories.comment.list(this.$route.params.id, this.exampleId)
},
async add(message: string) {
await this.$services.comment.create(this.$route.params.id, this.exampleId, message)
await this.$repositories.comment.create(this.$route.params.id, this.exampleId, message)
this.list()
},
async remove(item: CommentReadDTO) {
await this.$services.comment.delete(this.$route.params.id, item)
async remove(item: CommentItem) {
await this.$repositories.comment.delete(this.$route.params.id, item)
this.list()
},
async maybeUpdate(item: CommentReadDTO) {
await this.$services.comment.update(this.$route.params.id, item)
async maybeUpdate(item: CommentItem) {
await this.$repositories.comment.update(this.$route.params.id, item)
this.list()
}
}

9
frontend/domain/models/comment/comment.ts

@ -12,12 +12,3 @@ export class CommentItem {
return this.user === userId
}
}
export class CommentItemList {
constructor(
readonly count: number,
readonly next: string | null,
readonly prev: string | null,
readonly items: CommentItem[]
) {}
}

17
frontend/domain/models/comment/commentRepository.ts

@ -1,17 +0,0 @@
import { CommentItem, CommentItemList } from '~/domain/models/comment/comment'
export type SearchOption = { [key: string]: string | (string | null)[] }
export interface CommentRepository {
listAll(projectId: string, { limit, offset, q }: SearchOption): Promise<CommentItemList>
list(projectId: string, docId: number): Promise<CommentItem[]>
create(projectId: string, docId: number, text: string): Promise<CommentItem>
update(projectId: string, item: CommentItem): Promise<CommentItem>
delete(projectId: string, commentId: number): Promise<void>
deleteBulk(projectId: string, items: number[]): Promise<void>
}

11
frontend/pages/projects/_id/comments/index.vue

@ -29,9 +29,10 @@ import _ from 'lodash'
import Vue from 'vue'
import CommentList from '@/components/comment/CommentList.vue'
import FormDelete from '~/components/comment/FormDelete.vue'
import { CommentItem } from '~/domain/models/comment/comment'
import { Page } from '~/domain/models/page'
import { Project } from '~/domain/models/project/project'
import { getLinkToAnnotationPage } from '~/presenter/linkToAnnotationPage'
import { CommentListDTO, CommentReadDTO } from '~/services/application/comment/commentData'
export default Vue.extend({
components: {
@ -48,8 +49,8 @@ export default Vue.extend({
return {
dialogDelete: false,
project: {} as Project,
item: {} as CommentListDTO,
selected: [] as CommentReadDTO[],
item: {} as Page<CommentItem>,
selected: [] as CommentItem[],
isLoading: false
}
},
@ -57,7 +58,7 @@ export default Vue.extend({
async fetch() {
this.isLoading = true
this.project = await this.$services.project.findById(this.projectId)
this.item = await this.$services.comment.listProjectComment(this.projectId, this.$route.query)
this.item = await this.$repositories.comment.listAll(this.projectId, this.$route.query)
this.isLoading = false
},
@ -79,7 +80,7 @@ export default Vue.extend({
methods: {
async remove() {
await this.$services.comment.deleteBulk(this.projectId, this.selected)
await this.$repositories.comment.deleteBulk(this.projectId, this.selected)
this.$fetch()
this.dialogDelete = false
this.selected = []

3
frontend/plugins/services.ts

@ -1,7 +1,6 @@
import { Plugin } from '@nuxt/types'
import { repositories } from './repositories'
import { ConfigApplicationService } from '@/services/application/autoLabeling/configApplicationService'
import { CommentApplicationService } from '@/services/application/comment/commentApplicationService'
import { ExampleApplicationService } from '@/services/application/example/exampleApplicationService'
import { LabelApplicationService } from '@/services/application/label/labelApplicationService'
import { MemberApplicationService } from '@/services/application/member/memberApplicationService'
@ -20,7 +19,6 @@ export interface Services {
relationType: LabelApplicationService
member: MemberApplicationService
project: ProjectApplicationService
comment: CommentApplicationService
example: ExampleApplicationService
textClassification: TextClassificationService
sequenceLabeling: SequenceLabelingApplicationService
@ -45,7 +43,6 @@ const plugin: Plugin = (_, inject) => {
relationType: new LabelApplicationService(repositories.relationType),
member: new MemberApplicationService(repositories.member),
project: new ProjectApplicationService(repositories.project),
comment: new CommentApplicationService(repositories.comment),
example: new ExampleApplicationService(repositories.example),
textClassification: new TextClassificationService(repositories.category),
sequenceLabeling: new SequenceLabelingApplicationService(

27
frontend/repositories/comment/apiCommentRepository.ts

@ -1,6 +1,8 @@
import { CommentItem } from '@/domain/models/comment/comment'
import { Page } from '@/domain/models/page'
import ApiService from '@/services/api.service'
import { CommentRepository, SearchOption } from '@/domain/models/comment/commentRepository'
import { CommentItem, CommentItemList } from '@/domain/models/comment/comment'
export type SearchOption = { [key: string]: string | (string | null)[] }
function toModel(item: { [key: string]: any }): CommentItem {
return new CommentItem(
@ -21,16 +23,16 @@ function toPayload(item: CommentItem): { [key: string]: any } {
}
}
export class APICommentRepository implements CommentRepository {
export class APICommentRepository {
constructor(private readonly request = ApiService) {}
async listAll(
projectId: string,
{ limit = '10', offset = '0', q = '' }: SearchOption
): Promise<CommentItemList> {
): Promise<Page<CommentItem>> {
const url = `/projects/${projectId}/comments?q=${q}&limit=${limit}&offset=${offset}`
const response = await this.request.get(url)
return new CommentItemList(
return new Page(
response.data.count,
response.data.next,
response.data.previous,
@ -54,20 +56,21 @@ export class APICommentRepository implements CommentRepository {
return toModel(response.data)
}
async update(projectId: string, item: CommentItem): Promise<CommentItem> {
const url = `/projects/${projectId}/comments/${item.id}`
const payload = toPayload(item)
async update(projectId: string, comment: CommentItem): Promise<CommentItem> {
const url = `/projects/${projectId}/comments/${comment.id}`
const payload = toPayload(comment)
const response = await this.request.put(url, payload)
return toModel(response.data)
}
async delete(projectId: string, commentId: number): Promise<void> {
const url = `/projects/${projectId}/comments/${commentId}`
async delete(projectId: string, comment: CommentItem): Promise<void> {
const url = `/projects/${projectId}/comments/${comment.id}`
await this.request.delete(url)
}
async deleteBulk(projectId: string, items: number[]): Promise<void> {
async deleteBulk(projectId: string, comments: CommentItem[]): Promise<void> {
const url = `/projects/${projectId}/comments`
await this.request.delete(url, { ids: items })
const ids = comments.map((comment) => comment.id)
await this.request.delete(url, { ids })
}
}

39
frontend/services/application/comment/commentApplicationService.ts

@ -1,39 +0,0 @@
import { plainToInstance } from 'class-transformer'
import { CommentReadDTO, CommentListDTO } from './commentData'
import { CommentRepository, SearchOption } from '~/domain/models/comment/commentRepository'
import { CommentItem } from '~/domain/models/comment/comment'
export class CommentApplicationService {
constructor(private readonly repository: CommentRepository) {}
public async listProjectComment(
projectId: string,
options: SearchOption
): Promise<CommentListDTO> {
const item = await this.repository.listAll(projectId, options)
return new CommentListDTO(item)
}
public async list(projectId: string, docId: number): Promise<CommentReadDTO[]> {
const items = await this.repository.list(projectId, docId)
return items.map((item) => new CommentReadDTO(item))
}
public create(projectId: string, docId: number, text: string): Promise<CommentItem> {
return this.repository.create(projectId, docId, text)
}
public update(projectId: string, item: CommentReadDTO): Promise<CommentItem> {
const comment = plainToInstance(CommentItem, item)
return this.repository.update(projectId, comment)
}
public delete(projectId: string, item: CommentReadDTO): Promise<void> {
return this.repository.delete(projectId, item.id)
}
public deleteBulk(projectId: string, items: CommentReadDTO[]): Promise<void> {
const ids = items.map((item) => item.id)
return this.repository.deleteBulk(projectId, ids)
}
}

33
frontend/services/application/comment/commentData.ts

@ -1,33 +0,0 @@
import { CommentItem, CommentItemList } from '~/domain/models/comment/comment'
export class CommentReadDTO {
id: number
user: number
username: string
example: number
text: string
createdAt: string
constructor(item: CommentItem) {
this.id = item.id
this.user = item.user
this.username = item.username
this.example = item.example
this.text = item.text
this.createdAt = item.createdAt
}
}
export class CommentListDTO {
count: number
next: string | null
prev: string | null
items: CommentReadDTO[]
constructor(item: CommentItemList) {
this.count = item.count
this.next = item.next
this.prev = item.prev
this.items = item.items.map((_) => new CommentReadDTO(_))
}
}
Loading…
Cancel
Save