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:
@@ -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>
|
||||||
@@ -38,7 +38,7 @@ export default {
|
|||||||
default: new Array(),
|
default: new Array(),
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
92
tools/otagui/src/components/SingleOTAOptions.vue
Normal file
92
tools/otagui/src/components/SingleOTAOptions.vue
Normal 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>
|
||||||
@@ -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 = [
|
||||||
|
|||||||
@@ -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>>
|
||||||
Reference in New Issue
Block a user