Skip to content

Commit

Permalink
cleanup and document structure handling
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas committed Oct 7, 2023
1 parent 82c98ee commit c057271
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 79 deletions.
47 changes: 42 additions & 5 deletions webinstall/build.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
# structure
# below config we define the structure to be displayed
# basically there are 2 object types:
# children - a list of cfg objects that define the inputs to be shown
# if the parent is selected
# parameters:
# key: unique key - defines the name(part) in the cfg
# if not set a potential "value" is taken
# null (empty) is a valid key
# label: title to be shown, if unset key will be used
# resorce: a resource that is used by the value children
# simple string use as is
# string + ':' - add value to the resource
# type: if empty or 'frame' only the children are considered
# children: only for type empty or 'frame' - list of child objects
# target: how the selected child value should be stored:
# environment - set the environment to the child value
# define - add -D<childValue> to the flags
# define:name - add -D<name>=<childValue> to the flags
# values - a list of value objects for a particular config
# if the object is just a string it is converted to an object
# with value being set to the string
# parameters:
# key: unique key, defines the name(part) and the value store in cfg
# for the parent
# if not set, value is used
# null (empty) is a valid key
# value: the value (mandatory)
# if null the value will be set to undefined and ignored
# label: text to be shown
# if not set value will be used
# description,url
# resource: for parent-target environment:
# an object with allowed resource counts
# for other values: the resource to be counted
#
#
types:
- &m5base
type: select
Expand Down Expand Up @@ -71,13 +108,13 @@ types:
key: m5groove
label: 'M5 groove type'
values:
- label: 'CAN'
- key: 'CAN'
children:
- *m5groovecan
- label: 'I2C'
- key: 'I2C'
children:
- *m5groovei2c
- label: 'Serial'
- key: 'Serial'
children:
- *m5grooveserial
- &gpiopin
Expand All @@ -95,10 +132,10 @@ types:
key: serial1
children:
- <<: *gpiopin
label: RX
key: RX
target: "define:GWSERIAL_RX"
- <<: *gpiopin
label: TX
key: TX
target: "define:GWSERIAL_TX"

resources:
Expand Down
16 changes: 9 additions & 7 deletions webinstall/cibuild.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@
margin-right: 0.5em;
z-index: unset;
}
.configui .selector {
padding-bottom: 0.5em;
border-bottom: 1px solid grey;
}

.configui .selector .title {
font-weight: bold;
}
Expand All @@ -133,10 +130,15 @@
padding-bottom: 0;
border-bottom: unset;
}
.configui .selector.tdropdown {
padding-bottom: unset;
border-bottom: unset;
.configui .childFrame {
border-top: 1px solid grey;
margin-top: 0.3em;
}
.configui .tframe>.childFrame {
border-top: unset;
margin-top: 0.3em;
}

.configui .selector.tdropdown {
display: flex;
flex-direction: row;
Expand Down
148 changes: 81 additions & 67 deletions webinstall/cibuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,16 +243,44 @@ class PipelineInfo{
let parsed=yamlLoad(config);
return parsed;
}
const getVal=(cfg,keys)=>{
for (let i in keys){
let k=cfg[keys[i]];
if (k !== undefined) return k;
}
}
const KEY_NAMES=['key','value','label'];
const LABEL_NAMES=['label','value'];

const PATH_ATTR='data-path';
const SEPARATOR=':';
const expandObject=(obj,parent)=>{
if (typeof(obj) !== 'object'){
obj={value:obj}
}
let rt=Object.assign({},obj);
if (rt.value === undefined && rt.key !== undefined) rt.value=rt.key;
if (rt.key === undefined) rt.key=rt.value;
if (rt.value === null) rt.value=undefined;
if (rt.label === undefined){
if (rt.value !== undefined) rt.label=rt.value;
else rt.label=rt.key;
}
if (rt.resource === undefined && typeof(parent) === 'object'){
if (parent.resource !== undefined){
if (parent.resource.match(/:$/)){
if(rt.value !== undefined && rt.value !== null){
rt.resource=parent.resource+rt.value;
}
}
else{
rt.resource=parent.resource;
}
}
}
if (rt.target === undefined && typeof(parent) === 'object' && parent.target !== undefined){
rt.target=parent.target;
}
return rt;
}
const expandList=(lst,parent)=>{
let rt=[];
if (! lst) return rt;
lst.forEach((e)=>rt.push(expandObject(e,parent)));
return rt;
}
/**
*
* @param {build a selector} parent
Expand All @@ -262,27 +290,28 @@ class PipelineInfo{
* @param {*} callback will be called with: children,key,value,initial
* @returns
*/
const buildSelector=(parent,config,name,current,callback)=>{
const buildSelector=(parent,cfgBase,name,current,callback)=>{
let config=expandObject(cfgBase);
let rep=new RegExp("[^"+SEPARATOR+"]*","g");
let level=name.replace(rep,'');
let frame=addEl('div','selector level'+level.length+' t'+config.type,parent);
frame.setAttribute(PATH_ATTR,name);
let title=addEl('div','title t'+config.type,frame,config.label);
if (config.type === 'frame'){
callback(config.children,true,true,undefined,true);
let initialConfig=undefined
if (config.type === 'frame' || config.type === undefined){
initialConfig=config;
}
let expandedValues=expandList(config.values,config);
if (config.type === 'select') {
if (!config.values) return;
config.values.forEach((v) => {
for (let idx=0;idx<expandedValues.length;idx++){
let v=expandedValues[idx];
if (v.key === undefined) continue;
let ef = addEl('div', 'radioFrame', frame);
addEl('div', 'label', ef, getVal(v, LABEL_NAMES));
addEl('div', 'label', ef, v.label);
let re = addEl('input', 'radioCi', ef);
let val = v.value;
let key=getVal(v,KEY_NAMES);
if (val === undefined) val=key;
re.setAttribute('type', 'radio');
re.setAttribute('name', name);
re.addEventListener('change', (ev) => callback(v.children,key,val,v.resource,false));
re.addEventListener('change', (ev) => callback(v,false));
if (v.description){
if(v.url) {
let lnk = addEl('a', 'radioDescription', ef, v.description);
Expand All @@ -293,53 +322,35 @@ class PipelineInfo{
let de=addEl('span','radioDescription',ef,v.description);
}
}
if (key == current) {
if (v.key == current) {
re.setAttribute('checked','checked');
callback(v.children,key,val,v.resource,true);
initialConfig=v;
}
});
};
}
if (config.type === 'dropdown'){
if (!config.values) return;
const valForIdx=(idx)=>{
let v=config.values[idx];
if (typeof(v) !== 'object'){
v={label:v,value:v};
}
if (v.value === null) v.value=undefined;
if (v.key === null) v.key=undefined;
return v;
};
const resourceForVal=(v)=>{
if (v === undefined) return undefined;
let key=getVal(v,KEY_NAMES);
if (key === undefined) return key;
let resource=v.resource;
if (! resource && config.resource && config.resource.match(/:$/)){
resource=config.resource+key;
}
return resource;
};
let sel=addEl('select','t'+config.type,frame);
for (let idx=0;idx<config.values.length;idx++){
let v=valForIdx(idx);
for (let idx=0;idx<expandedValues.length;idx++){
let v=expandedValues[idx];
if (v.key === undefined) continue;
let opt=addEl('option','',sel,v.label);
let key=getVal(v,KEY_NAMES);
if (key === null) key=undefined;
opt.setAttribute('value',idx);
if (key == current){
if (v.key == current){
opt.setAttribute('selected',true);
callback(undefined,key,key,resourceForVal(v),true);
initialConfig=v;
}
};
sel.addEventListener('change',(ev)=>{
let resource;
let v=valForIdx(ev.target.value);
let v=expandedValues[ev.target.value];
if (! v) return;
callback(undefined,getVal(v,KEY_NAMES), v.value,resourceForVal(v),false);
callback(v,false);
});
}
return frame;
let childFrame=addEl('div','childFrame',frame);
if (initialConfig !== undefined){
callback(initialConfig,true,childFrame);
}
return childFrame;
}
const removeSelectors=(prefix,removeValues)=>{
forEachEl('.selectorFrame',(el)=>{
Expand All @@ -363,21 +374,25 @@ class PipelineInfo{
});
}
}
const buildSelectors=(prefix,configList,initial)=>{
const buildSelectors=(prefix,configList,initial,parent)=>{
removeSelectors(prefix,!initial);
if (!parent) parent=document.getElementById("selectors");;
if (!configList) return;
let parent=document.getElementById("selectors");
if (!parent) return;
let frame=addEl('div','selectorFrame',parent);
frame.setAttribute(PATH_ATTR,prefix);
configList.forEach((cfg)=>{
let key=getVal(cfg,KEY_NAMES);
let name=prefix?(prefix+SEPARATOR+key):key;
let expandedList=expandList(configList);
expandedList.forEach((cfg)=>{
if (cfg.key === undefined){
console.log("config without key",cfg);
return;
}
let name=prefix?(prefix+SEPARATOR+cfg.key):cfg.key;
let current=config[name];
buildSelector(frame,cfg,name,current,(children,key,value,resource,initial)=>{
buildSelectors(name,children,initial);
configStruct[name]={cfg:cfg, key: key, value:value,resource:resource};
buildValues(initial);
let childFrame=buildSelector(frame,cfg,name,current,
(child,initial,opt_frame)=>{
buildSelectors(name,child.children,initial,opt_frame||childFrame);
configStruct[name]=child;
buildValues(initial);
})
})
}
Expand All @@ -396,10 +411,9 @@ class PipelineInfo{
//round2: really collect values
for (let k in configStruct) {
let struct = configStruct[k];
if (!struct || !struct.cfg || struct.value === undefined) continue;
if (round > 0) config[k] = struct.key;
if (struct.cfg.target !== undefined) {
if (struct.cfg.target === 'environment') {
if (struct.target !== undefined) {
if (struct.target === 'environment') {
if (round > 0) environment = struct.value;
else allowedResources=struct.resource;
continue;
Expand All @@ -413,13 +427,13 @@ class PipelineInfo{
}
resList.push(struct);
}
if (struct.cfg.target === 'define') {
if (struct.target === 'define') {
flags += " -D" + struct.value;
continue;
}
const DEFPRFX = "define:";
if (struct.cfg.target.indexOf(DEFPRFX) == 0) {
let def = struct.cfg.target.substring(DEFPRFX.length);
if (struct.target.indexOf(DEFPRFX) == 0) {
let def = struct.target.substring(DEFPRFX.length);
flags += " -D" + def + "=" + struct.value;
continue;
}
Expand Down

0 comments on commit c057271

Please sign in to comment.