//global config variable const config=new Object(); function print(msg){ config.document.getElementById(config.debugArea).value+="\n"+msg; } function clear(){ config.document.getElementById(config.debugArea).value=""; } function doNothing(){ print('doNothing called'); } function generateDescription(){ //loop over all forms //read the setup print('Generate description'); setFormConfig(); } function setContainer(label,container){ if (!(config.formConfig.hasOwnProperty('container'))){ config.formConfig.container=new Array(); } config.formConfig.container[label]=container; } function getContainer(label){ return config.formConfig.container[label]; } function makeQuery(containerName,queryName,fieldName,filterArray){ let e=new Object(); e.containerName=containerName; e.queryName=queryName; e.fieldName=fieldName; e.filterArray=filterArray; return e; } function getDataFromQueries(queryArray,cb){ //queryArray should contain elements with //- fieldName to set the data variable //- containerName to select container (data,config,CRF) //- queryName to select query //- filterArray to perform filtering, empty array works //- callback cb to be called with no arguments // afterQuery(new Object(),-1,queryArray,cb); } function afterQuery(data,id,queryArray,cb){ //queryArray should contain elements with //- fieldName to set the data variable //- containerName to select container (data,config,CRF) //- queryName to select query //- filterArray to perform filtering, empty array works //- callback cb to be called with no arguments // //it should be called with id -1. // print('afterQuery['+id+'/'+queryArray.length+']: '); if (id>-1){ let fieldName=queryArray[id].fieldName; print('afterQuery['+fieldName+']: '+data.rows.length); config.formConfig[fieldName]=data; } id+=1; if (id==queryArray.length) { cb(); return; } let e=queryArray[id]; let qconfig=new Object(); qconfig.containerPath=getContainer(e.containerName); qconfig.schemaName="lists"; if ("schemaName" in e){ print('afterQuery: schemaName='+e.schemaName); qconfig.schemaName=e.schemaName; } if ("columns" in e){ print('afterQuery: columns='+e.columns); qconfig.columns=e.columns; } qconfig.queryName=e.queryName; //this should point to configuration container //don't filter -> so we can pick up other forms (say registration) later on //qconfig.filterArray=[LABKEY.Filter.create('Key',config.formId)]; if ("filterArray" in e) qconfig.filterArray=e.filterArray; //qconfig.filterArray=[LABKEY.Filter.create('formStatus',1)] qconfig.success=function(data){afterQuery(data,id,queryArray,cb);}; qconfig.failure=doNothing; LABKEY.Query.selectRows(qconfig); } function setFormConfig(){ //add object to store form related data config.formConfig=new Object(); config.formConfig.softwareVersion='0.0.1'; let debug=true; if (debug) print("setFormConfig"); //set containers for data and configuration //TODO: set this from a query // setContainer('data',LABKEY.ActionURL.getContainer()); setContainer('config',LABKEY.ActionURL.getContainer()); setContainer('CRF',LABKEY.ActionURL.getContainer()); let selectRows=new Object(); //this is local data selectRows.containerPath=getContainer('CRF'); selectRows.schemaName='lists'; selectRows.queryName='crfSettings'; //store form related data to this object selectRows.success=afterSettings; LABKEY.Query.selectRows(selectRows); } function afterSettings(data){ config.formConfig.settings=new Array(); for (let i=0;i<data.rows.length;i++){ let n=data.rows[i]['name']; let v=data.rows[i]['value']; config.formConfig.settings[n]=v; } let st=config.formConfig.settings; print('afterSettings'); for (let k in st){ print('\t'+k+'='+st[k]); } //if ('dataContainer' in st){ // setContainer('data',st['dataContainer']); //} let vname='configContainer'; if (vname in st){ setContainer('config',st[vname]); } print('Config: '+getContainer('config')); print('Data: '+getContainer('data')); collectData(); } function collectData(){ let queryArray=new Array(); //users queryArray.push(makeQuery('CRF','users','userData',[])); queryArray[queryArray.length-1].schemaName='core'; //Forms queryArray.push(makeQuery('config','Forms','formData',[])); //FormSetup queryArray.push(makeQuery('config','FormSetup','formSetup',[])); //inputLists queryArray.push(makeQuery('config','inputLists','inputLists',[])); // print('running getDataFromQueries'); getDataFromQueries(queryArray,fcontinue); } function findName(listId){ let frows=config.formConfig.inputLists.rows; for (let i=0;i<frows.length;i++){ if (frows[i]['Key']!=listId) continue; return frows[i]['queryName']; } } function fcontinue(){ print('loadedData'); let queryArray=new Array(); let frows=config.formConfig.formSetup.rows; for (let i=0;i<frows.length;i++){ let listId=frows[i]['queryName']; //skip forms only let showFlag=frows[i]['showFlag']; let showQuery=frows[i]['showQuery']; if (showFlag=='REVIEW') continue; let listName=findName(listId); print(listName); queryArray.push(makeQuery('data',listName,listName,[])); if (showFlag=='NONE') continue; queryArray.push(makeQuery('data',showQuery,showQuery,[])); } getDataFromQueries(queryArray,fcontinue1); } function getList(formId){ let fList=new Array(); let frows=config.formConfig.formSetup.rows; for (let i=0;i<frows.length;i++){ if (frows[i]['formName']!=formId) continue; let listId=frows[i]['queryName']; let showFlag=frows[i]['showFlag']; let showQuery=frows[i]['showQuery']; if (showFlag=='REVIEW') continue; let fObj=new Object(); fObj['queryName']=findName(listId); fObj['title']=frows[i]['title']; fList.push(fObj); if (showFlag=='NONE') continue; let fObj1=new Object(); fObj1['queryName']=showQuery; fObj1['title']=frows[i]['title']+' (details)'; fList.push(fObj1); } return fList; } function printField(field){ let name=field['name']; if (name=='Key') return; if (name=='crfRef') return; let type=field['type']; let qName=''; if ('lookup' in field){ qName=field.lookup.queryName; } print(name+' '+type+'/'+qName); printPDF(field); } function addLookup(lookupList,field){ if ('lookup' in field){ lookupList.add(field.lookup.queryName); } } function printFields(lookupList,listName){ let fields=config.formConfig[listName].metaData.fields; //print('getFields '+listName+': '+fields.length); for (f in fields){ printField(fields[f]); addLookup(lookupList,fields[f]); //printPDF(fields[f]); } } function fcontinue1(){ printLayout(); } function printData(){ let frows=config.formConfig.formData.rows; let lookupList=new Set(); for (let i=0;i<frows.length;i++){ let formId=frows[i]['Key']; print(frows[i]['formName']); printTitlePDF(20,frows[i]['formName']); let fList=getList(formId); for (let j=0;j<fList.length;j++){ print(fList[j]['queryName']); printTitlePDF(16,fList[j]['title']); printFields(lookupList,fList[j]['queryName']); } } print('all done'); let queryArray=new Array(); for (let item of lookupList){ queryArray.push(makeQuery('data',item,item,[])); } let cb=function(){printLookup(lookupList);}; getDataFromQueries(queryArray,cb); } function printQuery(queryName){ printTitlePDF(16,queryName); print(queryName); let frows=config.formConfig[queryName].rows; print('rows: '+frows); let fields=config.formConfig[queryName].metaData.fields; let field=undefined; for (f in fields){ if (fields[f].name=='Key') continue; field=fields[f]; break; } for (let i=0;i<frows.length;i++){ printPDFEntry(field,frows[i]); } } function printLookup(lookupList){ printTitlePDF(20,'Enumerators'); for (let item of lookupList){ printQuery(item); } config.doc.end(); } function checkBlob(){ print("checkBlob: "+config.blob); if (config.blob) { clearInterval(config.blobInterval); config.a.href = config.window.URL.createObjectURL(config.blob); print("HREF: "+config.a.href); config.a.download = 'test.pdf'; config.a.click(); config.window.URL.revokeObjectURL(config.a.href); } config.count=config.count+1; print("Eval: "+config.count); if (config.count>100){ clearInterval(config.blobInterval); } } function printLayout(){ config.doc=new PDFDocument(); //config.doc.end(); let stream = config.doc.pipe(blobStream()).on("finish",function(){ config.blob=stream.toBlob("application/pdf");}); print("BLob: "+config.blob); config.a = config.document.createElement("a"); config.document.body.appendChild(config.a); config.a.innerHTML="Download PDF"; config.a.style = "display: none"; config.count=0; //run until blob is set config.blobInterval=setInterval(checkBlob,1000); //pick data from crfForm list print("Printing form"); printData(); } function printTitlePDF(fontSize,title){ config.doc.y+=10; config.doc.font('Courier-Bold').fontSize(fontSize).text(title); } function printPDF(field){ //object field should have a name, type, caption //entry should have field.name //lookup is null or has a lookup table LUT //for value v of entry[field.name] // //the total width of a A4 page is 598 px, //left margin is 72. With a right margin of 50, //the total available with is 476 px. let w=476; let spacing=25; let w1=(w-spacing)*0.5; let fontSize=14; print('printPDF: entry['+field.name); print('printPDF: field type:'+field.type); //measure text let label=field.caption; let opt={width:w1}; config.doc.fontSize(fontSize); //for more eloquent display the height of the text //can be measured prior to output //use currentLineHeight to scale height //let lineH=config.doc.currentLineHeight(1); //let h=config.doc.heightOfString(label,opt)/lineH; //print label config.doc.font('Courier').text(label,opt); //align last row of description w/ first row of value config.doc.moveUp(); //store x value for later use let tx=config.doc.x; let ty=config.doc.y; //shift for value output config.doc.x+=w1+spacing; let v=field.type; if ('lookup' in field){ v+='/'+field.lookup.queryName; } print('v: '+v); config.doc.font('Courier-Bold').text(v,opt); //restore x value config.doc.x=tx; } function printPDFEntry(field,entry){ //object field should have a name, type, caption //entry should have field.name //lookup is null or has a lookup table LUT //for value v of entry[field.name] // //the total width of a A4 page is 598 px, //left margin is 72. With a right margin of 50, //the total available with is 476 px. let w=476; let spacing=25; let w1=(w-spacing)*0.5; let fontSize=14; print('printPDF: entry['+field.name); print('printPDF: field type:'+field.type); //measure text let label=entry[field.name]; let opt={width:w1}; config.doc.fontSize(fontSize); //for more eloquent display the height of the text //can be measured prior to output //use currentLineHeight to scale height //let lineH=config.doc.currentLineHeight(1); //let h=config.doc.heightOfString(label,opt)/lineH; //print label config.doc.font('Courier').text(label,opt); }