diff --git a/src/routes/model/+page.svelte b/src/routes/model/+page.svelte index df93546ca431a7c51a130b29fbbc313b64ffb57e..b4f1ede27b85d546fe16a85eceab90e2e66a6e58 100644 --- a/src/routes/model/+page.svelte +++ b/src/routes/model/+page.svelte @@ -4,12 +4,12 @@ Button, ButtonGroup, Col, - Container, FormGroup, - Icon, Input, Label, + Container, Form, FormGroup, + Icon, Input, InputGroup, InputGroupText, Label, ListGroup, ListGroupItem, Modal, ModalBody, ModalFooter, ModalHeader, Row, - Styles + Styles, Tooltip } from "@sveltestrap/sveltestrap"; import {onMount} from "svelte"; import InPlaceEdit from './InPlaceEdit.svelte' @@ -18,25 +18,96 @@ let changed = false; let open = false; let saveAlert = false; + + interface SettingsUi { + type:string; + label: string; + description: string; + bind:string; + } + class SettingsSwitch implements SettingsUi{ + readonly type="switch"; + label:string; + description:string; + bind:string; + constructor(label:string,description:string, bind:string) { + this.bind = bind; + this.label=label; + this.description = description; + } + } + class SettingsSelector implements SettingsUi{ + readonly type="selector"; + label:string; + description:string; + bind:string; + options:string[]; + constructor(label:string,description:string, bind:string,options:string[]) { + this.bind = bind; + this.label=label; + this.description = description; + this.options=options; + } + } + class SettingsTextfield implements SettingsUi{ + readonly type="textfield"; + label:string; + description:string; + bind:string; + input: string; + constructor(label:string,description:string, bind:string, input:string) { + this.bind = bind; + this.label=label; + this.description = description; + this.input=input; + } + } + class SettingsNumberfield implements SettingsUi{ + readonly type="numberfield"; + label:string; + description:string; + bind:string; + input: number; + constructor(label:string,description:string, bind:string, input:number) { + this.bind = bind; + this.label=label; + this.description = description; + this.input=input; + } + } + class SettingsLabel{ + readonly type="label" + label:string; + constructor(label:string) { + this.label=label; + } + } let modalModule = { name: '', - response: {}} + response: {}, + html:[] + } class group{ name: string; + loop: boolean = true; loopsize:number; - modules:string[]; + modules:string[]=[]; constructor(name: string, loopsize: number){ this.name = name; this.loopsize = loopsize; - this.modules = []; } } let groups : group[] = []; let modules: string[]=[]; let modulesModalOpen: boolean = false; let modulesModalIndex: number; + let loopOpen: boolean = false; const toggle = () => (open = !open); const toggleModules = () => (modulesModalOpen = !modulesModalOpen); + const toggleLoop =() => (loopOpen = !loopOpen); + + let testbool:boolean = true; + onMount(async ()=>{ const res = await fetch("http://127.0.0.1:8000/convergence"); const data = await res.json(); @@ -45,6 +116,7 @@ modules = modules.concat(data["PostprocessingSteps"]); modules = modules.concat(data["SizingLoop"]); modules = Array.from(new Set(modules)) + modules.sort() }) async function loadModel(){ const res = await fetch("http://127.0.0.1:8000/convergence"); @@ -66,10 +138,7 @@ async function uploadModel(){ const response = await fetch('http://127.0.0.1:8000/modules/update', { method: 'PUT', - body: JSON.stringify({ SetupSteps: SetupSteps, - StudyMission:StudySteps, - SizingLoop:SizingSteps, - PostprocessingSteps:PostprocessSteps}), + body: JSON.stringify({groups}), headers: { 'content-type': 'application/json' } @@ -85,9 +154,29 @@ const res = await fetch("http://127.0.0.1:8000/modules/"+module+"/config"); const data = await res.json(); modalModule.name = module; - modalModule.response = data; + modalModule.response = JSON.parse(data); + modalModule.html= [] + generateHTML(modalModule.response,modalModule.html) modalModule=modalModule; } + function generateHTML(json: object){ + Object.entries(json).forEach(([key, value]) =>{ + if(value.hasOwnProperty("value")){ + if(value.description&&value.description.includes("Switch")){ + modalModule.html.push(new SettingsSwitch(key,value.description,value)) + }else if(value.description&&value.description.includes("Selector")){ + modalModule.html.push(new SettingsSelector(key,value.description,value,["mode_0","mode_1","mode_2"])) + }else{ + modalModule.html.push(new SettingsTextfield(key,value.description,key,key)) + } + }else if(typeof value ==="object"){ + modalModule.html.push(new SettingsLabel(key)) + generateHTML(json[key]) + }else{ + return; + } + }) + } function dragStart(event,groupIndex :number, itemIndex :number) { const data = {groupIndex, itemIndex}; event.dataTransfer.setData('text/plain', JSON.stringify(data)); @@ -130,8 +219,6 @@ function addModules(index:number, modulname: string){ groups.at(index).modules.push(modulname) updateAll() - console.log("add") - console.log(modulname) } function submitGrpName(field:number) { return ({detail: newValue}) => { @@ -149,6 +236,13 @@ groups.at(grpIndex).modules.splice(modulIndex, 1); updateAll() } + function copyGroup(index:number){ + const newGroup = new group("copy of "+groups[index].name,groups[index].loopsize); + newGroup.modules=newGroup.modules.concat(groups[index].modules); + newGroup.loop = newGroup.loop; + groups.push(newGroup); + updateAll() + } </script> <Container> <h2>Simulationsmodel</h2> @@ -168,39 +262,70 @@ </ButtonGroup> <Row class="py-3"> {#each groups as groupitem, groupIndex(groupitem)} - <Col> - <h3><InPlaceEdit bind:value={groupitem.name} on:submit={submitGrpName(groupIndex)}/></h3> - <Button color="dark" outline on:click={()=>deleteGroup(groupIndex)}><Icon name="trash" /></Button> - <FormGroup> - <Label>Loopsize:</Label> - <Input type="number" placeholder="{groupitem.loopsize}" /> - </FormGroup> - <Button color="dark" outline on:click={()=>{modulesModalIndex=groupIndex;toggleModules()}}><Icon name="boxes" /> manage Modules</Button> - <ul class="list-group" - on:drop={event=>drop(event,groupIndex)} - on:dragover|preventDefault={event=>dragOver(event)}> - {#each groupitem.modules as item, itemIndex(itemIndex)} - <div class="item" data-index={itemIndex}> - <li class="list-group-item list-group-item-action" - draggable="true" on:dragstart={event=>dragStart(event,groupIndex,groupitem.modules.indexOf(item))} - on:click={getModuleConf(item),toggle}> - {item} - </li> - </div> - {/each} - </ul> + <Col > + <Row> + <h3><InPlaceEdit bind:value={groupitem.name} on:submit={submitGrpName(groupIndex)}/></h3> + <ButtonGroup> + <Button color="dark" outline on:click={()=>{modulesModalIndex=groupIndex;toggleModules()}}><Icon name="boxes"/> Modules</Button> + <Button color="dark" outline on:click={()=>{modulesModalIndex=groupIndex;toggleLoop()}}><Icon name="arrow-clockwise" /> + {#if groupitem.loop} + {groupitem.loopsize} + {:else} + auto + {/if} + </Button> + <Button color="dark" outline on:click={()=>copyGroup(groupIndex)}><Icon name="copy" /></Button> + <Button color="dark" outline on:click={()=>deleteGroup(groupIndex)}><Icon name="trash" /></Button> + </ButtonGroup> + </Row> + <ul class="list-group" + on:drop={event=>drop(event,groupIndex)} + on:dragover|preventDefault={event=>dragOver(event)}> + {#each groupitem.modules as item, itemIndex(itemIndex)} + <div class="item" data-index={itemIndex}> + <li class="list-group-item list-group-item-action" + draggable="true" on:dragstart={event=>dragStart(event,groupIndex,groupitem.modules.indexOf(item))} + on:click={getModuleConf(item),toggle}> + {item} + </li> + </div> + {/each} + </ul> </Col> {/each} </Row> <Modal isOpen={open} toggle={toggle} scrollable> - <ModalHeader toggle={toggle}>{modalModule.name}</ModalHeader> + <ModalHeader toggle={toggle}>{modalModule.name} settings</ModalHeader> <ModalBody> - {JSON.stringify(modalModule.response)} + {#each modalModule.html as element} + {#if element.type=="switch"} + <Input type="switch" label="{element.label}" bind:checked={element.bind.value}/> + <Tooltip target={element.label} placement="left"> + {element.description} + </Tooltip> + {:else if element.type=="label"} + <h6>{element.label}</h6> + {:else if element.type =="selector"} + <h6>{element.label}</h6> + <Input id={element.label} type="select" bind:value={element.bind.value}> + {#each element.options as option} + <option>{option}</option> + {/each} + </Input> + <Tooltip target={element.label} placement="left"> + {element.description} + </Tooltip> + {:else if element.type=="textfield"} + <h7>{element.label}</h7> + <Input id={element.label} type="text" /> + <Tooltip target={element.label} placement="left"> + {element.description} + </Tooltip> + {/if} + {/each} </ModalBody> <ModalFooter> - <Button color="primary" on:click={toggle}>Do Something</Button> - <Button color="danger" on:click={toggle}>Delete</Button> - <Button color="secondary" on:click={toggle}>Cancel</Button> + <Button on:click={console.log(modalModule.response)}>test switch</Button> </ModalFooter> </Modal> <Modal isOpen={modulesModalOpen} toggle={toggleModules} scrollable> @@ -226,5 +351,28 @@ </Row> </ModalBody> </Modal> + <Modal isOpen={loopOpen} toggle={toggleLoop} scrollable> + <ModalHeader toggle={toggleLoop}>Loop Settings for {groups[modulesModalIndex].name}</ModalHeader> + <ModalBody> + <Form> + <Label>Loopkind:</Label> + <Input name="loop" type="radio" bind:group={groups[modulesModalIndex].loop} value={true} label={"manual Loopsize"} /> + <Input name="loop" type="radio" bind:group={groups[modulesModalIndex].loop} value={false} label={"Autoloop"} /> + <br> + {#if groups[modulesModalIndex].loop} + <InputGroup size="sm"> + <InputGroupText>Loopsize</InputGroupText> + <Input type="number" min={0} bind:value={groups[modulesModalIndex].loopsize} placeholder={groups[modulesModalIndex].loopsize}/> + </InputGroup> + {:else} + <p> + Placeholder for Convsettings + </p> + {/if} + + </Form> + </ModalBody> + + </Modal> </Container> <Styles/> \ No newline at end of file