Browse Source

Divide ConfigCreationForm.vue into small components

pull/1206/head
Hironsan 3 years ago
parent
commit
aa9ec04cc9
15 changed files with 717 additions and 258 deletions
  1. 331
      frontend/components/containers/settings/ConfigCreationForm.vue
  2. 11
      frontend/components/containers/settings/ConfigList.vue
  3. 45
      frontend/components/containers/settings/form/ConfigHeader.vue
  4. 91
      frontend/components/containers/settings/form/ConfigLabelMapping.vue
  5. 131
      frontend/components/containers/settings/form/ConfigParameters.vue
  6. 131
      frontend/components/containers/settings/form/ConfigTemplate.vue
  7. 71
      frontend/components/containers/settings/form/ConfigTemplateName.vue
  8. 21
      frontend/components/containers/settings/form/LabelMapping.vue
  9. 2
      frontend/components/containers/settings/form/ObjectField.vue
  10. 25
      frontend/models/config/config-item-list.ts
  11. 20
      frontend/models/config/config-template.ts
  12. 31
      frontend/repositories/config/api.ts
  13. 8
      frontend/repositories/config/interface.ts
  14. 6
      frontend/rules/index.js
  15. 51
      frontend/services/application/config.service.ts

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

@ -2,246 +2,105 @@
<v-stepper
v-model="step.count"
>
<v-stepper-header>
<v-stepper-step
:complete="step.count > 1"
step="1"
>
Select a config template
</v-stepper-step>
<v-divider />
<v-stepper-step
:complete="step.count > 2"
step="2"
>
Configure parameters
</v-stepper-step>
<v-divider />
<v-stepper-step
:complete="step.count > 3"
step="3"
>
Test the config
</v-stepper-step>
</v-stepper-header>
<v-card>
<v-overlay :value="isLoading">
<v-progress-circular indeterminate size="64" />
</v-overlay>
<v-card-text class="pa-0">
<v-stepper-content step="1">
<h4 class="text-h6">Select a config template</h4>
<p class="font-weight-regular body-1">
You can select the template to create the auto-labeling configuration.
</p>
<v-select
v-model="templateName"
:items="templateNames"
label="Select a config template"
outlined
/>
</v-stepper-content>
<v-overlay :value="isLoading">
<v-progress-circular indeterminate size="64" />
</v-overlay>
<config-header :step="step.count" />
<config-template-name
v-model="templateConfig"
@next="step.next()"
/>
<config-parameters
v-if="templateConfig.model_attrs !== undefined"
v-model="templateConfig.model_attrs"
:is-passed="passTesting.parameter"
:error-messages="errors"
:response="response.parameter"
@prev="step.prev()"
@next="step.next()"
@onTest="testParameters"
/>
<v-stepper-content step="2">
<h4 class="text-h6">Set parameters</h4>
<p class="font-weight-regular body-1">
You can set parameters to fetch API response.
</p>
<template v-for="item in templateConfig.model_attrs">
<v-text-field
v-if="item.type === 'textField'"
v-model="item.value"
:label="item.name"
outlined
:key="item.name"
/>
<v-select
v-if="item.type === 'selectField'"
v-model="item.value"
:items="item.items"
:label="item.name"
outlined
:key="item.name"
/>
<object-field
v-if="item.type === 'objectField'"
v-model="item.value"
:title="item.name"
:key="item.name"
/>
</template>
<config-template
v-model="templateConfig.template"
:is-passed="passTesting.template"
:error-messages="errors"
:response="response.parameter"
:result="response.template"
@prev="step.prev()"
@next="step.next()"
@onTest="testTemplate"
/>
<h4 class="text-h6">Set mapping template</h4>
<p class="font-weight-regular body-1">
You can set mapping template to convert API response to doccano format.
</p>
<v-textarea
v-model="templateConfig.template"
outlined
label="Mapping Template"
/>
<h4 class="text-h6">Configure label mappings</h4>
<p class="font-weight-regular body-1">
Once you fetch the API response, you can convert the label into the defined one.
</p>
<label-mapping v-model="labelMapping" />
</v-stepper-content>
<v-stepper-content step="3">
<h4 class="text-h6">Test the defined config</h4>
<p class="font-weight-regular body-1">
Before saving the config, you need to test the defined config.
Please input sample text and press the <strong>Test</strong> button.
</p>
<v-text-field
v-model="sampleText"
outlined
label="Sample Text"
/>
<h4
v-if="response.length > 0"
class="text-h6"
>
Response
</h4>
<v-sheet
v-if="response.length > 0"
:dark="!$vuetify.theme.dark"
:light="$vuetify.theme.dark"
class="mb-5 pa-5"
>
<pre>{{ JSON.stringify(response, null, 4) }}</pre>
</v-sheet>
<v-alert
v-for="(error, index) in errors"
prominent
type="error"
:key="index"
>
<v-row align="center">
<v-col class="grow">
{{ error }}
</v-col>
</v-row>
</v-alert>
</v-stepper-content>
</v-card-text>
<v-card-actions class="me-4">
<v-spacer />
<v-btn
v-show="step.hasPrev()"
text
class="text-capitalize"
@click="step.prev()"
>
Prev
</v-btn>
<v-btn
v-show="step.hasNext()"
:disabled="disabled"
color="primary"
class="text-capitalize"
@click="step.next()"
>
Next
</v-btn>
<v-btn
v-show="step.isLast() && !passTesting"
:disabled="sampleText === '' || isLoading"
color="primary"
class="text-capitalize"
@click="testConfig"
>
Test
</v-btn>
<v-btn
v-show="step.isLast() && passTesting"
color="success"
class="text-capitalize"
@click="saveConfig"
>
Save
</v-btn>
</v-card-actions>
</v-card>
<config-label-mapping
v-model="labelMapping"
:error-messages="errors"
:is-passed="passTesting.mapping"
@prev="step.prev()"
@next="saveConfig"
@onTest="testMapping"
/>
</v-stepper>
</template>
<script lang="ts">
import Vue from 'vue'
import { FromApiTemplateRepository } from '@/repositories/template/api'
import { FromApiConfigItemListRepository } from '@/repositories/config/api'
import { TemplateApplicationService } from '@/services/application/template.service'
import { ConfigApplicationService } from '@/services/application/config.service'
import { ConfigTemplateItem } from '@/models/config/config-template'
import { ConfigItem } from '@/models/config/config-item-list'
import { ConfigItem, Parameters } from '@/models/config/config-item-list'
import { StepCounter } from '@/models/stepper'
import LabelMapping from '@/components/containers/settings/LabelMapping.vue'
import ObjectField from '@/components/containers/settings/ObjectField.vue'
import ConfigHeader from './form/ConfigHeader.vue'
import ConfigTemplateName from './form/ConfigTemplateName.vue'
import ConfigTemplate from './form/ConfigTemplate.vue'
import ConfigParameters from './form/ConfigParameters.vue'
import ConfigLabelMapping from './form/ConfigLabelMapping.vue'
export default Vue.extend({
components: {
LabelMapping,
ObjectField
ConfigHeader,
ConfigTemplate,
ConfigTemplateName,
ConfigParameters,
ConfigLabelMapping
},
data() {
return {
errors: [] as string[],
isLoading: false,
passTesting: false,
sampleText: '',
step: new StepCounter(1, 3),
templateName: null,
passTesting: {
parameter: false,
template: false,
mapping: false
},
step: new StepCounter(1, 4),
templateConfig: {},
templateNames: [] as string[],
labelMapping: [],
response: [] as object[]
response: {
parameter: [],
template: [],
mapping: []
}
}
},
async created() {
this.templateNames = await this.templateService.list(this.$route.params.id)
computed: {
configService(): ConfigApplicationService{
const repository = new FromApiConfigItemListRepository()
const service = new ConfigApplicationService(repository)
return service
}
},
watch: {
async templateName(val) {
const projectId = this.$route.params.id
const response: ConfigTemplateItem = await this.templateService.find(projectId, val)
this.templateConfig = response.toObject()
},
templateConfig: {
handler() {
this.passTesting = false
},
deep: true
},
labelMapping: {
handler() {
this.passTesting = false
// this.passTesting = false
},
deep: true
}
},
computed: {
disabled(): boolean {
return this.step.isFirst() && this.templateName === null
},
templateService(): TemplateApplicationService {
const repository = new FromApiTemplateRepository()
const service = new TemplateApplicationService(repository)
return service
},
configService(): ConfigApplicationService{
const repository = new FromApiConfigItemListRepository()
const service = new ConfigApplicationService(repository)
return service
}
},
methods: {
createConfig() {
const payload = {
@ -256,28 +115,54 @@ export default Vue.extend({
}
return ConfigItem.parseFromUI(payload)
},
testConfig() {
testMapping() {
const projectId = this.$route.params.id
const item = this.createConfig()
this.isLoading = true
this.configService.testMapping(projectId, item, this.response.template)
.then((value) => {
this.passTesting.mapping = true
// @ts-ignore
this.response.mapping = value
})
.catch((error) => {
this.errors = [error.message]
})
.finally(() => {
this.isLoading = false
})
},
testParameters(text: string) {
// @ts-ignore
const item = Parameters.parse(this.templateConfig.model_attrs)
this.isLoading = true
// @ts-ignore
this.configService.testParameters(this.templateConfig.model_name, item, text)
.then((value) => {
// @ts-ignore
this.response.parameter = value
this.passTesting.parameter = true
})
.catch((error) => {
this.errors = [error.message]
})
.finally(() => {
this.isLoading = false
})
},
testTemplate() {
const projectId = this.$route.params.id
this.isLoading = true
this.errors = []
this.response = []
this.configService.testConfig(projectId, item, this.sampleText)
.then(value => {
this.passTesting = value.valid
this.response = value.labels
// @ts-ignore
this.configService.testTemplate(projectId, this.response.parameter, this.templateConfig.template)
.then((value) => {
// @ts-ignore
this.response.template = value
this.passTesting.template = true
})
.catch((error) => {
const data = error.response.data
if ('non_field_errors' in data) {
this.errors = data['non_field_errors']
} else if ('template' in data) {
this.errors.push('The template need to be filled.')
} else if ('detail' in data) {
this.errors.push(data['detail'])
} else {
this.errors = data
}
this.errors = [error.message]
})
.finally(() => {
this.isLoading = false
@ -288,7 +173,7 @@ export default Vue.extend({
const item = this.createConfig()
this.isLoading = true
this.configService.save(projectId, item)
.then(item => {
.then(() => {
this.$emit('onCreate')
})
.finally(() => {

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

@ -55,7 +55,7 @@
<script lang="ts">
import Vue from 'vue'
import { headers, ConfigItemList } from '@/models/config/config-item-list'
import { ConfigItemList } from '@/models/config/config-item-list'
import { ConfigApplicationService } from '@/services/application/config.service'
import { FromApiConfigItemListRepository, ConfigItemResponse } from '@/repositories/config/api'
import ConfirmForm from '@/components/organisms/utils/ConfirmForm.vue'
@ -74,7 +74,14 @@ export default Vue.extend({
isLoading: false as Boolean,
items: ConfigItemList.valueOf([]) as ConfigItemList,
selected: [] as ConfigItemResponse[],
headers
headers: [
{
text: 'Model name',
align: 'left',
value: 'modelName',
sortable: false
}
]
}
},

45
frontend/components/containers/settings/form/ConfigHeader.vue

@ -0,0 +1,45 @@
<template>
<v-stepper-header>
<v-stepper-step
:complete="step > 1"
step="1"
>
Select a template
</v-stepper-step>
<v-divider />
<v-stepper-step
:complete="step > 2"
step="2"
>
Set parameters
</v-stepper-step>
<v-divider />
<v-stepper-step
:complete="step > 3"
step="3"
>
Set a template
</v-stepper-step>
<v-divider />
<v-stepper-step
:complete="step > 4"
step="4"
>
Set mappings
</v-stepper-step>
</v-stepper-header>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
step: {
type: Number,
default: 1,
required: true
}
}
})
</script>

91
frontend/components/containers/settings/form/ConfigLabelMapping.vue

@ -0,0 +1,91 @@
<template>
<v-stepper-content step="4">
<v-card>
<v-card-text class="pa-0">
<h4 class="text-h6">Configure label mappings</h4>
<p class="font-weight-regular body-1">
Once you fetch the API response, you can convert the label into the defined one.
</p>
<label-mapping v-model="mapping" />
<v-alert
v-for="(error, index) in errorMessages"
prominent
type="error"
:key="index"
>
<v-row align="center">
<v-col class="grow">
{{ error }}
</v-col>
</v-row>
</v-alert>
</v-card-text>
<v-card-actions class="pa-0">
<v-spacer />
<v-btn
text
class="text-capitalize"
@click="$emit('prev')"
>
Prev
</v-btn>
<v-btn
v-show="!isPassed"
color="primary"
class="text-capitalize"
@click="$emit('onTest')"
>
Test
</v-btn>
<v-btn
v-show="isPassed"
color="primary"
class="text-capitalize"
@click="$emit('next')"
>
Finish
</v-btn>
</v-card-actions>
</v-card>
</v-stepper-content>
</template>
<script lang="ts">
import Vue from 'vue'
import LabelMapping from './LabelMapping.vue'
export default Vue.extend({
components: {
LabelMapping
},
props: {
value: {
type: Array,
default: () => [],
required: true
},
errorMessages: {
type: Array,
default: () => [],
required: true
},
isPassed: {
type: Boolean,
default: false,
required: true
}
},
computed: {
mapping: {
get() {
return this.value
},
set(newVal) {
this.$emit('input', newVal)
}
}
}
})
</script>

131
frontend/components/containers/settings/form/ConfigParameters.vue

@ -0,0 +1,131 @@
<template>
<v-stepper-content step="2">
<v-card>
<v-card-text class="pa-0">
<v-form>
<h4 class="text-h6">Set parameters</h4>
<p class="font-weight-regular body-1">
You can set parameters to fetch API response.
</p>
<template v-for="item in value">
<v-text-field
v-if="item.type === 'textField'"
v-model="item.value"
:label="item.name"
outlined
:key="item.name"
/>
<v-select
v-if="item.type === 'selectField'"
v-model="item.value"
:items="item.items"
:label="item.name"
outlined
:key="item.name"
/>
<object-field
v-if="item.type === 'objectField'"
v-model="item.value"
:title="item.name"
:key="item.name"
/>
</template>
<h4 class="text-h6">Test the parameters</h4>
<p class="font-weight-regular body-1">
Before proceeding, you need to test the parameters whether they can fetch API response.
Please input sample text and press the <strong>Test</strong> button.
</p>
<v-text-field
v-model="sampleText"
outlined
label="Sample Text"
/>
<v-alert
v-for="(error, index) in errorMessages"
prominent
type="error"
:key="index"
>
<v-row align="center">
<v-col class="grow">
{{ error }}
</v-col>
</v-row>
</v-alert>
<h4 class="text-h6">
Response
</h4>
<v-sheet
:dark="!$vuetify.theme.dark"
:light="$vuetify.theme.dark"
class="mb-5 pa-5"
>
<pre>{{ JSON.stringify(response, null, 4) }}</pre>
</v-sheet>
</v-form>
</v-card-text>
<v-card-actions class="pa-0">
<v-spacer />
<v-btn
text
class="text-capitalize"
@click="$emit('prev')"
>
Prev
</v-btn>
<v-btn
v-show="!isPassed"
color="primary"
class="text-capitalize"
@click="$emit('onTest', sampleText)"
>
Test
</v-btn>
<v-btn
v-show="isPassed"
color="primary"
class="text-capitalize"
@click="$emit('next')"
>
Next
</v-btn>
</v-card-actions>
</v-card>
</v-stepper-content>
</template>
<script lang="ts">
import Vue from 'vue'
import ObjectField from './ObjectField.vue'
export default Vue.extend({
components: {
ObjectField
},
props: {
value: {
type: Array,
default: () => [],
required: true
},
errorMessages: {
type: Array,
default: () => [],
required: true
},
isPassed: {
type: Boolean,
default: false,
required: true
},
response: [String, Array, Object]
},
data() {
return {
sampleText: ''
}
}
})
</script>

131
frontend/components/containers/settings/form/ConfigTemplate.vue

@ -0,0 +1,131 @@
<template>
<v-stepper-content step="3">
<v-card>
<v-card-text class="pa-0">
<h4 class="text-h6">Set mapping template</h4>
<p class="font-weight-regular body-1">
Now, you can successfuly fetch the API response.
Next, you need to convert API response to doccano format with the mapping template.
</p>
<h4 class="text-h6">
Response
</h4>
<v-sheet
:dark="!$vuetify.theme.dark"
:light="$vuetify.theme.dark"
class="mb-5 pa-5"
>
<pre>{{ JSON.stringify(response, null, 4) }}</pre>
</v-sheet>
<h4 class="text-h6">
doccano format
</h4>
<v-sheet
:dark="!$vuetify.theme.dark"
:light="$vuetify.theme.dark"
class="mb-5 pa-5"
>
<pre>Text Classification</pre>
<pre>[{ "label": "Cat" }, ...]</pre>
<br>
<pre>Sequence Labeling</pre>
<pre>[{ "label": "Cat", "start_offset": 0, "end_offset": 5 }, ...]</pre>
<br>
<pre>Sequence to sequence</pre>
<pre>[{ "text": "Cat" }, ...]</pre>
</v-sheet>
<h4 class="text-h6">Mapping template</h4>
<p class="font-weight-regular body-1">
You can set mapping template(<a href="https://jinja.palletsprojects.com/en/2.11.x/">Jinja2</a> format) to convert API response to doccano format.
In the template, you can refer to the API response by the <strong>input</strong> variable.
If you want to know the Jinja2 notation, please refer to the site.
</p>
<v-textarea
v-model="value"
outlined
label="Mapping Template"
/>
<v-alert
v-for="(error, index) in errorMessages"
prominent
type="error"
:key="index"
>
<v-row align="center">
<v-col class="grow">
{{ error }}
</v-col>
</v-row>
</v-alert>
<h4 class="text-h6">
Result
</h4>
<v-sheet
:dark="!$vuetify.theme.dark"
:light="$vuetify.theme.dark"
class="mb-5 pa-5"
>
<pre>{{ JSON.stringify(result, null, 4) }}</pre>
</v-sheet>
</v-card-text>
<v-card-actions class="pa-0">
<v-spacer />
<v-btn
text
class="text-capitalize"
@click="$emit('prev')"
>
Prev
</v-btn>
<v-btn
v-show="!isPassed"
color="primary"
class="text-capitalize"
@click="$emit('onTest')"
>
Test
</v-btn>
<v-btn
v-show="isPassed"
color="primary"
class="text-capitalize"
@click="$emit('next')"
>
Next
</v-btn>
</v-card-actions>
</v-card>
</v-stepper-content>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
value: {
type: String,
default: '',
required: true
},
errorMessages: {
type: Array,
default: () => [],
required: true
},
isPassed: {
type: Boolean,
default: false,
required: true
},
response: [String, Object, Array],
result: Array
},
watch: {
value(val) {
this.$emit('input', val)
}
}
})
</script>

71
frontend/components/containers/settings/form/ConfigTemplateName.vue

@ -0,0 +1,71 @@
<template>
<v-stepper-content step="1">
<v-card>
<v-card-text class="pa-0">
<v-form v-model="valid">
<h4 class="text-h6">Select a config template</h4>
<p class="font-weight-regular body-1">
You can select the template to create the auto-labeling configuration.
</p>
<v-select
v-model="templateName"
:items="templateNames"
:rules="templateNameRules()"
label="Select a config template"
outlined
/>
</v-form>
</v-card-text>
<v-card-actions class="pa-0">
<v-spacer />
<v-btn
:disabled="!valid"
color="primary"
class="text-capitalize"
@click="$emit('next')"
>
Next
</v-btn>
</v-card-actions>
</v-card>
</v-stepper-content>
</template>
<script lang="ts">
import Vue from 'vue'
import { FromApiTemplateRepository } from '@/repositories/template/api'
import { TemplateApplicationService } from '@/services/application/template.service'
import { ConfigTemplateItem } from '@/models/config/config-template'
import { templateNameRules } from '@/rules/index'
export default Vue.extend({
data() {
return {
templateName: null,
templateNames: [] as string[],
templateNameRules,
valid: false
}
},
async created() {
this.templateNames = await this.templateService.list(this.$route.params.id)
},
watch: {
async templateName(val) {
const projectId = this.$route.params.id
const response: ConfigTemplateItem = await this.templateService.find(projectId, val)
this.$emit('input', response.toObject())
},
},
computed: {
templateService(): TemplateApplicationService {
const repository = new FromApiTemplateRepository()
const service = new TemplateApplicationService(repository)
return service
}
}
})
</script>

frontend/components/containers/settings/LabelMapping.vue → frontend/components/containers/settings/form/LabelMapping.vue

@ -104,7 +104,6 @@
<script lang="ts">
import Vue from 'vue'
import { headers } from '@/models/config/config-template'
import { FromApiLabelItemListRepository } from '@/repositories/label/api'
import { LabelApplicationService } from '@/services/application/label.service'
import { labelNameRules } from '@/rules/index'
@ -112,8 +111,26 @@ import { labelNameRules } from '@/rules/index'
export default Vue.extend({
data() {
return {
headers,
dialog: false,
headers: [
{
text: 'From',
align: 'left',
value: 'from',
sortable: false
},
{
text: 'To',
align: 'left',
value: 'to',
sortable: false
},
{
text: 'Actions',
value: 'actions',
sortable: false
}
],
valid: false,
editedIndex: -1,
editedItem: {

frontend/components/containers/settings/ObjectField.vue → frontend/components/containers/settings/form/ObjectField.vue

@ -199,4 +199,4 @@ export default Vue.extend({
/deep/ .v-toolbar__content {
padding: 0px !important;
}
</style>
</style>

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

@ -66,11 +66,22 @@ export class ConfigItem {
}
}
export const headers = [
{
text: 'Model name',
align: 'left',
value: 'modelName',
sortable: false
export class Parameters {
constructor(
private readonly parameters: { [key: string]: any }
) {}
static parse(parameters: {'name': string, 'value': string}[]): Parameters {
const _parameters: {[key: string]: any} = parameters.reduce((a, x) => ({...a, [x.name]: x.value}), {})
for (const [key, value] of Object.entries(_parameters)) {
if (Array.isArray(value)) {
_parameters[key] = value.reduce((a, x) => ({...a, [x.key]: x.value}), {})
}
}
return new Parameters(_parameters)
}
]
toObject(): object {
return this.parameters
}
}

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

@ -64,23 +64,3 @@ 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
}
]

31
frontend/repositories/config/api.ts

@ -1,6 +1,6 @@
import ApiService from '@/services/api.service'
import { ConfigItemListRepository, ConfigTestResponse } from '@/repositories/config/interface'
import { ConfigItemList, ConfigItem } from '@/models/config/config-item-list'
import { ConfigItemList, ConfigItem, Parameters } from '@/models/config/config-item-list'
export interface ConfigItemResponse {
id: number,
@ -60,4 +60,33 @@ export class FromApiConfigItemListRepository implements ConfigItemListRepository
const responseItem: ConfigTestResponse = response.data
return responseItem
}
async testParameters(modelName: string, parameters: Parameters, text: string) {
const url = 'auto-labeling-parameter-testing'
const response = await this.request.post(
url,
{
text,
model_name: modelName,
model_attrs: parameters.toObject()
}
)
const responseItem: ConfigTestResponse = response.data
return responseItem
}
async testTemplate(projectId: string, response: any, template: string): Promise<ConfigTestResponse> {
console.log(projectId)
const url = `/projects/${projectId}/auto-labeling-template-testing`
const _response = await this.request.post(url, { response, template })
const responseItem: ConfigTestResponse = _response.data
return responseItem
}
async testMapping(projectId: string, item: ConfigItem, response: any): Promise<ConfigTestResponse> {
const url = `/projects/${projectId}/auto-labeling-mapping-testing`
const _response = await this.request.post(url, {...item.toAPI(), response})
const responseItem: ConfigTestResponse = _response.data
return responseItem
}
}

8
frontend/repositories/config/interface.ts

@ -1,4 +1,4 @@
import { ConfigItem, ConfigItemList } from '@/models/config/config-item-list'
import { ConfigItem, ConfigItemList, Parameters } from '@/models/config/config-item-list'
export interface ConfigTestResponse {
valid: boolean,
@ -15,4 +15,10 @@ export interface ConfigItemListRepository {
update(projectId: string, item: ConfigItem): Promise<ConfigItem>
testConfig(projectId: string, item: ConfigItem, text: string): Promise<ConfigTestResponse>
testParameters(modelName: string, parameters: Parameters, text: string): Promise<ConfigTestResponse>
testTemplate(projectId: string, response: any, template: string): Promise<ConfigTestResponse>
testMapping(projectId: string, item: ConfigItem, response: any): Promise<ConfigTestResponse>
}

6
frontend/rules/index.js

@ -75,3 +75,9 @@ export const passwordRules = (msg) => {
v => (v && v.length <= 30) || msg.passwordLessThan30Chars
]
}
export const templateNameRules = () => {
return [
v => !!v || 'Name is required'
]
}

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

@ -1,4 +1,4 @@
import { ConfigItemList, ConfigItem } from '@/models/config/config-item-list'
import { ConfigItemList, ConfigItem, Parameters } from '@/models/config/config-item-list'
import { ConfigItemListRepository, ConfigTestResponse } from '@/repositories/config/interface'
export class ConfigApplicationService {
@ -20,5 +20,54 @@ export class ConfigApplicationService {
public testConfig(projectId: string, item: ConfigItem, text: string): Promise<ConfigTestResponse> {
return this.configRepository.testConfig(projectId, item, text)
.then((value) => {
return value
})
.catch((error) => {
const data = error.response.data
if ('non_field_errors' in data) {
throw new Error(data['non_field_errors'])
} else if ('template' in data) {
throw new Error('The template need to be filled.')
} else if ('detail' in data) {
throw new Error(data['detail'])
} else {
throw new Error(data)
}
})
}
public testParameters(modelName: string, parameters: Parameters, text: string) {
return this.configRepository.testParameters(modelName, parameters, text)
.then((value) => {
return value
})
.catch((error) => {
const data = error.response.data
throw new Error(data)
})
}
public testTemplate(projectId: string, response: any, template: string) {
return this.configRepository.testTemplate(projectId, response, template)
.then((value) => {
return value
})
.catch((error) => {
const data = error.response.data
throw new Error(data)
})
}
public testMapping(projectId: string, item: ConfigItem, response: any) {
return this.configRepository.testMapping(projectId, item, response)
.then((value) => {
return value
})
.catch((error) => {
const data = error.response.data
throw new Error(data)
})
}
}
Loading…
Cancel
Save