config-tools: bugfix for file related issue in UI

1. when using existing configuration, UI show the existing information.
2. remove launch script when removing post-launched VM.
3. new working folder created with no existing files.
4. automatically minimized.

Tracked-On: #7450
Signed-off-by: Conghui <conghui.chen@intel.com>
This commit is contained in:
Conghui 2022-05-10 23:25:14 +08:00 committed by acrnsi-robot
parent c31cad225c
commit f172502044
8 changed files with 159 additions and 29 deletions

View File

@ -392,6 +392,16 @@ pub fn acrn_read_dir(path: &str, recursive: bool) -> Result<Vec<DirEntry>, Strin
read_dir(path, recursive).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn acrn_remove_dir(path: &str) -> Result<(), String> {
fs::remove_dir_all(path).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn acrn_remove_file(path: &str) -> Result<(), String> {
fs::remove_file(path).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn open_devtools(window: Window) {
window.open_devtools()

View File

@ -19,6 +19,8 @@ fn main() {
configurator::acrn_is_file,
configurator::acrn_read_dir,
configurator::acrn_create_dir,
configurator::acrn_remove_dir,
configurator::acrn_remove_file,
configurator::open_devtools
])
.run(tauri::generate_context!())

View File

@ -72,7 +72,7 @@ class Configurator {
return invoke("acrn_write", {filePath, contents})
}
isFile(filePath: String): Promise<boolean> {
isFile(filePath: String): Promise<Boolean> {
return invoke("acrn_is_file", {path: filePath})
}
@ -84,6 +84,14 @@ class Configurator {
return invoke('acrn_create_dir', {path, recursive})
}
removeDir(path: String) {
return invoke('acrn_remove_dir', {path})
}
removeFile(path: String) {
return invoke('acrn_remove_file', {path})
}
runPython(code: String, isJSON = false): String | Object {
// @ts-ignore
let result = window.pydoide.runPython(code);

View File

@ -11,9 +11,17 @@
<b-accordion free>
<b-accordion-item visible>
<b-accordion-item :visible='showFlag'>
<template #title>
<div class="p-1 ps-3 fs-4">1. Import a board configuration file</div>
<div class="d-flex flex-column">
<div class="p-1 ps-3 fs-4">1. Import a board configuration file</div>
<div class="py-2" style="letter-spacing: 0.49px;">
{{currentBoardFile}}
</div>
<div class="py-2" style="letter-spacing: 0.49px;">
{{currentBoardManu}} {{CurrentBoardProd}}
</div>
</div>
</template>
<Board v-model:WorkingFolder="WorkingFolder" v-model:board="board" v-model:schemas="schemas"
@boardUpdate="boardUpdate"/>
@ -21,16 +29,16 @@
<Banner/>
<b-accordion-item>
<b-accordion-item :visible='showFlag'>
<template #title>
<div class="d-flex flex-column">
<div class="p-1 ps-3 fs-4">2. Create new or import an existing scenario</div>
<div class="py-2" style="letter-spacing: 0.49px;">
Current scenario: {{ scenarioHaveData ? 'scenario.xml' : 'none selected' }}
{{ scenarioHaveData ? 'Current scenario: scenario.xml' : '' }}
</div>
</div>
</template>
<Scenario v-if="boardHaveData" :scenario="scenario" @scenarioUpdate="scenarioUpdate"/>
<Scenario v-if="boardHaveData" :scenario="scenario" :WorkingFolder="WorkingFolder" @scenarioUpdate="scenarioUpdate"/>
</b-accordion-item>
<Banner>
<div style="position: relative">
@ -41,7 +49,7 @@
</div>
</Banner>
<b-accordion-item>
<b-accordion-item visible>
<template #title>
<div class="p-1 ps-3 d-flex w-100 justify-content-between align-items-center">
<div class="fs-4">3. Configure settings for scenario and launch scripts</div>
@ -92,11 +100,14 @@ import configurator from "../lib/acrn";
export default {
name: "Config",
components: {ConfigForm, TabBox, Scenario, Icon, Board, Banner, AngleLeft},
props: ['WorkingFolder'],
props: { WorkingFolder: {type: String},
isNewConfig: {type: String}
},
mounted() {
this.updateCurrentFormSchema()
window.getCurrentFormSchemaData = this.getCurrentFormSchemaData
window.getCurrentScenarioData = this.getCurrentScenarioData
this.showFlag = this.isNewConfig === 'true'
},
data() {
return {
@ -108,6 +119,10 @@ export default {
scenario: {},
currentFormSchema: {},
currentFormData: {},
currentBoardFile: '',
currentBoardManu: '',
CurrentBoardProd: '',
showFlag: false,
errors: []
}
},
@ -123,10 +138,26 @@ export default {
back() {
this.$router.back()
},
updateCurrentBoardInfo() {
// update the info in title
this.currentBoardFile = 'Current file: ' + this.board['name']
let boardContent = this.board.content
let reg = /(?<=Manufacturer).+(?=\\n)/
let result = boardContent.match(/Manufacturer.+\n/gm)
console.log(result)
if (result.length > 0) {
this.currentBoardManu = result[0]
}
var result_p = boardContent.match(/Product Name.+\n/gm)
if (result_p.length > 0) {
this.CurrentBoardProd = result_p[0]
}
},
boardUpdate(boardInfo, scenarioJSONSchema) {
this.board = boardInfo;
this.schemas = scenarioJSONSchema
this.updateCurrentFormSchema()
this.updateCurrentBoardInfo()
},
updateCurrentFormSchema() {
if (this.activeVMID === -1) {
@ -146,6 +177,7 @@ export default {
},
scenarioUpdate(scenarioData) {
this.scenario = scenarioData;
this.showFlag = false;
this.updateCurrentFormSchema()
this.updateCurrentFormData()
},
@ -209,14 +241,19 @@ export default {
msg = "Post-launched VMs require the Service VM. If you proceed, all post-launched VMs and their settings will also be deleted. Are you sure you want to proceed?"
isserivevm = true
} else {
msg = `Delete this virtual machine VM${this.activeVMID}?`
msg = `Delete this virtual machine VM${this.activeVMID}, launch script will alse be deleted if it exists.`
}
confirm(msg).then((r) => {
if (r) {
if (isserivevm) {
for (let i = postvmlist.length - 1; i >= 0; i--) {
for (let i=postvmlist.length-1; i>=0; i--) {
let launchScriptsname = this.WorkingFolder + `launch_user_vm_id${postvmlist[i]}.sh`
this.removeLaunchScript(launchScriptsname);
this.scenario.vm.splice(postvmlist[i], 1);
}
} else {
let launchScriptsname = this.WorkingFolder + `launch_user_vm_id${currentVMIndex}.sh`
this.removeLaunchScript(launchScriptsname);
}
this.vmNameChange('', this.scenario.vm[currentVMIndex].name)
this.scenario.vm.splice(currentVMIndex, 1);
@ -225,6 +262,16 @@ export default {
}
})
},
removeLaunchScript(filePath) {
console.log(filePath)
configurator.isFile(filePath)
.then((isFile) => {
if (isFile) {
configurator.removeFile(filePath)
.catch((err) => alert(`Launch script is not exist: ${filePath}`))
}
})
},
scenarioConfigFormDataUpdate(vmid, data) {
if (vmid === -1) {
this.scenario.hv = data
@ -285,7 +332,6 @@ export default {
this.updateCurrentFormData()
// get scenario XML with defaults
scenarioXMLData = scenarioWithDefault.xml
debugger
// begin write down and verify
configurator.writeFile(this.WorkingFolder + 'scenario.xml', scenarioXMLData)
.then(() => {

View File

@ -87,10 +87,22 @@ export default {
}
},
mounted() {
this.getBoardHistory()
.then(() => {
this.importBoard()
})
//get init board if it exist, add to history
this.getExistBoardPath()
.then((filePath) => {
if (filePath.length > 0) {
console.log("add exist board to history!")
configurator.addHistory('Board', filePath)
.then(() => {
this.getBoardHistory()
.then(() => {
this.importBoard()
})
})
}
})
this.getBoardHistory()
// Todo: auto load board
},
computed: {
@ -133,8 +145,26 @@ export default {
.then(() => configurator.addHistory('Board', boardFileNewPath))
.then(() => this.getBoardHistory())
})
.catch((err)=> {
alert(`Failed to load the file ${filepath}, it may not exist`)
console.log(err)
})
}
},
getExistBoardPath() {
// only return filename when using exist configuration.
return configurator.readDir(this.WorkingFolder, false)
.then((res) => {
let boardPath = ''
res.map((filepath) => {
if (filepath.path.search('board') != -1) {
boardPath = filepath.path
}
})
// only return the last vaild boardPath
return boardPath
})
},
openBoardFileSelectDialog() {
return configurator.openDialog({
title: "Open Board XML",

View File

@ -57,17 +57,30 @@ export default {
}
},
props: {
WorkingFolder: {
type: String
},
scenario: {
type: Object
}
},
mounted() {
this.getScenarioHistory().then(() => {
// delay 2s for board loading
setTimeout(() => {
this.loadScenario(true)
}, 2000);
})
//get init scenario if it exist, add to history
this.getExistScenarioPath()
.then((filePath) => {
if (filePath.length > 0) {
configurator.addHistory('Scenario', filePath)
.then(()=>{
this.getScenarioHistory().then(() => {
// delay 2s for board loading
setTimeout(() => {
this.loadScenario(true)
}, 2000);
})
})
}
})
this.getScenarioHistory()
// Todo: auto load scenario
},
methods: {
@ -89,6 +102,20 @@ export default {
})
}
},
getExistScenarioPath() {
// only return filename when using exist configuration.
return configurator.readDir(this.WorkingFolder, false)
.then((res) => {
let scenarioPath = ''
res.map((filepath) => {
if (filepath.path.search('scenario') != -1) {
scenarioPath = filepath.path
}
})
// only return the last vaild boardPath
return scenarioPath
})
},
openScenarioFileSelectDialog() {
configurator.openDialog({
title: "Open Existing Scenario XML",
@ -117,4 +144,4 @@ export default {
<style scoped>
</style>
</style>

View File

@ -52,7 +52,7 @@ export default {
},
methods: {
nextPage(folderPath) {
this.$router.push({name: 'Config', params: {WorkingFolder: folderPath}})
this.$router.push({name: 'Config', params: {WorkingFolder: folderPath, isNewConfig: true}})
},
usingWorkingFolder() {
let folderPath = this.WorkingFolder.length ? this.WorkingFolder : this.defaultWorkingFolder;
@ -65,9 +65,16 @@ export default {
.then((files) => {
console.log("Directory exists.", files)
if (files.length > 0) {
confirm("Directory exists, overwrite it?")
confirm(`Warning: all existing files in the following working folder will be deleted: \n${folderPath}`)
.then((r) => {
if (r) this.nextPage(folderPath)
if (r) {
configurator.removeDir(folderPath)
.then(()=> {
configurator.creatDir(folderPath)
this.nextPage(folderPath)
})
.catch((err) => alert(`${err}`))
}
})
} else {
this.nextPage(folderPath)
@ -101,4 +108,4 @@ export default {
<style scoped>
</style>
</style>

View File

@ -53,10 +53,10 @@ export default {
},
methods: {
nextPage(folderPath) {
this.$router.push({name: 'Config', params: {WorkingFolder: folderPath}})
this.$router.push({name: 'Config', params: {WorkingFolder: folderPath, isNewConfig:false}})
},
usingWorkingFolder() {
this.nextPage(this.currentSelected)
this.nextPage(this.currentSelected, true)
},
getHistory() {
configurator.getHistory("WorkingFolder")
@ -75,7 +75,7 @@ export default {
directory: true,
multiple: false
}).then(
(folderPath) => configurator.addHistory("WorkingFolder", folderPath)
(folderPath) => configurator.addHistory("WorkingFolder", folderPath + window.systemInfo.pathSplit)
).then(() => {
this.getHistory()
})