From 387e02931e2c57acd62c119e8682cd140d9f9d8e Mon Sep 17 00:00:00 2001 From: Hironsan Date: Tue, 8 Feb 2022 11:50:09 +0900 Subject: [PATCH 1/4] Fix ProgressAPI to return response --- backend/metrics/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/metrics/views.py b/backend/metrics/views.py index 1b9fde4f..4ed1e121 100644 --- a/backend/metrics/views.py +++ b/backend/metrics/views.py @@ -18,8 +18,9 @@ class ProgressAPI(APIView): def get(self, request, *args, **kwargs): examples = Example.objects.filter(project=self.kwargs["project_id"]).values("id") total = examples.count() - done = ExampleState.objects.count_done(examples, user=self.request.user) - return {"total": total, "remaining": total - done} + complete = ExampleState.objects.count_done(examples, user=self.request.user) + data = {"total": total, "remaining": total - complete, "complete": complete} + return Response(data=data, status=status.HTTP_200_OK) class MemberProgressAPI(APIView): From 0fd8e8992de3c76a0baf5c25dd432fd1805fe287 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Tue, 8 Feb 2022 13:40:45 +0900 Subject: [PATCH 2/4] Add AnnotationProgress.vue --- .../tasks/sidebar/AnnotationProgress.vue | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 frontend/components/tasks/sidebar/AnnotationProgress.vue diff --git a/frontend/components/tasks/sidebar/AnnotationProgress.vue b/frontend/components/tasks/sidebar/AnnotationProgress.vue new file mode 100644 index 00000000..6fb8f848 --- /dev/null +++ b/frontend/components/tasks/sidebar/AnnotationProgress.vue @@ -0,0 +1,46 @@ + + + From 6fad45af7a71c643aef0a9715f133ee07efc8382 Mon Sep 17 00:00:00 2001 From: Hironsan Date: Tue, 8 Feb 2022 13:41:13 +0900 Subject: [PATCH 3/4] Update repository and application service --- frontend/domain/models/metrics/metrics.ts | 6 ++++++ frontend/domain/models/metrics/metricsRepository.ts | 3 ++- frontend/repositories/metrics/apiMetricsRepository.ts | 8 +++++++- .../application/metrics/metricsApplicationService.ts | 6 +++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/frontend/domain/models/metrics/metrics.ts b/frontend/domain/models/metrics/metrics.ts index 5e420e1c..0a4c2747 100644 --- a/frontend/domain/models/metrics/metrics.ts +++ b/frontend/domain/models/metrics/metrics.ts @@ -6,3 +6,9 @@ export interface Progress { total: number progress: {user: string, done: number}[] } + +export interface MyProgress { + total: number + complete: number + remaining: number +} diff --git a/frontend/domain/models/metrics/metricsRepository.ts b/frontend/domain/models/metrics/metricsRepository.ts index c0cc37c5..d5168f11 100644 --- a/frontend/domain/models/metrics/metricsRepository.ts +++ b/frontend/domain/models/metrics/metricsRepository.ts @@ -1,7 +1,8 @@ -import { Distribution, Progress } from '~/domain/models/metrics/metrics' +import { Distribution, Progress, MyProgress } from '~/domain/models/metrics/metrics' export interface MetricsRepository { fetchCategoryDistribution(projectId: string): Promise fetchSpanDistribution(projectId: string): Promise fetchMemberProgress(projectId: string): Promise + fetchMyProgress(projectId: string): Promise } diff --git a/frontend/repositories/metrics/apiMetricsRepository.ts b/frontend/repositories/metrics/apiMetricsRepository.ts index 1897b4df..1705df80 100644 --- a/frontend/repositories/metrics/apiMetricsRepository.ts +++ b/frontend/repositories/metrics/apiMetricsRepository.ts @@ -1,6 +1,6 @@ import ApiService from '@/services/api.service' import { MetricsRepository } from '@/domain/models/metrics/metricsRepository' -import { Distribution, Progress } from '~/domain/models/metrics/metrics' +import { Distribution, Progress, MyProgress } from '~/domain/models/metrics/metrics' export class APIMetricsRepository implements MetricsRepository { constructor( @@ -24,4 +24,10 @@ export class APIMetricsRepository implements MetricsRepository { const response = await this.request.get(url) return response.data } + + async fetchMyProgress(projectId: string): Promise { + const url = `/projects/${projectId}/metrics/progress` + const response = await this.request.get(url) + return response.data + } } diff --git a/frontend/services/application/metrics/metricsApplicationService.ts b/frontend/services/application/metrics/metricsApplicationService.ts index 2b0f006a..eb3ab0af 100644 --- a/frontend/services/application/metrics/metricsApplicationService.ts +++ b/frontend/services/application/metrics/metricsApplicationService.ts @@ -1,5 +1,5 @@ import { MetricsRepository } from '~/domain/models/metrics/metricsRepository' -import { Progress, Distribution } from '~/domain/models/metrics/metrics' +import { Progress, Distribution, MyProgress } from '~/domain/models/metrics/metrics' export class MetricsApplicationService { constructor( @@ -17,4 +17,8 @@ export class MetricsApplicationService { public async fetchSpanDistribution(projectId: string): Promise { return await this.repository.fetchSpanDistribution(projectId) } + + public async fetchMyProgress(projectId: string): Promise { + return await this.repository.fetchMyProgress(projectId) + } } From b8d7495e43d1f7ac12db67d13d2a3992e2f3364a Mon Sep 17 00:00:00 2001 From: Hironsan Date: Tue, 8 Feb 2022 13:41:26 +0900 Subject: [PATCH 4/4] Update annotation pages to show progress --- frontend/composables/useExampleItem.ts | 9 ++++++++- .../projects/_id/image-classification/index.vue | 14 ++++++++++++-- .../intent-detection-and-slot-filling/index.vue | 12 +++++++++++- .../pages/projects/_id/sequence-labeling/index.vue | 12 +++++++++++- .../projects/_id/sequence-to-sequence/index.vue | 14 ++++++++++++-- .../pages/projects/_id/speech-to-text/index.vue | 14 ++++++++++++-- .../projects/_id/text-classification/index.vue | 8 ++++++-- 7 files changed, 72 insertions(+), 11 deletions(-) diff --git a/frontend/composables/useExampleItem.ts b/frontend/composables/useExampleItem.ts index b6e4faab..718382b6 100644 --- a/frontend/composables/useExampleItem.ts +++ b/frontend/composables/useExampleItem.ts @@ -5,7 +5,8 @@ import { ExampleDTO } from '@/services/application/example/exampleData' export const useExampleItem = () => { const state = reactive({ example: {} as ExampleDTO, - totalExample: 0 + totalExample: 0, + progress: {} }) const { app } = useContext() @@ -28,16 +29,22 @@ export const useExampleItem = () => { state.example = await exampleService.findById(projectId, state.example.id) } + const updateProgress = async(projectId: string) => { + state.progress = await app.$services.metrics.fetchMyProgress(projectId) + } + const confirm = async( projectId: string, ) => { await exampleService.confirm(projectId, state.example.id) await getExampleById(projectId) + updateProgress(projectId) } return { state, confirm, getExample, + updateProgress } } diff --git a/frontend/pages/projects/_id/image-classification/index.vue b/frontend/pages/projects/_id/image-classification/index.vue index 2646aa4a..6e4eafa4 100644 --- a/frontend/pages/projects/_id/image-classification/index.vue +++ b/frontend/pages/projects/_id/image-classification/index.vue @@ -62,7 +62,8 @@ @@ -78,10 +79,12 @@ import ListMetadata from '@/components/tasks/metadata/ListMetadata' import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop' import ToolbarMobile from '@/components/tasks/toolbar/ToolbarMobile' import { useLabelList } from '@/composables/useLabelList' +import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' export default { components: { + AnnotationProgress, LabelGroup, LabelSelect, LayoutText, @@ -118,7 +121,8 @@ export default { width: 0 }, mdiText, - mdiFormatListBulleted + mdiFormatListBulleted, + progress: {} } }, @@ -162,6 +166,7 @@ export default { async created() { this.getLabelList(this.projectId) this.project = await this.$services.project.findById(this.projectId) + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) }, methods: { @@ -202,9 +207,14 @@ export default { } }, + async updateProgress() { + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) + }, + async confirm() { await this.$services.example.confirm(this.projectId, this.image.id) await this.$fetch() + this.updateProgress() }, setImageSize(val) { diff --git a/frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue b/frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue index bdfd57a7..25904e20 100644 --- a/frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue +++ b/frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue @@ -44,7 +44,8 @@ @@ -56,9 +57,11 @@ import ListMetadata from '@/components/tasks/metadata/ListMetadata' import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop' import ToolbarMobile from '@/components/tasks/toolbar/ToolbarMobile' import LabelGroup from '@/components/tasks/textClassification/LabelGroup' +import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' export default { components: { + AnnotationProgress, EntityEditor, LayoutText, ListMetadata, @@ -83,6 +86,7 @@ export default { project: {}, exclusive: false, enableAutoLabeling: false, + progress: {} } }, @@ -123,6 +127,7 @@ export default { this.spanTypes = await this.$services.spanType.list(this.projectId) this.categoryTypes = await this.$services.categoryType.list(this.projectId) this.project = await this.$services.project.findById(this.projectId) + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) }, methods: { @@ -165,9 +170,14 @@ export default { await this.listSpan(this.doc.id) }, + async updateProgress() { + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) + }, + async confirm() { await this.$services.example.confirm(this.projectId, this.doc.id) await this.$fetch() + this.updateProgress() } } } diff --git a/frontend/pages/projects/_id/sequence-labeling/index.vue b/frontend/pages/projects/_id/sequence-labeling/index.vue index d588b5aa..ac3aeca5 100644 --- a/frontend/pages/projects/_id/sequence-labeling/index.vue +++ b/frontend/pages/projects/_id/sequence-labeling/index.vue @@ -38,7 +38,8 @@ @@ -40,11 +41,13 @@ import LayoutText from '@/components/tasks/layout/LayoutText' import ListMetadata from '@/components/tasks/metadata/ListMetadata' import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop' import ToolbarMobile from '@/components/tasks/toolbar/ToolbarMobile' +import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' import Seq2seqBox from '~/components/tasks/seq2seq/Seq2seqBox' export default { components: { + AnnotationProgress, LayoutText, ListMetadata, Seq2seqBox, @@ -62,7 +65,8 @@ export default { annotations: [], docs: [], project: {}, - enableAutoLabeling: false + enableAutoLabeling: false, + progress: {} } }, @@ -104,6 +108,7 @@ export default { async created() { this.project = await this.$services.project.findById(this.projectId) + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) }, methods: { @@ -139,9 +144,14 @@ export default { } }, + async updateProgress() { + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) + }, + async confirm() { await this.$services.example.confirm(this.projectId, this.doc.id) await this.$fetch() + this.updateProgress() } } } diff --git a/frontend/pages/projects/_id/speech-to-text/index.vue b/frontend/pages/projects/_id/speech-to-text/index.vue index e08831e3..35457689 100644 --- a/frontend/pages/projects/_id/speech-to-text/index.vue +++ b/frontend/pages/projects/_id/speech-to-text/index.vue @@ -36,7 +36,8 @@ /> @@ -47,12 +48,14 @@ import LayoutText from '@/components/tasks/layout/LayoutText' import ListMetadata from '@/components/tasks/metadata/ListMetadata' import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop' import ToolbarMobile from '@/components/tasks/toolbar/ToolbarMobile' +import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' import Seq2seqBox from '~/components/tasks/seq2seq/Seq2seqBox' import AudioViewer from '~/components/tasks/audio/AudioViewer' export default { components: { + AnnotationProgress, AudioViewer, LayoutText, ListMetadata, @@ -72,7 +75,8 @@ export default { items: [], project: {}, enableAutoLabeling: false, - isLoading: false + isLoading: false, + progress: {} } }, @@ -116,6 +120,7 @@ export default { async created() { this.project = await this.$services.project.findById(this.projectId) + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) }, methods: { @@ -151,9 +156,14 @@ export default { } }, + async updateProgress() { + this.progress = await this.$services.metrics.fetchMyProgress(this.projectId) + }, + async confirm() { await this.$services.example.confirm(this.projectId, this.item.id) await this.$fetch() + this.updateProgress() } } } diff --git a/frontend/pages/projects/_id/text-classification/index.vue b/frontend/pages/projects/_id/text-classification/index.vue index bd502803..81636cb9 100644 --- a/frontend/pages/projects/_id/text-classification/index.vue +++ b/frontend/pages/projects/_id/text-classification/index.vue @@ -45,7 +45,8 @@ @@ -63,10 +64,12 @@ import { useExampleItem } from '@/composables/useExampleItem' import { useLabelList } from '@/composables/useLabelList' import { useProjectItem } from '@/composables/useProjectItem' import { useTeacherList } from '@/composables/useTeacherList' +import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' export default { components: { + AnnotationProgress, ButtonLabelSwitch, LabelGroup, LabelSelect, @@ -85,7 +88,7 @@ export default { const { app, params, query } = useContext() const projectId = params.value.id const { state: projectState, getProjectById } = useProjectItem() - const { state: exampleState, confirm, getExample } = useExampleItem() + const { state: exampleState, confirm, getExample, updateProgress } = useExampleItem() const { state: teacherState, annotateLabel, @@ -101,6 +104,7 @@ export default { getLabelList(projectId) getProjectById(projectId) + updateProgress(projectId) const { fetch } = useFetch(async() => { await getExample(