Browse Source

Implement a feature to validate and save a new auto labeling config

pull/1206/head
Hironsan 4 years ago
parent
commit
faaba2be84
7 changed files with 138 additions and 14 deletions
  1. 66
      frontend/components/containers/settings/ConfigCreationForm.vue
  2. 12
      frontend/components/containers/settings/ConfigList.vue
  3. 26
      frontend/models/config/config-item-list.ts
  4. 20
      frontend/models/config/config-template.ts
  5. 9
      frontend/repositories/config/api.ts
  6. 7
      frontend/repositories/config/interface.ts
  7. 12
      frontend/services/application/config.service.ts

66
frontend/components/containers/settings/ConfigCreationForm.vue

@ -26,7 +26,7 @@
</v-stepper-header> </v-stepper-header>
<v-card> <v-card>
<v-card-text>
<v-card-text class="pa-0">
<v-stepper-content step="1"> <v-stepper-content step="1">
<h4 class="text-h6">Select a config template</h4> <h4 class="text-h6">Select a config template</h4>
<p class="font-weight-regular body-1"> <p class="font-weight-regular body-1">
@ -62,6 +62,7 @@
:key="item.name" :key="item.name"
/> />
</template> </template>
<h4 class="text-h6">Set mapping template</h4> <h4 class="text-h6">Set mapping template</h4>
<p class="font-weight-regular body-1"> <p class="font-weight-regular body-1">
You can set mapping template to convert API response to doccano format. You can set mapping template to convert API response to doccano format.
@ -71,10 +72,12 @@
outlined outlined
label="Mapping Template" label="Mapping Template"
/> />
<h4 class="text-h6">Configure label mappings</h4> <h4 class="text-h6">Configure label mappings</h4>
<p class="font-weight-regular body-1"> <p class="font-weight-regular body-1">
Once you fetch the API response, you can convert the label into the defined one. Once you fetch the API response, you can convert the label into the defined one.
</p> </p>
<label-mapping v-model="templateConfig.label_mapping" />
</v-stepper-content> </v-stepper-content>
<v-stepper-content step="3"> <v-stepper-content step="3">
@ -90,7 +93,7 @@
/> />
</v-stepper-content> </v-stepper-content>
</v-card-text> </v-card-text>
<v-card-actions>
<v-card-actions class="me-4">
<v-spacer /> <v-spacer />
<v-btn <v-btn
v-show="step.hasPrev()" v-show="step.hasPrev()"
@ -110,10 +113,18 @@
Next Next
</v-btn> </v-btn>
<v-btn <v-btn
v-show="!step.hasNext()"
:disabled="!passTesting"
v-show="step.isLast() && !passTesting"
color="primary" color="primary"
class="text-capitalize" class="text-capitalize"
@click="testConfig"
>
Test
</v-btn>
<v-btn
v-show="step.isLast() && passTesting"
color="success"
class="text-capitalize"
@click="saveConfig"
> >
Save Save
</v-btn> </v-btn>
@ -125,11 +136,19 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue' import Vue from 'vue'
import { FromApiTemplateRepository } from '@/repositories/template/api' import { FromApiTemplateRepository } from '@/repositories/template/api'
import { FromApiConfigItemListRepository } from '@/repositories/config/api'
import { TemplateApplicationService } from '@/services/application/template.service' import { TemplateApplicationService } from '@/services/application/template.service'
import { ConfigApplicationService } from '@/services/application/config.service'
import { ConfigTemplateItem } from '@/models/config/config-template' import { ConfigTemplateItem } from '@/models/config/config-template'
import { StepCounter } from '@/models/config/stepper';
import { ConfigItem } from '@/models/config/config-item-list'
import { StepCounter } from '@/models/stepper'
import LabelMapping from '@/components/containers/settings/LabelMapping.vue'
export default Vue.extend({ export default Vue.extend({
components: {
LabelMapping
},
data() { data() {
return { return {
passTesting: false, passTesting: false,
@ -161,13 +180,44 @@ export default Vue.extend({
const repository = new FromApiTemplateRepository() const repository = new FromApiTemplateRepository()
const service = new TemplateApplicationService(repository) const service = new TemplateApplicationService(repository)
return service return service
},
configService(): ConfigApplicationService{
const repository = new FromApiConfigItemListRepository()
const service = new ConfigApplicationService(repository)
return service
} }
}, },
methods: { methods: {
validate(): boolean {
return false
createConfig() {
const payload = {
// @ts-ignore
modelName: this.templateConfig.model_name,
// @ts-ignore
modelAttrs: this.templateConfig.model_attrs,
// @ts-ignore
template: this.templateConfig.template,
// @ts-ignore
labelMapping: this.templateConfig.label_mapping
}
return ConfigItem.parseFromUI(payload)
},
testConfig() {
const projectId = this.$route.params.id
const item = this.createConfig()
this.configService.testConfig(projectId, item, this.sampleText)
.then(value => {
this.passTesting = value.valid
})
},
saveConfig() {
const projectId = this.$route.params.id
const item = this.createConfig()
this.configService.save(projectId, item)
.then(item => {
this.$emit('onCreate')
})
} }
} }
}) })
</script>
</script>

12
frontend/components/containers/settings/ConfigList.vue

@ -21,7 +21,9 @@
</v-btn> </v-btn>
</template> </template>
<template v-slot:content="modal"> <template v-slot:content="modal">
<config-creation-form />
<config-creation-form
@onCreate="onCreate();modal.close()"
/>
</template> </template>
</base-modal> </base-modal>
<base-modal> <base-modal>
@ -41,7 +43,7 @@
title="Delete Config" title="Delete Config"
message="Are you sure you want to delete these configs?" message="Are you sure you want to delete these configs?"
item-key="modelName" item-key="modelName"
@ok="remove();modal.close"
@ok="remove();modal.close()"
@cancel="modal.close" @cancel="modal.close"
/> />
</template> </template>
@ -98,10 +100,16 @@ export default Vue.extend({
await this.configService.delete(projectId, item.id) await this.configService.delete(projectId, item.id)
} }
this.items = await this.configService.list(projectId) this.items = await this.configService.list(projectId)
this.selected = []
this.isLoading = false this.isLoading = false
}, },
isDeletable(): boolean { isDeletable(): boolean {
return this.selected.length > 0 return this.selected.length > 0
},
async onCreate() {
this.isLoading = true
this.items = await this.configService.list(this.$route.params.id)
this.isLoading = false
} }
} }
}) })

26
frontend/models/config/config-item-list.ts

@ -26,7 +26,21 @@ export class ConfigItem {
return new ConfigItem(id, model_name, model_attrs, template, label_mapping) return new ConfigItem(id, model_name, model_attrs, template, label_mapping)
} }
toObject(): Object {
static parseFromUI(
{ modelName, modelAttrs, template, labelMapping }:
{
modelName: string,
modelAttrs: {'name': string, 'value': string}[],
template: string,
labelMapping: {'from': string, 'to': string}[]
}
): ConfigItem {
const mapping = labelMapping.reduce((a, x) => ({...a, [x.from]: x.to}), {})
const attributes = modelAttrs.reduce((a, x) => ({...a, [x.name]: x.value}), {})
return new ConfigItem(99999, modelName, attributes, template, mapping)
}
toObject(): object {
return { return {
id: this.id, id: this.id,
modelName: this.modelName, modelName: this.modelName,
@ -35,6 +49,16 @@ export class ConfigItem {
labelMapping: this.labelMapping labelMapping: this.labelMapping
} }
} }
toAPI(): object {
return {
id: this.id,
model_name: this.modelName,
model_attrs: this.modelAttrs,
template: this.template,
label_mapping: this.labelMapping
}
}
} }
export const headers = [ export const headers = [

20
frontend/models/config/config-template.ts

@ -56,3 +56,23 @@ export class ConfigTemplateItem {
} }
} }
} }
export const headers = [
{
text: 'From',
align: 'left',
value: 'from',
sortable: false
},
{
text: 'To',
align: 'left',
value: 'to',
sortable: false
},
{
text: 'Actions',
value: 'actions',
sortable: false
}
]

9
frontend/repositories/config/api.ts

@ -1,5 +1,5 @@
import ApiService from '@/services/api.service' import ApiService from '@/services/api.service'
import { ConfigItemListRepository } from '@/repositories/config/interface'
import { ConfigItemListRepository, ConfigTestResponse } from '@/repositories/config/interface'
import { ConfigItemList, ConfigItem } from '@/models/config/config-item-list' import { ConfigItemList, ConfigItem } from '@/models/config/config-item-list'
export interface ConfigItemResponse { export interface ConfigItemResponse {
@ -53,4 +53,11 @@ export class FromApiConfigItemListRepository implements ConfigItemListRepository
const url = `/projects/${projectId}/auto-labeling-configs/${itemId}` const url = `/projects/${projectId}/auto-labeling-configs/${itemId}`
await this.request.delete(url) await this.request.delete(url)
} }
async testConfig(projectId: string, item: ConfigItem, text: string): Promise<ConfigTestResponse> {
const url = `/projects/${projectId}/auto-labeling-config-testing`
const response = await this.request.post(url, {config: {...item.toAPI()}, input: text})
const responseItem: ConfigTestResponse = response.data
return responseItem
}
} }

7
frontend/repositories/config/interface.ts

@ -1,5 +1,10 @@
import { ConfigItem, ConfigItemList } from '@/models/config/config-item-list' import { ConfigItem, ConfigItemList } from '@/models/config/config-item-list'
export interface ConfigTestResponse {
valid: boolean,
labels?: object[]
}
export interface ConfigItemListRepository { export interface ConfigItemListRepository {
list(projectId: string): Promise<ConfigItemList> list(projectId: string): Promise<ConfigItemList>
@ -8,4 +13,6 @@ export interface ConfigItemListRepository {
delete(projectId: string, itemId: number): Promise<void> delete(projectId: string, itemId: number): Promise<void>
update(projectId: string, item: ConfigItem): Promise<ConfigItem> update(projectId: string, item: ConfigItem): Promise<ConfigItem>
testConfig(projectId: string, item: ConfigItem, text: string): Promise<ConfigTestResponse>
} }

12
frontend/services/application/config.service.ts

@ -1,5 +1,5 @@
import { ConfigItemList } from '@/models/config/config-item-list'
import { ConfigItemListRepository } from '@/repositories/config/interface'
import { ConfigItemList, ConfigItem } from '@/models/config/config-item-list'
import { ConfigItemListRepository, ConfigTestResponse } from '@/repositories/config/interface'
export class ConfigApplicationService { export class ConfigApplicationService {
constructor( constructor(
@ -10,7 +10,15 @@ export class ConfigApplicationService {
return this.configRepository.list(id) return this.configRepository.list(id)
} }
public save(projectId: string, item: ConfigItem): Promise<ConfigItem> {
return this.configRepository.create(projectId, item)
}
public delete(projectId: string, itemId: number) { public delete(projectId: string, itemId: number) {
return this.configRepository.delete(projectId, itemId) return this.configRepository.delete(projectId, itemId)
} }
public testConfig(projectId: string, item: ConfigItem, text: string): Promise<ConfigTestResponse> {
return this.configRepository.testConfig(projectId, item, text)
}
} }
Loading…
Cancel
Save