Browse Source

Merge pull request #2028 from doccano/enhancement/order-by-score

[Enhancement] order by score
pull/2031/head
Hiroki Nakayama 2 years ago
committed by GitHub
parent
commit
28c683113e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 71 additions and 15 deletions
  1. 18
      backend/examples/migrations/0007_example_score.py
  2. 1
      backend/examples/models.py
  3. 1
      backend/examples/serializers.py
  4. 2
      backend/examples/views/example.py
  5. 21
      frontend/components/tasks/toolbar/ToolbarLaptop.vue
  6. 9
      frontend/composables/useExampleItem.ts
  7. 3
      frontend/pages/projects/_id/image-captioning/index.vue
  8. 3
      frontend/pages/projects/_id/image-classification/index.vue
  9. 3
      frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue
  10. 3
      frontend/pages/projects/_id/object-detection/index.vue
  11. 3
      frontend/pages/projects/_id/segmentation/index.vue
  12. 3
      frontend/pages/projects/_id/sequence-labeling/index.vue
  13. 3
      frontend/pages/projects/_id/sequence-to-sequence/index.vue
  14. 3
      frontend/pages/projects/_id/speech-to-text/index.vue
  15. 4
      frontend/repositories/example/apiDocumentRepository.ts
  16. 6
      frontend/services/application/example/exampleApplicationService.ts

18
backend/examples/migrations/0007_example_score.py

@ -0,0 +1,18 @@
# Generated by Django 4.0.7 on 2022-10-21 07:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("examples", "0006_alter_example_upload_name"),
]
operations = [
migrations.AddField(
model_name="example",
name="score",
field=models.FloatField(default=100),
),
]

1
backend/examples/models.py

@ -18,6 +18,7 @@ class Example(models.Model):
project = models.ForeignKey(to=Project, on_delete=models.CASCADE, related_name="examples")
annotations_approved_by = models.ForeignKey(to=User, on_delete=models.SET_NULL, null=True, blank=True)
text = models.TextField(null=True, blank=True)
score = models.FloatField(default=100)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
updated_at = models.DateTimeField(auto_now=True)

1
backend/examples/serializers.py

@ -45,6 +45,7 @@ class ExampleSerializer(serializers.ModelSerializer):
"text",
"is_confirmed",
"upload_name",
"score",
]
read_only_fields = ["filename", "is_confirmed", "upload_name"]

2
backend/examples/views/example.py

@ -18,7 +18,7 @@ class ExampleList(generics.ListCreateAPIView):
serializer_class = ExampleSerializer
permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)]
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
ordering_fields = ("created_at", "updated_at")
ordering_fields = ("created_at", "updated_at", "score")
search_fields = ("text", "filename")
model = Example
filter_class = ExampleFilter

21
frontend/components/tasks/toolbar/ToolbarLaptop.vue

@ -6,6 +6,8 @@
<button-filter :value="filterOption" @click:filter="changeFilter" />
<button-order :value="orderOption" @click:order="changeOrder" />
<button-guideline @click:guideline="dialogGuideline = true" />
<v-dialog v-model="dialogGuideline">
<form-guideline :guideline-text="guidelineText" @click:close="dialogGuideline = false" />
@ -64,6 +66,7 @@ import ButtonClear from './buttons/ButtonClear.vue'
import ButtonComment from './buttons/ButtonComment.vue'
import ButtonFilter from './buttons/ButtonFilter.vue'
import ButtonGuideline from './buttons/ButtonGuideline.vue'
import ButtonOrder from './buttons/ButtonOrder.vue'
import ButtonPagination from './buttons/ButtonPagination.vue'
import ButtonReview from './buttons/ButtonReview.vue'
import ButtonKeyboardShortcut from './buttons/ButtonKeyboardShortcut.vue'
@ -80,6 +83,7 @@ export default Vue.extend({
ButtonComment,
ButtonFilter,
ButtonGuideline,
ButtonOrder,
ButtonKeyboardShortcut,
ButtonPagination,
ButtonReview,
@ -134,6 +138,10 @@ export default Vue.extend({
filterOption(): string {
// @ts-ignore
return this.$route.query.isChecked
},
orderOption(): string {
// @ts-ignore
return this.$route.query.ordering
}
},
@ -143,6 +151,7 @@ export default Vue.extend({
query: {
page: page.toString(),
isChecked: this.filterOption,
ordering: this.$route.query.ordering,
q: this.$route.query.q
}
})
@ -153,11 +162,23 @@ export default Vue.extend({
query: {
page: '1',
isChecked,
ordering: this.$route.query.ordering,
q: this.$route.query.q
}
})
},
changeOrder(ordering: string) {
this.$router.push({
query: {
page: '1',
isChecked: this.filterOption,
q: this.$route.query.q,
ordering
}
})
},
updateAutoLabeling(isEnable: boolean) {
if (isEnable) {
this.$emit('update:enable-auto-labeling', true)

9
frontend/composables/useExampleItem.ts

@ -14,9 +14,14 @@ export const useExampleItem = () => {
const getExample = async (
projectId: string,
{ page, q, isChecked }: { page: string; q: string; isChecked: string }
{
page,
q,
isChecked,
ordering
}: { page: string; q: string; isChecked: string; ordering: string }
) => {
const examples = await exampleService.fetchOne(projectId, page, q, isChecked)
const examples = await exampleService.fetchOne(projectId, page, q, isChecked, ordering)
state.totalExample = examples.count
if (!_.isEmpty(examples) && examples.items.length !== 0) {
state.example = examples.items[0]

3
frontend/pages/projects/_id/image-captioning/index.vue

@ -112,7 +112,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const image = this.images.items[0]
this.setImageSize(image)

3
frontend/pages/projects/_id/image-classification/index.vue

@ -115,7 +115,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const image = this.images.items[0]
this.setImageSize(image)

3
frontend/pages/projects/_id/intent-detection-and-slot-filling/index.vue

@ -91,7 +91,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const doc = this.docs.items[0]
await this.listSpan(doc.id)

3
frontend/pages/projects/_id/object-detection/index.vue

@ -134,7 +134,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const image = this.images.items[0]
if (this.enableAutoLabeling) {

3
frontend/pages/projects/_id/segmentation/index.vue

@ -135,7 +135,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const image = this.images.items[0]
if (this.enableAutoLabeling) {

3
frontend/pages/projects/_id/sequence-labeling/index.vue

@ -124,7 +124,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const doc = this.docs.items[0]
if (this.enableAutoLabeling && !doc.isConfirmed) {

3
frontend/pages/projects/_id/sequence-to-sequence/index.vue

@ -71,7 +71,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const doc = this.docs.items[0]
if (this.enableAutoLabeling) {

3
frontend/pages/projects/_id/speech-to-text/index.vue

@ -76,7 +76,8 @@ export default {
this.projectId,
this.$route.query.page,
this.$route.query.q,
this.$route.query.isChecked
this.$route.query.isChecked,
this.$route.query.ordering
)
const item = this.items.items[0]
if (this.enableAutoLabeling) {

4
frontend/repositories/example/apiDocumentRepository.ts

@ -30,9 +30,9 @@ export class APIExampleRepository implements ExampleRepository {
async list(
projectId: string,
{ limit = '10', offset = '0', q = '', isChecked = '' }: SearchOption
{ limit = '10', offset = '0', q = '', isChecked = '', ordering = '' }: SearchOption
): Promise<ExampleItemList> {
const url = `/projects/${projectId}/examples?limit=${limit}&offset=${offset}&q=${q}&confirmed=${isChecked}`
const url = `/projects/${projectId}/examples?limit=${limit}&offset=${offset}&q=${q}&confirmed=${isChecked}&ordering=${ordering}`
const response = await this.request.get(url)
return new ExampleItemList(
response.data.count,

6
frontend/services/application/example/exampleApplicationService.ts

@ -19,14 +19,16 @@ export class ExampleApplicationService {
projectId: string,
page: string,
q: string,
isChecked: string
isChecked: string,
ordering: string
): Promise<ExampleListDTO> {
const offset = (parseInt(page, 10) - 1).toString()
const options: SearchOption = {
limit: '1',
offset,
q,
isChecked
isChecked,
ordering
}
return await this.list(projectId, options)
}

Loading…
Cancel
Save