Merge "Refactor the frontend for batch generation." am: 89e47defef

Original change: https://android-review.googlesource.com/c/platform/development/+/1775725

Change-Id: I0e9ccb6d87ced9b6bdf2d0f0035bbeb18a45ea29
This commit is contained in:
Treehugger Robot
2021-07-23 17:30:24 +00:00
committed by Automerger Merge Worker
5 changed files with 248 additions and 137 deletions

View File

@@ -1,76 +1,55 @@
<template> <template>
<form @submit.prevent="sendForm"> <v-row>
<FileSelect <v-col
v-if="input.isIncremental" v-for="flag in basicFlags"
v-model="input.incremental" :key="flag.key"
label="Select the source file" cols="12"
:options="targetDetails" md="4"
/> >
<FileSelect <BaseCheckbox
v-model="input.target" v-model="otaConfig[flag.key]"
label="Select a target file" :label="flag.label"
:options="targetDetails"
/>
<v-row>
<v-col
v-for="flag in basicFlags"
:key="flag.key"
cols="12"
md="4"
>
<BaseCheckbox
v-model="input[flag.key]"
:label="flag.label"
/>
</v-col>
</v-row>
<div v-if="input.isPartial">
<v-divider />
<h3>Select Partitions</h3>
<PartialCheckbox
v-model="input.partial"
:labels="updatablePartitions"
/> />
<v-divider /> </v-col>
</div> </v-row>
<v-btn <div v-if="otaConfig.isPartial">
block <v-divider />
@click="moreOptions = !moreOptions" <h3>Select Partitions</h3>
> <PartialCheckbox
More Options v-model="otaConfig.partial"
</v-btn> :labels="updatablePartitions"
<v-row v-if="moreOptions">
<v-col
v-for="flag in extraFlags"
:key="flag.key"
cols="12"
md="4"
>
<BaseCheckbox
v-model="input[flag.key]"
:label="flag.label"
/>
</v-col>
</v-row>
<v-divider class="my-5" />
<BaseInput
v-model="input.extra"
:label="'Extra Configurations'"
/> />
<v-divider class="my-5" /> <v-divider />
<v-btn </div>
block <v-btn
type="submit" block
@click="moreOptions = !moreOptions"
>
More Options
</v-btn>
<v-row v-if="moreOptions">
<v-col
v-for="flag in extraFlags"
:key="flag.key"
cols="12"
md="4"
> >
Submit <BaseCheckbox
</v-btn> v-model="otaConfig[flag.key]"
</form> :label="flag.label"
/>
</v-col>
</v-row>
<v-divider class="my-5" />
<BaseInput
v-model="otaConfig.extra"
:label="'Extra Configurations'"
/>
</template> </template>
<script> <script>
import BaseInput from '@/components/BaseInput.vue' import BaseInput from '@/components/BaseInput.vue'
import BaseCheckbox from '@/components/BaseCheckbox.vue' import BaseCheckbox from '@/components/BaseCheckbox.vue'
import FileSelect from '@/components/FileSelect.vue'
import PartialCheckbox from '@/components/PartialCheckbox.vue' import PartialCheckbox from '@/components/PartialCheckbox.vue'
import { OTAConfiguration, OTABasicFlags, OTAExtraFlags } from '@/services/JobSubmission.js' import { OTAConfiguration, OTABasicFlags, OTAExtraFlags } from '@/services/JobSubmission.js'
@@ -78,7 +57,6 @@ export default {
components: { components: {
BaseInput, BaseInput,
BaseCheckbox, BaseCheckbox,
FileSelect,
PartialCheckbox, PartialCheckbox,
}, },
props: { props: {
@@ -86,18 +64,14 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
incrementalSource: { targetBuilds: {
type: String, type: Array,
default: '', default: () => []
}, }
targetBuild: {
type: String,
default: '',
},
}, },
data() { data () {
return { return {
input: new OTAConfiguration(), otaConfig: new OTAConfiguration(),
moreOptions: false, moreOptions: false,
basicFlags: OTABasicFlags, basicFlags: OTABasicFlags,
extraFlags: OTAExtraFlags extraFlags: OTAExtraFlags
@@ -109,49 +83,24 @@ export default {
* @return Array<String> * @return Array<String>
*/ */
updatablePartitions() { updatablePartitions() {
if (!this.input.target) return [] // TODO(lishutong): currently only give the partition list of first
// build, should use the intersections of the partitions of
// all given builds.
if (!this.targetBuilds | this.targetBuilds.length===0) return []
if (this.targetBuilds[0] === '') return []
let target = this.targetDetails.filter( let target = this.targetDetails.filter(
(d) => d.path === this.input.target (d) => d.path === this.targetBuilds[0]
) )
return target[0].partitions return target[0].partitions
}, },
checkIncremental() {
return this.input.isIncremental
},
}, },
watch: { watch: {
incrementalSource: { otaConfig: {
handler: function () { handler () {
this.input.isIncremental = true this.$emit('update:otaConfig', this.otaConfig)
this.input.incremental = this.incrementalSource
}, },
}, deep: true
targetBuild: { }
handler: function () { }
this.input.target = this.targetBuild
},
},
checkIncremental: {
handler: function () {
this.$emit('update:isIncremental', this.checkIncremental)
},
},
},
methods: {
/**
* Send the configuration to the backend.
*/
async sendForm() {
try {
let response_message = await this.input.sendForm()
alert(response_message)
} catch (err) {
alert(
'Job cannot be started properly for the following reasons: ' + err
)
}
this.input = new OTAInput()
},
},
} }
</script> </script>

View File

@@ -38,7 +38,7 @@ export default {
default: new Array(), default: new Array(),
}, },
modelValue: { modelValue: {
type: String, type: Array,
required: true required: true
}, },
}, },

View File

@@ -0,0 +1,92 @@
<template>
<form @submit.prevent="sendForm">
<FileSelect
v-if="otaConfig.isIncremental"
v-model="incrementalSource"
label="Select the source file"
:options="targetDetails"
/>
<FileSelect
v-model="targetBuild"
label="Select a target file"
:options="targetDetails"
/>
<OTAOptions
:targetDetails="targetDetails"
:targetBuilds="[targetBuild]"
@update:otaConfig="otaConfig=$event"
/>
<v-divider class="my-5" />
<v-btn
block
type="submit"
>
Submit
</v-btn>
</form>
</template>
<script>
import OTAOptions from '@/components/OTAOptions.vue'
import FileSelect from '@/components/FileSelect.vue'
import { OTAConfiguration } from '@/services/JobSubmission.js'
export default {
components: {
OTAOptions,
FileSelect,
},
props: {
targetDetails: {
type: Array,
default: () => [],
}
},
data() {
return {
incrementalSource: '',
targetBuild: '',
otaConfig: new OTAConfiguration(),
}
},
computed: {
checkIncremental() {
return this.otaConfig.isIncremental
},
},
watch: {
checkIncremental: {
handler: function () {
this.$emit('update:isIncremental', this.checkIncremental)
},
},
},
created() {
this.$emit('update:isIncremental', this.checkIncremental)
this.$emit('update:handler', this.setIncrementalSource, this.setTargetBuild)
},
methods: {
/**
* Send the configuration to the backend.
*/
async sendForm() {
try {
let response_message = await this.otaConfig.sendForm(
this.targetBuild, this.incrementalSource)
alert(response_message)
this.otaConfig.reset()
} catch (err) {
alert(
'Job cannot be started properly for the following reasons: ' + err
)
}
},
setIncrementalSource (build) {
this.incrementalSource = build
},
setTargetBuild (build) {
this.targetBuild = build
}
},
}
</script>

View File

@@ -21,32 +21,50 @@ export class OTAConfiguration {
* disable checkboxes of which dependencies are not fulfilled. * disable checkboxes of which dependencies are not fulfilled.
*/ */
this.verbose = false, this.verbose = false,
this.target = '',
this.incremental = '',
this.isIncremental = false, this.isIncremental = false,
this.partial = [], this.partial = [],
this.isPartial = false, this.isPartial = false,
this.extra_keys = [], this.extra_keys = [],
this.extra = '', this.extra = ''
this.id = uuid.v1()
} }
/** /**
* Start the generation process, will throw an error if not succeed * Start an OTA package generation from target build to incremental source.
* Throw an error if not succeed, otherwise will return the message from
* the backend.
* @param {String} targetBuild
* @param {String} incrementalSource
* @return String
*/ */
async sendForm() { async sendForm(targetBuild, incrementalSource='') {
let jsonOptions = Object.assign({}, this)
jsonOptions.target = targetBuild
jsonOptions.incremental = incrementalSource
jsonOptions.id = uuid.v1()
for (let flag of OTAExtraFlags) { for (let flag of OTAExtraFlags) {
if (this[flag.key]) { if (jsonOptions[flag.key]) {
this.extra_keys.push(flag.key) jsonOptions.extra_keys.push(flag.key)
} }
} }
try { try {
let response = await ApiServices.postInput(JSON.stringify(this), this.id) let response = await ApiServices.postInput(JSON.stringify(jsonOptions), jsonOptions.id)
return response.data return response.data
} catch (err) { } catch (err) {
throw err throw err
} }
} }
/**
* Reset all the flags being set in this object.
*/
reset() {
for (let flag of OTAExtraFlags) {
if (this[flag.key]) {
delete this[flag.key]
}
}
this.constructor()
}
} }
export const OTABasicFlags = [ export const OTABasicFlags = [

View File

@@ -1,14 +1,24 @@
<template> <template>
<v-row> <v-row>
<v-col <v-col
id="dynamic-component-demo"
cols="12" cols="12"
md="6" md="6"
> >
<OTAOptions <button
v-for="tab in tabs"
:key="tab.label"
:class="['tab-button', { active: currentTab === tab.component }]"
@click="currentTab = tab.component"
>
{{ tab.label }}
</button>
<component
:is="currentTab"
class="tab-component"
:targetDetails="targetDetails" :targetDetails="targetDetails"
:incrementalSource="incrementalSource"
:targetBuild="targetBuild"
@update:isIncremental="isIncremental = $event" @update:isIncremental="isIncremental = $event"
@update:handler="setHandler"
/> />
</v-col> </v-col>
<v-divider vertical /> <v-divider vertical />
@@ -17,10 +27,12 @@
md="6" md="6"
class="library" class="library"
> >
<!-- the key-binding refresh has to be used to reload the methods-->
<BuildLibrary <BuildLibrary
:refresh="refresh"
:isIncremental="isIncremental" :isIncremental="isIncremental"
@update:incrementalSource="incrementalSource = $event" @update:incrementalSource="addIncrementalSource"
@update:targetBuild="targetBuild = $event" @update:targetBuild="addTargetBuild"
@update:targetDetails="targetDetails = $event" @update:targetDetails="targetDetails = $event"
/> />
</v-col> </v-col>
@@ -28,28 +40,68 @@
</template> </template>
<script> <script>
import OTAOptions from '@/components/OTAOptions.vue' import SingleOTAOptions from '@/components/SingleOTAOptions.vue'
import BuildLibrary from '@/components/BuildLibrary.vue' import BuildLibrary from '@/components/BuildLibrary.vue'
export default { export default {
components: { components: {
OTAOptions, SingleOTAOptions,
BuildLibrary BuildLibrary,
}, },
data() { data() {
return { return {
incrementalSource: '',
targetBuild: '',
targetDetails: [], targetDetails: [],
isIncremental: false isIncremental: false,
currentTab: 'SingleOTAOptions',
refresh: false,
tabs: [
{label: 'Single OTA', component: 'SingleOTAOptions'},
],
} }
}, },
methods: {
setHandler(addIncrementalSource, addTargetBuild) {
this.refresh = true,
this.addIncrementalSource = addIncrementalSource
this.addTargetBuild = addTargetBuild
this.refresh = false
},
addIncrementalSource: () => {},
addTargetBuild: () => {}
}
} }
</script> </script>
<style scoped> <style scoped>
.library { .library {
overflow: scroll; overflow: scroll;
height:calc(100vh - 80px); height: calc(100vh - 80px);
} }
.tab-component {
border: 3px solid #eee;
border-radius: 2px;
padding: 20px;
}
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.demo-tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>> </style>>