You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.8 KiB

2 years ago
  1. import { Page } from '@/domain/models/page'
  2. import { Project } from '@/domain/models/project/project'
  3. import ApiService from '@/services/api.service'
  4. import { TagItem } from '~/domain/models/tag/tag'
  5. const sortableFieldList = ['name', 'projectType', 'createdAt', 'author'] as const
  6. type SortableFields = (typeof sortableFieldList)[number]
  7. export class SearchQuery {
  8. readonly limit: number = 10
  9. readonly offset: number = 0
  10. readonly q: string = ''
  11. readonly sortBy: SortableFields = 'createdAt'
  12. readonly sortDesc: boolean = false
  13. constructor(_limit: string, _offset: string, _q?: string, _sortBy?: string, _sortDesc?: string) {
  14. this.limit = /^\d+$/.test(_limit) ? parseInt(_limit) : 10
  15. this.offset = /^\d+$/.test(_offset) ? parseInt(_offset) : 0
  16. this.q = _q || ''
  17. this.sortBy = (
  18. _sortBy && sortableFieldList.includes(_sortBy as SortableFields) ? _sortBy : 'createdAt'
  19. ) as SortableFields
  20. this.sortDesc = _sortDesc === 'true'
  21. }
  22. }
  23. function toModel(item: { [key: string]: any }): Project {
  24. return new Project(
  25. item.id,
  26. item.name,
  27. item.description,
  28. item.guideline,
  29. item.project_type,
  30. item.random_order,
  31. item.collaborative_annotation,
  32. item.single_class_classification,
  33. item.allow_overlapping,
  34. item.grapheme_mode,
  35. item.use_relation,
  36. item.tags.map((tag: { [key: string]: any }) => new TagItem(tag.id, tag.text, tag.project)),
  37. item.allow_member_to_create_label_type,
  38. item.users,
  39. item.created_at,
  40. item.updated_at,
  41. item.author,
  42. item.is_text_project
  43. )
  44. }
  45. function toPayload(item: Project): { [key: string]: any } {
  46. return {
  47. id: item.id,
  48. name: item.name,
  49. description: item.description,
  50. guideline: item.guideline,
  51. project_type: item.projectType,
  52. random_order: item.enableRandomOrder,
  53. collaborative_annotation: item.enableSharingMode,
  54. single_class_classification: item.exclusiveCategories,
  55. allow_overlapping: item.allowOverlappingSpans,
  56. grapheme_mode: item.enableGraphemeMode,
  57. use_relation: item.useRelation,
  58. tags: item.tags,
  59. allow_member_to_create_label_type: item.allowMemberToCreateLabelType,
  60. resourcetype: item.resourceType
  61. }
  62. }
  63. export class APIProjectRepository {
  64. constructor(private readonly request = ApiService) {}
  65. async list(query: SearchQuery): Promise<Page<Project>> {
  66. const fieldMapper = {
  67. name: 'name',
  68. createdAt: 'created_at',
  69. projectType: 'project_type',
  70. author: 'created_by'
  71. }
  72. const sortBy = fieldMapper[query.sortBy]
  73. const ordering = query.sortDesc ? `-${sortBy}` : `${sortBy}`
  74. const url = `/projects?limit=${query.limit}&offset=${query.offset}&q=${query.q}&ordering=${ordering}`
  75. const response = await this.request.get(url)
  76. return new Page(
  77. response.data.count,
  78. response.data.next,
  79. response.data.previous,
  80. response.data.results.map((project: { [key: string]: any }) => toModel(project))
  81. )
  82. }
  83. async findById(id: string): Promise<Project> {
  84. const url = `/projects/${id}`
  85. const response = await this.request.get(url)
  86. return toModel(response.data)
  87. }
  88. async create(item: Project): Promise<Project> {
  89. const url = `/projects`
  90. const payload = toPayload(item)
  91. const response = await this.request.post(url, payload)
  92. return toModel(response.data)
  93. }
  94. async update(item: Project): Promise<void> {
  95. const url = `/projects/${item.id}`
  96. const payload = toPayload(item)
  97. await this.request.patch(url, payload)
  98. }
  99. async bulkDelete(projectIds: number[]): Promise<void> {
  100. const url = `/projects`
  101. await this.request.delete(url, { ids: projectIds })
  102. }
  103. async clone(project: Project): Promise<Project> {
  104. const url = `/projects/${project.id}/clone`
  105. const response = await this.request.post(url)
  106. return toModel(response.data)
  107. }
  108. }