diff --git a/frontend/components/project/ProjectList.vue b/frontend/components/project/ProjectList.vue
index 0cc4e9a2..7e129cbd 100644
--- a/frontend/components/project/ProjectList.vue
+++ b/frontend/components/project/ProjectList.vue
@@ -3,12 +3,15 @@
:value="value"
:headers="headers"
:items="items"
+ :options.sync="options"
+ :server-items-length="total"
:search="search"
:loading="isLoading"
:loading-text="$t('generic.loading')"
:no-data-text="$t('vuetify.noDataAvailable')"
:footer-props="{
'showFirstLastPage': true,
+ 'items-per-page-options': [10, 50, 100],
'items-per-page-text': $t('vuetify.itemsPerPageText'),
'page-text': $t('dataset.pageText')
}"
@@ -36,19 +39,21 @@
{{tag.text}}
-
+ v-for="tag in item.tags"
+ :key="tag.id"
+ outlined v-text="tag.text"
+ />
diff --git a/frontend/domain/models/project/project.ts b/frontend/domain/models/project/project.ts
index 36ccef5e..dc0eedcc 100644
--- a/frontend/domain/models/project/project.ts
+++ b/frontend/domain/models/project/project.ts
@@ -1,4 +1,5 @@
-import { Expose } from 'class-transformer'
+import "reflect-metadata"
+import { Expose, Type } from 'class-transformer'
export type ProjectType = 'DocumentClassification' | 'SequenceLabeling' | 'Seq2seq' | 'IntentDetectionAndSlotFilling' | 'ImageClassification' | 'Speech2text'
@@ -74,6 +75,16 @@ export class ProjectReadItem {
}
}
+export class ProjectItemList {
+ count: number;
+ next: string | null;
+ prev: string | null;
+
+ @Type(() => ProjectReadItem)
+ @Expose({ name: 'results' })
+ items: ProjectReadItem[];
+}
+
export class ProjectWriteItem {
constructor(
public id: number,
diff --git a/frontend/domain/models/project/projectRepository.ts b/frontend/domain/models/project/projectRepository.ts
index ebba0e17..223ea017 100644
--- a/frontend/domain/models/project/projectRepository.ts
+++ b/frontend/domain/models/project/projectRepository.ts
@@ -1,8 +1,9 @@
-import { ProjectReadItem, ProjectWriteItem } from '~/domain/models/project/project'
+import { ProjectReadItem, ProjectWriteItem, ProjectItemList } from '~/domain/models/project/project'
+export type SearchOption = {[key: string]: string | (string | null)[]}
export interface ProjectRepository {
- list(): Promise
+ list({ limit, offset, q }: SearchOption): Promise
findById(id: string): Promise
diff --git a/frontend/pages/projects/index.vue b/frontend/pages/projects/index.vue
index 24e0fe83..4b7c99ce 100644
--- a/frontend/pages/projects/index.vue
+++ b/frontend/pages/projects/index.vue
@@ -33,17 +33,20 @@
+ :total="projects.count"
+ @update:query="updateQuery"
+ />
diff --git a/frontend/repositories/project/apiProjectRepository.ts b/frontend/repositories/project/apiProjectRepository.ts
index b9ad2e24..6da0810f 100644
--- a/frontend/repositories/project/apiProjectRepository.ts
+++ b/frontend/repositories/project/apiProjectRepository.ts
@@ -1,7 +1,7 @@
import { plainToInstance } from 'class-transformer'
import ApiService from '@/services/api.service'
-import { ProjectRepository } from '@/domain/models/project/projectRepository'
-import { ProjectReadItem, ProjectWriteItem } from '~/domain/models/project/project'
+import { ProjectRepository, SearchOption } from '@/domain/models/project/projectRepository'
+import { ProjectReadItem, ProjectWriteItem, ProjectItemList } from '~/domain/models/project/project'
export class APIProjectRepository implements ProjectRepository {
@@ -9,10 +9,10 @@ export class APIProjectRepository implements ProjectRepository {
private readonly request = ApiService
) {}
- async list(): Promise {
- const url = `/projects`
+ async list({ limit = '10', offset = '0', q = '' }: SearchOption): Promise {
+ const url = `/projects?limit=${limit}&offset=${offset}&q=${q}`
const response = await this.request.get(url)
- return response.data.map((item: any) => plainToInstance(ProjectReadItem, item))
+ return plainToInstance(ProjectItemList, response.data)
}
async findById(id: string): Promise {
diff --git a/frontend/services/application/project/projectApplicationService.ts b/frontend/services/application/project/projectApplicationService.ts
index 74adebad..0f490995 100644
--- a/frontend/services/application/project/projectApplicationService.ts
+++ b/frontend/services/application/project/projectApplicationService.ts
@@ -1,5 +1,5 @@
-import { ProjectDTO, ProjectWriteDTO } from './projectData'
-import { ProjectRepository } from '~/domain/models/project/projectRepository'
+import { ProjectDTO, ProjectWriteDTO, ProjectListDTO } from './projectData'
+import { ProjectRepository, SearchOption } from '~/domain/models/project/projectRepository'
import { ProjectWriteItem } from '~/domain/models/project/project'
@@ -8,10 +8,10 @@ export class ProjectApplicationService {
private readonly repository: ProjectRepository
) {}
- public async list(): Promise {
+ public async list(options: SearchOption): Promise {
try {
- const items = await this.repository.list()
- return items.map(item => new ProjectDTO(item))
+ const items = await this.repository.list(options)
+ return new ProjectListDTO(items)
} catch(e: any) {
throw new Error(e.response.data.detail)
}
diff --git a/frontend/services/application/project/projectData.ts b/frontend/services/application/project/projectData.ts
index dd6ba5d8..e1800cea 100644
--- a/frontend/services/application/project/projectData.ts
+++ b/frontend/services/application/project/projectData.ts
@@ -1,4 +1,4 @@
-import { ProjectReadItem, ProjectType } from '~/domain/models/project/project'
+import { ProjectReadItem, ProjectType, ProjectItemList } from '~/domain/models/project/project'
export class ProjectDTO {
id: number
@@ -45,3 +45,17 @@ export class ProjectDTO {
}
export type ProjectWriteDTO = Pick
+
+export class ProjectListDTO {
+ count: number
+ next : string | null
+ prev : string | null
+ items: ProjectDTO[]
+
+ constructor(item: ProjectItemList) {
+ this.count = item.count
+ this.next = item.next
+ this.prev = item.prev
+ this.items = item.items.map(_ => new ProjectDTO(_))
+ }
+}