Browse Source

Enable to bulk assign in frontend

pull/2261/head
Hironsan 1 year ago
parent
commit
01ee5903be
4 changed files with 156 additions and 1 deletions
  1. 8
      frontend/components/example/ActionMenu.vue
  2. 132
      frontend/components/example/FormAssignment.vue
  3. 12
      frontend/pages/projects/_id/dataset/index.vue
  4. 5
      frontend/repositories/example/apiAssignmentRepository.ts

8
frontend/components/example/ActionMenu.vue

@ -5,12 +5,13 @@
@create="$emit('create')"
@upload="$emit('upload')"
@download="$emit('download')"
@assign="$emit('assign')"
/>
</template>
<script lang="ts">
import Vue from 'vue'
import { mdiUpload, mdiDownload } from '@mdi/js'
import { mdiAccountCheck, mdiUpload, mdiDownload } from '@mdi/js'
import ActionMenu from '~/components/utils/ActionMenu.vue'
export default Vue.extend({
@ -30,6 +31,11 @@ export default Vue.extend({
title: this.$t('dataset.exportDataset'),
icon: mdiDownload,
event: 'download'
},
{
title: 'Assign to member',
icon: mdiAccountCheck,
event: 'assign'
}
]
}

132
frontend/components/example/FormAssignment.vue

@ -0,0 +1,132 @@
<template>
<v-card>
<v-toolbar color="primary white--text" flat>
<v-toolbar-title>Assign examples to members</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-container fluid>
<v-row>
<v-card-title class="pb-0 pl-3">Select assignment strategy</v-card-title>
<v-col cols="12">
<v-select
v-model="selectedStrategy"
:items="strategies"
item-text="displayName"
item-value="value"
outlined
dense
hide-details
></v-select>
{{ strategies.find((strategy) => strategy.value === selectedStrategy)?.description }}
Note that assigning to an administrator does not make sense.
</v-col>
</v-row>
<v-row>
<v-card-title class="pb-0 pl-3">Allocate weights</v-card-title>
<v-col v-for="(member, i) in members" :key="member.id" cols="12" class="pt-0 pb-0">
<v-subheader class="pl-0">{{ member.username }}</v-subheader>
<v-slider v-model="workloadAllocation[i]" :max="100" class="align-center">
<template #append>
<v-text-field
v-model="workloadAllocation[i]"
class="mt-0 pt-0"
type="number"
style="width: 60px"
></v-text-field>
</template>
</v-slider>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn class="text-capitalize" text color="primary" data-test="cancel-button" @click="cancel">
Cancel
</v-btn>
<v-btn
class="text-none"
text
:disabled="!validateWeight"
data-test="delete-button"
@click="agree"
>
Assign
</v-btn>
</v-card-actions>
</v-card>
</template>
<script lang="ts">
import Vue from 'vue'
import { MemberItem } from '~/domain/models/member/member'
export default Vue.extend({
data() {
return {
members: [] as MemberItem[],
workloadAllocation: [] as number[],
selectedStrategy: 'weighted_sequential'
}
},
async fetch() {
this.members = await this.$repositories.member.list(this.projectId)
this.workloadAllocation = this.members.map(() => Math.round(100 / this.members.length))
},
computed: {
projectId() {
return this.$route.params.id
},
strategies() {
return [
{
displayName: 'Weighted sequential',
value: 'weighted_sequential',
description:
'Assign examples to members in order of their workload. The total weight must equal 100.'
},
{
displayName: 'Weighted random',
value: 'weighted_random',
description:
'Assign examples to members randomly based on their workload. The total weight must equal 100.'
},
{
displayName: 'Sampling without replacement',
value: 'sampling_without_replacement',
description: 'Assign examples to members randomly without replacement.'
}
]
},
validateWeight(): boolean {
if (this.selectedStrategy === 'sampling_without_replacement') {
return true
} else {
return this.workloadAllocation.reduce((acc, cur) => acc + cur, 0) === 100
}
}
},
methods: {
agree() {
const workloads = this.workloadAllocation.map((weight, i) => ({
weight,
member_id: this.members[i].id
}))
console.log(workloads)
this.$repositories.assignment.bulkAssign(this.projectId, {
strategy_name: this.selectedStrategy,
workloads
})
this.$emit('assigned')
},
cancel() {
this.$emit('cancel')
}
}
})
</script>

12
frontend/pages/projects/_id/dataset/index.vue

@ -4,6 +4,7 @@
<action-menu
@upload="$router.push('dataset/import')"
@download="$router.push('dataset/export')"
@assign="dialogAssignment = true"
/>
<v-btn
class="text-capitalize ms-2"
@ -33,6 +34,9 @@
<v-dialog v-model="dialogDeleteAll">
<form-delete-bulk @cancel="dialogDeleteAll = false" @remove="removeAll" />
</v-dialog>
<v-dialog v-model="dialogAssignment">
<form-assignment @assigned="assigned" @cancel="dialogAssignment = false" />
</v-dialog>
</v-card-title>
<image-list
v-if="project.isImageProject"
@ -83,6 +87,7 @@ import { mapGetters } from 'vuex'
import Vue from 'vue'
import { NuxtAppOptions } from '@nuxt/types'
import DocumentList from '@/components/example/DocumentList.vue'
import FormAssignment from '~/components/example/FormAssignment.vue'
import FormDelete from '@/components/example/FormDelete.vue'
import FormDeleteBulk from '@/components/example/FormDeleteBulk.vue'
import ActionMenu from '~/components/example/ActionMenu.vue'
@ -98,6 +103,7 @@ export default Vue.extend({
AudioList,
DocumentList,
ImageList,
FormAssignment,
FormDelete,
FormDeleteBulk
},
@ -114,6 +120,7 @@ export default Vue.extend({
return {
dialogDelete: false,
dialogDeleteAll: false,
dialogAssignment: false,
item: {} as ExampleListDTO,
selected: [] as ExampleDTO[],
members: [] as MemberItem[],
@ -204,6 +211,11 @@ export default Vue.extend({
async unassign(assignmentId: string) {
await this.$repositories.assignment.unassign(this.projectId, assignmentId)
this.item = await this.$services.example.list(this.projectId, this.$route.query)
},
async assigned() {
this.dialogAssignment = false
this.item = await this.$services.example.list(this.projectId, this.$route.query)
}
}
})

5
frontend/repositories/example/apiAssignmentRepository.ts

@ -15,4 +15,9 @@ export class APIAssignmentRepository {
const url = `/projects/${projectId}/assignments/${assignmentId}`
await this.request.delete(url)
}
async bulkAssign(projectId: string, workloadAllocation: Object): Promise<void> {
const url = `/projects/${projectId}/assignments/bulk_assign`
await this.request.post(url, workloadAllocation)
}
}
Loading…
Cancel
Save