浏览代码

Renaming crf directory

klanecek 1 年之前
父节点
当前提交
1b1b1d2f43

文件差异内容过多而无法显示
+ 0 - 0
web/crf/blob-stream.js


+ 0 - 8
web/crf/blob-stream.js.license

@@ -1,8 +0,0 @@
-MIT LICENSE
-Copyright (c) 2014 Devon Govett
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 453
web/crf/crfData.js

@@ -1,453 +0,0 @@
-//not tested yet.
-//to use, add crfTecant/crfData.js to requiresScript and in the call-back, run init
-//will work with crfSetup as setup object
-
-var crfData={};
-
-crfData.init=
-function(cb=null){
-   this.print('[crfData:init]');
-   let that=this;
-   let action=function(){that.afterScripts(cb);};
-   LABKEY.requiresScript(["crf/runQuery.js","crf/variableList.js"],action);
-}
-
-crfData.afterScripts=
-function(cb=null){
-   if (cb) cb();
-}
-
-crfData.setSetup=
-function(setup){
-   this.setup=setup;
-}
-
-crfData.getContainer=
-function(label){
-   return this.setup.getContainer(label);
-}
-
-crfData.print=
-function(msg){
-   console.log(msg);
-}
-
-//getters
-crfData.getSnapshotObject=
-function(){
-   if (!("dataQueriesSnapshot" in this))
-      this.dataQueriesSnapshot=new Object();
-   return this.dataQueriesSnapshot;
-}
-
-
-crfData.getQuerySnapshot=
-function(queryName){
-   //check whether queryName is in snapshotObject?
-   return this.getSnapshotObject()[queryName];
-}
-
-crfData.getLayoutObject=
-function(){
-   if (!("dataQueriesLayout" in this))
-      this.dataQueriesLayout=new Object();
-   return this.dataQueriesLayout;
-}
-
-crfData.getQueryLayout=
-function(queryName){
-   //check whether queryName is in snapshotObject?
-   return this.getLayoutObject()[queryName];
-}
-
-crfData.getLookupObject=
-function(){
-   if (!("lookup" in this))
-      this.lookup=new Object();
-   return this.lookup;
-}
-
-crfData.getLookup=
-function(queryName){
-   let x=this.getLookupObject();
-   if (queryName in x) return x[queryName];
-   return null;
-}
-
-crfData.getRegistration=
-function(){
-   let fName='[getRegistration]';
-   let regQueryPars=variableList.parseVariables(this.setup.getSettings('registrationQuery'));
-   let query=regQueryPars['query'];
-   //this.print(fName+' query '+query);
-   return this.getQuerySnapshot(query).rows;
-}
-
-crfData.getCrfEntry=
-function(){
-   return this.getQuerySnapshot('crfEntry').rows[0];
-}
-
-crfData.getActiveQueries=
-function(){
-   if (!("activeQueries" in this))
-      this.activeQueries=new Object();
-   return this.activeQueries;
-}
-
-crfData.getActiveQuery=
-function(queryName){
-   let aq=this.getActiveQueries();
-   if (queryName in aq) return aq[queryName];
-   return null;
-}
-
-crfData.getRegistrationMap=
-function(value=null){
-   let rows=this.getRegistration();
-   let qMap=new Object();
-   let key='Key';
-   if (!value) value='participantStudyId';
-   for (let i=0;i<rows.length;i++){
-      qMap[rows[i][key]]=rows[i][value];
-   }
-   return qMap;
-}
-
-crfData.getRegistrationEntryMap=
-function(key=null){
-   let rows=this.getRegistration();
-   let qMap=new Object();
-   if (!key) key='Key';
-   for (let i=0;i<rows.length;i++){
-      qMap[rows[i][key]]=rows[i];
-   }
-   return qMap;
-}
-
-crfData.getCrfRefForData=
-function(){
-   let parentCrf=this.getCrfEntry()['parentCrf'];
-   if (!parentCrf) return this.getCrfEntry()['entryId'];
-   return parentCrf;
-}
-
-
-crfData.setDataLayout=
-function(formId,role,cb){
-   let fName='[setDataLayout]';
-   this.print(fName);
-	let rowsSetup=this.setup.selectFormSetupRows(formId);
-   let queryArray=new Array();
-	let dS=this.getLayoutObject();//reference only
-	let qMap=this.setup.getMap('inputLists');
-   let qMapInverse=this.setup.invertMap(qMap);
-   this.clearActiveQueries();
-	//config.formConfig.lookup=new Object();
-	for (let i=0;i<rowsSetup.length;i++){
-		let entry=rowsSetup[i];
-		//skip review rows
-		if (entry['showFlag']=='REVIEW')
-			continue;
-      let accessMode=role+'Mode';
-		//skipField
-		if (entry[accessMode]=="NONE") continue;
-
-		let queryId=entry['queryName'];
-		let q=qMap[queryId];
-		queryArray.push(runQuery.makeQuery(dS,'data',q,q,[]));
-      this.addActiveQuery(crfSetup.getEntryMap('inputLists')[queryId]);
-      this.print(fName+' adding '+q);
-		if (entry['showQuery']!="NONE"){
-			let sq=entry['showQuery'];
-		   queryArray.push(runQuery.makeQuery(dS,'data',sq,sq,[]));
-         //need inverse of qMap
-         let sQueryId=qMapInverse[sq];
-         this.addActiveQuery(crfSetup.getEntryMap('inputLists')[sQueryId]);
-         this.print(fName+' adding '+sq);
-			
-		}
-   }
-	//always add reviews
-   let q='reviewComments';
-   queryArray.push(runQuery.makeQuery(dS,'data',q,q,[]));
-   let rQueryId=qMapInverse[q];
-   if (!rQueryId){
-      this.print(fName+' missing query '+q+' in inputLists');
-      return
-   }
-   this.addActiveQuery(crfSetup.getEntryMap('inputLists')[rQueryId]);
-	
-   //debug
-   this.print("List of datasets in form : ");
-	for (f in this.getActiveQueries()){
-      let entry=this.getActiveQuery(f);
-      this.print("\t"+f+" ID: "+entry['Key']+' title '+entry['title']);
-   }
-
-   let that=this;
-   let action=function(){that.processLayout(cb);};
-   runQuery.getDataFromQueries(this,queryArray,action);
-}
-
-//this happens after the for loop, so all dataQueries objects are set
-crfData.processLayout=
-function(cb=null){
-   let fName='[processLayout]';
-   let qList=this.getActiveQueries();
-   //for layouts
-   let queryArray=new Array();
-   let targetObject=this.getLookupObject();
-   let lookupSet=new Object();
-   for (let qId in qList){
-      let entry=this.getActiveQuery(qId);
-      let q=entry['queryName'];
-      let qobject=this.getQueryLayout(q);
-	   this.print(fName+" inspecting layout for "+q+" "+qobject);
-	   qobject.fields=qobject.metaData.fields;
-	   qobject.title=entry['title'];
-
-      //check for lookups
-	   for (let f in qobject.fields){
-		   //anything else is simple but lookup
-		   let field=qobject.fields[f];
-		   if (!("lookup" in field)) continue;
-         let lookup=field.lookup;
-         let qObject=this.getLookup(lookup.queryName);
-         if (qObject) continue;
-         //add to list
-         let qName=lookup.queryName;
-         let qCode=qName+':'+lookup.keyColumn+':'+lookup.displayColumn;
-         let e=runQuery.makeQuery(targetObject,'data',qName,qCode,[]);
-         //adjust minor settings
-         if (lookup.containerPath) e.containerPath=lookup.containerPath;
-         e.schemaName=lookup.schemaName;
-         e.columns=lookup.keyColumn+','+lookup.displayColumn;
-         lookupSet[qCode]=e;
-         this.print(fName+' inserting '+qCode);
-      }
-   }
-   for (let x in lookupSet){
-      queryArray.push(lookupSet[x]);
-      this.print(fName+' adding '+x);
-      for (let v in lookupSet[x]){
-         this.print(fName+' value ['+v+'] '+lookupSet[x][v]);
-      }
-   }
-   //this.print(fName+' print '+targetObject.print);
-   let that=this;
-   let action=function(){that.processLookup(cb);};
-   this.print(fName+' getDataFromQueries');
-   runQuery.getDataFromQueries(this,queryArray,action);
-   this.print(fName+' getDataFromQueries done');
-}
-
-crfData.processLookup=
-function(cb=null){
-   let fName="[processLookup]";
-
-   let obj=this.getLookupObject();
-   for (let q in obj){
-	   this.print(fName+" "+q);
-      let a=q.split(':');
-      if (a.length<3) continue;
-      let lookupName=a[0];
-      let key=a[1];
-      let val=a[2];
-      obj[lookupName]=new Object();
-      this.print(fName+' adding ['+lookupName+'] '+key+'/'+val);
-      let lObject=obj[lookupName];
-
-	   lObject.LUT=new Array();//key to value
-	   lObject.ValToKey=new Array();//value to key
-	   lObject.keyColumn=key
-	   lObject.displayColumn=val;
-      
-      let qRows=obj[q].rows;
-	   for (let i=0;i<qRows.length;i++){
-         let r=qRows[i];
-         this.print(fName+' LUT ['+r[key]+'] '+r[val]);
-		   lObject.LUT[r[key]]=r[val];
-		   lObject.ValToKey[r[val]]=r[key];
-	   }
-   }
-	if (cb) cb();
-}
-
-crfData.setData=
-function(crfRef,cb=null, schemaName=null){
-	fName='[setData]';
-	//let crfMatch=this.getCRFref();
-	//let parentCrf=config.formConfig.crfEntry['parentCrf'];
-	//if (parentCrf!=undefined) crfMatch=parentCrf;
-
-	this.print(fName+' form crf ['+crfRef+'] ');
-
-   let queryArray=new Array();
-   let targetObject=this.getSnapshotObject();
-	//collect data and execute callback cb for queries in cb.queryList
-   let qList=this.getActiveQueries();
-	for (let qId in qList){
-      let entry=qList[qId];
-      let q=entry['queryName'];
-		let filters=[LABKEY.Filter.create("crfRef",crfRef)];
-      let fieldName=q;
-      if (schemaName=='study') fieldName=q+'Study';
-      queryArray.push(runQuery.makeQuery(targetObject,'data',q,fieldName,filters,schemaName));
-
-	}
-   runQuery.getDataFromQueries(this,queryArray,cb);
-}
-
-crfData.setDataForQuery=
-function(queryName,crfRef=null,cb=null,schemaName='lists',crfField='crfRef'){
-   let queryArray=new Array();
-   let targetObject=this.getSnapshotObject();
-	
-   let filters=[LABKEY.Filter.create(crfField,crfRef)];
-   let fieldName=q;
-   if (schemaName=='study') fieldName=q+'Study';
-   queryArray.push(runQuery.makeQuery(targetObject,'data',q,fieldName,filters,schemaName));
-   runQuery.getDataFromQueries(this,queryArray,cb);
-}
-
-crfData.uploadData=
-function(id,crfRef,cb=null){
-   let fName='[uploadData['+id+']'+crfRef+']';
-   this.print(fName);
-   let qList=this.getActiveQueries();
-   let modArray=new Array();
-   let schemaName='study';
-   let containerName='data';
-   for (let qId in qList){
-
-      let entry=qList[qId];
-      let q=entry['queryName'];
-
-      this.print(fName+' working on '+q);
-      
-      //determine rows that need to be updated form querySnapshot
-      let studyRows=this.getQuerySnapshot(q+'Study').rows;
-      let listRows=this.getQuerySnapshot(q).rows;
-      this.print(fName+' studies '+studyRows.length+' lists '+listRows.length);
-      //rows to be UPDATED (already in dataset)
-      let modRows=new Array();
-      for (let i=0;i<studyRows.length;i++){
-         let entry=studyRows[i];
-         //
-         if (! (i<listRows.length) ) continue;
-         let entryList=listRows[i];
-		   //keeps study only variables (ParticipantId, SequenceNum)
-		   for (let f in entryList) {
-			   entry[f]=entryList[f];
-			   this.print(fName+" copying ["+f+"]: "+entry[f]+"/"+entryList[f]);
-		   }
-         modRows.push(entry);
-      }
-
-      //rows to be INSERTED 
-      let insRows=new Array();
-      let participantField=crfSetup.getRows('studyData')[0]["SubjectColumnName"];
-      for (let i=studyRows.length;i<listRows.length;i++){
-         let entry=listRows[i];
-         //make sure you have the participantField right
-         //
-         entry[participantField]=id;
-         entry.crfRef=crfRef;;
-         entry.SequenceNum=crfRef;
-         entry.SequenceNum=entry.SequenceNum % 1000000000;
-		
-         if (listRows.length>1){
-            entry.SequenceNum+=i/100;
-         }
-         this.print( "Adding sequence number "+entry.SequenceNum);
-         insRows.push(entry);
-      }
-
-      if (modRows.length>0)
-         modArray.push(runQuery.makeModification('update',containerName,schemaName,q,modRows));
-      //determine rows that need to be inserted from querySnapshot
-      if (insRows.length>0)
-         modArray.push(runQuery.makeModification('insert',containerName,schemaName,q,insRows));
-
-   }
-   //do the whole batch
-   runQuery.modifyDataFromQueries(this,modArray,cb);
-}
-
-crfData.removeData=
-function(cb=null){
-   let qList=this.getActiveQueries();
-   let modArray=new Array();
-   for (let qId in qList){
-      let entry=qList[qId];
-      let q=entry['queryName'];
-      
-      //determine rows that need to be updated form querySnapshot
-      let studyRows=this.getQuerySnapshot(q+'Study').rows;
-      if (studyRows.length>0)
-         modArray.push(runQuery.makeModification('delete','data','study',q,studyRows));
-
-      let listRows=this.getQuerySnapshot(q).rows;
-      if (listRows.length>0)
-         modArray.push(runQuery.makeModification('delete','data','lists',q,listRows));
-   }
-   //do the whole batch
-   runQuery.modifyDataFromQueries(this,modArray,cb);
-}
-
-
-
-crfData.setRegistration=
-function(cb=null){
-   let regQuerySettings=this.setup.getSettings('registrationQuery');
-   let regQueryPars=variableList.parseVariables(regQuerySettings);
-   let q=regQueryPars['query'];
-   if (!q){
-      this.print('Registration query not set, got ['+regQuerySettings+'] for settings, should have query=X format');
-      return;
-   }
-   let queryArray=new Array();   
-   let targetObject=this.getSnapshotObject();
-   let filters=[];
-   queryArray.push(runQuery.makeQuery(targetObject,'data',q,q,filters));
-   runQuery.getDataFromQueries(this,queryArray,cb);
-}
-
-crfData.setCrfEntry=
-function(crfRef,cb=null){
-   let q='crfEntry';
-   let queryArray=new Array();   
-   let targetObject=this.getSnapshotObject();
-	let filters=[LABKEY.Filter.create('entryId',crfRef)];
-   queryArray.push(runQuery.makeQuery(targetObject,'data',q,q,filters));
-   runQuery.getDataFromQueries(this,queryArray,cb);
-}
-
-crfData.createCrfStatus=
-function(crfEntry){
-   let crfStatus=new Object();
-   crfStatus.entryId=crfEntry.entryId;
-   crfStatus.submissionDate=new Date();
-   crfStatus.FormStatus=crfEntry.FormStatus;
-   crfStatus.User=crfEntry.UserId;
-   crfStatus.Form=crfEntry.Form;
-   return crfStatus;
-}
-
-crfData.addActiveQuery=
-function(entry){
-   let aq=this.getActiveQueries();
-   let qName=entry['queryName'];
-   if (qName in aq) return;
-   aq[qName]=entry;
-   return;
-}
-
-crfData.clearActiveQueries=
-function(){
-   let aq=this.getActiveQueries();
-   for (q in aq){
-      delete aq[q];
-   }
-}

+ 0 - 56
web/crf/crfHTML.css

@@ -1,56 +0,0 @@
-table {margin-bottom:20px;table-layout:fixed; border-collapse:collapse; border-spacing:10px}
-table.t1 {width:400px; border:1px solid black}
-table.t1 th {border:1px solid black;padding:4px;background-color:#e0e0e0}
-table.t1 td {text-align:center}
-table.t2 {width:800px; border:1px solid black;}
-table.t2 th {border:1px solid black;padding:4px;background-color:#e0e0e0}
-table.t2 td {border:1px solid black; text-align:center}
-
-table.tOverview {border: 1px solid black}
-table.tOverview th {background-color: #cccc99;padding: 4px}
-table.tOverview td {width: 20px; padding: 4px; text-align:center;border: 1px solid grey}
-
-div.d1 {text-align:center; width:400px; background-color:#e0e0e0;
-        font-size:20px; margin-bottom:20px}
-
-.box{
-width:120px;
-height:120px;
-}
-
-.gold{ background-color: gold; }
-.red{ background-color: darkred; }
-.green {background-color: green;}
-.orange {background-color: orange;}
-.blue {background-color: steelblue;}
-.brown {background-color: tan;}
-.yellow {background-color: #ffffcc;}
-.salmon {background-color: #ffcccc;}
-.teal {background-color: #cccc99;}
-.mauve {background-color: #ccccff;}
-.fuchsia {background-color: #ffccff;}
-.brick {background-color: #cc6666;}
-.empty { background-color: #cccccc;
-      border-style: dashed;
-}
-.white { background-color: white;}
-
-.large{
-	font-size: 30px;
-}
-
-.medium{
-   font-size: 24px;
-}
-
-.small{font-size: 12px;}
-
-.center{
-	text-align: center;
-}
-
-.stretch {
-   padding: 50px;
-}
-
-.topLess { border-top: none;}

+ 0 - 207
web/crf/crfHTML.js

@@ -1,207 +0,0 @@
-var crfHTML={};
-
-crfHTML.print=
-function(msg){
-   console.log(msg);
-}
-
-crfHTML.init=
-function(cb=null){
-   LABKEY.requiresCss("crf/crfHTML.css");
-   this.print('CSS loaded');
-   if (cb) cb();
-}
-
-crfHTML.getElement=
-function(id){
-   return document.getElementById(id);
-}
-
-crfHTML.append=
-function(element,id=null,el=null){
-   if (id) document.getElementById(id).appendChild(element);
-   if (el) el.appendChild(element);
-}
-
-crfHTML.addStyle=
-function(el,style){
-   el.classList.add(style);
-}
-
-
-crfHTML.clearStyle=
-function(el,style){
-   el.classList.remove(style);
-}
-
-crfHTML.createSelect=
-function(qMap,id=null,el=null){
-   let fName='[makeSelect]';
-   let input=document.createElement('select');
-   this.addSelectOptions(input,qMap);
-   this.append(input,id,el);
-   return input;
-}
-
-crfHTML.createTable=
-function(id=null,el=null,style=null){
-   let table=document.createElement('table');
-   this.append(table,id,el);
-   if (style) this.addStyle(style);
-   return table;
-}
-
-crfHTML.createBox=
-function(id=null,el=null){
-   let fbox=document.createElement('div');
-   fbox.classList.add("box");
-   this.append(fbox,id,el);
-   return fbox;
-}
-
-crfHTML.createParagraph=
-function(text,id=null,el=null){
-   let fp=document.createElement("p");
-   fp.innerHTML=text;
-   fp.classList.add("center");
-   this.append(fp,id,el);
-   return fp;
-}
-
-crfHTML.createTblHeader=
-function(id=null,el=null){
-   let element=document.createElement('th');
-   this.append(element,id,el);
-   return element;
-}
-
-crfHTML.createButton=
-function(id=null,el=null){
-   let button=document.createElement('input');
-   button.type='button';
-   this.append(button,id,el);
-   return button;
-}
-
-crfHTML.createTextNode=
-function(text,id=null,el=null){
-	let tNode=document.createTextNode(text);
-   this.append(tNode,id,el);
-   return tNode;
-}
-
-crfHTML.setTextNode=
-function(el,text){
-   el.nodeValue=text;
-}
-
-crfHTML.createDiv=
-function(divId=null,id=null,el=null){
-   let div=document.createElement('div');
-   if (divId) div.id=divId;
-   this.append(div,id,el);
-   return div;
-}
-
-crfHTML.createTextArea=
-function(id=null,el=null){
-   let area=document.createElement('textarea');
-   this.append(area,id,el);
-   return area;
-}
-
-crfHTML.createLabel=
-function(label,id=null,el=null){
-   let x=document.createElement('label');
-   x.innerText=label;
-   this.append(x,id,el);
-   return x;
-}
-
-crfHTML.createDate=
-function(id=null,el=null){
-   let x=document.createElement('input');
-   x.type='date';
-   this.append(x,id,el);
-   return x;
-}
-
-crfHTML.createTextInput=
-function(id=null,el=null){
-   let x=document.createElement('input');
-   x.type='text';
-   this.append(x,id,el);
-   return x;
-}
-
-crfHTML.createFileInput=
-function(id=null,el=null){
-   let x=document.createElement('input');
-   x.type='file';
-   this.append(x,id,el);
-   return x;
-}
-
-crfHTML.createCheckbox=
-function(id=null,el=null){
-   let x=document.createElement('input');
-   x.type='checkbox';
-   this.append(x,id,el);
-   return x;
-}
-
-crfHTML.clear=
-function(el){
-   while (el.hasChildNodes()){
-      el.removeChild(el.lastChild);
-   }
-}
-
-crfHTML.clearOptions=
-function(input){
-   while(input.options.length) input.remove(0);
-}
-
-crfHTML.addSelectOptions=
-function(input,qMap){
-   let fName='[addSelectOptions]';
-   this.clearOptions(input);
-   let opt = document.createElement("option");
-	opt.text = "<Select>";
-	opt.value = -1;
-	input.options[0] = opt;
-	this.print(fName+": Adding <Select>");
-	
-
-	//add other, label them with LUT
-	for (let v in qMap) {
-		this.print(fName+': populating '+v+': '+qMap[v]);
-
-		let opt = document.createElement("option");
-		opt.text = qMap[v];
-		opt.value = v;
-		input.options[input.options.length] = opt;
-		
-	}
-	input.selectedIndex=0;	
-}
-
-crfHTML.updateSelect=
-function(input,cell,x,value){
-   let fName='[updateSelect]';
-   this.print(fName+' value '+value);
-   let children=cell.children;
-   for (let i=0;i<children.length;i++){
-      let el=children[i];
-      let lab=el.value;
-      this.print(fName+' style ['+el.className+']');
-      this.clearStyle(el,'teal');
-      if (lab==value){
-         lab+='[*]';
-         this.addStyle(el,'teal');
-      }
-      this.print(fName+' '+lab);
-
-   }
-   input.value=x;
-}

+ 0 - 459
web/crf/crfManager.js

@@ -1,459 +0,0 @@
-//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);
-	
-	
-}
-

+ 0 - 217
web/crf/crfParticipant.js

@@ -1,217 +0,0 @@
-function print(config,msg){
-	let el=config.document.getElementById(config.debugId);
-	if (el===null) {
-		//alert("Debug section not initialized. Message: "+msg);
-		return;
-	}
-	el.value+="\n"+msg;
-}
-
-function clear(config){
-	let el=config.document.getElementById(config.debugId);
-	if (el===null) {
-		//alert("Debug section not initialized");
-		return;
-	}
-	config.document.getElementById(config.debugId).value="";
-}
-
-function createRowSelector(schemaName,queryName){
-	let selectRows=new Object();
-	selectRows.schemaName=schemaName;
-	selectRows.queryName=queryName;
-	return selectRows;
-}
-
-
-function buildTable(config){
-	//print(config,'buildTable');
-	addRow(config,'ParticipantId',[config.id]);
-	let selectRows=createRowSelector('lists',config.setup);
-	selectRows.success=function (data){afterSetup(config,data);}
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function afterSetup(config,data){
-	//print(config,'afterSetup ['+data.rows.length+']');
-	config.setupRows=data.rows;
-	let selectRows=createRowSelector('study','DataSets');
-	selectRows.success=function (data){afterDatasets(config,data);}
-	LABKEY.Query.selectRows(selectRows);
-}
-
-//build a local copy of enum's
-function afterDatasets(config,data){
-	//print(config,'afterDatasets ['+data.rows.length+']');
-	config.datasets=data.rows;
-	//debug mode -> jump ahead
-	//afterEnumValues(config);
-	let selectRows=createRowSelector('ListManager','ListManager');
-	selectRows.filterArray=[LABKEY.Filter.create('Name','enum',
-		LABKEY.Filter.Types.STARTS_WITH)];
-	selectRows.success=function (data){afterEnums(config,data);}
-	LABKEY.Query.selectRows(selectRows);
-	//print(config,'enums');
-}
-
-//parse list of lists; get values
-function afterEnums(config,data){
-	//print(config,'afterEnums: '+data.rows.length);
-	config.enums=data.rows;
-	config.enumValues=new Object();
-	for (row of config.enums){
-		//print(config,'afterEnums: '+row.Name);
-		config.enumValues[row.Name]=new Object();
-	}
-	for (lst in config.enumValues){
-		let selectRows=createRowSelector('lists',lst);
-		selectRows.success=function (data){addEnumValues(config,data);}
-		LABKEY.Query.selectRows(selectRows);
-	}
-}
-
-function addEnumValues(config, data){
-	//find out the variable name
-	//
-	let varName="NONE";
-	for (field of data.metaData.fields){
-		if (field.name=="Key")
-			continue;
-		varName=field.name;
-	}
-
-	//print(config,'addEnumValues ['+data.queryName+']: '+varName);
-
-	config.enumValues[data.queryName].map=new Object();
-	for (row of data.rows)
-		config.enumValues[data.queryName].map[row["Key"]]=row[varName];
-	waitForEnumCompleted(config);
-
-}
-
-function waitForEnumCompleted(config){
-	for (lst in config.enumValues){
-		if (!("map" in config.enumValues[lst]))
-			return;
-		//print(config,'['+lst+']: '+
-		//	Object.keys(config.enumValues[lst].map).length);
-	}
-	//print(config,"Enum completed");
-	afterEnumValues(config);
-	
-
-}
-
-function datasetName(config,id){
-	for (let i=0;i<config.datasets.length;i++){
-		if (config.datasets[i].DataSetId==id)
-			return config.datasets[i].Name;
-	}
-	return "NONE";
-}
-
-function afterEnumValues(config){
-	
-	config.entries=new Object();
-	for (let i=0;i<config.setupRows.length;i++){
-		//print(config,'['+i+']: '+config.setupRows[i].dataset);
-		let queryName=datasetName(config,config.setupRows[i].dataset);
-
-		//print(config,"Adding dataset: "+queryName);
-		config.entries[queryName]=new Object();
-		config.setupRows[i].datasetName=queryName;
-	}
-	
-	for (let ds in config.entries){
-		//print(config,"Querying dataset: "+ds);
-		let selectRows=createRowSelector('study',ds);
-		selectRows.filterArray=[LABKEY.Filter.create('ParticipantId',config.id)];
-		selectRows.success=function (data){afterQuery(config,data);}
-		LABKEY.Query.selectRows(selectRows);
-	}
-	//print(config,'afterDatasets: Done');
-}
-
-function afterQuery(config,data){
-	//print(config,'afterQuery ['+data.queryName+']: '+data.rows.length);
-	config.entries[data.queryName].rows=data.rows;
-	config.entries[data.queryName].metaData=data.metaData;
-	waitForAll(config);
-}
-
-function waitForAll(config){
-	//print(config,'waitForAll');
-	for (let ds in config.entries){
-		if (!("rows" in config.entries[ds])) 
-			return;
-		//print(config,ds+': '+config.entries[ds].rows.length);
-	}
-	//only get here if all rows are set
-	//print(config,'waitForAll: Done');
-	updateValues(config);
-}
-
-function getField(fields,name){
-	for (field of fields){
-		if (field.name==name) 
-			return field;
-	}
-	return undefined;
-}
-
-
-function updateValues(config){
-	//print(config,'updateValues');
-	for (let row of config.setupRows){
-		let ds=row.datasetName;
-		let vars=row.variables.split(';');
-		//print(config,'Dataset: '+row.datasetName+' Vars: '+vars);
-		if (config.entries[ds].rows.length==0){
-			addRow(config,ds,["no events"],config.missingStyle);
-			continue;
-		}
-		addRow(config,ds,vars,config.headerStyle);
-		let md=config.entries[ds].metaData;
-		for (let dataRow of config.entries[ds].rows){
-			let displayRow=new Array();
-			for (let v of vars){
-				//print(config,ds+'['+v+']: '+ dataRow[v]);
-				//check if it is a lookup
-				let field=getField(md.fields,v);
-				let value=dataRow[v];
-				if ("lookup" in field){
-					//print(config,"Lookup: "+field.lookup.table);
-					let lut=config.enumValues[field.lookup.table];
-					value=lut.map[value];
-				}
-				displayRow.push(value);
-			}
-			addRow(config,'',displayRow);
-		}
-	}
-	E
-}	
-
-function setStyle(object,style){
-	if (style!=undefined)
-		for (attr in style)
-			object.style[attr]=style[attr];
-}
-
-function addRow(config,header,values,style){
-	//let headerColor="#d0e8f8";
-	let row=config.table.insertRow();
-	let cell=config.document.createElement('th');
-	setStyle(cell,style);
-	row.appendChild(cell);
-	let cellData=config.document.createTextNode(header);
-	//print(config,'Adding header '+header);
-	cell.appendChild(cellData);
-	//new cell
-	for (v of values){
-		cell=row.insertCell();
-		setStyle(cell,style);
-		cellData=config.document.createTextNode(v);
-		cell.appendChild(cellData);
-	}
-}

+ 0 - 182
web/crf/crfPrint.js

@@ -1,182 +0,0 @@
-var crfPrint={};
-
-//printing section
-//
-crfPrint.set=
-function(parentClass){
-   this.parent=parentClass;
-}
-
-crfPrint.checkBlob=
-function(){
-	this.parent.print("checkBlob: "+this.blob);
-	if (this.blob) {
-		clearInterval(this.blobInterval);
-		this.a.href = this.parent.config.window.URL.createObjectURL(this.blob);
-		this.parent.print("HREF: "+this.a.href);
-		this.a.download = 'test.pdf';
-		this.a.click();
-		this.parent.config.window.URL.revokeObjectURL(this.a.href);
-	}
-	this.count=this.count+1;
-	this.parent.print("Eval: "+this.count);
-	if (this.count>100){
-		clearInterval(this.blobInterval);
-	}
-
-}
-
-crfPrint.printForm=
-function(){
-   let that=this;
-   let action=function(){that.afterScripts();};
-   LABKEY.Utils.requiresScript(["crf/blob-stream.js","crf/pdfkit.standalone.js"],action);
-}
-
-crfPrint.afterScripts=
-function(){
-   let config=this.parent.config;
-	this.doc=new PDFDocument();
-   let that=this;
-	//config.doc.end();
-   let action=function(){that.blob=that.stream.toBlob("application/pdf");};
-	this.stream = this.doc.pipe(blobStream()).on("finish",action);
-	
-	this.parent.print("BLob: "+this.blob);
-	this.a = this.parent.config.document.createElement("a");
-	this.parent.config.document.body.appendChild(this.a);
-	this.a.innerHTML="Download PDF";
-	this.a.style = "display: none";
-	this.count=0;
-	//run until blob is set
-   let iAction=function(){that.checkBlob();}
-   this.blobInterval=setInterval(iAction,1000);
-
-	//pick data from crfForm list
-   this.parent.print("Printing form");
-	this.printHeader();
-
-   let foo=function(){that.formatPrintData();};
-	this.parent.setData(foo);
-}
-
-crfPrint.printHeader=
-function(){
-   let config=this.parent.config;
-	this.doc.fontSize(25).text(config.formConfig.form['formName']);
-	this.doc.moveDown();
-	let crfEntry=config.formConfig.crfEntry;
-	let site=config.formConfig.currentSite;
-	let val=new Object();
-	let user=config.formConfig.user;
-	val['A']={o:crfEntry,f:'EudraCTNumber',t:'Eudra CT Number'};
-	val['B']={o:crfEntry,f:'StudyCoordinator',t:'Study Coordinator'};
-	val['C']={o:crfEntry,f:'StudySponsor',t:'Study Sponsor'};
-	val['D']={o:site,f:'siteName',t:'Site'};
-	val['E']={o:site,f:'sitePhone',t:'Phone'};
-	val['F']={o:user,f:'DisplayName',t:'Investigator'};
-
-	for (let f in val){
-		this.parent.print('Printing for '+f);
-		let e=val[f];
-		let entry=new Object();
-		entry[f]=e.o[e.f];
-		this.printPDF(entry,
-			{name:f,caption:e.t,type:'string'},null);
-	}
-	this.doc.moveDown();
-}
-
-crfPrint.formatPrintData=
-function(){
-   let config=this.parent.config;
-	qS=this.parent.getQueryList();
-	for (let q in qS){
-		this.parent.print('Setting up '+q);
-		let qData=this.parent.getQuerySnapshot(q);
-      let qLayout=this.parent.getQueryLayout(q);
-		this.parent.print('Number of rows: '+qData.rows.length);
-		if (qData.rows.length>0){
-			this.doc.fontSize(20).text(qLayout.title);
-		}
-      let fields=qLayout.fields;
-		for (let i=0;i<qData.rows.length;i++){
-			let entry=qData.rows[i];
-		   for (let f in fields){
-				let field=fields[f];
-				let lookup=null;
-				if (field.lookup){
-					lookup=this.parent.getLookup(field.lookup.queryName);
-				}
-				if (field.hidden) continue;
-				this.printPDF(entry,field,lookup);
-			}
-		}
-		this.doc.moveDown();
-	}
-	this.parent.print("All done");
-   this.doc.end();
-}
-
-crfPrint.printPDF=
-function(entry,field,lookup){
-	//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;	
-	
-	this.parent.print('printPDF: entry['+field.name+']='+entry[field.name]);
-	let v=entry[field.name];
-	if (lookup!=null){
-		v=lookup.LUT[v];
-	}
-	this.parent.print('printPDF: field type:'+field.type);
-	if (field.type=="date"){
-		let d=new Date(v);
-		v=d.getDate()+'/'+(d.getMonth()+1)+'/'+d.getFullYear();
-	}	
-	if (v===null) v=' / ';
-	if (v===undefined) v=' / ';
-
-	//measure text
-	let label=field.caption;
-	let opt={width:w1};
-	this.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
-	this.doc.font('Courier').text(label,opt);
-	
-	//align last row of description w/ first row of value
-	this.doc.moveUp();
-
-	//store x value for later use
-	let tx=this.doc.x;
-	let ty=this.doc.y;
-
-	//shift for value output
-	this.doc.x+=w1+spacing;
-	
-	this.doc.font('Courier-Bold').text(v,opt);
-
-	//restore x value
-	this.doc.x=tx;
-	
-}
-
-

+ 0 - 562
web/crf/crfReview.js

@@ -1,562 +0,0 @@
-
-function renderMessages(id, messages) {
-	if (messages && messages.length > 0) {
-		let errorDiv = document.createElement('div');
-		let style='padding: 10px; background-color: #ffe5e5;' 
-		style+='color: #d83f48; font-weight: bold;';
-		errorDiv.setAttribute('style', style);
-		errorDiv.innerHTML = messages.join('<br/>');
-		document.getElementById(id).appendChild(errorDiv);
-	}
-};
-
-function validateChartConfig(chartConfig, aes, scales, measureStore) {
-	let hasNoDataMsg = LABKEY.vis.GenericChartHelper.validateResponseHasData(measureStore, false);
-	if (hasNoDataMsg != null)
-		return {"success": false, "messages": [hasNoDataMsg]};
-
-	let measureNames = Object.keys(chartConfig.measures);
-	for (let i = 0; i < measureNames.length; i++) {
-		let measureProps = chartConfig.measures[measureNames[i]];
-		if (measureProps && 
-			measureProps.name && 
-			measureStore.records()[0][measureProps.name] == undefined){
-					                    
-			let retVal=new Object();
-			retVal.success=false;
-			retVal.messages=['The measure, ' + 
-				measureProps.label + 
-				', is not available. It may have been renamed or removed.']
-			return retVal;
-		}
-	}
-
-	 let messages = [];
-	 let axisMeasureNames = ['x', 'xSub', 'y'];
-	 for (let i = 0; i < axisMeasureNames.length; i++) {
-		 if (measureNames.indexOf(axisMeasureNames[i]) > 0) {
-			let validation = LABKEY.vis.GenericChartHelper.validateAxisMeasure(
-				chartConfig.renderType, chartConfig, axisMeasureNames[i],
-				aes, scales, measureStore.records());
-			if (validation.message != null)
-				messages.push(validation.message);
-			if (!validation.success)
-				return {"success": false, "messages": messages};
-		 }
-	}
-
-	return {"success": true, "messages": messages};
-
-}
-
-function selectRowsCallback(renderConfig, measureStore) {
-	let responseMetaData = measureStore.getResponseMetadata();
-	for (let f in measureStore)
-		document.getElementById('debugCode').value+='\n '+f+' '+typeof(f);
-	let record=measureStore.records()[1];
-	for (let f in record)
-		document.getElementById('debugCode').value+='\n '+f+ ' ' +typeof(f);
-
-	//try something stupid
-	let participantField=document.getElementById('participantField').innerHTML;
-	let participantCode=document.getElementById('participantCode').innerHTML;
-	let visitField=document.getElementById('visitField').innerHTML;
-	let visitCode=document.getElementById('visitCode').innerHTML;
-	let selectedParticipantData=new Array();
-	let otherParticipantData=new Array();
-	let i=0;
-	let maxValue=-1e30;
-	while (i<measureStore.records().length){
-		let record=measureStore.records()[i];
-		//document.getElementById('debugCode').value+='\n '+record[participantField].value;
-		let pMatch=record[participantField].value==participantCode;
-		let vMatch=true;
-		if (visitField in record)
-			vMatch=record[visitField].value==visitCode;
-		let sMatch=true;
-		if ('SequenceNum' in record)
-			sMatch=record['SequenceNum'].value<renderConfig.visitThreshold;
-
-		if (pMatch && vMatch) {
-			if (sMatch)
-				selectedParticipantData.push(record);
-			measureStore.records().splice(i,1);	
-			if (!sMatch)
-				continue;
-			if (record['value'].value>maxValue)
-				maxValue=record['value'].value;
-			continue;
-		}
-		record[participantField].value=renderConfig.labelOthers;
-		if (!pMatch || sMatch) otherParticipantData.push(record);
-		measureStore.records().splice(i,1);	
-
-	}
-	document.getElementById('debugCode').value+='\nrecords: '+otherParticipantData.length;
-	document.getElementById('debugCode').value+='\nownData: '+selectedParticipantData.length;
-	document.getElementById('debugCode').value+='\nmaxValue: '+maxValue;
-	for (let i=0;i<otherParticipantData.length;i++)
-		measureStore.records().push(otherParticipantData[i]);
-	for (let i=0;i<selectedParticipantData.length;i++)
-		measureStore.records().push(selectedParticipantData[i]);
-	
-
-        // chartConfig is the saved information about the chart (labels, scales, etc.)
-
-	let chartConfig = new Object();
-	chartConfig.renderType="line_plot";
-
-
-	let mX=new Object();
-	mX.displayFieldJsonType="";
-        mX.hidden=false;
-        mX.fieldKey="percentile";
-        mX.label="Percentile";
-        mX.schemaName="study";
-        mX.type="float";
-        mX.normalizedType="float";
-        mX.measure=true;
-        mX.name="percentile";
-        mX.queryName="SUVQuantiles";
-        mX.alias="percentile";
-        mX.shortCaption="Percentile";
-        mX.dimension=false;
-
-	document.getElementById('debugCode').value+='\nplot: '+renderConfig.plot;
-	if (renderConfig.plot=="time"){
-		mX.fieldKey="SequenceNum";
-		mX.label="Visit ID";
-		mX.name="SequenceNum";
-		mX.alias="Visit";
-		mX.shortCaption="Visit ID";
-	}
-
-	let mY=new Object();
-        mY.displayFieldJsonType="";
-        mY.hidden=false;
-        mY.fieldKey="value";
-        mY.label="SUV Value";
-        mY.schemaName="study";
-        mY.type="float";
-        mY.normalizedType="float";
-        mY.measure=true;
-        mY.name="value";
-        mY.queryName="SUVQuantiles";
-        mY.alias="value";
-        mY.shortCaption="Value";
-        mY.dimension=false;
-
-
-	let mS=new Object();
-        mS.displayFieldJsonType="";
-        mS.hidden=false;
-        mS.fieldKey=participantField;
-        mS.label="Participant ID";
-        mS.schemaName="study";
-        mS.type="string";
-        mS.normalizedType="string";
-        mS.measure=false;
-        mS.name=participantField;
-        mS.queryName="SUVQuantiles";
-        mS.alias=participantField;
-        mS.shortCaption="Participant ID";
-        mS.dimension=true;
-
-	chartConfig.measures=new Object();
-        chartConfig.measures.x=mX;
-        chartConfig.measures.y=mY;
-        chartConfig.measures.series=mS;
-        chartConfig.measures.pointClickFn=null;
-        chartConfig.scales=new Object();
-        chartConfig.scales.x=new Object();
-        chartConfig.scales.x.trans="linear";
-        chartConfig.scales.y=new Object();
-        chartConfig.scales.y.trans="linear";
-	chartConfig.scales.y.min=0;
-	chartConfig.scales.y.max=renderConfig.max;
-	if (renderConfig.max<0)
-		chartConfig.scales.y.max=1.5*maxValue;
-        chartConfig.labels=new Object();
-        chartConfig.labels.main=renderConfig.title;
-        chartConfig.labels.subtitle="";
-        chartConfig.labels.x="Percentile";
-        chartConfig.labels.y="SUV Value";
- 	chartConfig.width=null;
-        chartConfig.height=null;
-        chartConfig.pointType="outliers";
-        chartConfig.geomOptions=new Object();
-        chartConfig.geomOptions.label="SUVQuantiles";
-        chartConfig.geomOptions.subtitle="";
-        chartConfig.geomOptions.width=null;
-        chartConfig.geomOptions.height=null;
-        chartConfig.geomOptions.pointType="outliers";
-        chartConfig.geomOptions.pointFillColor="111111";
-        chartConfig.geomOptions.lineWidth=2;
-        chartConfig.pointFillColor="111111";
-        chartConfig.lineWidth="3";
-        chartConfig.lineColor="000000";
-        chartConfig.boxFillColor="3366FF";
-        chartConfig.hideDataPoints=false;
-//        chartConfig.colorPaletteScale="ColorDiscrete";
-        chartConfig.geomOptions.colorPaletteScale="Light";
-        chartConfig.chartLayout="single";
-        chartConfig.chartSubjectSelection="subjects";
-        chartConfig.displayIndividual=true;
-        chartConfig.displayAggregate=false;
-        chartConfig.errorBars="None";
-        chartConfig.pieInnerRadius=0;
-	chartConfig.pieOuterRadius=80;
-        chartConfig.showPiePercentages=true;
-        chartConfig.pieHideWhenLessThanPercentage=5;
-        chartConfig.piePercentagesColor="333333";
-        chartConfig.gradientPercentage=95;
-        chartConfig.gradientColor="FFFFFF";
-        chartConfig.binThreshold=10000;
-        chartConfig.binShapeGroup="hex";
-        chartConfig.binColorGroup="BlueWhite";
-        chartConfig.binSingleColor="000000";
-        chartConfig.showOutliers=true;
-        chartConfig.binShape="hex";
-
-        chartConfig.labels.x="Percentile";
-
-
-	if (renderConfig.plot=="time"){
-        	chartConfig.labels.x="Visit ID";
-        	chartConfig.labels.y="SUV"+renderConfig.suv+"%";
-	}
-
-	if (!chartConfig.hasOwnProperty('width') || 
-
-		chartConfig.width == null) 
-		chartConfig.width = 1000;
-        if (!chartConfig.hasOwnProperty('height') || 
-		chartConfig.height == null) 
-		chartConfig.height = 600;
-	if (renderConfig.hasOwnProperty('width')){
-		chartConfig.width=renderConfig.width;
-		chartConfig.height=0.6*renderConfig.width;
-	}
-
-
-	let xAxisType = chartConfig.measures.x ? (
-		chartConfig.measures.x.normalizedType || 
-		chartConfig.measures.x.type) : null;
-        let chartType = LABKEY.vis.GenericChartHelper.getChartType(
-		chartConfig.renderType, xAxisType);
-        let aes = LABKEY.vis.GenericChartHelper.generateAes(
-                chartType, chartConfig.measures, 
-		responseMetaData.schemaName, responseMetaData.queryName);
-
-        let valueConversionResponse = 
-		LABKEY.vis.GenericChartHelper.doValueConversion(
-			chartConfig, aes, chartType, measureStore.records());
-     	if (!Ext4.Object.isEmpty(valueConversionResponse.processed)) {
-               Ext4.Object.merge(chartConfig.measures, 
-		       valueConversionResponse.processed);
-               aes = LABKEY.vis.GenericChartHelper.generateAes(
-                       chartType, chartConfig.measures, 
-		       responseMetaData.schemaName, responseMetaData.queryName);
-        }
-        let data = measureStore.records();
-	
-        if (chartType == 'scatter_plot' && 
-		data.length > chartConfig.geomOptions.binThreshold) {
-               chartConfig.geomOptions.binned = true;
-        }
-        let scales = LABKEY.vis.GenericChartHelper.generateScales(
-		chartType, chartConfig.measures, chartConfig.scales, 
-		aes, measureStore);
-        let geom = LABKEY.vis.GenericChartHelper.generateGeom(
-		chartType, chartConfig.geomOptions);
-	document.getElementById('debugCode').value+='\n geom color '+geom.color;
-	
-
-        let labels = LABKEY.vis.GenericChartHelper.generateLabels(
-		chartConfig.labels);
-
-	if (chartType == 'bar_chart' || chartType == 'pie_chart') {
-            	let dimName = null, subDimName = null; measureName = null,
-	               aggType = 'COUNT';
-
-        	if (chartConfig.measures.x) {
-			dimName = chartConfig.measures.x.converted ? 
-				chartConfig.measures.x.convertedName : 
-				chartConfig.measures.x.name;
-        	}
-        	if (chartConfig.measures.xSub) {
-	        	subDimName = chartConfig.measures.xSub.converted ? 
-				chartConfig.measures.xSub.convertedName : 
-				chartConfig.measures.xSub.name;
-		}
-	
-		if (chartConfig.measures.y) {
-			measureName = chartConfig.measures.y.converted ? 
-				chartConfig.measures.y.convertedName : 
-				chartConfig.measures.y.name;
-
-			if (Ext4.isDefined(chartConfig.measures.y.aggregate)) {
-				aggType = chartConfig.measures.y.aggregate;
-                	}
-                	else if (measureName != null) {
-				aggType = 'SUM';
-			}
-
-		}
-
-
-		data = LABKEY.vis.getAggregateData(data, dimName, subDimName, 
-			measureName, aggType, '[Blank]', false);
-        }
-
-	let plotConfig = LABKEY.vis.GenericChartHelper.generatePlotConfig(
-		renderConfig.chartId,chartConfig, labels, aes, scales, geom, data);
-	document.getElementById('debugCode').value+='\n plotConfig layers: '+plotConfig.layers.length;
-	for (let i=0;i<plotConfig.layers.length;i++){
-		let l=plotConfig.layers[i];
-		document.getElementById('debugCode').value+='\n color: '+l.aes.pathColor;
-		if (l.data===null)
-			continue;
-		document.getElementById('debugCode').value+='\n data: '+l.data.length;
-
-	}
-        let validation = validateChartConfig(chartConfig, aes, scales, measureStore);
-        renderMessages(renderConfig.chartId, validation.messages);
-        if (!validation.success)
-            return;
-	
-	let plot;
-        if (chartType == 'pie_chart') {
-            new LABKEY.vis.PieChart(plotConfig);
-        }
-        else {
-            plot = new LABKEY.vis.Plot(plotConfig);
-            plot.render();
-        }
-	   
-
-
-
-}
-
-function plotAll() {
-
-	let participantField=document.getElementById('participantField').innerHTML;
-	let visitField=document.getElementById('visitField').innerHTML;
-	document.getElementById('debugCode').value+='\n'+participantField;
-
-	let organs=["3","4","5"];
-		
-	for (let i=0;i < organs.length; i++){
-
-		let renderConfig=new Object();
-        	//all additional configuration stuff goes in here
-
-		renderConfig.chartId='SUVall_organ'+organs[i];
-		renderConfig.width=500;
-		renderConfig.participantCode=document.getElementById("participantCode").innerHTML;
-		renderConfig.visitCode=document.getElementById("visitCode").innerHTML;
-		renderConfig.labelOthers='other visits/participants';
-		renderConfig.plot="percentile";
-		renderConfig.max=10;
-		renderConfig.title="SUV cumulative distribution";
-
-		// When all the dependencies are loaded we then load the data via the MeasureStore selectRows API.
-		// The queryConfig object stores all the information needed to make a selectRows request
-		
-		let queryConfig = new Object;
-	        queryConfig.schemaName="study";
-        	queryConfig.queryName="SUVQuantiles";
-        	queryConfig.viewName=null;
-        	queryConfig.dataRegionName="Dataset";
-	        queryConfig.queryLabel="SUVQuantiles";
-        	queryConfig.parameters= new Object();
-		queryConfig.requiredVersion=13.2;
-	        queryConfig.maxRows=-1;
-        	queryConfig.sort="lsid";
-	        queryConfig.method="POST";
-        	queryConfig.columns=["percentile","value",participantField,visitField];
-	        queryConfig.filterArray=new Array();
-        	//queryConfig.filterArray.push({
-		//	"name":"patientCode",
-		//	"value":renderConfig.participantCode,
-		//	"type":"eq"});
-	        //queryConfig.filterArray.push({
-		//	"name":"visitCode",
-		//	"value":renderConfig.visitCode,
-		//	"type":"eq"});
-        	queryConfig.filterArray.push({
-			"name":"organ",
-			"value":organs[i],
-			"type":"eq"});
-
-		if (queryConfig.filterArray && 
-			queryConfig.filterArray.length > 0) {
-            		let filters = [];
-            		for (let i = 0; i < queryConfig.filterArray.length; i++) {
-                		let f = queryConfig.filterArray[i];
-                		filters.push(LABKEY.Filter.create(
-					f.name,  f.value, 
-					LABKEY.Filter.getFilterTypeForURLSuffix(f.type)));
-            		}
-            		queryConfig.filterArray = filters;
-        	}
-        	queryConfig.success = function(data){
-			selectRowsCallback(renderConfig,data);};
-        	queryConfig.containerPath = LABKEY.ActionURL.getContainer();
-        	LABKEY.Query.MeasureStore.selectRows(queryConfig);
-	}
-};
-
-function plotParticipant() {
-
-	let participantField=document.getElementById('participantField').innerHTML;
-	let participantCode=document.getElementById('participantCode').innerHTML;
-	let visitField=document.getElementById('visitField').innerHTML;
-	let visitCode=document.getElementById('visitCode').innerHTML;
-
-	let visitValue=parseInt(visitCode.split('_')[1])+1;
-	document.getElementById('debugCode').value+='\n'+visitValue;
-
-	let organs=["3","4","5"];
-		
-	for (let i=0;i < organs.length; i++){
-
-		let renderConfig=new Object();
-        	//all additional configuration stuff goes in here
-
-		renderConfig.chartId='SUVparticipant_organ'+organs[i];
-		renderConfig.width=500;
-		renderConfig.participantCode=document.getElementById("participantCode").innerHTML;
-		renderConfig.visitCode=document.getElementById("visitCode").innerHTML;
-		renderConfig.labelOthers='other visits';
-		renderConfig.plot="percentile";
-		renderConfig.max=10;
-		renderConfig.title="SUV cumulative distribution";
-		renderConfig.visitThreshold=visitValue;
-
-		// When all the dependencies are loaded we then load the data via the MeasureStore selectRows API.
-		// The queryConfig object stores all the information needed to make a selectRows request
-		
-		let queryConfig = new Object;
-	        queryConfig.schemaName="study";
-        	queryConfig.queryName="SUVQuantiles";
-        	queryConfig.viewName=null;
-        	queryConfig.dataRegionName="Dataset";
-	        queryConfig.queryLabel="SUVQuantiles";
-        	queryConfig.parameters= new Object();
-		queryConfig.requiredVersion=13.2;
-	        queryConfig.maxRows=-1;
-        	queryConfig.sort="lsid";
-	        queryConfig.method="POST";
-        	queryConfig.columns=["SequenceNum","percentile","value",participantField,visitField];
-	        queryConfig.filterArray=new Array();
-        	queryConfig.filterArray.push({
-			"name":"patientCode",
-			"value":renderConfig.participantCode,
-			"type":"eq"});
-	        //queryConfig.filterArray.push({
-		//	"name":"visitCode",
-		//	"value":renderConfig.visitCode,
-		//	"type":"eq"});
-        	queryConfig.filterArray.push({
-			"name":"organ",
-			"value":organs[i],
-			"type":"eq"});
-
-		if (queryConfig.filterArray && 
-			queryConfig.filterArray.length > 0) {
-            		let filters = [];
-            		for (let i = 0; i < queryConfig.filterArray.length; i++) {
-                		let f = queryConfig.filterArray[i];
-                		filters.push(LABKEY.Filter.create(
-					f.name,  f.value, 
-					LABKEY.Filter.getFilterTypeForURLSuffix(f.type)));
-            		}
-            		queryConfig.filterArray = filters;
-        	}
-        	queryConfig.success = function(data){
-			selectRowsCallback(renderConfig,data);};
-		queryConfig.containerPath=LABKEY.ActionURL.getContainer();
-        	LABKEY.Query.MeasureStore.selectRows(queryConfig);
-	}
-};
-
-function plotTime() {
-
-	let participantField=document.getElementById('participantField').innerHTML;
-	let participantCode=document.getElementById('participantCode').innerHTML;
-	let visitField=document.getElementById('visitField').innerHTML;
-	let visitCode=document.getElementById('visitCode').innerHTML;
-
-	let visitValue=parseInt(visitCode.split('_')[1])+1;
-	document.getElementById('debugCode').value+='\n'+visitValue;
-
-
-
-	let organs=["3","4","5"];
-		
-	for (let i=0;i < organs.length; i++){
-
-		let renderConfig=new Object();
-        	//all additional configuration stuff goes in here
-
-		renderConfig.chartId='SUVparticipant_organ'+organs[i];
-		renderConfig.width=500;
-		renderConfig.participantCode=document.getElementById("participantCode").innerHTML;
-		renderConfig.visitCode=document.getElementById("visitCode").innerHTML;
-		renderConfig.labelOthers='others';
-		renderConfig.suv=95;
-		renderConfig.plot="time";
-		if (organs[i]=="4")
-			renderConfig.suv=70;
-		renderConfig.max=-1;
-		renderConfig.visitThreshold=visitValue;
-		renderConfig.title="Quantitative inflamation time-curve";
-
-		// When all the dependencies are loaded we then load the data via the MeasureStore selectRows API.
-		// The queryConfig object stores all the information needed to make a selectRows request
-		
-		let queryConfig = new Object;
-	        queryConfig.schemaName="study";
-        	queryConfig.queryName="SUVQuantiles";
-        	queryConfig.viewName=null;
-        	queryConfig.dataRegionName="Dataset";
-	        queryConfig.queryLabel="SUVQuantiles";
-        	queryConfig.parameters= new Object();
-		queryConfig.requiredVersion=13.2;
-	        queryConfig.maxRows=-1;
-        	queryConfig.sort="lsid";
-	        queryConfig.method="POST";
-        	queryConfig.columns=["SequenceNum","value",participantField];
-	        queryConfig.filterArray=new Array();
-        	//queryConfig.filterArray.push({
-		//	"name":"patientCode",
-		//	"value":renderConfig.participantCode,
-		//	"type":"eq"});
-	        queryConfig.filterArray.push({
-			"name":"percentile",
-			"value":renderConfig.suv,
-			"type":"eq"});
-        	queryConfig.filterArray.push({
-			"name":"organ",
-			"value":organs[i],
-			"type":"eq"});
-
-		if (queryConfig.filterArray && 
-			queryConfig.filterArray.length > 0) {
-            		let filters = [];
-            		for (let i = 0; i < queryConfig.filterArray.length; i++) {
-                		let f = queryConfig.filterArray[i];
-                		filters.push(LABKEY.Filter.create(
-					f.name,  f.value, 
-					LABKEY.Filter.getFilterTypeForURLSuffix(f.type)));
-            		}
-            		queryConfig.filterArray = filters;
-        	}
-        	queryConfig.success = function(data){
-			selectRowsCallback(renderConfig,data);};
-        	queryConfig.containerPath = LABKEY.ActionURL.getContainer();
-        	LABKEY.Query.MeasureStore.selectRows(queryConfig);
-	}
-};

+ 0 - 465
web/crf/crfReviewSection.js

@@ -1,465 +0,0 @@
-//loadFile is in fileManager.js
-var crfReviewSection={};
-
-crfReviewSection.set=
-function(parentClass){
-   if ("parent" in this) 
-      return;
-   this.parent=parentClass;
-}
-
-crfReviewSection.generateErrorMessage=
-function (id,listName,msg){
-	this.parent.print('generateErrorMessage:');
-	let eid=listName+"_errorMsg";
-	let el=config.document.getElementById(eid);
-	if (el===null){
-		el=config.document.createElement("p");
-		config.document.getElementById(id).appendChild(el);
-	}
-	el.innerHTML=msg;
-}
-
-crfReviewSection.clearErrorMessage=
-function(listName){
-	let eid=listName+"_errorMsg";
-	let el=config.document.getElementById(eid);
-	if (el===null) return;
-	el.remove();
-}
-
-
-
-
-crfReviewSection.generateSection=
-function(listName,id,callback){
-   let that=this;
-   let action=function(){that.fcontinue(listName,id,callback);};
-   LABKEY.requiresScript(["crf/fileManager.js"],action);
-}
-
-crfReviewSection.fcontinue=
-function(listName,id,callback){
-	//callback should be generateReviewSectionCB and it takes no arguments
-	this.parent.print("generateReviewSection");
-   let config=this.parent.config;
-	//need base path
-
-
-	config.loadFileConfig=new Object();
-	
-	
-	config.loadFileConfig.cb=callback;
-	config.loadFileConfig.id=id;
-	config.loadFileConfig.url=fileManager.getBasePath()+'/@files/reportSetup/'+listName+'.json';
-	fileManager.loadFile();
-	//load file and continue in the next function
-}
-
-crfReviewSection.getParticipantCode=
-function(pid){
-
-	let filters=[LABKEY.Filter.create("crfRef",this.parent.getCRFref())];
-   let config=this.parent.config;
-	let mfId=config.formConfig.form['masterQuery'];
-   let queryName=config.formConfig.queryMap[mfId];
-   let that=this;
-	pid.afterId=function(id){that.setParticipantCode(id);};
-	pid.participantField=config.formConfig.studyData["SubjectColumnName"];
-	let cb=function(data){that.afterRegistration(pid,data);}
-   //untested
-   this.parent.selectRows('lists',queryName,filters,cb,this.parent.getContainer('data'));
-}
-
-crfReviewSection.visitCodeFromVisitId=
-function(visitId){
-	if (visitId<0) return "NONE";
-	let project=this.parent.getContainer('data');
-this.parent.print('visitCodeFromVisitId: '+project.search('retro'));
-	if (project.search('retro')>-1)
-		visitId-=1;
-	return 'VISIT_'+visitId.toString();
-}
-
-crfReviewSection.replaceSlash=
-function(x){
-	return x.replace(/\//,'_');
-}
-
-crfReviewSection.setParticipantCode=
-function(pid){
-	let fName='[setParticipantCode]';
-	let rows=pid.registration.rows;
-   let config=this.parent.config;
-	//pick from study
-	let participantField=config.formConfig.studyData["SubjectColumnName"];
-	if (rows.length==1){
-		this.parent.print(fName+': '+rows[0][participantField]+'/'+rows[0].visitId);
-		let visitCode=this.visitCodeFromVisitId(rows[0].visitId);
-		this.parent.print('setParticipantCode: '+pid.participantId+'/'+visitCode);
-		pid.participantCode=this.replaceSlash(pid.participantId);
-		pid.visitCode=visitCode;
-	}
-	this.generateReviewSection2(pid);
-}
-
-crfReviewSection.CB=
-function(){
-   let config=this.parent.config;
-	let listName=config.loadFileConfig.listName;
-	let id=config.loadFileConfig.id;
-
-	this.parent.clearErrorMessage(listName);
-
-	let pid=new Object();
-	pid.participantCode="NONE";
-	pid.visitCode="NONE";
-	this.getParticipantCode(pid);
-	this.parent.print('Get participant code sent');
-	//involves database search, continue after callback
-}
-
-crfReviewSection.getValueFromElement=
-function(id,defaultValue){
-   let config=this.parent.config;
-	let e=config.document.getElementById(id);
-	if (e!=null){
-		defaultValue=e.innerHTML;
-	}
-	return defaultValue;
-}
-
-crfReviewSection.pickParticipantCodeFromPage=
-function(){
-	let pid=new Object();
-	pid.participantCode=this.getValueFromElement("participantCode","NIX-LJU-D2002-IRAE-A000");
-	pid.visitCode=this.getValueFromElement("visitCode","VISIT_1");
-	this.generateReviewSection2(pid);
-}
-
-crfReviewSection.patternReplace=
-function(src,replacements,values){
-
-	for (rep in replacements){
-		let txt1=src.replace(new RegExp(rep),values[replacements[rep]]);
-		src=txt1;
-	}
-	return src;
-
-}
-
-crfReviewSection.plotImage=
-function(cell,k,row,rowVariable,obj,pid){
-   let config=this.parent.config;
-	let baseDir=this.patternReplace(obj.imageDir,obj.replacements,pid);
-	this.parent.print('Base dir: '+pid.basePath);
-	pid[obj.variable]=obj.values[k];
-	cell.id=pid[obj.variable]+"_"+rowVariable+pid[rowVariable];
-	let img=null;
-	let imgId=cell.id+'_img_';
-	img=config.document.getElementById(imgId);
-	if (img===null){
-		img=config.document.createElement('img');
-		img.id=imgId;
-		cell.appendChild(img);
-	}
-	let imgSrc=patternReplace(obj.file,obj.replacements,pid);
-   this.parent.print('Image: '+imgSrc);
-	let imagePath=pid.basePath+'/'+baseDir+'/'+imgSrc;
-			
-	img.src=imagePath;
-	img.width="300";
-
-	
-}
-
-crfReviewSection.showReport=
-function(cell,k,row,rowVariable,obj,pid){
-
-	cell.width="300px";
-	cell.id='report_'+obj.values[k]+"_"+rowVariable+pid[rowVariable];
-	let reportConfig=new Object();
-	reportConfig.partName="Report";
-	reportConfig.renderTo=cell.id;
-	//reportConfig.showFrame=false;
-	//reportConfig.width="300";
-	reportConfig.frame="none";
-	reportConfig.partConfig=new Object();
-	reportConfig.partConfig.width="300";
-	reportConfig.partConfig.title="R Report";
-	reportConfig.partConfig.reportName=obj.values[k];
-	for (f in obj.parameters){
-		reportConfig.partConfig[f]=pid[f];
-	}
-	reportConfig.partConfig.showSection="myscatterplot";
-	let reportWebPartRenderer = new LABKEY.WebPart(reportConfig);
-   this.parent.print('Render to: '+reportConfig.renderTo);
-	reportWebPartRenderer.render();
-}
-
-crfReviewSection.showProbability=
-function(cell,k,row,rowSetup,j,obj,pid){
-   this.parent.print('showProbability: '+rowSetup);
-	let rowVariable=rowSetup.variable;	
-	cell.id='prob_'+obj.values[k]+"_"+rowVariable+pid[rowVariable];
-
-	let probDensity=new Object();
-	probDensity.mean=rowSetup.mean[j];
-	probDensity.sigma=rowSetup.sigma[j];
-
-   this.parent.print('showProbability: mean '+probDensity.mean+' sigma '+probDensity.sigma);
-
-
-	probDensity.func=obj.values[k];
-	probDensity.organCode=pid.organCode;
-	pid[obj.variable]=rowSetup[obj.variable][j];
-	probDensity.percentile=pid.percentile;
-	let selectRows=new Object();
-	selectRows.queryName=obj.queryName;
-	selectRows.schemaName="study";
-	selectRows.filterArray=[];
-	selectRows.containerPath=getContainer('data');
-	for (let f in obj.filters){
-		selectRows.filterArray.push(
-				LABKEY.Filter.create(f,pid[obj.filters[f]]));
-	   this.parent.print('Filter ['+f+']: '+pid[obj.filters[f]]);
-	}
-	selectRows.success=function(data){ 
-		this.drawProbability(data,cell,obj,pid,probDensity);}
-	LABKEY.Query.selectRows(selectRows);
-}
-
-crfReviewSection.erf=
-function(x){
-	let fx=[0,0.02,0.04,0.06,0.08,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
-		1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,
-		2.1,2.2,2.3,2.4,2.5,3,3.5];
-	let fy=[0,0.222702589,0.328626759,0.428392355,0.520499878,
-		0.603856091,0.677801194,0.742100965,0.796908212,
-	 	0.842700793,0.880205070,0.910313978,0.934007945,
-		0.952285120,0.966105146,0.976348383,
-		0.983790459,0.989090502,0.992790429,0.995322265,
-		0.997020533,0.998137154,0.998856823,0.999311486,
-		0.999593048,0.999977910,0.999999257];
-	let n=32;
-	let i0=n-1;
-
-	for (let i=1;i<n;i++){
-		if (Math.abs(x)>fx[i]) continue;
-		i0=i-1;
-		break;
-	}
-	let fval=1;
-	if (i0<n-1){
-		//interpolate
-		let y1=fy[i0+1];
-		let y0=fy[i0];
-		let x1=fx[i0+1];
-		let x0=fx[i0];
-		fval=y0+(y1-y0)/(x1-x0)*(Math.abs(x)-x0);
-	}
-   this.parent.print('Erf: '+fval);
-	if (x<0) return -fval;
-	return fval;
-}
-
-crfReviewSection.setLine=
-function(fbox,name,value,fontSize){
-	let fpId=fbox.id+name;
-	let fp=config.document.getElementById(fpId);
-	if (fp===null){
-		fp=config.document.createElement("p");
-		fp.id=fpId;
-		fbox.appendChild(fp);
-	}
-	fp.classList.add("center");
-	fp.style.textAlign="center";
-	fp.style.fontSize=fontSize;
-	fp.innerText=value;
-}	
-
-crfReviewSection.drawProbability=
-function(data,cell,obj,pid,probDensity){
-this.parent.print('drawProbability');
-	if (data.rows.length!=1){
-	   this.parent.print("drawProbability row length mismatch: "+data.rows.length);
-		return;
-	}
-	//possible mismatch; I assume the dataset will have a field called value
-	let val=data.rows[0].value;
-
-	let prob=0;
-	let fz=-100;
-
-	if (probDensity.func=="gaus"){
-		fz=(val-probDensity.mean)/probDensity.sigma/Math.sqrt(2);
-		prob=0.5+0.5*erf(fz);
-	}
-	let color="red";
-	let fzx=fz*Math.sqrt(2);
-   this.parent.print('drawProbability '+fzx);
-
-	for (let i=1;i<obj.intervals.n;i++){
-		if (fzx>obj.intervals.zlimits[i]) continue;
-		color=obj.intervals.colors[i-1];
-		break;
-	}
-	
-	let fboxId=cell.id+'_fbox_';
-	let fbox=config.document.getElementById(fboxId);
-	if (fbox===null){
-		fbox=config.document.createElement("div");
-		fbox.id=fboxId;
-		cell.appendChild(fbox);
-	}
-	fbox.style.backgroundColor=color;
-	fbox.style.width="180px";
-	fbox.style.height="180px";
-	
-
-   this.parent.print('organCode '+probDensity.organCode);
-	let organName="Lung";
-
-	if (probDensity.organCode==4){
-		organName="Thyroid";
-	}
-	if (probDensity.organCode==5){
-		organName="Bowel";
-	}
-
-	this.setLine(fbox,'_fp4_',organName,"16px");
-	this.setLine(fbox,'_fp_',val.toPrecision(3),"25px");
-	this.setLine(fbox,'_fp1_',"SUV("+probDensity.percentile+"%)","16px");
-	this.setLine(fbox,'_fp2_',fzx.toPrecision(3),"25px");
-	this.setLine(fbox,'_fp3_',"z-value","16px");
-
-
-}
-crfReviewSection.generateReviewSection2=
-function(pid){ 
-	let config=this.parent.config;
-	let listName=config.loadFileConfig.listName;
-	let id=config.loadFileConfig.id;
-	
-   this.parent.print('generateReviewSection2: '+pid.participantCode+'/'+
-		pid.visitCode);
-	if (pid.participantCode=="NONE" || pid.visitCode=="NONE"){
-		this.generateErrorMessage(id,listName,
-			"ParticipantId/visitId not set");
-		return;
-	}
-	
-
-   this.parent.print('JSON: '+config.loadFileConfig.json);
-
-	let json=config.loadFileConfig.json;
-	let nrows=json.rows.values.length;
-	let ncol=json.columns.length;
-
-	pid.basePath=fileManager.getBasePath()+"/@files";
-	
-	
-	let el=config.document.getElementById(id);
-	let tableId=id+'_Table';
-	let table=config.document.getElementById(tableId);
-	if (table==null){
-		table=config.document.createElement('table');
-		table.id=tableId;
-		el.appendChild(table);
-	}
-	table.style.tableLayout="fixed";
-	table.style.columnWidth="300px";
-	
-	for (let i=0;i<nrows;i++){
-		pid[json.rows.variable]=json.rows.values[i];
-		//let organ=organs[i];
-		let row=null;
-		if (i<table.rows.length)
-			row=table.rows[i];
-		else
-			row=table.insertRow();
-
-		let ic=0;
-		for (let j=0;j<ncol;j++){
-			let obj=json.columns[j];
-			let nv=obj.values.length;
-			for (let k=0;k<nv;k++){
-				let cell=null;
-				if (ic<row.cells.length)
-					cell=row.cells[ic];
-				else
-					cell=row.insertCell();
-				if (obj.display=="image") 
-					this.plotImage(cell,k,row,json.rows.variable,obj,pid);
-				if (obj.display=="report") 
-					this.showReport(cell,k,row,json.rows.variable,obj,pid);
-				if (obj.display=="probability"){ 
-					this.showProbability(cell,k,row,json.rows,i,obj,pid);
-				}	
-				ic++;
-			}
-
-
-		}
-		
-
-	}
-}
-
-///>>>>>>>>>>>>>>end of reviewSection(REPORT)
-
-crfReviewSection.afterRegistration=
-function(data,fc){
-	let fName='[afterRegistration/'+data.queryName+']';
-   this.parent.print(fName+": rows:"+data.rows.length);
-	fc.registration=data;
-	let registrationData=fc.registration;
-	this.parent.clearErr();
-	if (registrationData.rows.length!=1){
-		let msg=fName+": ERROR: Found "+registrationData.rows.length;
-		msg+=" registration entries for crfrefid "+this.parent.getCRFref();
-	   this.parent.print(msg);
-		fc.afterId(fc);
-		return;
-	}
-   this.parent.print(fName+'registration participant field: '+fc.participantField);
-	fc.participantId=registrationData.rows[0][fc.participantField];
-	//could be a lookup field (particularly for studies)
-   this.parent.print('ID: '+fc.participantId);	
-	let fields=registrationData.metaData.fields;
-	let field="NONE";
-	for (f in fields){
-		if (fields[f]["name"]==fc.participantField)
-			field=fields[f];
-	}
-	if ("lookup" in field){
-		let pid=fc.participantId;
-	   this.parent.print("Using lookup for participantId: "+pid);
-		let lookup=field["lookup"];
-   	this.parent.print("Lookup: ["+lookup.schemaName+','+lookup.queryName+']');
-
-      //load lookup
-      let that=this;
-		let cb=function(data){that.afterRegistrationLookup(data,lookup.displayColumn,fc)};
-		let filters=[LABKEY.Filter.create(lookup.keyColumn,pid)];
-      this.parent.selectRows(lookup.schemaName,lookup.queryName,filters,cb,lookup.containerPath);
-
-	}
-	else{
-		//afterParticipantId(configUpload);
-		fc.afterId(fc);
-	}
-}
-
-crfReviewSection.afterRegistrationLookup=
-function(data,displayColumn,fc){
-   this.parent.print("afterRegistrationLookup");
-	let entry=data.rows[0];
-	fc.participantId=entry[displayColumn];
-   this.parent.print('Setting to '+fc.participantId);
-	fc.afterId(fc);
-	//afterParticipantId(configUpload);
-}
-
-
-

+ 0 - 81
web/crf/crfRoleSelector.js

@@ -1,81 +0,0 @@
-var crfRoleSelector={};
-
-crfRoleSelector.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.afterScripts(cb);};
-   LABKEY.requiresScript(["crf/crfHTML.js"],action);
-}
-
-crfRoleSelector.afterScripts=
-function(cb=null){
-   if (cb) cb();
-}
-
-crfRoleSelector.set=
-function(setup){
-   this.setup=setup;
-}
-
-crfRoleSelector.print=
-function(msg){
-   console.log(msg);
-}
-
-
-crfRoleSelector.makePortal=
-function(cb=null){
-   //cb is a callback function that gets executed on select change
-   let fName='[crfRoleSelector::makePortal]';
-   let userId=LABKEY.Security.currentUser.id;
-   let userRoles=['crfEditor','crfMonitor','crfSponsor','crfManager'];
-   //let siteRows=this.setup.getRows('siteData');
-   //find possible matches between user and sites
-   let options=new Object();
-   let siteMap=this.setup.getEntryMap('siteData:siteNumber');
-   let userMap=this.setup.getEntryMap('users:UserId');
-   for (let i=0;i<userRoles.length;i++){
-      let listName=userRoles[i]+'s';
-      let listRows=this.setup.getRows(listName);
-      for (let j=0;j<listRows.length;j++){
-         if (listRows[j]['User']!=userId) continue;
-         let siteNumber=listRows[j]['Site'];
-         let siteRow=siteMap[siteNumber];
-         options[userRoles[i]+':'+siteNumber]=userRoles[i]+' for '+siteRow['siteName'];
-      }
-   }
-   for (let opt in options){
-      this.print(fName+' ['+opt+'] '+options[opt]);
-   }
-   let table=crfHTML.createTable('formDiv');
-   let row=table.insertRow();
-   let cell=row.insertCell();
-   this.roleLabel=crfHTML.createTextNode('Please select role and site',null,cell);
-   row=table.insertRow();
-   cell=row.insertCell();
-   this.roleSelect=crfHTML.createSelect(options,null,cell);
-   let that=this;
-   this.roleSelect.onchange=function(){that.onChange(cb);}
-}
-
-crfRoleSelector.onChange=
-function(cb=null){
-   crfHTML.setTextNode(this.roleLabel,this.roleSelect.value);
-   if (cb) cb();
-}
-
-crfRoleSelector.getRoleAndSite=
-function(){
-   if (this.roleSelect.selectedIndex==0)
-      return null;
-   return this.roleSelect.value;
-}
-
-crfRoleSelector.setRoleAndSite=
-function(roleAndSite,cb=null){
-   if (!roleAndSite) return;
-   this.roleSelect.value=roleAndSite;
-   if (cb) cb();
-}
-   
-

+ 0 - 495
web/crf/crfSetup.js

@@ -1,495 +0,0 @@
-var crfSetup={};
-
-crfSetup.print=
-function(msg){
-   console.log(msg);
-}
-
-crfSetup.init=
-function(cb=null){
-   let fName="[crfSetup:init]";
-   this.print(fName);
-   let that=this;
-   let action=function(){that.afterScripts(cb);}
-   LABKEY.requiresScript(["crf/runQuery.js"],action);
-}
-
-crfSetup.afterScripts=
-function(cb=null){
-   if (cb) cb();
-}
-
-crfSetup.setContainer=
-function(label,container){
-	if (!(this.hasOwnProperty('container'))){
-		this.container=new Array();
-	}
-	this.container[label]=container;
-}
-
-crfSetup.getContainer=
-function(label){
-	return this.container[label];
-}
-
-crfSetup.getSettings=
-function(variable){
-   if (variable in this.settings){
-      return this.settings[variable];
-   }
-   return null;
-}
-
-crfSetup.getRows=
-function(objectName){
-   if (objectName in this)
-      return this[objectName].rows;
-   return new Array();
-}
-
-crfSetup.getMaps=
-function(){
-   return this.getObject('maps');
-}
-
-crfSetup.getEntryMaps=
-function(){
-   return this.getObject('entryMaps');
-}
-
-crfSetup.getMap=
-function(queryName){
-   let maps=this.getMaps();
-   if (!(queryName in maps))
-      this.parseMap(queryName);
-   return maps[queryName];
-
-}
-
-crfSetup.getEntryMap=
-function(queryName){
-   let entryMaps=this.getEntryMaps();
-   if (!(queryName in entryMaps))
-      this.parseEntryMap(queryName);
-   return entryMaps[queryName];
-}
-
-crfSetup.getAdditionalDataObject=
-function(){
-   return this.getObject('additionalData');
-}
-
-crfSetup.getAdditionalData=
-function(queryName){
-   let adObject=this.getAdditionalDataObject();
-	if (queryName in adObject){
-		this.print(fName+': Returning preset value');
-		return adObject[queryName];
-	}
-   return null;
-}
-
-
-crfSetup.getTargetStatus=
-function(action){
-   return this.getObject('targetStatus')[action];
-}
-
-crfSetup.getTargetRecipient=
-function(action){
-   return this.getObject('targetRecipient')[action];
-}
-
-crfSetup.getActionSettings=
-function(action){
-   return this.getObject('actionSettings')[action];
-}
-
-
-crfSetup.getObject=
-function(name){
-   if (!(name in this))
-      this[name]=new Object;
-   return this[name];
-}
-
-crfSetup.addObject=
-function(masterObject,objectName,object){
-   let obj=this.getObject(masterObject);
-   obj[objectName]=object;
-}
-
-crfSetup.invertMap=
-function(qMap){
-   let qInverseMap=new Object();
-   for (let q in qMap){
-      qInverseMap[qMap[q]]=q;
-   }
-   return qInverseMap;
-}
-
-crfSetup.getStudyIdLabel
-=function(){
-   return 'participantStudyId';
-}
-
-crfSetup.getLocalIdLabel
-=function(){
-   return 'participantLocalId';
-}
-
-crfSetup.getParticipantLabel=
-function(entry){
-   let pid=entry[this.getStudyIdLabel()];
-   let loc=entry[this.getLocalIdLabel()];
-   let label='';
-   if (pid) {
-      label+=pid;
-      if (loc) label+=' ';
-   }
-   if (loc) label+='(Local: '+loc+')';
-   if (label.length==0) label="NONE";
-   return label;
- 
-}
-
-crfSetup.getStudyId=
-function(label){
-   this.print('getStudyId: label ['+label+']');
-   return label.replace(/ ?\([^\)]*\)/,"");
-}
-
-crfSetup.getLocalId=
-function(label){
-   return label.replace(/^.*\(Local: ([^\)]*)\)$/,"$1");
-}
-
-
-
-crfSetup.setContainers=
-function(cb=null){
-
-   this.setContainer('data',LABKEY.ActionURL.getContainer());
-	this.setContainer('config',LABKEY.ActionURL.getContainer());
-	this.setContainer('CRF',LABKEY.ActionURL.getContainer());
-   let selectRows=new Object();
-	//this is local data
-	selectRows.containerPath=this.getContainer('CRF');
-	selectRows.schemaName='lists';
-	selectRows.queryName='crfSettings';
-	//store form related data to this object
-   let that=this;
-	selectRows.success=function(data){that.parseSettings(data,cb);};
-	LABKEY.Query.selectRows(selectRows);
-}
-
-crfSetup.parseSettings=
-function(data,cb){
-   let fName="[parseSettings]";
-	this.settings=new Array();
-	for (let i=0;i<data.rows.length;i++){
-		let n=data.rows[i]['name'];
-		let v=data.rows[i]['value'];
-		this.settings[n]=v;
-	}
-
-	this.print(fName);
-	for (let k in this.settings){
-		this.print(fName+'\t'+k+'='+this.settings[k]);
-	}
-
-	//if ('dataContainer' in st){
-	//	setContainer('data',st['dataContainer']);
-	//}
-	let vname='configContainer';
-	if (vname in this.settings){
-		this.setContainer('config',this.settings[vname]);
-	}
-	this.print(fName+' config: '+this.getContainer('config'));
-	this.print(fName+' data: '+this.getContainer('data'));
-
-   if (cb) cb();
-
-}
-
-crfSetup.parseSetup=
-function(cb=null){
-	//setup queryArray
-	let queryArray=new Array();
-
-   //targetObject
-   let targetObject=this;
-
-   //static variables
-	queryArray.push(runQuery.makeQuery(targetObject,'data','crfStaticVariables','crfStaticVariables',[]));
-	//Forms 
-	queryArray.push(runQuery.makeQuery(targetObject,'config','Forms','dataForms',[]));
-   //also formData
-	//users
-	queryArray.push(runQuery.makeQuery(targetObject,'data','users','users',[]));
-	queryArray[queryArray.length-1].schemaName='core';
-   //also userData
-	//inputLists
-	queryArray.push(runQuery.makeQuery(targetObject,'config','inputLists','inputLists',[]));
-	//crfEditors
-	queryArray.push(runQuery.makeQuery(targetObject,'config','crfEditors','crfEditors',[]));
-   //crfEditorData
-	//crfMonitors
-	queryArray.push(runQuery.makeQuery(targetObject,'config','crfMonitors','crfMonitors',[]));
-   //crfMonitorData
-	//crfSponsors
-	queryArray.push(runQuery.makeQuery(targetObject,'config','crfSponsors','crfSponsors',[]));
-   //crfSponsorData
-	//crfManagers
-	queryArray.push(runQuery.makeQuery(targetObject,'config','crfManagers','crfManagers',[]));
-	//FormStatus
-   //
-
-	queryArray.push(runQuery.makeQuery(targetObject,'config','FormStatus','formStatusAll',[]));
-   let statusFilter=[];
-   if ("formStatus" in this)
-      statusFilter.push(LABKEY.Filter.create('Key',this.formStatus));
-	queryArray.push(runQuery.makeQuery(targetObject,'config','FormStatus','formStatus',statusFilter));
-   //crfButtons
-	let statusButtonFilter=[];
-   if ("formStatus" in this)
-	   statusButtonFilter.push(LABKEY.Filter.create('sourceFormStatus',this.formStatus));
-	queryArray.push(
-		runQuery.makeQuery(targetObject,'config','crfButtons','crfButtons',statusButtonFilter));
-	//site
-	queryArray.push(runQuery.makeQuery(targetObject,'config','site','siteData',[]));
-	//crfEntry
-	queryArray.push(runQuery.makeQuery(targetObject,'data','crfEntry','crfEntries',[]));
-   //specialFields 
-   queryArray.push(runQuery.makeQuery(targetObject,'data','specialFields','specialFields',[]));
-	//FormSetup	
-	queryArray.push(runQuery.makeQuery(targetObject,'config','FormSetup','formSetup',[]));
-	//generateConfig
-   queryArray.push(
-		runQuery.makeQuery(targetObject,'config','generateConfig','generateConfigData',[]));	
-
-   //parentCrf
-   if ("parentCrf" in this){
-		let crfFilter=LABKEY.Filter.create('entryId',this.parentCrf);
-		queryArray.push(runQuery.makeQuery(targetObject,'data','crfEntry','parentCrfData',[crfFilter]));	
-	}
-
-
-   let that=this;
-   let action=function(){that.addStudyProperties(cb);};
-	runQuery.getDataFromQueries(this,queryArray,action);
-}
-
-crfSetup.addStudyProperties=
-function(cb){
-   //setup queryArray
-	let queryArray=new Array();
-   let targetObject=this;
-	
-	queryArray.push(runQuery.makeQuery(targetObject,'data','StudyProperties','studyData',[]));
-   //also studyDataAll1
-	let e=queryArray[queryArray.length-1];
-	e.schemaName='study';
-   let columnModel="";
-	let varRows=this.getRows('crfStaticVariables');
-	for (let i=0;i<varRows.length;i++){
-      if (i>0) columnModel+=',';
-      columnModel+=varRows[i]['staticVariable'];
-   }
-	e.columns=columnModel;
-   let that=this;
-   //let action=function(){that.fcontinue();};
-   //let action=function(){that.parseQueryMap(cb);};
-   let action=cb;
-   runQuery.getDataFromQueries(this,queryArray,action);
-
-}
-
-
-crfSetup.selectFormSetupRows=
-function(formId){
-	let formSetupRows=new Array();
-   let config=this.config;
-	let allRows=this.getRows("formSetup");
-	for (let i=0;i<allRows.length;i++){
-		let formEntry=allRows[i];
-		if (formEntry.formName==formId)
-			formSetupRows.push(formEntry);
-	}
-	return formSetupRows;
-}
-
-crfSetup.findSetupRow=
-function(sectionId){
-   let key=sectionId.replace('section','');
-   return this.getEntryMap('formSetup')[key];
-}
-
-
-crfSetup.parseMap=
-function(queryName){
-   let fName='[parseMap/'+queryName+']';
-   let key="Key";
-   let value="value";
-   if (queryName=="inputLists")
-      value="queryName";
-   if (queryName=="users"){
-      key="UserId";
-      value="DisplayName";
-   }
-   if (queryName=='dataForms')
-      value='formName';
-   if (queryName=='formStatus')
-      value='formStatus';
-
-   this.print(fName);
-   let rows=this.getRows(queryName);
-   this.maps[queryName]=new Object();
-   let qMap=this.maps[queryName];
-   for (let i=0;i<rows.length;i++){
-      let r=rows[i];
-      qMap[r[key]]=r[value];
-      //this.print(fName+' ['+r[key]+'] '+r[value]);
-   }
-   
-}
-
-crfSetup.parseEntryMap=
-function(queryName){
-   //queryMap can be a combination of queryName:key where key is an override of standard keys given below
-   let fName='[parseEntryMap/'+queryName+']';
-   let tA=queryName.split(':');
-   let q=tA[0];
-   let rows=this.getRows(q);
-   this.entryMaps[queryName]=new Object();
-   let qMap=this.entryMaps[queryName];
-   let key='Key';
-   if (q=='users') key='UserId';
-   if (q=='siteData') key='siteNumber';
-   if (tA.length>1) key=tA[1];
-   for (let i=0;i<rows.length;i++){
-      let r=rows[i];
-      qMap[r[key]]=r;
-      this.print(fName+' ['+r[key]+'] '+r);
-   }
-}
- 
-crfSetup.printMap=
-function(queryName){
-   let fName='[printMap]';
-   let qMap=this.getMap(queryName);
-   for (let x in qMap){
-      this.print(fName+' ['+x+'] '+qMap[x]);
-   }
-}
-
-crfSetup.setAdditionalData=
-function(crfRef,formId){
-   let formRows=this.selectFormSetupRows(formId);
-   for (let i=0;i<formRows.length;i++){
-      this.setAdditionalDataEntry(crfRef,formRows[i]);
-   }
-}
-
-crfSetup.setAdditionalDataEntry=
-function(crfRef,formSetupEntry){
-   //return information on additional data associated with the form
-   //additionalData is a sub-list with multiple entries per patient/visit
-   
-   //argument is the row of the formSetup setup list
-	let queryName=this.getMap('inputLists')[formSetupEntry['queryName']];
-	let fName='[getAdditionalData/'+queryName+']';
-	this.print(fName);
-
-   
-   //additionalData holds a reference to all queries already parsed
-   //this helps in reducing number of calls to the database (I assume)a
-
-   let adObject=this.getAdditionalDataObject();
-
-   //first time we see this query, so we have to do the setup
-	this.print(fName+': generating');
-	adObject[queryName]=new Object();
-	
-   //takes address, so further changes will be to the newly created object
-   //in fact, ad is just a short alias of the long variable name on the right
-	let ad=adObject[queryName];
-
-   //no additional data
-	if (formSetupEntry["showFlag"]==="NONE") {
-		this.print(fName+": empty");
-		return ad;
-	}
-
-   //use showFlag to setup report section of the CRF list
-	if (formSetupEntry["showFlag"]==="REVIEW") {
-		//abuse additionalData to signal different segment
-		this.print(fName+": generateReport");
-		ad.isReview=true;
-		return ad;
-	}
-
-   //setup the additionalData memory object
-	this.print(fName+': setting values');
-	ad.showFlag=formSetupEntry["showFlag"];
-	ad.showFlagValue=formSetupEntry["showFlagValue"];
-	ad.queryName=formSetupEntry["showQuery"];
-
-   //for data queries, limit to present CRF only
-	ad.filters=new Object();
-	ad.filters['crfRef']=crfRef;
-
-   //compose a long debug message
-	let msg=fName+": flag "+ad.showFlag;
-	msg+=" value "+ad.showFlagValue;
-	msg+=" query "+ad.queryName;
-	this.print(msg);
-
-	return ad;	
-}
-
-crfSetup.findTitle=
-function(queryId){
-   let entry=this.getEntryMap('inputLists')[queryId];
-   if (entry) 
-      return entry['title'];
-   return "NONE";
-}
-
-crfSetup.parseButtons=
-function(){
-	let rows=this.getRows('crfButtons');
-
-	for (let i=0; i<rows.length; i++){
-		let action=rows[i].action;//String
-      let tstatus=rows[i].targetFormStatus;
-      let trecip=rows[i].targetRecipient;
-   	this.addTargetStatus(action,tstatus);
-		this.addTargetRecipient(action,trecip);
-		//allow for settings to be promoted with each action (and potentially parsed and acted upon)
-		//config.formConfig.actionSettings[action]=undefined;
-		let aSet=rows[i].actionSettings;
-		if (aSet){
-			this.addActionSettings(action,variableList.parseVariables(aSet));
-			variableList.printVariables(this,this.getActionSettings(action));
-		}
-
-	}
-}
-
-
-crfSetup.addTargetStatus=
-function(action,tstatus){
-   this.addObject('targetStatus',action,tstatus);
-}
-
-crfSetup.addTargetRecipient=
-function(action,x){
-   this.addObject('targetRecipient',action,x);
-}
-
-crfSetup.addActionSettings=
-function(action,x){
-   this.addObject('actionSettings',action,x);
-}
-

+ 0 - 3834
web/crf/crfVisit.js

@@ -1,3834 +0,0 @@
-const config=new Object();
-
-function clear(){
-	let el=config.document.getElementById(config.debugId);
-	if (el===null) {
-		//alert("Debug section not initialized");
-		return;
-	}
-	config.document.getElementById(config.debugId).value="";
-}
-
-function print(msg){
-	let el=config.document.getElementById(config.debugId);
-	if (el===null) {
-		//alert("Debug section not initialized. Message: "+msg);
-		return;
-	}
-	el.value+="\n"+msg;
-}
-
-function makeQuery(containerName,queryName,fieldName,filterArray){
-   //generates an instruction entry that looks up queryName from container and stores
-   //the resulting table to fieldName potentially using 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+']: ');
-
-	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 getCRFrefFirst(){
-	//crfRef is part of html call and gets stored in the page
-	return config.document.getElementById(config.crfRefId).innerHTML;
-}
-
-
-function getCRFref(){
-	//'crfRefId'
-	return	config.formConfig.crfEntry['entryId'];
-}
-
-function getCRFrefData(){
-	let parentCrf=config.formConfig.crfEntry['parentCrf'];
-	if (parentCrf!=undefined) return parentCrf;
-	return getCRFref();
-}
-
-
-function onFailure(errorInfo, options, responseObj){
-	
-	if (errorInfo && errorInfo.exception)
-		alert("Failure: " + errorInfo.exception);
-	else
-		alert("Failure: " + responseObj.statusText);
-}
-
-function doNothing(){
-	print('doNothing called');
-}
-
-function generateDebugSection(){
-	//let debug=true;
-	//if (debug) print("generateDebugSection "+sectionName);
-
-	let formName=config.debugDiv;
-	let sectionName="debugSection";
-	let sectionTitle="Debug Messages";
-	let tb=config.document.createElement('table');
-	tb.className='t2';
-	let row=tb.insertRow();
-	let cell=config.document.createElement('th');
-	row.appendChild(cell);	
-	cell.setAttribute("colspan","4");
-	cell.style.fontSize="20px";
-	cell.style.textAlign="center";
-	let cellData=config.document.createTextNode(sectionTitle);
-	cell.appendChild(cellData);
-	cell=row.insertCell();
-	let input=config.document.createElement("input");	
-	input.type="button";
-	input.id="toggle"+sectionName+"VisbilityButton";
-	input.onclick=function(){toggleVisibility(sectionName,input.id)};
-	cell.appendChild(input);
-	config.document.getElementById(formName).appendChild(tb);
-	
-
-	let div=config.document.createElement('div');
-	div.id=sectionName;
-	config.document.getElementById(formName).appendChild(div);	
-	
-	//start open (for debug)
-	
-	//input.value="Hide";
-	//div.style.display="block";
-
-	//start hidden (for production)
-	input.value="Show";
-	div.style.display="none";
-
-	let debugArea=config.document.createElement('textarea');
-	debugArea.rows=10;
-	debugArea.cols=95;
-	debugArea.id=config.debugId;
-	div.appendChild(debugArea);
-
-	//print('ver: 0.10');
-
-}
-
-
-
-
-function getAdditionalData(formSetupEntry){
-
-	let queryName=config.formConfig.queryMap[formSetupEntry['queryName']];
-	let fName='[getAdditionalData/'+queryName+']';
-	print(fName);
-
-	if (queryName in config.formConfig.additionalData){
-		print(fName+': Returning preset value');
-		return config.formConfig.additionalData[queryName];
-	}
-	print(fName+': generating');
-	config.formConfig.additionalData[queryName]=new Object();
-	//takes address, so further changes will be to the newly created object
-	let ad=config.formConfig.additionalData[queryName];
-
-	if (formSetupEntry["showFlag"]==="NONE") {
-		print(fName+": empty");
-		return ad;
-	}
-	if (formSetupEntry["showFlag"]==="REVIEW") {
-		//abuse additionalData to signal different segment
-		print(fName+": generateReport");
-		ad.isReview=true;
-		return ad;
-	}
-	print(fName+': setting values');
-	ad.showFlag=formSetupEntry["showFlag"];
-	ad.showFlagValue=formSetupEntry["showFlagValue"];
-   //variables associated with target query
-   let qVars=formSetupEntry["showQuery"].split(';');
-	ad.queryName=qVars[0];
-   //remove first element
-   qVars.shift();
-   //join back to string for parsing
-   let code=qVars.join(";");
-   //if empty string, set to undefined for parseCode
-   if (code.length==0){
-      code=undefined;
-   }
-   //parse var=value pairs
-   ad.variableDefinition=parseCode(code);
-   //print for debugging
-   for (let f in ad.variableDefinition){
-      let v=ad.variableDefinition[f];
-      print(fName+': adding ['+f+']='+v);
-   }
-	ad.filters=new Object();
-	ad.filters['crfRef']=getCRFref();
-	let msg=fName+": flag "+ad.showFlag;
-	msg+=" value "+ad.showFlagValue;
-	msg+=" query "+ad.queryName;
-	print(msg);
-	return ad;	
-}
-
-function generateSetup(){
-   let setup=new Object();
- //setVariables contains special variables that have a 
-   //preset value in a specified table:
-   //A.) these values won't appear in the form 
-   //B.) will be submitted with value specified to the database
-   //make sure setVariables object is present in an object
-   setup.setVariables=new Object();
-   return setup;
-}	
-
-function fullAccessSetup(sectionId,listName){
-	//generate setup object whcih should contain fields:
-	//readonlyFlag - whether the dataset is writeable
-	//filters - selection fields that allow creation of LABKEY.Filter.create()
-	//getInputId - formating of unique ids for html elements
-	//addApply - whether a submit/Save button is generated
-	//unique - whether entries in list are unique
-
-	let debug=true;
-	if (debug) print("fullAccessSetup");
-
-	let setup=generateSetup();
-	setup.queryName=listName;
-	setup.readonlyFlag=function(vName){return false};
-	setup.filters=new Object();
-	setup.filters['crfRef']=getCRFref();
-	setup.getInputId=function(vName){return sectionId+"_"+vName;}
-	setup.addApply="Save";
-	setup.isReview=false;
-   setup.sectionId=sectionId;
-	return setup;
-
-}
-
-function readonlySetup(sectionId,listName){
-	//see definition of setup object above
-	let debug=true;
-	if (debug) print("readonlySetup");
-
-	let setup=generateSetup();
-	setup.queryName=listName;
-	setup.readonlyFlag=function(vName){return true};
-	setup.filters=new Object();
-	setup.filters['crfRef']=getCRFref();
-	setup.getInputId=function(vName){return sectionId+'_'+vName;}
-	setup.isReview=false;
-   setup.sectionId=sectionId;
-	return setup;
-}
-
-function getSetup(sectionId,listName,writeAccess=true){
-	//change to section granulated permission of type EDIT, COMMENT, READ
-	//let formStatus=config.formConfig.formStatus;
-	//equivalent to READ
-
-	if (!writeAccess)
-	//if (formStatus=="Submitted")
-		return readonlySetup(sectionId,listName);
-	//if (formStatus=="Approved")
-	//	return readonlySetup(listName);
-	return fullAccessSetup(sectionId,listName);
-}
-	
-function parseVariableDefinition(formSetupEntry){
-   let fName='parseVariableDefinition['+formSetupEntry['title']+']';
-   let code=formSetupEntry['variableDefinition'];
-   print(fName+' '+code);
-   return parseCode(code);
-}
-
-function parseCode(code){
-   //helper function to decode content of variableDefinition 
-   //to a JS object
-   //
-   //should contain semicolon split var=value pairs
-   let vars=new Object();
-   if (code==undefined)
-      //variableDefinition field is empty, return empyt object
-      return vars;
-   let ar=code.split(';');
-   for (let i=0;i<ar.length;i++){
-      q=ar[i].split('=');
-      vars[q[0]]=q[1];
-   }
-   return vars;
-}
-
-function setHelp(setup,formSetupEntry){
-   let helpRows=config.formConfig.help.rows;
-   for (let i=0;i<helpRows.length;i++){
-      let eh=helpRows[i];
-      if (eh['query']==formSetupEntry['queryName']){
-         if (!("help" in setup)){
-            setup["help"]=new Object();
-            setup["help"].rows=new Array();
-         }
-         setup["help"].rows.push(eh);
-         print('Adding help to '+config.formConfig.queryMap[eh['query']]);
-      }
-   }
-   //this updates setup
-}
-
-
-function generateSection(formSetupEntry){
-
-   //generates a (hideable) section according to setup in formEntrySetup
-
-	let listName=config.formConfig.queryMap[formSetupEntry['queryName']];
-   let sectionId='section'+formSetupEntry['Key'];
-	let fName='[generateSection/'+listName+'/'+sectionId+']';
-	let sectionTitle=formSetupEntry['title'];	
-	let accessModeColumn=config.formConfig.operator+'Mode';
-	let accessMode=formSetupEntry[accessModeColumn];
-	//this will fix it for later use as well
-	let additionalData=getAdditionalData(formSetupEntry);
-	print(fName);
-
-	let formName=config.masterForm;//this is HTML designator of area on page
-	let debug=true;
-	let tb=config.document.createElement('table');
-	tb.className='t2';
-	let row=tb.insertRow();
-	let cell=config.document.createElement('th');
-	row.appendChild(cell);	
-	cell.setAttribute("colspan","4");
-	cell.style.fontSize="20px";
-	cell.style.textAlign="center";
-	let cellData=config.document.createTextNode(sectionTitle);
-	cell.appendChild(cellData);
-	cell=row.insertCell();
-	let input=config.document.createElement("input");	
-	input.type="button";
-	input.value="Show";
-	input.id="toggle"+sectionId+"VisbilityButton";
-	input.onclick=function(){toggleVisibility(sectionId,input.id)};
-   //toggleVisibilityArgumentList changed!
-	cell.appendChild(input);
-	config.document.getElementById(formName).appendChild(tb);
-
-	let div=config.document.createElement('div');
-   //relabel this to allow multiple entries for the same list
-	div.id=sectionId;
-	div.style.display="none";
-	config.document.getElementById(formName).appendChild(div);	
-
-	let divTable=config.document.createElement('div');
-	divTable.id=sectionId+"Table";
-	div.appendChild(divTable);
-	
-	if ("showFlag" in additionalData) {
-
-		additionalData.divName=sectionId+"SubDiv";
-		additionalData.divQueryName=sectionId+"SubDivList";
-
-		let div1=config.document.createElement('div');
-		div1.id=additionalData.divName;
-		div1.style.display="none";
-		div.appendChild(div1);
-	
-		let div2=config.document.createElement('div');
-		div2.id=additionalData.divQueryName;
-		div1.appendChild(div2);
-
-	}
-	if (debug) print(fName+" master table");
-
-	let writeMode=accessMode=="EDIT";	
-
-   //setup stores some common values that get passed to generateTable
-   //most significantly, whether fields are changeable or not
-	
-	if ("isReview" in additionalData){
-		generateReviewSection(listName,div.id,generateReviewSectionCB);
-		return;	
-	}
-	//master table is unique per visit
-
-	let setup=getSetup(sectionId,listName,writeMode);
-	
-	setup.unique=true;
-
-   setHelp(setup,formSetupEntry);
-
-   //set variables from formSetup variableDefinition field 
-   //to setup.setVariables
-   setup.setVariables=parseVariableDefinition(formSetupEntry);
-   for (x in setup.setVariables){
-      print(fName+' setVariables '+x+':'+setup.setVariables[x]);
-   }
-
-
-	generateTable(listName,divTable.id,additionalData,setup);
-	
-	if (debug) print(fName+" master table: done");
-
-	let generateSubTable=true;
-	//generateSubTable equivalent to read/write access to section
-	if (accessMode != "EDIT")
-		generateSubTable=false;
-	
-	if (! ("showFlag" in additionalData) ) generateSubTable=false;
-	
-	if (generateSubTable){
-		let qName=additionalData.queryName;
-		let dName=additionalData.divName;
-		
-      let subsectionId='sub'+sectionId;
-		let subSetup=fullAccessSetup(subsectionId,qName);
-
-		//only set master query for additionalData
-		subSetup.masterQuery=listName;
-		//if (readonly) setup=readonlySetup(config);
-		generateTable(qName,dName,additionalData,subSetup);
-		//generateTable(formSetupEntry,qName,dName,additionalData,setup);
-	}
-
-	print(fName+" generate review");
-
-	let divReviewList=config.document.createElement('div');
-	divReviewList.id=sectionId+"ReviewList";
-	div.appendChild(divReviewList);
-	
-	let divReview=config.document.createElement('div');
-	divReview.id=sectionId+"Review";
-	div.appendChild(divReview);
-
-
-	//assume we already have listId (content of config.setupQueryName is listId)
-	//we need listName also
-	//qconfig.queryName=config.setupQueryName;
-	generateReview(divReview.id,divReviewList.id,listName,accessMode);
-   //generateReview depends on listName
-   
-   print(fName+" generate review complete");
-
-	if (accessMode!='GENERATE') return;
-	print('Adding generate button');	
-	//add generateButton
-	let divGenerateButton=config.document.createElement('div');
-	divGenerateButton.id=sectionId+'GenerateButton';
-	div.appendChild(divGenerateButton);
-	print('Adding generate button completed to here');	
-	let cb=function(){onGenerateQuery(listName);};
-	generateButton(divGenerateButton.id,'Generate','Generate '+listName,'XX',cb);
-	print('Adding generate button completed');	
-}
-
-//>>>>reviewSection associated routines
-
-function parseResponseXML(){
-	//print(config.config,'Status:' +this.status);
-	print('Status:'+this.status);
-	if (this.status!=200) return;
-	config.loadFileConfig.json=JSON.parse(this.responseText);
-	config.loadFileConfig.cb();
-}
-
-function loadFile(){
-	print('YY: '+config.loadFileConfig.url);
-
-	let connRequest=new XMLHttpRequest();
-	connRequest.addEventListener("loadend",parseResponseXML);
-		//function(e){parseResponseXML(e,config);});
-	connRequest.open("GET", config.loadFileConfig.url);
-	connRequest.send();
-}
-
-
-function getBasePath(){
-	let server=LABKEY.ActionURL.getBaseURL();
-	let basePath=server+"_webdav";
-	basePath+=LABKEY.ActionURL.getContainer();
-	return basePath;
-}
-
-
-function generateReviewSection(listName,id,callback){
-	//callback should be generateReviewSectionCB and it takes no arguments
-	print("generateReviewSection");
-	//need base path
-
-
-	config.loadFileConfig=new Object();
-	
-	
-	config.loadFileConfig.cb=callback;
-	config.loadFileConfig.id=id;
-	config.loadFileConfig.url=getBasePath()+'/@files/reportSetup/'+listName+'.json';
-	loadFile();
-	//load file and continue in the next function
-}
-
-
-function generateErrorMessage(id,listName,msg){
-	print('generateErrorMessage:');
-	let eid=listName+"_errorMsg";
-	let el=config.document.getElementById(eid);
-	if (el===null){
-		el=config.document.createElement("p");
-		config.document.getElementById(id).appendChild(el);
-	}
-	el.innerHTML=msg;
-}
-
-function clearErrorMessage(listName){
-	let eid=listName+"_errorMsg";
-	let el=config.document.getElementById(eid);
-	if (el===null) return;
-	el.remove();
-}
-
-function getParticipantCode(pid){
-	let selectRows=new Object();
-	selectRows.schemaName='lists';
-	//we should now which form we are in
-	let mfId=config.formConfig.form['masterQuery'];
-	selectRows.queryName=config.formConfig.queryMap[mfId];
-	//point to data container
-	selectRows.containerPath=getContainer('data');
-	
-
-	//selectRows.queryName='PET';
-	pid.afterId=setParticipantCode;
-	pid.participantField=config.formConfig.studyData["SubjectColumnName"];
-	selectRows.success=function(data){afterRegistration(pid,data);}
-	selectRows.filterArray=[LABKEY.Filter.create("crfRef",getCRFref())];
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function visitCodeFromVisitId(visitId){
-	if (visitId<0) return "NONE";
-	let project=getContainer('data');
-	print('visitCodeFromVisitId: '+project.search('retro'));
-	if (project.search('retro')>-1)
-		visitId-=1;
-	return 'VISIT_'+visitId.toString();
-}
-
-function replaceSlash(x){
-	return x.replace(/\//,'_');
-}
-
-function setParticipantCode(pid){
-	let fName='[setParticipantCode]';
-	let rows=pid.registration.rows;
-	//pick from study
-	let participantField=config.formConfig.studyData["SubjectColumnName"];
-	if (rows.length==1){
-		print(fName+': '+rows[0][participantField]+'/'+rows[0].visitId);
-		let visitCode=visitCodeFromVisitId(rows[0].visitId);
-		print('setParticipantCode: '+pid.participantId+'/'+visitCode);
-		pid.participantCode=replaceSlash(pid.participantId);
-		pid.visitCode=visitCode;
-	}
-	generateReviewSection2(pid);
-}
-
-
-function generateReviewSectionCB(){
-
-	let listName=config.loadFileConfig.listName;
-	let id=config.loadFileConfig.id;
-
-	clearErrorMessage(listName);
-
-	let pid=new Object();
-	pid.participantCode="NONE";
-	pid.visitCode="NONE";
-	getParticipantCode(pid);
-	print('Get participant code sent');
-	//involves database search, continue after callback
-}
-
-function getValueFromElement(id,defaultValue){
-	let e=config.document.getElementById(id);
-	if (e!=null){
-		defaultValue=e.innerHTML;
-	}
-	return defaultValue;
-}
-
-function pickParticipantCodeFromPage(){
-	let pid=new Object();
-	pid.participantCode=getValueFromElement("participantCode","NIX-LJU-D2002-IRAE-A000");
-	pid.visitCode=getValueFromElement("visitCode","VISIT_1");
-	generateReviewSection2(pid);
-}
-
-
-function patternReplace(src,replacements,values){
-
-	for (rep in replacements){
-		let txt1=src.replace(new RegExp(rep),values[replacements[rep]]);
-		src=txt1;
-	}
-	return src;
-
-}
-
-function plotImage(cell,k,row,rowVariable,obj,pid){
-	let baseDir=patternReplace(obj.imageDir,obj.replacements,pid);
-	print('Base dir: '+pid.basePath);
-	pid[obj.variable]=obj.values[k];
-	cell.id=pid[obj.variable]+"_"+rowVariable+pid[rowVariable];
-	let img=null;
-	let imgId=cell.id+'_img_';
-	img=config.document.getElementById(imgId);
-	if (img===null){
-		img=config.document.createElement('img');
-		img.id=imgId;
-		cell.appendChild(img);
-	}
-	let imgSrc=patternReplace(obj.file,obj.replacements,pid);
-	print('Image: '+imgSrc);
-	let imagePath=pid.basePath+'/'+baseDir+'/'+imgSrc;
-			
-	img.src=imagePath;
-	img.width="300";
-
-	
-}
-
-function showReport(cell,k,row,rowVariable,obj,pid){
-
-	cell.width="300px";
-	cell.id='report_'+obj.values[k]+"_"+rowVariable+pid[rowVariable];
-	let reportConfig=new Object();
-	reportConfig.partName="Report";
-	reportConfig.renderTo=cell.id;
-	//reportConfig.showFrame=false;
-	//reportConfig.width="300";
-	reportConfig.frame="none";
-	reportConfig.partConfig=new Object();
-	reportConfig.partConfig.width="300";
-	reportConfig.partConfig.title="R Report";
-	reportConfig.partConfig.reportName=obj.values[k];
-	for (f in obj.parameters){
-		reportConfig.partConfig[f]=pid[f];
-	}
-	reportConfig.partConfig.showSection="myscatterplot";
-	let reportWebPartRenderer = new LABKEY.WebPart(reportConfig);
-	print('Render to: '+reportConfig.renderTo);
-	reportWebPartRenderer.render();
-}
-
-
-function showProbability(cell,k,row,rowSetup,j,obj,pid){
-	print('showProbability: '+rowSetup);
-	let rowVariable=rowSetup.variable;	
-	cell.id='prob_'+obj.values[k]+"_"+rowVariable+pid[rowVariable];
-
-	let probDensity=new Object();
-	probDensity.mean=rowSetup.mean[j];
-	probDensity.sigma=rowSetup.sigma[j];
-
-	print('showProbability: mean '+probDensity.mean+' sigma '+probDensity.sigma);
-
-
-	probDensity.func=obj.values[k];
-	probDensity.organCode=pid.organCode;
-	pid[obj.variable]=rowSetup[obj.variable][j];
-	probDensity.percentile=pid.percentile;
-	let selectRows=new Object();
-	selectRows.queryName=obj.queryName;
-	selectRows.schemaName="study";
-	selectRows.filterArray=[];
-	selectRows.containerPath=getContainer('data');
-	for (let f in obj.filters){
-		selectRows.filterArray.push(
-				LABKEY.Filter.create(f,pid[obj.filters[f]]));
-		print('Filter ['+f+']: '+pid[obj.filters[f]]);
-	}
-	selectRows.success=function(data){
-		drawProbability(data,cell,obj,pid,probDensity);}
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function erf(x){
-	let fx=[0,0.02,0.04,0.06,0.08,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
-		1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,
-		2.1,2.2,2.3,2.4,2.5,3,3.5];
-	let fy=[0,0.222702589,0.328626759,0.428392355,0.520499878,
-		0.603856091,0.677801194,0.742100965,0.796908212,
-	 	0.842700793,0.880205070,0.910313978,0.934007945,
-		0.952285120,0.966105146,0.976348383,
-		0.983790459,0.989090502,0.992790429,0.995322265,
-		0.997020533,0.998137154,0.998856823,0.999311486,
-		0.999593048,0.999977910,0.999999257];
-	let n=32;
-	let i0=n-1;
-
-	for (let i=1;i<n;i++){
-		if (Math.abs(x)>fx[i]) continue;
-		i0=i-1;
-		break;
-	}
-	let fval=1;
-	if (i0<n-1){
-		//interpolate
-		let y1=fy[i0+1];
-		let y0=fy[i0];
-		let x1=fx[i0+1];
-		let x0=fx[i0];
-		fval=y0+(y1-y0)/(x1-x0)*(Math.abs(x)-x0);
-	}
-	print('Erf: '+fval);
-	if (x<0) return -fval;
-	return fval;
-}
-
-
-function setLine(fbox,name,value,fontSize){
-	let fpId=fbox.id+name;
-	let fp=config.document.getElementById(fpId);
-	if (fp===null){
-		fp=config.document.createElement("p");
-		fp.id=fpId;
-		fbox.appendChild(fp);
-	}
-	fp.classList.add("center");
-	fp.style.textAlign="center";
-	fp.style.fontSize=fontSize;
-	fp.innerText=value;
-}	
-
-function drawProbability(data,cell,obj,pid,probDensity){
-	print('drawProbability');
-	if (data.rows.length!=1){
-		print("drawProbability row length mismatch: "+data.rows.length);
-		return;
-	}
-	//possible mismatch; I assume the dataset will have a field called value
-	let val=data.rows[0].value;
-
-	let prob=0;
-	let fz=-100;
-
-	if (probDensity.func=="gaus"){
-		fz=(val-probDensity.mean)/probDensity.sigma/Math.sqrt(2);
-		prob=0.5+0.5*erf(fz);
-	}
-	let color="red";
-	let fzx=fz*Math.sqrt(2);
-	print('drawProbability '+fzx);
-
-	for (let i=1;i<obj.intervals.n;i++){
-		if (fzx>obj.intervals.zlimits[i]) continue;
-		color=obj.intervals.colors[i-1];
-		break;
-	}
-	
-	let fboxId=cell.id+'_fbox_';
-	let fbox=config.document.getElementById(fboxId);
-	if (fbox===null){
-		fbox=config.document.createElement("div");
-		fbox.id=fboxId;
-		cell.appendChild(fbox);
-	}
-	fbox.style.backgroundColor=color;
-	fbox.style.width="180px";
-	fbox.style.height="180px";
-	
-
-	print('organCode '+probDensity.organCode);
-	let organName="Lung";
-
-	if (probDensity.organCode==4){
-		organName="Thyroid";
-	}
-	if (probDensity.organCode==5){
-		organName="Bowel";
-	}
-
-	setLine(fbox,'_fp4_',organName,"16px");
-	setLine(fbox,'_fp_',val.toPrecision(3),"25px");
-	setLine(fbox,'_fp1_',"SUV("+probDensity.percentile+"%)","16px");
-	setLine(fbox,'_fp2_',fzx.toPrecision(3),"25px");
-	setLine(fbox,'_fp3_',"z-value","16px");
-
-
-}
-
-function generateReviewSection2(pid){ 
-	
-	let listName=config.loadFileConfig.listName;
-	let id=config.loadFileConfig.id;
-	
-	print('generateReviewSection2: '+pid.participantCode+'/'+
-		pid.visitCode);
-	if (pid.participantCode=="NONE" || pid.visitCode=="NONE"){
-		generateErrorMessage(id,listName,
-			"ParticipantId/visitId not set");
-		return;
-	}
-	
-
-	print('JSON: '+config.loadFileConfig.json);
-
-	let json=config.loadFileConfig.json;
-	let nrows=json.rows.values.length;
-	let ncol=json.columns.length;
-
-	pid.basePath=getBasePath()+"/@files";
-	
-	
-	let el=config.document.getElementById(id);
-	let tableId=id+'_Table';
-	let table=config.document.getElementById(tableId);
-	if (table==null){
-		table=config.document.createElement('table');
-		table.id=tableId;
-		el.appendChild(table);
-	}
-	table.style.tableLayout="fixed";
-	table.style.columnWidth="300px";
-	
-	for (let i=0;i<nrows;i++){
-		pid[json.rows.variable]=json.rows.values[i];
-		//let organ=organs[i];
-		let row=null;
-		if (i<table.rows.length)
-			row=table.rows[i];
-		else
-			row=table.insertRow();
-
-		let ic=0;
-		for (let j=0;j<ncol;j++){
-			let obj=json.columns[j];
-			let nv=obj.values.length;
-			for (let k=0;k<nv;k++){
-				let cell=null;
-				if (ic<row.cells.length)
-					cell=row.cells[ic];
-				else
-					cell=row.insertCell();
-				if (obj.display=="image") 
-					plotImage(cell,k,row,json.rows.variable,obj,pid);
-				if (obj.display=="report") 
-					showReport(cell,k,row,json.rows.variable,obj,pid);
-				if (obj.display=="probability"){ 
-					showProbability(cell,k,row,json.rows,i,obj,pid);
-				}	
-				ic++;
-			}
-
-
-		}
-		
-
-	}
-}
-
-///>>>>>>>>>>>>>>end of reviewSection(REPORT)
-
-function generateReview(divReviewId,divReviewListId, listName, accessMode){
-	let listId=config.formConfig.fields[listName].queryId;
-
-	//listId is a number->should it be queryName?
-	
-
-	let debug=true;
-	if (debug) print("Generate review for: "+listId+'/'+listName);
-	
-	let reviewSetup=generateSetup();
-	reviewSetup.readonlyFlag=function(vName){
-		if (vName=="queryName") return true; 
-		if (vName=="queryname") return true; 
-		if (vName=="ModifiedBy") return true;
-		return false;};
-	reviewSetup.addApply="Add Review";
-
-	let generateTableFlag=true;
-	let formStatus=config.formConfig.formStatus;
-	//COMMENTS allowed or not
-	//three levels of access: EDIT, COMMENT, READ
-	if (accessMode == "READ"){
-	//if (formStatus == "Approved" ){
-		delete reviewSetup.addApply;
-		reviewSetup.readonlyFlag=function(vName){return false;}
-		generateTableFlag=false;
-	}
-	
-	reviewSetup.filters=new Object();
-	reviewSetup.filters["crfRef"]=getCRFref();
-	
- 	reviewSetup.filters["queryName"]=listId;//entry in reviewComments list is queryname, all in small caps
-	//needs listName, in argument
-	
-	reviewSetup.getInputId=function(vName){return divReviewId+"_add"+vName};
-	reviewSetup.divReviewListId=divReviewListId;
-	reviewSetup.isReview=true;	
-
-	if (debug) {
-		let msg="Review: divId: "+divReviewId;
-		//msg+=" inputId: "+reviewSetup.getInputId;
-		print(msg);
-	}
-	updateListDisplay(divReviewListId,"reviewComments",reviewSetup.filters,true);
-
-	if (! generateTableFlag) return;
-
-	
-	generateTable("reviewComments",divReviewId,new Object(),reviewSetup);
-}	
-
-//>>>>>>>>>>trigger visibility of additional lists
-
-function setListVisibility(input,setup,readonlyFlag){
-	let debug=true;
-	let fName="[setListVisibility/"+setup.queryName+"]";
-	print(fName);
-	let additionalData=config.formConfig.additionalData[setup.queryName];
-	
-	let x = config.document.getElementById(additionalData.divName);
-	if (debug) print(fName+": Div: "+x);
-	x.style.display="none";
-
-	let sText;
-   if ("setVariable" in input){
-      sText=input.setVariable;
-   }
-	else{
-      if (readonlyFlag) sText=input.innerText;
-	   else sText=input.options[input.selectedIndex].text;
-   }
-   
-			
-	if (debug) print(fName+": Selected option text: "+sText);
-
-	if (sText == additionalData.showFlagValue){
-		let filters=new Object();
-		if ("filters" in additionalData) filters=additionalData.filters;
-		x.style.display = "block";
-		updateListDisplay(additionalData.divQueryName,
-			additionalData.queryName,filters,readonlyFlag);
-	}
-}
-
-//>>have list refresh when data is added (not optimal yet)
-
-function updateListDisplay(divName,queryName,filters,readonlyFlag){
-	//use Labkey.QueryWebPart to show list
-
-	let debug=true;
-	let fName="[updateListDisplay]";
-
-	if (debug) 
-		print(fName+": Query - "+queryName
-			+" div - "+divName);
-
-	if (divName=="NONE") return;
-  
-
-	let crfRef=getCRFref();
-	let div=config.document.getElementById(divName);
-   print(fName+": setting border");
-   div.style.border="thin solid black";
-   div.style.width="800px";
-
-	if (debug)
-		print(fName+": generating WebPart: "+queryName);
-	
-	var qconfig=new Object();
-	qconfig.renderTo=divName;
-	//point to data container
-	qconfig.containerPath=getContainer('data');
-	qconfig.schemaName='lists'; 
-	qconfig.queryName=queryName;
-	qconfig.buttonBarPosition='top';
-	qconfig.filters=[];
-	for (f in filters){
-		qconfig.filters.push(LABKEY.Filter.create(f, filters[f]));
-	}
-	qconfig.success=updateSuccess;
-	qconfig.failure=updateFailure;
-	//show only print button
-	if (readonlyFlag){
-		qconfig.buttonBar=new Object();
-		qconfig.buttonBar.items=["print"];
-	}
-
-	LABKEY.QueryWebPart(qconfig);
-	
-}
-
-function updateSuccess(data){
-	print("Update success");
-}
-
-function updateFailure(data){
-	print("Update failed");
-}
-
-
-function toggleVisibility(sectionId,buttonName){
-	let fName='[toggleVisibility/'+sectionId+']';
-	print(fName);
-
-	let x = config.document.getElementById(sectionId);
-	if (x.style.display === "none") {
-		//exclude non data sections (like debug)...
-		print(fName+': issuing setData(populateSection)');
-    		x.style.display = "block";
-		config.document.getElementById(buttonName).value="Hide";
-		let cb=function(){populateSection(sectionId);};
-		setData(cb);
-
-  	} else {
-    		x.style.display = "none";
-		config.document.getElementById(buttonName).value="Show";
-
-  	}
-}
-
-function generateButtonBU(divName,title,buttonName,callback,
-	callbackParameters){
-	let debug=true;
-	if (debug) print("generateButtonBU");
-	
-	let tb=config.document.createElement('table');
-	tb.className="t2";
-	
-	let r1=tb.insertRow();
-	th=config.document.createElement('th');
-	r1.appendChild(th);
-	th.innerHTML=title;
-	//*!*
-	let c2=r1.insertCell();
-	let i1=config.document.createElement("input");	
-	i1.type="button";
-	i1.value=buttonName;
-	i1.style.fontSize="20px";
-	i1.onclick=function(){callback(callbackParameters);}
-	c2.appendChild(i1);	
-
-	let c1=r1.insertCell();
-	c1.setAttribute("colspan","1");
-	c1.id=callbackParameters.submitReportId;
-
-	let el=config.document.getElementById(divName);
-	if (debug) print("generateButton: element["+divName+"]: "+el);
-	
-	
-	el.appendChild(tb);
-	
-	
-}
-
-function generateButton(divName,caption,label,callbackLabel,callback){
-	let debug=true;
-	if (debug) print("generateButtonX");
-	
-	let tb=config.document.createElement('table');
-	tb.className="t2";
-	
-	let r1=tb.insertRow();
-	th=config.document.createElement('th');
-	r1.appendChild(th);
-	th.innerHTML=caption;
-	//*!*
-	let c2=r1.insertCell();
-	let i1=config.document.createElement("input");	
-	i1.type="button";
-	i1.value=label;
-	i1.style.fontSize="20px";
-	i1.onclick=callback;
-	i1.id='button_'+callbackLabel;
-	c2.appendChild(i1);	
-
-	let c1=r1.insertCell();
-	c1.setAttribute("colspan","1");
-	//this is only for saveReview?
-	c1.id=divName+'_reportField';
-	//c1.id=config.submitReportId;
-
-	let el=config.document.getElementById(divName);
-	if (debug) print("generateButton: element["+divName+"]: "+el);
-	
-	
-	el.appendChild(tb);
-	
-	
-}
-
-function generateSubQuery(input, setup, readonlyFlag){
-	let fName="[generateSubQuery]";
-	if (setup.isReview) return;
-
-	if (!(setup.queryName in config.formConfig.additionalData)){
-		print(fName+': no additionalData entry (probably a subquery)');
-		return;
-	}
-
-	let additionalData=config.formConfig.additionalData[setup.queryName];
-	if (!("showFlag" in additionalData))
-		return;
-
-	print(fName);
-		
-	let expId=setup.getInputId(additionalData.showFlag);
-	if (expId!=input.id) {
-		print(fName+": ignoring field "+input.id+"/"+expId);
-		return;
-	}
-
-	print(fName+": Setting onChange to "+input.id);
-	if (!readonlyFlag)
-		input.onchange=function(){setListVisibility(input,setup,readonlyFlag)};
-}
-
-
-//>>populate fields
-//
-//
-//split to field generation and field population
-//
-function addFieldRow(tb,field,setup,additionalData){
-
-	let fName="[addFieldRow/"+setup.queryName+':'+field.name+']';
-
-	let vName=field.name;
-	let vType=field.type;
-	let isLookup=("lookup" in field);
-	print(fName+": ["+vName+"/"+vType+'/'+isLookup+"]");
-	
-	let row=tb.insertRow();
-	let cell=config.document.createElement('th');
-	row.appendChild(cell);
-	
-	let text = config.document.createTextNode(field.shortCaption);
-	cell.appendChild(text);
-	let cell1=row.insertCell();
-		
-	
-	let input=null;
-	cell1.colSpan="3";
-
-	let readonlyFlag=setup.readonlyFlag(vName);
-
-   print(fName+' inputType '+field.inputType);
-	//set the html input object
-	while (1){
-
-		if (readonlyFlag){
-			input=config.document.createElement('label');
-			input.innerText='Loading';
-			break;
-		}
-	
-
-		//lookup
-		if (isLookup){
-			input = config.document.createElement("select");
-			break;
-		}
-
-		//date
-		if (vType=="date"){ 
-			input = config.document.createElement("input");
-			input.type="date";
-			break;
-		}
-
-		//string
-		if (vType=="string"){
-			//we have to make sure UNDEF is carried to below
-			//since we are adapting file to either show
-			//current file or allow user to select a file
-			//
-			//TODO change this so one can always select file
-			//but also show the selected file
-
-			if(vName.search("reviewComment")>-1){
-				input = config.document.createElement("textarea");
-				input.cols="65";
-				input.rows="5";
-				break;
-			}
-
-         if (field.inputType=="textarea"){
-            input = config.document.createElement("textarea");
-            input.cols="65";
-            input.rows="5";
-            break;
-         }
-
-			input=config.document.createElement('input');
-			input.type="text";
-			
-			if (vName.search('_file_')<0) break;
-			cell1.setAttribute('colspan',"1");
-			let cell2=row.insertCell();
-			cell2.setAttribute('colspan',"2");
-			let input1=config.document.createElement('input');
-			input1.type="file";
-			input1.id=setup.getInputId(vName)+'_file_';
-			cell2.appendChild(input1);
-			break;
-				
-		}
-
-
-		if (vType=="float"){
-			input = config.document.createElement("input");
-			input.type="text";
-			break;
-		}	
-		
-		
-		if (vType=="boolean"){
-			input = config.document.createElement("input");
-			input.type="checkbox";
-			print("Creating checkbox");
-			break;
-		}
-		break;
-	}
-	
-	input.id=setup.getInputId(vName);
-	cell1.appendChild(input);
-	print(fName+': adding element '+input.id);
-	print(fName+': listing element '+config.document.getElementById(input.id));
-	
-
-	//connect associated list
-	generateSubQuery(input,setup,readonlyFlag);	
-
-	if (readonlyFlag) {
-		print(fName+': exiting(readonlyFlag)');
-		return;
-	}
-	
-	if (!isLookup) 	{
-		print(fName+': exiting (not lookup)');
-		return;
-	}
-
-	let lookup=field["lookup"];
-
-	//get all values from config.formConfig.lookup[X]
-	let lObject=config.formConfig.lookup[lookup.queryName];
-	
-	//debug
-	print(fName+": query: "+lookup.queryName);
-	print(fName+": ElementId: "+input.id);
-	print(fName+": No of options: " +lObject.LUT.length);
-	print(fName+": Element: "+input);
-
-	//set the lut value (input is text label) for readonly
-   input.style.textAlign="center";
-   //input.style.textAlignLast="center";
-
-   	//clear existing fields from input	
-	for(let i = input.options.length; i >= 0; i--) {
-		input.remove(i);
-   }
-	
-	//create option -1
-	let opt = config.document.createElement("option");
-	opt.text = "<Select>";
-	opt.value = -1;
-	input.options[0] = opt;
-	print(fName+": Adding <Select>");
-	
-
-	//add other, label them with LUT
-	for (let v in lObject.LUT) {
-		print(fName+': populating '+v+': '+lObject.LUT[v]);
-
-		let opt = config.document.createElement("option");
-		opt.text = lObject.LUT[v];
-		opt.value = v;
-		input.options[input.options.length] = opt;
-		
-	}
-	input.selectedIndex=0;	
-
-}
-
-function selectEntry(entryRows,setVariables){
-   let fName='[selectEntry]';
-   for (let i=0;i<entryRows.length;i++){
-      let tE=entryRows[i];
-      //this could be empty, end will be reached
-      let doContinue=false;
-      for (v in setVariables){
-         print(fName+' '+v+' '+tE[v]+'/'+setVariables[v]);
-         if (tE[v]!=setVariables[v]){
-            doContinue=true;
-            break;
-         }
-      }
-      if (doContinue) continue;
-		return tE;
-   }
-   let tE=Object();
-   tE['notValid']=true;
-   return tE;
-}
-
-
-
-function populateFieldRow(entry,field,setup){
-
-   if (!(field.name in setup.setVariables))
-	   populateField(entry,field,setup);
-	populateSubQuery(entry,field,setup);
-}
-
-function populateSubQuery(entry,field,setup){
-	let fName='[populateSubQuery/'+setup.queryName+':'+field.name+']';
-	if (setup.isReview) return;
-	
-	if (!(setup.queryName in config.formConfig.additionalData)){
-		let msg=fName+': no additionalData entry for '+setup.queryName;
-		msg+=' (probably a subquery)';
-		print(msg);
-		return;
-	}
-	//find if field is connected to a sub array
-	//find queryName
-	//
-	let additionalData=config.formConfig.additionalData[setup.queryName];	
-	print(fName);
-	//let flag=additionalData.showFlag;
-	
-	if (!("showFlag" in additionalData)) return;
-	let eId=setup.getInputId(additionalData.showFlag);
-	let id=setup.getInputId(field.name);
-	
-	if (eId!=id) {
-		print(fName+": X ignoring field "+id+"/"+eId);
-		return;
-	}
-	
-	print(fName+': id '+id);
-	//hard to estimate readonlyFlag
-	//
-   let readonlyFlag=setup.readonlyFlag(field.name);
-
-	let input=config.document.getElementById(id);
-   if (input){
-	   let eType=input.nodeName.toLowerCase();
-	   readonlyFlag=eType!="select";
-   }
-   else{
-      input=new Object();
-      input.setVariable=getLookupLabel(field,setup.setVariables[field.name])
-   }
-	setListVisibility(input,setup,readonlyFlag);
-
-}
-
-function getLookupLabel(field,value){
-   let lookup=field["lookup"];
-   //get all values from config.formConfig.lookup[X]
-   let lObject=config.formConfig.lookup[lookup.queryName];
-   return lObject.LUT[value];
-	
-}
-
-function populateField(entry,field,setup){
-
-	let vName=field.name;
-	let fName='[populateFieldName/'+vName+']';
-
-	let varValue="UNDEF";
-
-	//if (vName in setup.filters) varValue=setup.filters[vName];
-	if (vName in entry) varValue=entry[vName];
-	//if part of the filter, set it to value
-	if (vName in setup.filters) varValue=setup.filters[vName];
-	
-	let isLookup=("lookup" in field);
-	
-	print(fName+' v='+varValue+'/'+isLookup+' ['+
-		setup.getInputId(field.name)+']');
-	
-	let vType=field.type;
-	let id=setup.getInputId(vName);
-	let input=config.document.getElementById(id);
-
-		
-	//date
-	if (vType=="date"){
-		if (varValue==="UNDEF") varValue=new Date();
-		else varValue=new Date(varValue);
-	}
-	
-	//lookup for readonly
-	if (isLookup && varValue!="UNDEF"){
-      varValue=getLookupLabel(field,varValue);
-	}
-
-	print('Element: '+input);
-	//figure out the element type
-	let eType=input.nodeName.toLowerCase();
-	print('Element type: '+eType);
-   print('Value '+varValue);
-
-
-	//change varValue for printing
-	if (varValue=="UNDEF") varValue="";
-	//HTMLTextArea, createElement(textArea)
-	if (eType==="textarea"){
-		input.value=varValue;
-		return;
-	}
-	//Text, createTextNode
-	if (eType==="#text"){
-		input.nodeValue=varValue;
-		return;
-	}
-	//HTMLLabelElement, createElement('label')
-	if (eType==="label"){
-		input.innerText=varValue;
-		return;
-	}
-
-	//HTMLSelectElement, createElement('select')
-	if (eType==="select"){
-		input.selectedIndex=0;
-		for (let i=0;i<input.options.length;i++){
-			let v=input.options[i].text;
-			if (v!=varValue) continue;
-			input.selectedIndex=i;
-			break;
-		}
-		return;
-	}
-
-	if (eType!="input"){
-		print('Unknown type: '+eType+' encountered, igonring');
-		return;
-	}
-	
-	//HTMLInputElement
-	let type=input.type;
-
-	if (type=="date"){
-		input.valueAsDate=varValue;
-		return;
-	}
-	//string,float
-	if (type=="text"){
-		input.value=varValue;
-		return;
-	}
-	//boolean
-	if (type=="checkbox"){
-		input.checked=varValue;
-		return;
-	}
-	print('Unknown input type: '+type+'. Ignoring.');
-}
-
-
-function populateTable(listName,writeMode,setup){
-//function populateTable(formSetupEntry){
-	//let listName=config.formConfig.queryMap[formSetupEntry['queryName']];
-	//let accessMode=config.formConfig.operator+'Mode';
-	//let writeMode=formSetupEntry[accessMode]=='EDIT';
-
-	let fName='[populateTable/'+listName+']';
-   print(fName+' setup '+setup);
-	
-	//data snapshot
-	let fQuery=config.formConfig.dataQueries[listName];
-	
-	//here I assume that listName was parsed during setDataLayout and setData 
-	//so that rows was set (even if they are empty)
-	print(fName+"]: nrows "+fQuery.rows.length);
-	
-   //this makes sure that matching versus set variables is performed
-   //only entry with matching value of setVariable will be selected
-	let entry=selectEntry(fQuery.rows,setup.setVariables);
-
-	let fields=fQuery.fields;
-	let helpRows=new Array();
-
-	for (f in fields){	
-		let field=fields[f];
-		//each field is a new row
-		print(fName+": Adding field: "+f+'/'+field.name+' hidden: '+field.hidden);
-		if (field.hidden) continue;
-		if (field.name=="crfRef") continue;
-      populateFieldRow(entry,field,setup);
-	   let helpItem=getHelpItem(field,setup);
-      if (helpItem) helpRows.push(helpItem);
-	}
-
-   populateHelp(listName,helpRows,setup);
-
-}
-
-function getHelpVar(queryName,code,setup){
-   let fName='[getHelpVar]';
-   print(fName+' code '+code);
-   let subs=code.match(/_[^_]*_/g);
-   if (!subs){
-      print(fName+' no match for '+code);
-      return code;
-   }
-   let rpc=new Object();
-   for (let i=0;i<subs.length;i++){
-      let c=subs[i].replace(/_/g,'');
-      print(fName+' ['+i+'] '+c);
-      let qf=c.match(/\[[^\]]*\]/g);
-      let lField=undefined;
-      if (qf){
-         qf[0]=qf[0].replace(/[\[\]]/g,'');
-         lField=qf[0];
-         print(fName+' lField '+lField);
-      }
-      //drop field
-      c=c.replace(/\[[^\]]*\]/,'');
-      
-      //field in lookup (if not lookup.keyColumn)
-      //query
-      let query=queryName;
-      let vField=c;
-      let qq=c.split(':');
-      if (qq.length>1){
-         query=qq[0];
-         vField=qq[1];
-      }
-      
-      let value='';
-      if (vField in setup.setVariables){
-         value=setup.setVariables[vField];
-      }
-      else{
-         //robustify
-         if (!(query in config.formConfig.dataQueries)){
-            print(fName+' query '+query+' not available, check configuration');
-            return "INVALID";
-         }
-         if (config.formConfig.dataQueries[query].rows.length==0){
-            print(fName+' returning INVALID');
-            return "INVALID";
-         }
-         value=config.formConfig.dataQueries[query].rows[0][vField];
-      }
-      print(fName+' query '+query+' vField '+vField+' value '+value);
-      if (lField==undefined){
-         rpc[subs[i]]=value;
-         continue;
-      }
-      let fQuery=config.formConfig.dataQueries[query];
-      //variable vField must be a lookup
-      //let field=fQuery.fields[vField];
-      let field=undefined;
-      for (let f in fQuery.fields){
-         if (fQuery.fields[f].name==vField){
-            field=fQuery.fields[f];
-         }
-      }
-      let lookup=config.formConfig.lookup[field.lookup.queryName];
-
-      for (let j=0;j<lookup.rows.length;j++){
-         let o=lookup.rows[j];
-         if (o[lookup.keyColumn]==value){
-            rpc[subs[i]]=o[lField];
-            break;
-         }
-      }
-   }
-   for (let x in rpc){
-      code=code.replace(x,rpc[x]);
-   }
-   print(fName+' returning '+code);
-   return code;
-}
-
-function getHelpItem(field,setup){
-   if (!("help" in setup)) return undefined;
-
-   let fName='[getHelpItem]';
-   print(fName);
-
-   for (let i=0;i<setup["help"].rows.length;i++){
-      if (setup["help"].rows[i]["variable"]==field.name){
-         helpItem=new Object();
-         helpItem.setup=setup["help"].rows[i];
-         helpItem.field=field;
-         print(fName+' adding help for '+field.name);
-         return helpItem;
-      }
-   }
-   return undefined;
-}
-
-function generateHelp(tb,helpRows,setup){
-   let fName='[generateHelp]';
-   for (let i=0; i<helpRows.length; i++){
-      let eh=helpRows[i];
-      let row=tb.insertRow();
-      let th=config.document.createElement('th');
-      row.appendChild(th);
-      th.innerHTML=eh.setup['helpTitle']; 
-      let cell=row.insertCell();
-      cell.setAttribute('colspan','3');
-      let el=config.document.createElement('textarea');
-      //el.id=sectionId+'_help';
-      el.cols="70";
-      el.rows="10";
-      el.value="Loading";
-      el.id=setup.sectionId+"_help"+eh.setup['Key'];
-      print(fName+' creating '+el.id);
-      cell.appendChild(el);
-   }
-}
-
-function populateHelp(listName,helpRows,setup){
-   let fName='[populateHelp]';
-   print(fName);
-   for (let i=0; i<helpRows.length; i++){
-      let eh=helpRows[i];
-      let id=setup.sectionId+'_help'+eh.setup['Key']
-      let el=config.document.getElementById(id);
-      let lookup=eh.field['lookup'];
-      let qName=lookup.queryName;
-      let tLookup=config.formConfig.lookup[qName];
-      let varName=getHelpVar(listName,eh.setup['fieldDescriptor'],setup);
-      if (varName=="INVALID"){
-         el.value="Please select patient/timepoint";
-         continue;
-      }
-      let text="";
-      for (let j=0;j<tLookup.rows.length;j++){
-         //print(tLookup.rows[j][tLookup.keyColumn]+' '+tLookup.rows[j][tLookup.displayColumn]+
-         //' '+tLookup.rows[j][varName]);
-         text+=tLookup.rows[j][tLookup.displayColumn]+" - "+tLookup.rows[j][varName]+"\n";
-      }
-      print(fName+' setting '+id+': '+el);
-      el.value=text;
-   }
-}
-
-
-function generateTable(listName,divName,additionalData,setup){
-	let debug=true;
-	let fName="[generateTable/"+listName+"]";	
-	if (debug) print(fName);
-
-	//is listName and setup.queryName a duplicate of the same value
-	print(fName+': setup.queryName '+setup.queryName);	
-	//assume data is set in config.formConfig.dataQueries[data.queryName].rows;
-	
-
-
-	//data snapshot
-	let fQuery=config.formConfig.dataQueries[listName];
-
-	//here I assume that listName was parsed during setDataLayout and setData 
-	//so that rows was set (even if they are empty)
-	print(fName+": Nrows "+fQuery.rows.length);
-	
-	let entry=selectEntry(fQuery.rows,setup.setVariables);
-	
-	let tb=config.document.createElement('table');
-	tb.className="t2";
-	config.document.getElementById(divName).appendChild(tb);
-
-	//this are the fields (probably constant)
-	let fields=fQuery.fields;
-	let helpRows=new Array();
-
-	for (f in fields){
-		let field=fields[f];
-		//each field is a new row
-		print(fName+": Adding field: "+f+'/'+field.name);
-		if (field.hidden) continue;
-		if (field.name=="crfRef") continue;
-      //do not expose fields indicated in setVariables
-      if (field.name in setup.setVariables) continue;
-		addFieldRow(tb,field,setup,additionalData);
-		populateFieldRow(entry,field,setup);
-      let helpItem=getHelpItem(field,setup);
-      if (helpItem) helpRows.push(helpItem);
-	}
-
-   generateHelp(tb,helpRows,setup);
-   populateHelp(listName,helpRows,setup);
-   
-
-	//add comment field	
-	if (!("addApply" in setup)) {
-		print(fName+"generateTable: done");
-		return;
-	}
-	
-	let row=tb.insertRow();
-
-	let th=config.document.createElement('th');
-	row.appendChild(th);
-	th.innerHTML=setup.addApply; 
-	let cell=row.insertCell();
-	//cell.setAttribute("colspan","2");
-	let input=config.document.createElement("input");	
-	input.type="button";
-	input.value=setup.addApply;
-	cell.appendChild(input);	
-	let cell1=row.insertCell();
-	cell1.setAttribute("colspan","2");
-	cell1.id=setup.getInputId("rerviewLastSave");
-	cell1.innerHTML="No recent update";
-	//saveReview is a generic name for saving content of the html page to a list entry
-	input.onclick=function(){saveReview(listName,cell1.id,setup)};
-}	
-	
-function saveReview(queryName,elementId,setup){
-	//loads any queryName
-
-	let debug=true;
-	if (debug) print("saveReview: elementId "+elementId+" queryName "+queryName);
-	let useInsert=false;
-	
-	if (!("unique" in setup)) useInsert=true;
-
-	let fQuery=config.formConfig.dataQueries[queryName];
-
-   let entry=selectEntry(fQuery.rows,setup.setVariables);
-
-	if ("notValid" in entry) useInsert=true;
-
-	if (useInsert) entry=new Object();
-	
-	entry.crfRef=getCRFrefData();
-
-	if (debug) print("Set crfRef="+entry.crfRef);
-
-	//if ("queryName" in setup.filters) {
-	//	entry.queryName=setup.filters["queryName"];
-	//	if (debug) print("Setting queryName: "+entry.queryName);
-	//}
-
-	let fields=fQuery.fields;
-	for (f in fields){
-
-		let field=fields[f];
-		if (debug) print("saveReview field: "+field.name);
-		if (field.hidden) continue;
-		
-		let vName=field.name;
-		let vType=field.type;
-
-		if (debug) print("vType: "+vType);
-		
-		if (vName=="crfRef") continue;
-		//need to save queryName for reviewComments
-		
-		let eId=setup.getInputId(vName);
-		
-		let el=config.document.getElementById(eId);
-				
-		if (!el) {
-			if (debug) print("saveReview element: "+eId+" not found");
-			continue;
-		}
-		if (debug) print("saveReview element: "+eId);
-
-		
-		let eType=el.nodeName.toLowerCase();
-
-		if (eType==="select"){
-			entry[vName]=el.options[el.selectedIndex].value;
-			continue;
-		}
-	
-		if (eType==="td"){
-			entry[vName]=el.innerText;
-			continue;
-		}
-		
-		if (vType=="date"){
-			let date=el.valueAsDate;
-			if (date==="null") continue;
-			date.setUTCHours(12);
-			entry[vName]=date.toString();
-			print("Setting date to "+entry[vName]);
-			continue;
-		}
-
-		if (vType=="string"){
-			entry[vName]=el.value;
-			
-			if (vName.search('_file_')<0) 
-				continue;
-			
-			//upload file
-			let id1=eId+'_file_';
-			let input1=config.document.getElementById(id1);
-			print('Attachment field: '+input1.value);
-			//entry[vName]=el.files[0].stream();
-			let ctx=new Object();
-			ctx['dirName']='consent';
-			ctx['ID']=entry['crfRef'];
-			//should point to data container
-			ctx['project']=getContainer('data');
-			//need ID->crf!
-			//assume crfRef will get set before this
-			//element is encountered
-			uploadFile(input1,ctx);
-			let fv=el.value;
-			let suf=fv.split('.').pop();
-			entry[vName]=entry['crfRef']+'.'+suf;
-			continue;
-			
-		}	
-		if (vType=="float" || vType=="int"){
-			entry[vName]=el.value;
-			if (vName=="queryName") {
-				print('Parsing queryName: '+el.innerText);
-				entry[vName]=config.formConfig.fields[el.innerText].queryId;
-				//use queryMap lookup
-			}
-			continue;
-		}	
-		if (vType=="boolean"){
-			entry[vName]=el.checked;
-			continue;
-		}
-
-
-	}
-
-   //update values from setup.setVariables 
-   for (v in setup.setVariables){
-      entry[v]=setup.setVariables[v];
-   }
-	
-	let qconfig=new Object();
-	qconfig.rows=[entry];
-	//should point to data container
-	qconfig.containerPath=getContainer('data');
-	qconfig.schemaName='lists';
-	qconfig.queryName=queryName;
-
-	//only update comments
-	print("modifyRows: useInsert "+useInsert);
-	qconfig.success=function(data){updateLastSavedFlag(data,setup,elementId)};
-	if (!useInsert){
-		LABKEY.Query.updateRows(qconfig);
-	}
-	else{
-		LABKEY.Query.insertRows(qconfig);
-	}
-}
-
-function updateLastSavedFlag(data,setup,elementId){
-	let debug=true;
-	if (debug) print("Update last saved flag to "+elementId);
-	let el=config.document.getElementById(elementId);
-	let dt=new Date();
-	el.innerHTML="Last saved "+dt.toString();
-	if (data.queryName=="reviewComments"){
-		updateListDisplay(setup.divReviewListId,"reviewComments",setup.filters,true);
-	}	
-	//refresh stored data!
-	let writeMode=!setup.readonlyFlag();
-	if ("unique" in setup)
-		setData(function (){populateTable(data.queryName,writeMode,setup);});
-	if ("masterQuery" in setup){
-		let ad=config.formConfig.additionalData[setup.masterQuery];
-		print('Updating list display: '+setup.queryName+'/'+ad.queryName);
-		updateListDisplay(ad.divQueryName,ad.queryName,ad.filters,false);
-	}
-}
-
-//******************************************upload to database *********************
-
-
-function onDatabaseUpload(){
-	let fName='[onDatabaseUpload]';
-	print(fName);
-	config.upload=new Object();
-	//figure out the participantId
-	
-	let masterQueryId=config.formConfig.form["masterQuery"];
-	print(fName+': master query: '+masterQueryId);
-	let pidClass=new Object();
-	pidClass.afterId=afterParticipantId;
-	//use stored name of participantField 
-	//for migrating data from lists to study
-	//this is to avoid conflicts in column assignments
-	//since datasets contain all fields of a list plus
-	//default fields of which participantId is one
-	pidClass.participantField=config.registrationParticipantIdField;
-	let qconfig=new Object();
-	qconfig.queryName=config.formConfig.queryMap[masterQueryId];
-	//queryMap holds mapping for queries in visit; 
-	//masterQuery should be one of them, so this is safe.
-	qconfig.schemaName='lists';
-	qconfig.containerPath=getContainer('data');
-	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref())];
-	qconfig.success=function(data){afterRegistration(data,pidClass);};
-	LABKEY.Query.selectRows(qconfig);
-	//waitForCompleteUpload(config);//
-
-}
-
-function afterRegistration(data,fc){
-	let fName='[afterRegistration/'+data.queryName+']';
-	print(fName+": rows:"+data.rows.length);
-	fc.registration=data;
-	let registrationData=fc.registration;
-	clearErr();
-	if (registrationData.rows.length!=1){
-		let msg=fName+": ERROR: Found "+registrationData.rows.length;
-		msg+=" registration entries for crfrefid "+getCRFref();
-		print(msg);
-		fc.afterId(fc);
-		return;
-	}
-	print(fName+'registration participant field: '+fc.participantField);
-	fc.participantId=registrationData.rows[0][fc.participantField];
-	//could be a lookup field (particularly for studies)
-	print('ID: '+fc.participantId);	
-	let fields=registrationData.metaData.fields;
-	let field="NONE";
-	for (f in fields){
-		if (fields[f]["name"]==fc.participantField)
-			field=fields[f];
-	}
-	if ("lookup" in field){
-		let pid=fc.participantId;
-		print("Using lookup for participantId: "+pid);
-		let lookup=field["lookup"];
-		print("Lookup: ["+lookup.schemaName+','+lookup.queryName+']');
-		let qconfig=new Object();
-		//should point to data container
-		qconfig.containerPath=getContainer('data');
-		qconfig.schemaName=lookup.schemaName;
-		qconfig.queryName=lookup.queryName;
-		qconfig.filterArray=
-			[LABKEY.Filter.create(lookup.keyColumn,pid)];
-		qconfig.success=function(data){
-			afterRegistrationLookup(data,lookup.displayColumn,fc)};
-		LABKEY.Query.selectRows(qconfig);
-	}
-	else{
-		//afterParticipantId(configUpload);
-		fc.afterId(fc);
-	}
-}
-
-function afterRegistrationLookup(data,displayColumn,fc){
-	print("afterRegistrationLookup");
-	let entry=data.rows[0];
-	fc.participantId=entry[displayColumn];
-	print('Setting to '+fc.participantId);
-	fc.afterId(fc);
-	//afterParticipantId(configUpload);
-}
-
-
-function afterParticipantId(fc){
-	print("Setting participantId to "+fc.participantId);
-	config.upload.participantId=fc.participantId;
-	//another select rows to update all queries from setup
-	//just use registration for test
-	let formSetupRows=config.formConfig.formSetupRows;
-	config.upload.queries=new Array();
-	print("Form rows: "+formSetupRows.length);
-	for (let i=0;i<formSetupRows.length;i++){
-		let entry=formSetupRows[i];
-		//skip reviews
-		if (entry.showFlag=="REVIEW") continue;
-		//use lookup table to convert from id to name
-		let queryName=config.formConfig.queryMap[entry.queryName];
-		config.upload.queries.push({queryName:queryName,queryStatus:"QUEUED"});
-		print('form ['+i+']='+queryName+' '+entry.showFlag+'/'+entry.showQuery);
-		if (entry.showQuery=="NONE")
-			continue;
-		config.upload.queries.push({queryName:entry.showQuery,queryStatus:"QUEUED"});
-	}
-	//add reviews
-	config.upload.queries.push({queryName:"reviewComments",queryStatus:"QUEUED"});
-	config.upload.queryId=0;
-	copyToDataset();
-
-}
-
-
-
-function copyToDataset(){
-	let fName='[copyToDataset]: ';
-	print(fName+'['+config.upload.queryId+'/'+config.upload.queries.length+']');
-	//watch dog + scheduler
-	//
-
-	//watchdog part
-	if (config.upload.queryId==config.upload.queries.length) {
-		print(fName+'completing');
-		let targetStatus=config.formConfig.targetStatus['onDatabaseUpload'];
-		let targetRecipient=config.formConfig.targetRecipient['onDatabaseUpload'];
-		let action=new Object();
-		action.name='onDatabaseUpload';
-		action.cb=function(data){sendEmail(data,targetRecipient,redirect,'Form uploaded');}
-		updateFlag(targetStatus,action);//Approved
-		return;
-	}
-
-	//scheduler
-	let queryName=config.upload.queries[config.upload.queryId].queryName;
-	print("copyToDataset["+config.upload.queryId+"/"+
-			config.upload.queries.length+"]: "+queryName);
-	let qconfig=new Object();
-	qconfig.queryName=queryName;
-	qconfig.schemaName="lists";
-	qconfig.containerPath=getContainer('data');
-	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref())];
-	qconfig.success=afterListData;
-	LABKEY.Query.selectRows(qconfig);
-}
-
-function afterListData(data){
-	let fName='[afterListData]: ';
-
-	let queryName=config.upload.queries[config.upload.queryId].queryName;
-	print(fName+" ["+queryName+"/list]: "+data.rows.length+" entries");
-	config.upload.queries[config.upload.queryId].listData=data;
-	let id=config.upload.participantId;
-
-	let qconfig=new Object();
-	qconfig.queryName=queryName;
-	qconfig.schemaName="study";
-	qconfig.containerPath=getContainer('data');
-	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref())];
-	qconfig.filterArray.push(LABKEY.Filter.create('ParticipantId',id));
-	qconfig.success=afterStudyData;
-	LABKEY.Query.selectRows(qconfig);
-}
-
-
-function afterStudyData(data){
-
-	let fName='[afterStudyData]: ';
-	let queryObj=config.upload.queries[config.upload.queryId];
-	queryObj.studyData=data;
-
-	let msg=fName+"["+queryObj.queryName+"/study]: "+data.rows.length+" entries";
-	print(msg);
-	
-
-	let listRows=queryObj.listData.rows;
-	//skip uploading an empty set
-	if (listRows.length==0){
-		printErr("List "+queryObj.queryName+" empty.");
-		queryObj.queryStatus="DONE";
-		config.upload.queryId+=1;
-		//back to watchdog
-		copyToDataset();
-		return;
-	}
-	
-
-	let studyRows=queryObj.studyData.rows;
-
-	for (let i=0;i<studyRows.length;i++){
-		let entry=studyRows[i];
-		//
-		if (! (i<listRows.length) ) continue;
-		let entryList=listRows[i];
-		//keeps study only variables (ParticipantId, SequenceNum)
-		for (let f in entryList) {
-			entry[f]=entryList[f];
-			print(fName+"Copying ["+f+"]: "+entry[f]+"/"+entryList[f]);
-		}
-	}
-	print(fName+' copying completed');
-
-	if (studyRows.length>0) {
-		let qconfig=new Object();
-		qconfig.queryName=queryObj.queryName;
-		qconfig.schemaName="study";
-		qconfig.rows=studyRows;
-		qconfig.containerPath=getContainer('data');
-		qconfig.success=afterStudyUpload;
-		LABKEY.Query.updateRows(qconfig);
-		print(fName+'updateRows sent');
-
-	}
-	else{
-		let data=new Object();
-		data.rows=new Array();
-		afterStudyUpload(data);
-	}
-}
-
-function afterStudyUpload(data){
-	let fName='[afterStudyUpload] ';
-	print(fName);
-	//let participantField=config.participantField;
-	let participantField=config.formConfig.studyData["SubjectColumnName"];
-	print(fName+' participantField: '+participantField);
-
-	let queryObj=config.upload.queries[config.upload.queryId];
-	let queryName=queryObj.queryName;
-	printErr("Updated "+data.rows.length+" rows to "+queryName);
-	
-	let studyRows=queryObj.studyData.rows;
-	let listRows=queryObj.listData.rows;
-	
-	let rows=new Array();
-	//also updating existing rows, if they exist
-	for (let i=studyRows.length;i<listRows.length;i++){
-		let entry=listRows[i];
-		//make sure you have the participantField right
-		//
-		entry[participantField]=config.upload.participantId;
-		entry.crfRef=getCRFref();
-		entry.SequenceNum=getCRFref();
-		entry.SequenceNum=entry.SequenceNum % 1000000000;
-		
-		if (listRows.length>1){
-			entry.SequenceNum+=i/100;
-		}
-		print( "Adding sequence number "+entry.SequenceNum);
-		rows.push(entry);
-	}
-	if (rows.length>0){
-
-		let qconfig=new Object();
-		qconfig.queryName=queryName;
-		qconfig.schemaName="study";
-		qconfig.containerPath=getContainer('data');
-		qconfig.success=afterListUpload;
-		qconfig.rows=rows;
-		LABKEY.Query.insertRows(qconfig);
-	}
-	else{
-		let data=new Object();
-		data.rows=rows;
-		afterListUpload(data);
-	}
-			
-}
-
-function afterListUpload(data){
-	
-	let queryObj=config.upload.queries[config.upload.queryId];
-	let queryName=queryObj.queryName;
-	printErr("Inserted "+data.rows.length+" rows to "+queryName);
-	queryObj.queryStatus="DONE";
-	config.upload.queryId+=1;
-	copyToDataset();
-
-}
-
-
-
-
-//*************************update for further review *************************
-
-function onUpdateForReview(){
-	let targetStatus=config.formConfig.targetStatus['onUpdateForReview'];
-	let targetRecipient=config.formConfig.targetRecipient['onUpdateForReview'];
-	let action=new Object();
-	action.name='onUpdateForReview';
-	action.cb=function(data){sendEmail(data,targetRecipient,redirect,'Form updated for review');};
-
-	updateFlag(targetStatus,action);
-}
-
-function updateFlag(flag,action){
-	let qconfig=new Object();
-	qconfig.schemaName='lists';
-	qconfig.queryName='crfEntry';
-	qconfig.containerPath=getContainer('data');
-	qconfig.success=function(data){setFlag(data,flag,action);}
-	qconfig.filterArray=[LABKEY.Filter.create("entryId",getCRFref())];
-	LABKEY.Query.selectRows(qconfig);
-}
-
-function setFlag(data,flag,action){
-	let fName='[setFlag]';
-	let debug=true;
-	if (data.rows.length!=1){
-		let msg=fName+": ERROR: Found "+data.rows.length;
-		msg+=" entries for crfrefid "+getCRFref();
-		print(msg);
-		return;
-	}
-	let entry=data.rows[0];
-	entry.FormStatus=flag;
-	let uId=config.formConfig.currentUser.UserId;
-	entry[config.formConfig.operator]=uId;
-
-	print(fName+': Form: '+entry.Form);
-	print(fName+": set form status to "+entry.FormStatus);
-	
-	let qconfig=new Object();
-	qconfig.schemaName='lists';
-	qconfig.queryName='crfEntry';
-	qconfig.containerPath=getContainer('data');
-	qconfig.rows=[entry];
-	//qconfig.success=function(data){completeWithFlag(data,flag);}
-	qconfig.success=function(data){completeWithFlag(data,action);};
-	LABKEY.Query.updateRows(qconfig);
-	
-}
-
-function completeWithFlag(data,action){
-	let fName='[completeWithFlag]';
-	print(fName+': nrows '+data.rows.length);
-
-	let fentry=data.rows[0];
-	print(fName+': form status '+fentry.FormStatus);
-	print(fName+': form '+fentry.Form);
-
-	let entry=new Object();
-	entry.entryId=getCRFref();
-	entry.submissionDate=new Date();
-	entry.FormStatus=fentry.FormStatus;
-	entry.User=config.formConfig.currentUser.UserId;
-	entry.Form=fentry.Form;
-	entry.operator=config.formConfig.operator;
-	entry.action=action.name;
-
-	let qconfig=new Object();
-	qconfig.schemaName='lists';
-	qconfig.queryName='crfStatus';
-	qconfig.containerPath=getContainer('data');
-	qconfig.rows=[entry];
-	//qconfig.success=function(data){completeWithFlag(data,flag);}
-	qconfig.success=action.cb;
-	LABKEY.Query.insertRows(qconfig);
-
-}
-
-//************************************************ submit *******************************************
-
-function onSubmit(){
-	//update list storage and change status
-
-	let debug=true;
-	hideErr();
-	clearErr();
-	printErr("onSubmit");
-
-	setData(verifyData);
-	
-
-
-}
-
-function verifyData(){
-	let queries=config.formConfig.dataQueries;
-	for (q in queries){
-		let qData=queries[q];
-		if (q=="reviewComments") continue;
-		//if it doesn't have additionalData, it is a sub query
-		if (!(q in config.formConfig.additionalData))
-			continue;
-		if (qData.rows.length<1){
-			printErr('Missing entry for query '+q);
-			return false;
-		}
-	}
-	let targetStatus=config.formConfig.targetStatus['onSubmit'];	
-	let targetRecipient=config.formConfig.targetRecipient['onSubmit'];
-	print('verifyStatus: targetStatus: '+targetStatus);
-	let fName='verifyStatus';
-	//useful for debug
-	//let finalStep=doNothing;
-	//production mode
-	let finalStep=redirect;
-	
-	let action=new Object();
-	action.name='onSubmit';
-	action.cb=function(data){sendEmail(data,targetRecipient,finalStep,'Form sumbitted');};
-	updateFlag(targetStatus,action);
-}
-
-function getEmail(recipientCode){
-
-	print('getEmail w/'+recipientCode);
-	let recipients=new Array();
-	let typeTo=LABKEY.Message.recipientType.to;
-	let create=LABKEY.Message.createRecipient;
-	let currentUser=config.formConfig.currentUser;
-	let formCreator=config.formConfig.formCreator;
-	let currentSite=config.formConfig.currentSite;
-	let userRows=config.formConfig.userRows;
-	let parentUser=undefined;
-	if ("parentCrfData" in config.formConfig){
-		let parentCrf=config.formConfig.parentCrfData;
-		parentUser=getUser(parentCrf.rows[0].UserId,'parentUser');
-	}
-	
-
-	let recipientCategories=recipientCode.split(',');
-	for (let i=0;i<recipientCategories.length;i++){
-
-		let recipient=recipientCategories[i];
-		print('Checking '+recipient);
-		if (recipient=='crfEditor'){
-			print('Adding :'+formCreator.Email);
-			recipients.push(create(typeTo,formCreator.Email));
-			if (parentUser==undefined) continue;
-			print('Adding :'+parentUser.Email);
-			recipients.push(create(typeTo,parentUser.Email));
-			continue;
-		}
-		//Monitor or Sponsor
-		let fList=recipient+'s';
-		let fRows=config.formConfig[fList];
-		for (let i=0;i<fRows.length;i++){
-			print('Checking '+fRows[i].User+'/'+fRows[i].Site);
-			if (fRows[i].Site!=currentSite.siteNumber) continue;
-			for (let j=0;j<userRows.length;j++){
-				if (userRows[j].UserId!=fRows[i].User) continue;
-				print('Adding :'+userRows[j].Email);
-				recipients.push(create(typeTo,userRows[j].Email));
-				break;
-			}
-		}
-	}
-
-	return recipients;
-}
-
-function sendEmail(data,recipient='crfEditor',cb=redirect,subj='Form submitted'){
-
-	print('sendEmail; recipient: '+recipient);
-
-	let st=config.formConfig.settings;
-	let cvar='sendEmail';
-	if (cvar in st){
-		print(cvar+' set to '+st[cvar]);
-		if (st[cvar]=='FALSE'){
-			print('Skipping sending emails');
-			redirect();
-			return;
-		}
-	}
-	
-	print('send email '+data.rows.length);
-	let crf=data.rows[0]['entryId'];
-	let formId=data.rows[0]['Form'];
-	let link=LABKEY.ActionURL.getBaseURL();
-	link+=LABKEY.ActionURL.getContainer();
-	link+='/crf-visit.view?';
-	link+='entryId='+crf;
-	link+='&formId='+formId;
-	link+='&role='+recipient;
-
-	//debug
-	let recipients=getEmail(recipient);
-	//from crfManagers list
-	
-	let typeHtml=LABKEY.Message.msgType.html;
-	let typePlain=LABKEY.Message.msgType.plain;
-	let msg1=LABKEY.Message.createMsgContent(typePlain,link);
-
-	//let cb=doNothing;
-	//let cb=redirect;
-	LABKEY.Message.sendMessage({
-		msgFrom:'labkey@fmf.uni-lj.si',
-		msgSubject:subj,
-		msgRecipients:recipients,
-		msgContent:[msg1],
-		success: cb
-	});
-
-}
-
-function hideErr(){
-	let el=config.document.getElementById("errorDiv");
-	el.style.display="none";
-}
-
-function clearErr(){
-	let el=config.document.getElementById("errorTxt");
-	el.value="";
-}
-
-function showErr(){
-	let el=config.document.getElementById("errorDiv");
-	el.style.display="block";
-}
-
-function printErr(msg){
-	showErr();
-	el=config.document.getElementById("errorTxt");
-	el.style.color="red";
-	el.value+="\n"+msg;
-}
-
-
-//**************************************************
-//
-function onRemoveCRF(){
-	let debug=true;
-
-	if (debug){
-		print("Removing CRF");
-	}
-
-	let selectRows=new Object();
-	//points to data container
-	selectRows.containerPath=getContainer('config');
-	selectRows.schemaName="lists";
-	selectRows.queryName="inputLists";
-	selectRows.success=afterInputLists;
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function afterInputLists(data){
-	let debug=true;
-	if (debug)
-		print("After input lists");
-	config.inputLists=data;
-	config.inputListsIterator=0;
-
-	removeCRFLoop();
-}
-
-function removeCRFLoop(){
-	let debug=true;
-
-	let i=config.inputListsIterator;
-	let iMax=config.inputLists.rows.length;
-	//in fact, we are adding two additional passages of the loop, one for 
-	//crfEntry, the second for the same query, but using parentCrf as the 
-	//selection variable
-	let iTotal=iMax+1;
-	//let iTotal=iMax+1;
-	
-	if (debug)
-		print("removeCRFLoop ["+i+"/"+iMax+"]");
-
-	if (i>iTotal){
-		if (0) return;
-		redirect();
-	}
-	let queryName="crfEntry";
-	let idVar="entryId";
-	let idValue=getCRFref();
-	
-	if (i<iMax){
-		//in all but crfEntry, variable is called crfRef
-		queryName=config.inputLists.rows[i].queryName;
-		idVar="crfRef";
-	}
-	//for i=iMax and i=iMax+1, query is crfEntry.
-
-	//delete also crfEntries where parentCrf is set to crf that we are deleting
-	if (i==iTotal){
-		idVar='parentCrf';
-	}
-	
-	if (debug)
-		print("["+i+"/"+iMax+"] "+queryName+":"+idVar+'/'+idValue);
-
-	let selectRows=new Object();
-	//points to data container
-	selectRows.containerPath=getContainer('data');
-	selectRows.schemaName="lists";
-	selectRows.queryName=queryName;
-	selectRows.filterArray=[LABKEY.Filter.create(idVar,idValue)];
-	selectRows.success=removeListCRF;
-	selectRows.failure=skipListCRF;
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function removeListCRF(data){
-	let debug=true;
-
-	if (debug)
-		print(data.queryName+": "+data.rows.length);
-
-	config.inputListsIterator+=1;
-	
-	if (data.rows.length==0){
-		removeCRFLoop();
-		return;
-	}
-
-	let deleteRows=new Object();
-	//points to data container
-	deleteRows.containerPath=getContainer('data');
-	deleteRows.schemaName=data.schemaName;
-	deleteRows.queryName=data.queryName;
-	deleteRows.success=function(data){removeCRFLoop()};
-	deleteRows.rows=data.rows;
-	LABKEY.Query.deleteRows(deleteRows);
-	
-}
-
-function skipListCRF(errorInfo){
-	let debug=true;
-
-	if (debug)
-		print("Error in removeCRF: "+errorInfo.exception);
-
-	config.inputListsIterator+=1;
-	
-	removeCRFLoop();
-	
-}
-
-
-
-function redirect(){
-
-	let debug=false;
-	let formUrl="begin";
-	let params=new Object();
-	params.name=formUrl;
-	params.pageId="CRF";
-
-	//points to crf container
-	let containerPath=getContainer('CRF');
-        
-	// This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-        
-	var homeURL = LABKEY.ActionURL.buildURL(
-			"project", formUrl , containerPath, params);
-        print("Redirecting to "+homeURL);
-	if (debug) return;	 
-	window.location = homeURL;
-
-	
-
-}
-
-//printing section
-
-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 printForm(){
-
-	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");
-	printHeader();
-	setData(formatPrintData);
-}
-
-function printHeader(){
-	config.doc.fontSize(25).text(config.formConfig.form['formName']);
-	config.doc.moveDown();
-	let crfEntry=config.formConfig.crfEntry;
-	let site=config.formConfig.currentSite;
-	let val=new Object();
-	let user=config.formConfig.user;
-	val['A']={o:crfEntry,f:'EudraCTNumber',t:'Eudra CT Number'};
-	val['B']={o:crfEntry,f:'StudyCoordinator',t:'Study Coordinator'};
-	val['C']={o:crfEntry,f:'StudySponsor',t:'Study Sponsor'};
-	val['D']={o:site,f:'siteName',t:'Site'};
-	val['E']={o:site,f:'sitePhone',t:'Phone'};
-	val['F']={o:user,f:'DisplayName',t:'Investigator'};
-
-	for (let f in val){
-		print('Printing for '+f);
-		let e=val[f];
-		let entry=new Object();
-		entry[f]=e.o[e.f];
-		printPDF(entry,
-			{name:f,caption:e.t,type:'string'},null);
-	}
-	config.doc.moveDown();
-}
-
-function formatPrintData(){
-	qS=config.formConfig.dataQueries;
-	for (let q in qS){
-		print('Setting up '+q);
-		let qData=qS[q];
-		print('Number of rows: '+qData.rows.length);
-		if (qData.rows.length>0){
-			config.doc.fontSize(20).text(qData.title);
-		}
-		for (let i=0;i<qData.rows.length;i++){
-			let entry=qData.rows[i];
-		       	for (let f in qData.fields){
-				let field=qData.fields[f];
-				let lookup=null;
-				if (field.lookup){
-					lookup=config.formConfig.lookup[field.lookup.queryName];
-				}
-				if (field.hidden) continue;
-				printPDF(entry,field,lookup);
-			}
-		}
-		config.doc.moveDown();
-	}
-	print("All done");
-	config.doc.end();
-}
-
-function printPDF(entry,field,lookup){
-	//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+']='+entry[field.name]);
-	let v=entry[field.name];
-	if (lookup!=null){
-		v=lookup.LUT[v];
-	}
-	print('printPDF: field type:'+field.type);
-	if (field.type=="date"){
-		let d=new Date(v);
-		v=d.getDate()+'/'+(d.getMonth()+1)+'/'+d.getFullYear();
-	}	
-	if (v===null) v=' / ';
-	if (v===undefined) v=' / ';
-
-	//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;
-	
-	config.doc.font('Courier-Bold').text(v,opt);
-
-	//restore x value
-	config.doc.x=tx;
-	
-}
-
-
-//master section, entry point from html files
-
-function generateMasterForm(){
-
-	generateDebugSection();
-	//read enviroment from lists disperesed on labkey
-	setFormConfig();
-}
-
-
-//helper function to set basic parameters on web page 
-//(fields defined in html file)
-function populateBasicData(){
-
-	config.document.getElementById('version').innerText=
-      config.formConfig.softwareVersion;	
-	config.document.getElementById('eudraCTNumber').innerText=
-		config.formConfig.crfEntry.EudraCTNumber;
-	config.document.getElementById('studyCoordinator').innerText=
-		config.formConfig.crfEntry.StudyCoordinator;
-	config.document.getElementById('studySponsor').innerText=
-		config.formConfig.crfEntry.StudySponsor;
-	config.document.getElementById('siteName').innerText=
-		config.formConfig.currentSite['siteName'];
-	config.document.getElementById('sitePhone').innerText=
-		config.formConfig.currentSite['sitePhone'];
-	config.document.getElementById('investigatorName').innerText=
-		config.formConfig.user['DisplayName'];
-   let h1=config.formConfig.form['formName'];
-   config.document.getElementById('formTitle').innerText=h1;
-   print('Setting title to '+h1);
-
-}
-
-
-//come here after the layout is read from labkey page
-//
-function generateErrorMsg(msg){
-	let txt=config.document.createElement('p');
-	txt.innerText=msg;
-	config.document.getElementById(config.masterForm).appendChild(txt);
-	generateButton("submitDiv",'Exit','Exit','redirect',redirect);
-}
-
-function getUser(id,field){
-	if (field in config.formConfig) return config.formConfig[field];
-	let uRows=config.formConfig.userRows;
-	for (let i=0;i<uRows.length;i++){
-		let userId=uRows[i].UserId;
-		if (userId!=id) continue;
-		config.formConfig[field]=uRows[i];
-		return config.formConfig[field];
-	}
-	return null;
-}	
-
-
-function afterConfig(){
-
-	let debug=true;
-
-	if (debug)
-		print("afterConfig");	
-
-	populateBasicData();
-	
-	//check if user has permission on the form
-	let currentUser=getUser(LABKEY.Security.currentUser.id,'currentUser');
-	let currentSite=config.formConfig.currentSite;
-	let formCreator=getUser(config.formConfig.crfEntry.UserId,'formCreator');
-	let formCreatorId=formCreator.UserId;
-
-
-
-	//let formSite=config.formConfig.crfEntry.Site;
-	let fList=config.formConfig.operator+'s';
-	let fRows=config.formConfig[fList];
-	//let currentSiteId=-1;
-	
-	//depending on operator mode, we should decide what is right
-	let operator=config.formConfig.operator;
-	if (operator=='crfEditor'){
-		//editor can only edit its own forms
-		if (currentUser.UserId!=formCreatorId){
-			let msg='User '+currentUser.DisplayName;
-			msg+=' has no permission on this form';
-			generateErrorMsg(msg);
-			return;
-		}
-	}
-	if (operator=='crfMonitor' || operator=='crfSponsor'){
-		//monitor can look at forms based on his site
-		//find monitor line
-		let operatorSites=new Array();
-		for (let i=0;i<fRows.length;i++){
-			if (fRows[i].User!=currentUser.UserId) continue;
-			operatorSites.push(fRows[i].Site);
-		}
-		print('operator Site: '+operatorSites.length);
-		if (operatorSites.length==0){
-			let msg='User '+currentUser.DisplayName;
-			msg+=' is not a '+operator;
-			generateErrorMsg(msg);
-			return;
-		}
-
-		let selectedSite=-1;
-		let siteCandidates="[";
-		for (let i=0;i<operatorSites.length;i++){
-			if (i>0) siteCandidates+=", ";
-			siteCandidates+=operatorSites[i];
-			if (operatorSites[i]!=currentSite.siteNumber) continue;
-			selectedSite=currentSite.siteNumber;
-			break;
-		}
-		siteCandidates+="]";
-		if (selectedSite==-1){
-			let msg='User '+currentUser.DisplayName;
-			msg+=' is not a '+operator+' for site ';
-			msg+=currentSite.siteName+'('+currentSite.siteNumber+')';
-			msg+='/'+siteCandidates;
-			generateErrorMsg(msg);
-			return;
-		}
-	}
-
-
-	print('User '+currentUser.DisplayName+'/'+
-		config.formConfig.currentSite['siteName']+
-		' acting as '+config.formConfig.operator);	
-
-
-	let rows=config.formConfig.crfButtons.rows;
-	config.formConfig.targetStatus=new Array();
-	config.formConfig.targetRecipient=new Array();
-
-	for (let i=0; i<rows.length; i++){
-		let action=rows[i].action;//String
-		let tstatus=rows[i].targetFormStatus;
-		let trecip=rows[i].targetRecipient;
-		config.formConfig.targetStatus[action]=tstatus;
-		config.formConfig.targetRecipient[action]=trecip;
-	}
-	let formStatus=config.formConfig.formStatus;
-
-	//let functionArray=new Array();
-
-	print("Generating buttons for formStatus \""+ formStatus+"\"");
-
-	let buttonRows=config.formConfig.crfButtons.rows;
-	for (let i=0;i<buttonRows.length;i++){
-		let bt=buttonRows[i];
-		if (typeof window[bt.action]==="function"){
-			generateButton("submitDiv",bt.caption,bt.label,bt.action,
-				window[bt.action]);
-		}
-		else{
-			print('No match for function :'+bt.action+
-				' obj: '+window[bt.action]);
-		}
-	}
-
-	print('Here');
-
-
-	//here we should get data. For now, just initialize objects that will hold data
-	setDataLayout(afterDataLayout);//callback is afterDataLayout
-}
-	
-function afterDataLayout(){
-
-	setData(afterData);//callback is afterData
-}
-
-function afterData(){
-	let fName='afterData';
-	//operatorBasedAccessMode	
-	let accessMode=config.formConfig.operator+'Mode';
-	let rowsSetup=config.formConfig.formSetupRows;
-   print(fName+' list of sections');
-	for (let i=0;i<rowsSetup.length;i++){
-		let entry=rowsSetup[i];
-		let queryName=config.formConfig.queryMap[entry['queryName']];
-      print(fName+'\t'+queryName);
-   }	
-	for (let i=0;i<rowsSetup.length;i++){
-		let entry=rowsSetup[i];
-		let queryName=config.formConfig.queryMap[entry['queryName']];
-		print(fName+" ["+queryName+"]: showFlag: "+entry["showFlag"]);
-		print(fName+" ["+queryName+"]: accessMode: "+entry[accessMode]);
-
-		const nData=config.formConfig.dataQueries[queryName].rows.length;
-		
-		print(fName+" ["+queryName+"]: nData: "+nData);
-
-
-		//skip sections
-		//also from fields
-		if (entry[accessMode]=="NONE") continue;
-		//skip readonly empty records
-		//if (entry[accessMode]=="READ" && nData==0) continue;
-			
-		//let additionalData=new Object();
-		//setAdditionalData(additionalData,entry);
-		//section fits one dataset/list
-		generateSection(entry);
-		//generateSection(queryName,entry["title"],entry[accessMode], 
-		//		additionalData);
-	}
-
-}
-
-function findSetupRow(sectionId){
-	let rowsSetup=config.formConfig.formSetupRows;
-   let key=sectionId.replace('section','');
-	for (let i=0;i<rowsSetup.length;i++){
-		let e=rowsSetup[i];
-		//let queryName1=config.formConfig.queryMap[e['queryName']];
-		if (e.formName!=config.formId) continue;
-      if (e['Key']==key) return e;
-		//if (queryName1!=queryName) continue;
-	}
-	return null;
-}
-
-function populateSection(sectionId){
-   //queryName should be found from setup
-	let fName='[populateSection/'+sectionId+']';
-	print(fName);
-
-	let entry=findSetupRow(sectionId);
-	//ignore names without associated entry in formSetup
-	if (entry==undefined){
-		print(fName+': no matching FormSetup entry found');
-		return;
-	}
-  
-   let queryName=config.formConfig.queryMap[entry['queryName']];
-	//populate comes after generate, we should be pretty safe in taking
-	//already generated additionalData
-	
-	if (!(queryName in config.formConfig.additionalData)){
-		print(fName+': no additionalData generated for '+queryName);
-		return;
-	}
-	
-	let additionalData=config.formConfig.additionalData[queryName];
-	print(fName+': using additionalData '+additionalData);
-	if ("isReview" in additionalData){
-		generateReviewSection(queryName,queryName,generateReviewSectionCB);
-		return;	
-	}
-
-	let accessMode=config.formConfig.operator+'Mode';
-	let aM=entry[accessMode];
-	print(fName+': accessMode '+aM);
-
-
-	if (aM!='GENERATE'){
-		let writeMode=(aM=='EDIT');
-      print(fName+': writeMode '+writeMode);
-      let setup=getSetup(sectionId,queryName,writeMode);
-      setup.setVariables=parseVariableDefinition(entry);
-      setHelp(setup,entry);
-		populateTable(queryName,writeMode,setup);
-		return;
-	}
-
-	//deal with generate
-	//
-	//already available -> shift to READ mode
-	let divTable=sectionId+'Table';
-	let divObj=config.document.getElementById(divTable);
-	let divRev=config.document.getElementById(sectionId+'Review');
-	let divRLi=config.document.getElementById(sectionId+'ReviewList');
-	let divGBu=config.document.getElementById(sectionId+'GenerateButton');
-
-	print('div GBU: '+divGBu);
-	divObj.style.display="block";
-	divRev.style.display="block";
-	divRLi.style.display="block";
-	if (divGBu!=undefined) divGBu.style.display="none";
-
-	let nData=config.formConfig.dataQueries[queryName].rows.length;
-	print('['+queryName+']: nrows '+nData);
-	if (nData>0){
-      let setup=getSetup(sectionId,queryName,false);
-      setup.setVariables=parseVariableDefinition(entry);
-      //this fails for setVariables, although they are available via entry['variableDefinition']
-		populateTable(queryName,false,setup);
-		return;
-	}
-	//hide table
-	divObj.style.display="none";
-	divRev.style.display="none";
-	divRLi.style.display="none";
-	if (divGBu!=undefined) divGBu.style.display="block";
-	//add buttons?
-	//is button already generated?
-	
-	//populateTable(entry);
-	
-}		
-
-//*******    generateQuery infrastructure *********************
-
-function onGenerateQuery(queryName){
-	print('onGenerateQuery '+queryName);
-//
-	let cfgRows=config.formConfig.generateConfigData.rows;
-//	//queryName to queryId?
-	let queryId=config.formConfig.fields[queryName].queryId;
-	let cfgRow=undefined;
-
-	for (let i=0;i<cfgRows.length;i++){
-		if (cfgRows[i].queryId!=queryId) continue;
-		cfgRow=cfgRows[i];
-		break;
-	}
-	if (cfgRow==undefined){
-		print('generateConfig for queryName['+queryId+']='+queryName+' not found');
-		return;
-	}
-	//add config to the list
-	if (!("generateConfig" in config.formConfig)){
-		config.formConfig.generateConfig=new Object();
-	}
-	config.formConfig.generateConfig[queryName]=cfgRow;
-
-	if (!("generateForm" in config.formConfig)){
-		config.formConfig.generateForm=new Object();
-	}
-	
-//
-	let formRows=config.formConfig.formRows;	
-	let formId=cfgRow.formId;
-	for (let i=0;i<formRows.length;i++){
-		if (formRows[i].Key==formId) {
-			config.formConfig.generateForm[queryName]=formRows[i];
-			break;
-		}
-	}
-	//print('XcfgRow '+config.formConfig.generateForm[queryName]);
-//
-//	//check if all required datasets were at least saved
-	checkGenerationFields(queryName);
-}
-
-function checkGenerationFields(queryName){
-	let genForm=config.formConfig.generateForm[queryName];
-	let genCfg=config.formConfig.generateConfig[queryName];
-	let mailRecipient=genCfg.emailRecipient;
-	
-	//list of queries that are part of Registration form
-	print('checkRegistrationFields');	
-	print('setRecipient: '+mailRecipient);
-	let formId=genForm.Key;
-	print("Checking form w/id "+formId);
-	let selectGenerationRows=selectFormSetupRows(formId);
-	//registration rows
-	for (let i=0;i<selectGenerationRows.length;i++){
-		let row=selectGenerationRows[i];
-		let queryId=row.queryName;
-		let fQueryName=config.formConfig.queryMap[queryId];
-		if (fQueryName==queryName) continue;
-		let fQuery=config.formConfig.dataQueries[fQueryName];
-		print('Checking '+fQueryName+' nrows: '+fQuery.rows.length);
-		if (fQuery.rows.length==0){ 
-			generateError(queryName,fQueryName);
-			return;
-		}
-	}
-	generateMessage(queryName,'Vailidation OK');
-	print('callback: set recipient: '+mailRecipient);
-	let cb=function(){prepareForm(queryName,formId,mailRecipient);};
-	generateListEntry(formId,queryName,cb);
-}
-
-
-
-function prepareForm(queryName,formId,mailRecipient){
-
-	print('prepareForm: recipient '+mailRecipient);
-//
-//	return;
-	//look for existing registration entry
-	let selectRows=new Object();
-	//inputLists should be in configuration container
-	selectRows.containerPath=getContainer('data');
-	selectRows.schemaName='lists';
-	selectRows.queryName='crfEntry';
-	selectRows.success=function(data){generateForm(data,queryName,mailRecipient);};
-	let formFilter=LABKEY.Filter.create('Form',formId);
-	let parentCrfFilter=LABKEY.Filter.create('parentCrf',getCRFref());
-
-	selectRows.filterArray=[formFilter,parentCrfFilter];
-	LABKEY.Query.selectRows(selectRows);
-}
-
-function generateError(queryName,fQueryName){
-	let elName=queryName+'GenerateButton'+'_reportField';
-	let el=config.document.getElementById(elName);
-	el.innerText='Error: '+fQueryName+' was not set';
-	el.style.color='red';
-}
-function generateMessage(queryName,msg){
-	let elName=queryName+'GenerateButton'+'_reportField';
-	let el=config.document.getElementById(elName);
-	el.innerText=msg;
-	el.style.color='green';
-}
-
-function generateForm(data,queryName,mailRecipient){
-
-	print('generateForm, recpioent: '+mailRecipient);
-//	
-	const nData=data.rows.length;
-	print('Registration: '+nData+' rows');
-
-	let formRow=config.formConfig.generateForm[queryName];
-
-	//we have to generate masterQuery with parentCrf and crfRef 
-	//and crfEntry with new entryId and parentCrf equal to crfRef
-	if (nData>0) {
-		generateMessage(queryName,'Registration already generated.');
-		return;
-	}
-	let formId=formRow.Key;
-	let formName=formRow.formName;
-	let crfBase=config.formConfig.crfEntry;
-	let crfEntry=new Object();
-	//add new reference
-	crfEntry.entryId=Date.now();
-	crfEntry.parentCrf=getCRFref();
-	crfEntry["Date"]=new Date();
-	crfEntry["View"]="[VIEW]";
-	crfEntry.formStatus=1;//In progress
-//	//set other variables
-	//requires studyData as part of formConfig
-//	let studyData=config.formConfig.studyData;
-	print('Adding study: '+crfBase.EudraCTNumber);
-	crfEntry.EudraCTNumber=crfBase.EudraCTNumber;
-	crfEntry.StudyCoordinator=crfBase.StudyCoordinator;
-	crfEntry.StudySponsor=crfBase.StudySponsor;
-	crfEntry.RegulatoryNumber=crfBase.RegulatoryNumber;
-//
-//	//find sponsor for site
-	let site=crfBase.Site;
-	let crfSponsors=config.formConfig.crfSponsors;
-	let users=config.formConfig.userRows;
-	for (let i=0;i<crfSponsors.length;i++){
-		//print('Checking for site '+crfSponsors[i].Site);
-		if (crfSponsors[i].Site!=site) continue;
-		config.formConfig.sponsorId=crfSponsors[i].User;
-		//print('Setting id '+config.formConfig.sponsorId);
-		//finds first
-		break;
-	}
-	for (let j=0;j<users.length;j++){
-		if (config.formConfig.sponsorId!=users[j].UserId) continue;
-		config.formConfig.sponsor=users[j];
-		//finds first (should be unique)
-		break;
-	}
-	print('Selecting '+config.formConfig.sponsor.DisplayName+' as sponsor');
-	//different user than the original form...
-	//should be set to the study sponsor
-	crfEntry.UserId=config.formConfig.sponsor.UserId;
-	crfEntry.Site=site;
-//	//set formId to one found through registration search
-	crfEntry.Form=formId;
-////
-	let qconfig=new Object();
-	qconfig.schemaName='lists';
-	qconfig.queryName='crfEntry';
-	qconfig.success=function(data){sendEmail(data,mailRecipient,doNothing,formName+' generated');}
-	qconfig.rows=[crfEntry];
-	LABKEY.Query.insertRows(qconfig);
-
-}
-//
-function generateListEntry(formId,queryName,cb){
-
-	//check if registration was already generated
-
-	let formRows=config.formConfig.formRows;
-	let qForm=undefined;
-	for (let i=0;i<formRows.length;i++){
-		if (formRows[i].Key!=formId) continue;
-		qForm=formRows[i];
-	}
-	let nData=config.formConfig.dataQueries[queryName].rows.length
-	if (nData>0) return;
-	//only generate record for parentCrfRef
-	
-	//let qArray=new Array();
-	//let e1=new Object();
-	//e1.crfRef=data.rows[0].entryId;
-	//e1.submissionDate=new Date();
-	//only for registration
-	//e1.registrationStatus=0;
-	//qArray.push(e1);
-	
-	let e2=new Object();
-	e2.crfRef=getCRFref();
-	e2.registrationStatus=0;
-	e2.submissionDate=new Date();
-	print('set values');
-	
-	let qconfig=new Object();	
-	qconfig.containerPath=getContainer('data');
-	qconfig.schemaName='lists';
-	qconfig.queryName=queryName;
-	qconfig.success=cb;
-	qconfig.rows=[e2]
-	LABKEY.Query.insertRows(qconfig);
-
-}
-		
-// ******************** end form generator (Registration) ********************
-
-//jump to populate table/generate review, etc defined at the begining of the file
-
-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];
-}
-
-//entry point from generateMasterForm
-function setFormConfig(){
-
-	//add object to store form related data
-	config.formConfig=new Object();
-
-   config.formConfig.softwareVersion='0.15.14';
-
-	let debug=true;
-
-	if (debug)
-		print("generateMasterForm1");	
-	
-	//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'));
-
-	let selectRows=new Object();
-	//this is local data
-	selectRows.containerPath=getContainer('data');
-	selectRows.schemaName='lists';
-	selectRows.queryName='crfEntry';
-	//use first-> we must first establish link to the rigth crf entry
-	selectRows.filterArray=[LABKEY.Filter.create('entryId',getCRFrefFirst())];
-	//store form related data to this object
-	selectRows.success=afterCRFEntry;
-	LABKEY.Query.selectRows(selectRows);
-
-}
-
-function afterCRFEntry(data){
-	config.formConfig.crfEntry=data.rows[0];
-	print("Setting crfEntry (x) to "+config.formConfig.crfEntry["entryId"]);
-	//for empty records or those with parentCrf not set, parentCrf comes up as null
-	//nevertheless, with two equal signs, check against undefined also works
-	print('parentCrf set to '+config.formConfig.crfEntry.parentCrf);
-	
-	collectData();
-}
-
-function collectData(){
-
-	let varLabel='sourceFormStatus';
-	let formStatus=config.formConfig.crfEntry['FormStatus'];
-
-	let queryArray=new Array();
-	//site
-	queryArray.push(makeQuery('config','site','siteData',[]));
-	//users
-	queryArray.push(makeQuery('CRF','users','userData',[]));
-	queryArray[queryArray.length-1].schemaName='core';
-	//crfEditors
-	queryArray.push(makeQuery('config','crfEditors','crfEditorsData',[]));
-	//crfMonitors
-	queryArray.push(makeQuery('config','crfMonitors','crfMonitorsData',[]));
-	//crfSponsors
-	queryArray.push(makeQuery('config','crfSponsors','crfSponsorsData',[]));
-	//study
-	queryArray.push(makeQuery('data','Study','studyDataAll',[]));
-	let e=queryArray[queryArray.length-1];
-	e.schemaName='study';
-	e.columns="SubjectColumnName,EudraCTNumber,StudySponsor";
-	e.columns+=",StudyCoordinator,RegulatoryNumber";
-	
-	//formStatus
-	let formFilter=LABKEY.Filter.create('Key',formStatus);
-	queryArray.push(makeQuery('config','FormStatus','formStatusData',[formFilter]));
-	//crfButtons
-	let statusFilter=LABKEY.Filter.create(varLabel,formStatus);
-	queryArray.push(makeQuery('config','crfButtons','crfButtons',[statusFilter]));
-	//Forms	
-	queryArray.push(makeQuery('config','Forms','formData',[]));
-	//FormSetup	
-	queryArray.push(makeQuery('config','FormSetup','formSetup',[]));
-	//generateConfig
-	queryArray.push(makeQuery('config','generateConfig','generateConfigData',[]));	
-	//parentCrf
-	let parentCrf=config.formConfig.crfEntry['parentCrf'];
-	if (parentCrf!=undefined){
-		let crfFilter=LABKEY.Filter.create('entryId',parentCrf);
-		queryArray.push(makeQuery('data','crfEntry','parentCrfData',[crfFilter]));	
-	}	
-   queryArray.push(makeQuery('data','help','help'));
-
-	print('running getDataFromQueries');
-	getDataFromQueries(queryArray,fcontinue);
-}
-
-function selectFormSetupRows(formId){
-	let formSetupRows=new Array();
-	let allRows=config.formConfig.formSetup.rows;
-	for (let i=0;i<allRows.length;i++){
-		let formEntry=allRows[i];
-		if (formEntry.formName==formId)
-			formSetupRows.push(formEntry);
-	}
-	return formSetupRows;
-}
-
-function fcontinue(){
-	//parse site
-	config.formConfig.siteRows=config.formConfig.siteData.rows;
-	let sRows=config.formConfig.siteRows;
-	for (let i=0;i<sRows.length;i++){
-		let siteId=sRows[i].siteNumber;
-		print('site '+siteId);
-		if (siteId==config.formConfig.crfEntry.Site){
-			config.formConfig.currentSite=sRows[i];
-			break;
-		}
-	}
-	//config.formConfig.site=data.rows[0];
-	print("Setting site name to "+config.formConfig.currentSite.siteName);
-	//study
-	config.formConfig.studyData=config.formConfig.studyDataAll.rows[0];
-	print("XSetting participantField to "+
-			config.formConfig.studyData["SubjectColumnName"]);
-	
-	config.formConfig.crfEditors=config.formConfig.crfEditorsData.rows;
-	config.formConfig.crfMonitors=config.formConfig.crfMonitorsData.rows;
-	config.formConfig.crfSponsors=config.formConfig.crfSponsorsData.rows;
-
-	config.formConfig.userRows=config.formConfig.userData.rows;
-	let uRows=config.formConfig.userRows;
-	for (let i=0;i<uRows.length;i++){
-		let userId=uRows[i].UserId;
-		if (userId==config.formConfig.crfEntry.UserId){
-			config.formConfig.user=uRows[i];
-			break;
-		}
-	}
-	//config.formConfig.user=data.rows[0];
-	print("Setting user to "+config.formConfig.user["DisplayName"]);
-
-
-
-	let fsRows=config.formConfig.formStatusData.rows;
-	config.formConfig.formStatus=fsRows[0].formStatus;
-	config.formConfig.operator=config.role;
-	//config.formConfig.operator=fsRows[0].operator;
-
-	print('Setting operator to: '+config.formConfig.operator);
-	
-	config.formConfig.formRows=config.formConfig.formData.rows;
-	
-	let formRows=config.formConfig.formRows;
-	//filter out the current form
-	for (let i=0;i<formRows.length;i++){
-		if (formRows[i].Key==config.formId){
-			config.formConfig.form=formRows[i];
-			break;
-		}
-	}
-	
-	config.formConfig.formSetupRows=selectFormSetupRows(config.formId);
-
-	print("Number of datasets for form ["+config.formId+"]: "+
-			config.formConfig.formSetupRows.length);
-
-
-
-	let fields=config.formConfig.formSetup.metaData.fields;
-
-	//get the lookup for queryName column
-	let formQueryName='queryName';
-	let field="NONE";
-	for (f in fields){
-		if (fields[f]['name']!=formQueryName) continue;
-		field=fields[f];
-		break;
-	}
-	let lookup=field.lookup;
-
-	print("Getting dataset names from "+lookup.queryName);
-	let selectRows=new Object();
-	//inputLists should be in configuration container
-	selectRows.containerPath=getContainer('config');
-	selectRows.schemaName=lookup.schemaName;
-	selectRows.queryName=lookup.queryName;
-	selectRows.success=afterFormDatasets;
-	LABKEY.Query.selectRows(selectRows);
-
-}
-
-function afterFormDatasets(data){
-	print('afterFormDatasets: '+data.rows.length);
-	config.formConfig.formDatasets=data;//inputLists
-	config.formConfig.fields=new Object();
-	config.formConfig.queryMap=new Object();
-	config.formConfig.additionalData=new Object();
-
-	let rows=config.formConfig.formSetupRows;
-
-	//should skip report only rows
-	for (let i=0;i<rows.length;i++){
-		let entry=rows[i];
-		let reviewField=(entry['showFlag']=='REVIEW');
-		//is the operator set yet?
-		let accessMode=config.formConfig.operator+'Mode';
-		let skipField=(entry[accessMode]=="NONE");
-		let queryId=entry['queryName'];
-		let lookupRows=config.formConfig.formDatasets.rows;
-		print('QueryID['+i+']='+queryId);
-		let dentry;
-
-		for (let j=0;j<lookupRows.length;j++){
-	
-			if (queryId!=lookupRows[j]['Key']) continue;
-			dentry=lookupRows[j];
-			break;
-		}
-		let qName=dentry['queryName'];
-
-		//update list of dataset formConfig is observing (fields/queryMap)
-		while (1){
-			//review contains no data
-			if (reviewField) break;
-			if (skipField) break;
-			//already in fields
-			if (qName in config.formConfig.fields) break;
-			config.formConfig.fields[qName]=new Object();
-			break;
-		}
-
-		while(1){
-			//already done
-			if (queryId in config.formConfig.queryMap) break;
-			config.formConfig.queryMap[queryId]=qName;
-			break;
-		}
-		if (reviewField) continue;
-		if (skipField) continue;
-		//only do this for real lists
-		let field=config.formConfig.fields[qName];
-		field.title=entry['title'];
-		field.queryId=queryId;
-
-	}
-	print("List of datasets in form : ");
-	for (f in config.formConfig.fields){
-		let field=config.formConfig.fields[f];
-		print("\t"+f+" ID: "+field.queryId+' title '+field.title);
-	}
-	afterConfig();
-
-}
-
-//>>>>>>>>>>>>>>>>>new>>>>>>>>>>>>
-
-function setDataLayout(cb){
-	let rowsSetup=config.formConfig.formSetupRows;
-	config.formConfig.dataQueries=new Object();
-	let dS=config.formConfig.dataQueries;//reference only
-	let qMap=config.formConfig.queryMap;
-	config.formConfig.lookup=new Object();
-	for (let i=0;i<rowsSetup.length;i++){
-		let entry=rowsSetup[i];
-		//skip review rows
-		if (entry['showFlag']=='REVIEW')
-			continue;
-		let queryId=entry['queryName'];
-		let queryName=qMap[entry['queryName']];
-		dS[queryName]=new Object();
-		dS[queryName].title=entry['title'];
-		if (entry['showQuery']!="NONE"){
-			let sqName=entry['showQuery'];
-			dS[sqName]=new Object();
-			dS[sqName].title=findTitle(sqName);
-			
-		}
-	}
-	//always add reviews
-	//
-
-	config.formConfig.dataQueries['reviewComments']=new Object();
-
-	//perhaps we will need queryId, but this is stuff for later
-	for (q in config.formConfig.dataQueries){
-		//callback will be a watchdog and will complete only 
-		//when all data will be gathered
-		let dq=config.formConfig.dataQueries[q];
-		dq.collectingLayout="INITIALIZED";
-
-		let selectRows=new Object();
-		selectRows.queryName=q;
-		selectRows.schemaName='lists';
-		selectRows.containerPath=getContainer('data');
-		//we are only interested in metadata
-		selectRows.success=function(data){afterDatasets(data,cb);}
-		LABKEY.Query.selectRows(selectRows);
-	}
-}
-
-function findTitle(queryName){
-//find by name from formDatasets 
-//and set associated title as title
-	let rows=config.formConfig.formDatasets.rows;
-	for (let i=0;i<rows.length;i++){
-		let entry=rows[i];
-		if (entry['queryName']!=queryName) continue;
-		return entry['title'];
-	}
-	return "NONE";
-}
-
-//this happens after the for loop, so all dataQueries objects are set
-function afterDatasets(data,cb){
-	let qobject=config.formConfig.dataQueries[data.queryName];
-	print("Inspecting layout for "+data.queryName+" "+qobject);
-	qobject.fields=data.metaData.fields;
-	qobject.collectingLayout="STARTED";
-	//qobject.started="TRUE";
-	qobject.lookup=new Object();//keep track of objects
-
-	let i=0;	
-	for (let f in qobject.fields){
-		//anything else is simple but lookup
-		let field=qobject.fields[f];
-		if (!("lookup" in field)) continue;
-		qobject.lookup[f]="PENDING";
-		print("Adding pending lookup for field "+f);
-		if (field.lookup.queryName in config.formConfig.lookup){
-		       qobject.lookup[f]="DONE";
-	       	       continue;
-		}
-		print("Setting up query for field "+f);
-		config.formConfig.lookup[field.lookup.queryName]=new Object();
-		let lObject=config.formConfig.lookup[field.lookup.queryName];
-		lObject.keyColumn=field.lookup.keyColumn;
-		lObject.displayColumn=field.lookup.displayColumn;
-		let selectRows=new Object();
-		selectRows.schemaName=field.lookup.schemaName;
-		selectRows.queryName=field.lookup.queryName;
-		selectRows.containerPath=getContainer('data');
-		if ("containerPath" in field.lookup){
-			selectRows.containerPath=field.lookup.containerPath;
-		}
-		//selectRows.columns=field.lookup.keyColumn+","+field.lookup.displayColumn;
-      //get all, descriptions may be hidden in further variables
-		//wait for all lookups to return
-		selectRows.success=function(data){addLookup(data,qobject,f,cb);};
-		print("Sending query: ["+
-				field.lookup.queryName+"] "+
-				field.lookup.keyColumn+'/'+
-				field.lookup.displayColumn);
-		LABKEY.Query.selectRows(selectRows);
-		i+=1;
-	}
-	if (i==0){
-		print("No lookups for "+data.queryName);
-		qobject.collectingLayout="FINISHED";
-	}
-	//check if done (both here and in lookup
-	//this only passes if no lookups are anywhere in the dataset assembly
-	if (!dataLayoutSet()) return;
-	cb();
-}
-
-function addLookup(data,qobject,f,cb){
-	print("Adding lookup "+data.queryName+' '+qobject+' '+f);
-	let lObject=config.formConfig.lookup[data.queryName];
-	lObject.LUT=new Array();//key to value
-	lObject.ValToKey=new Array();//value to key
-	let key=lObject.keyColumn;
-	let val=lObject.displayColumn;
-
-	for (let i=0;i<data.rows.length;i++){
-		lObject.LUT[data.rows[i][key]]=data.rows[i][val];
-		lObject.ValToKey[data.rows[i][val]]=data.rows[i][key];
-	}
-   lObject.rows=data.rows;
-	qobject.lookup[f]="DONE";
-	if (!dataLayoutSet()) return;
-	cb();
-}
-
-function dataLayoutSet(){
-	print("Checking layout completeness");
-	let dq=config.formConfig.dataQueries;
-	for (f in dq){
-		print("["+f+"]: "+dq[f].collectingLayout);
-		if (dq[f].collectingLayout=="INITIALIZED")
-			return 0;
-		if (dq[f].collectingLayout=="FINISHED")
-			continue; //OK
-		let qobject=dq[f];
-		for (q in qobject.lookup){
-			if (qobject.lookup[q]=="DONE") {
-				print("["+f+"/"+q+"]: DONE");
-				continue;//OK
-			}
-			print("["+f+"/"+q+"]: "+qobject.lookup[q]);
-			return 0;
-		}
-		dq[f].collectingLayout="FINISHED";
-	}
-	print("Success");
-	return 1;	
-}
-
-function setData(cb){
-	fName='[setData]';
-	print(fName+': cb '+cb);	
-	let crfMatch=getCRFref();
-	let parentCrf=config.formConfig.crfEntry['parentCrf'];
-	if (parentCrf!=undefined) crfMatch=parentCrf;
-
-	print(fName+' form crf ['+getCRFref()+'] matching for crfRef='+crfMatch);
-	//collect data and execute callback cb for queries in cb.queryList
-	for (q in config.formConfig.dataQueries){
-		let fQuery=config.formConfig.dataQueries[q];
-		fQuery.collectingData="STARTED";
-		let selectRows=new Object();
-		selectRows.containerPath=getContainer('data');
-		selectRows.queryName=q;
-		selectRows.schemaName='lists';
-		selectRows.filterArray=[
-			LABKEY.Filter.create("crfRef",crfMatch)
-		];
-		selectRows.success=function(data){assembleData(data,cb);};
-		LABKEY.Query.selectRows(selectRows);
-	}
-}
-
-function assembleData(data,cb){
-	let fName='[assembleData/'+data.queryName+']';
-	let fQuery=config.formConfig.dataQueries[data.queryName];
-	fQuery.rows=data.rows;
-	fQuery.collectingData="FINISHED";
-	print(fName+': adding data');
-	for (q in config.formConfig.dataQueries){
-		let dq=config.formConfig.dataQueries[q];
-		//print("assembleData ["+q+"]: "+dq.collectingData);
-		if (dq.collectingData=="STARTED") return;
-	}
-	print(fName+': completing');
-	cb();
-}
-
-
-function uploadFile(inputElement,context){
-	//context should have ID and dirName attributes; 
-	//path will be dirName/ID/fieldName_ID.suf
-	//where suf is identical to localPath content picked from
-	//inputElement
-	print('uploadFile: '+inputElement.value+'/');
-	if (inputElement.type=="text") return;
-	print('uploadFile: '+inputElement.files+'/');
-	print('uploadFile: '+inputElement.files.length+'/');
-	if (inputElement.files.length>0){
-		let file=inputElement.files[0];
-		print('uploadFile: '+inputElement.value+'/'+file.size);
-	}
-
-	let url=LABKEY.ActionURL.getBaseURL();
-	url+='_webdav';
-	url+=LABKEY.ActionURL.getContainer();
-	url+='/@files';
-	url+='/'+context['dirName'];
-
-	print('uploadFile url: '+url);
-	let uploadConfig=new Object();
-	uploadConfig.inputElement=inputElement;
-	uploadConfig.context=context;
-	uploadConfig.url=url;
-	uploadConfig.success=afterBaseDir;
-	uploadConfig.failure=tryMakeDir;
-	webdavCheck(uploadConfig);
-}
-
-function afterBaseDir(cfg){
-	print('afterBaseDir');
-	cfg.url+='/'+cfg.context['ID'];
-	cfg.success=afterIDDir;
-	cfg.failure=tryMakeDir;
-	webdavCheck(cfg);
-}
-
-function afterIDDir(cfg){
-	print('afterIDDir');
-	if (cfg.inputElement.files.length==0){
-	       	print('No files found');	
-		return;
-	}
-	let file=cfg.inputElement.files[0];
-	print('Uploading '+file.name);
-	let suf=file.name.split('.').pop();
-	cfg.url+='/'+cfg.context['ID']+'.'+suf;
-	cfg.success=afterUpload;
-	cfg.failure=onFailure;
-	cfg.data=file;
-	webdavPut(cfg);
-}
-
-function afterUpload(cfg){
-	print('afterUpload');
-}
-
-function tryMakeDir(cfg){
-	print('tryMakeDir '+cfg.url);
-	cfg.failure=onFailure;
-	webdavMakeDir(cfg);
-}
-
-
-
-
-
-function request(cfg,verb,data){
-	print('request['+verb+'] '+cfg.url);
-	let connRequest=new XMLHttpRequest();
-	connRequest.addEventListener("loadend",
-		function(){checkResponse(connRequest,cfg);});
-	connRequest.open(verb, cfg.url);
-	connRequest.send(data);
-	//print('request['+verb+'] sent');
-}
-
-function checkResponse(xrq,cfg){
-	//print('checkResponse: readyState '+xrq.readyState);
-	//print('checkResponse: status '+xrq.status);
-	if (xrq.status<400) {
-		//client errors 400-499
-		//server errors 500-599
-		cfg.success(cfg);
-		return;
-	}
-	cfg.status=xrq.status;
-	cfg.failure(cfg);
-}
-
-function webdavMakeDir(cfg){ request(cfg,'MKCOL',null);}
-function webdavCheck(cfg) { request(cfg,'GET',null);}
-function webdavPut(cfg) { request(cfg,'PUT',cfg.data);}
-
-
-function onFailure(cfg){
-	print('request failed with status='+cfg.status);
-}
-

+ 0 - 2312
web/crf/crfVisitNew.js

@@ -1,2312 +0,0 @@
-var crfVisit={};
-
-//crfVisit.config=new Object();
-
-crfVisit.setDebug=
-function(debug=null){
-   if (debug){
-      this.print=function(msg){debug.this.print(msg);};
-      this.clear=function(){debug.clear();}
-      return;
-   }
-   //provide default functions if not debug object is available
-   this.print=function(msg){console.log(msg);}
-   this.clear=function(){;}
-}
-
-crfVisit.setDebug();
-
-
-crfVisit.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.scriptsLoaded(cb);};
-   let dependencies=new Array();
-   dependencies.push('crf/runQuery.js');
-   dependencies.push("crf/crfReviewSection.js");
-   dependencies.push("crf/participantIdManager.js");
-   dependencies.push("crf/variableList.js");
-   dependencies.push("crf/webdav.js");
-   dependencies.push("crf/crfPrint.js");
-   dependencies.push("crf/crfSetup.js");
-   dependencies.push("crf/crfData.js");
-   dependencies.push("crf/crfHTML.js");
-   dependencies.push("crf/generateRegistration.js");
-   dependencies.push("crf/formPortalNew.js");
-   LABKEY.Utils.requiresScript(dependencies,action);
-}
-
-crfVisit.scriptsLoaded=
-function(cb=null){
-   participantIdManager.set(crfSetup,crfData);
-   webdav.set(this);
-   crfReviewSection.set(this);
-   crfPrint.set(this);
-   crfData.setSetup(crfSetup);
-   crfHTML.init();
-   //generateRegistration.init();
-   let initRegistration=function(){generateRegistration.init(cb);};
-   let initIdManager=function(){participantIdManager.init(initRegistration);};
-   let initCrfData=function(){crfData.init(initIdManager)};
-   let initFormPortal=function(){formPortal.init(initCrfData);};
-   crfSetup.init(initFormPortal);
-}
-
-
-crfVisit.getContainer=
-function(label){
-	return crfSetup.getContainer(label);
-}
-
-crfVisit.getCrfRefFirst=
-function(){
-	//crfRef is part of html call and gets stored in the page
-	return this.crfRef;
-}
-
-crfVisit.getCrfRef=
-function (){
-	//'crfRefId'
-	return crfData.getCrfEntry()['entryId'];
-}
-
-crfVisit.getCrfRefData=
-function(){
-	let parentCrf=crfData.getCrfEntry()['parentCrf'];
-	if (parentCrf!=undefined) return parentCrf;
-	return this.getCrfRef();
-}
-
-crfVisit.onFailure=
-function(errorInfo, options, responseObj){
-	
-	if (errorInfo && errorInfo.exception)
-		alert("Failure: " + errorInfo.exception);
-	else
-		alert("Failure: " + responseObj.statusText);
-}
-
-crfVisit.doNothing=
-function (){
-	this.print('doNothing called');
-}
-
-crfVisit.getIdManager=
-function(){
-   if (!("masterForm" in participantIdManager)){
-      participantIdManager.siteNumber=crfData.getCrfEntry()['Site'];
-      participantIdManager.masterForm=this.masterForm;
-      participantIdManager.generateTable();
-   }
-   return participantIdManager;
-}
-
-crfVisit.getSetupObject=
-function(){
-   if (!("setups" in this))
-      this.setups=new Object();
-   return this.setups;
-}
-
-crfVisit.getStoredSetup=
-function(sectionId){
-   let sObj=this.getSetupObject();
-   if (sectionId in sObj) return sObj[sectionId];
-   return null;
-}
-
-crfVisit.addSetup=
-function(sectionId,setup){
-   let sObj=this.getSetupObject();
-   sObj[sectionId]=setup;
-}
-   
-crfVisit.makeSetup=
-function(sectionId,listName){
-	//generate setup object whcih should contain fields:
-	//readonlyFlag - whether the dataset is writeable
-	//filters - selection fields that allow creation of LABKEY.Filter.create()
-	//getInputId - formating of unique ids for html elements
-   //
-
-   let fName='[Setup]';
-	this.print(fName+' '+sectionId+'/'+listName);
-   let setup=new Object();
-	setup.queryName=listName;
-	setup.readonlyFlag=function(vName){return false};
-	setup.filters=new Object();
-	setup.filters['crfRef']=this.getCrfRef();
-	setup.getInputId=function(vName){return sectionId+"_"+vName;}
-   setup.sectionId=sectionId;
-	setup.isReview=false;
-   this.addSetup(sectionId,setup);
-   setup.setVariables=new Object();
-   return setup;
-	
-}
-
-crfVisit.makeFullAccessSetup=
-function(sectionId,listName){
-	//addApply - whether a submit/Save button is generated
-	let setup=this.makeSetup(sectionId,listName);
-	setup.addApply="Save";
-	return setup;
-
-}
-
-crfVisit.makeReadonlySetup=
-function(sectionId,listName){
-   let setup=this.makeSetup(sectionId,listName);
-	//see definition of setup object above, change readonly flag
-	setup.readonlyFlag=function(vName){return true};
-	return setup;
-}
-
-crfVisit.getSetup=
-function(sectionId,listName,writeAccess=true){
-	//change to section granulated permission of type EDIT, COMMENT, READ
-	//let formStatus=config.formConfig.formStatus;
-	//equivalent to READ
-   let setup=this.getStoredSetup(sectionId);
-   if (setup) return setup;
-
-
-	if (!writeAccess)
-	//if (formStatus=="Submitted")
-		return this.makeReadonlySetup(sectionId,listName);
-	//if (formStatus=="Approved")
-	//	return readonlySetup(listName);
-	return this.makeFullAccessSetup(sectionId,listName);
-}
-
-crfVisit.generateSection=
-function(formSetupEntry){
-   let that=this;
-	let listName=crfSetup.getMap('inputLists')[formSetupEntry['queryName']];
-   let sectionId="section"+formSetupEntry['Key'];
-   //if (!listName) is for debugSection
-   if (!listName){
-      listName="debugSection";
-   }
-	let fName='[generateSection/'+listName+']';
-	let sectionTitle=formSetupEntry['title'];	
-	let accessModeColumn=this.role+'Mode';
-	let accessMode=formSetupEntry[accessModeColumn];
-	//this will fix it for later use as well
-	this.print(fName+' title '+sectionTitle);
-
-	let tb=crfHTML.createTable(this.masterForm);
-	tb.className='t2';
-	let row=tb.insertRow();
-	let cell=crfHTML.createTblHeader(null,row);
-	cell.setAttribute("colspan","4");
-	cell.style.fontSize="20px";
-	cell.style.textAlign="center";
-   crfHTML.createTextNode(sectionTitle,null,cell);
-	cell=row.insertCell();
-	let input=crfHTML.createButton(null,cell);
-	input.value="Show";
-	input.id="toggle"+sectionId+"VisbilityButton";
-	input.onclick=function(){that.toggleVisibility(sectionId,input.id)};
-
-	let div=crfHTML.createDiv(sectionId,this.masterForm);
-	div.style.display="none";
-
-   //here divert for debugArea
-   if (listName=="debugSection"){
-      let debugArea=crfHTML.createTextArea(null,div);
-      debugArea.rows=10;
-      debugArea.cols=95;
-      debugArea.id=this.debugId;
-      return;
-   }
-
-	let additionalData=crfSetup.getAdditionalData(listName);
-	let divTable=crfHTML.createDiv(sectionId+"Table",null,div);
-	
-	if ("showFlag" in additionalData) {
-		additionalData.divName=sectionId+"SubDiv";
-		additionalData.divQueryName=sectionId+"SubDivList";
-
-		let div1=crfHTML.createDiv(additionalData.divName,null,div);
-		div1.style.display="none";
-		let div2=crfHTML.createDiv(additionalData.divQueryName,null,div1);
-
-	}
-	this.print(fName+" generate master table");
-
-	let writeMode=accessMode=="EDIT";	
-	let setup=this.getSetup(sectionId,listName,writeMode);
-   setup.setVariables=variableList.parseVariables(formSetupEntry['variableDefinition']);
-	
-
-   if	("isReview" in additionalData){
-      crfReviewSection.set(this);
-      let action=function(){crfReviewSection.CB();};
-		crfReviewSection.generateSection(listName,div.id,action);
-		return;	
-	}
-	//master table is unique per visit
-
-	
-	setup.unique=true;
-	this.generateTable(listName,divTable.id,additionalData,setup);
-	
-	this.print("generate master table: done");
-
-	let generateSubTable=true;
-	//generateSubTable equivalent to read/write access to section
-	if (accessMode != "EDIT")
-		generateSubTable=false;
-	
-	if (! ("showFlag" in additionalData) ) generateSubTable=false;
-	
-	if (generateSubTable){
-		let qName=additionalData.queryName;
-		let dName=additionalData.divName;
-		
-      let subsectionId='sub'+sectionId;
-		let xsetup=this.makeFullAccessSetup(subsectionId,qName);
-		//only set master query for additionalData
-		xsetup.masterQuery=listName;
-		//if (readonly) setup=readonlySetup(config);
-      xsetup.subTable=true;
-      this.generateTable(qName,dName,additionalData,xsetup);
-		//generateTable(formSetupEntry,qName,dName,additionalData,setup);
-	}
-
-	this.print("generate review");
-
-	let divReviewList=crfHTML.createDiv(sectionId+"ReviewList",null,div);
-	let divReview=crfHTML.createDiv(sectionId+"Review",null,div);
-
-
-	//assume we already have listId (content of config.setupQueryName is listId)
-	//we need listName also
-	//qconfig.queryName=config.setupQueryName;
-	this.generateReview(divReview.id,divReviewList.id,listName,accessMode);
-
-	if (accessMode!='GENERATE') return;
-	this.print('Adding generate button');	
-	//add generateButton
-	let divGenerateButton=crfHTML.createDiv(listName+"GenerateButton",null,div);
-	this.print('Adding generate button completed to here');	
-   let cb=function(){that.onGenerateQuery(listName);};
-	this.generateButton(divGenerateButton.id,'Generate','Generate '+listName,'onGenerateQuery',cb);
-	this.print(fName+' adding generate button completed');	
-}
-
-crfVisit.generateReview=
-function(divReviewId,divReviewListId, listName, accessMode){
-   let qMapInvert=crfSetup.invertMap(crfSetup.getMap('inputLists'));
-	let listId=qMapInvert[listName]
-
-	//listId is a number->should it be queryName?
-	
-   let fName='[generateReview]';
-   this.print(fName+" list "+listId+'/'+listName);
-	let reviewSetup=new Object();
-   reviewSetup.setVariables=new Object();
-	reviewSetup.readonlyFlag=function(vName){
-		if (vName=="queryName") return true; 
-		if (vName=="queryname") return true; 
-		if (vName=="ModifiedBy") return true;
-		return false;};
-	reviewSetup.addApply="Add Review";
-   reviewSetup.reviewTable=true;
-
-	let generateTableFlag=true;
-	let formStatus=crfData.getCrfEntry()['FormStatus'];
-	//COMMENTS allowed or not
-	//three levels of access: EDIT, COMMENT, READ
-	if (accessMode == "READ"){
-	//if (formStatus == "Approved" ){
-		delete reviewSetup.addApply;
-		reviewSetup.readonlyFlag=function(vName){return false;}
-		generateTableFlag=false;
-	}
-	
-	reviewSetup.filters=new Object();
-	reviewSetup.filters["crfRef"]=this.crfRef;
-   if (crfData.getCrfEntry()['parentCrf']){
-      let parentCrf=crfData.getCrfEntry()['parentCrf'];
-      reviewSetup.filters["crfRef"]=this.crfRef+";"+parentCrf;
-   }
- 	reviewSetup.filters["queryName"]=listId;//entry in reviewComments list is queryname, all in small caps
-	//needs listName, in argument
-	
-	reviewSetup.getInputId=function(vName){return listName+"_add"+vName};
-	reviewSetup.divReviewListId=divReviewListId;
-	reviewSetup.isReview=true;	
-   this.addSetup(divReviewId,reviewSetup);
-
-   let msg="Review: divId: "+divReviewId;
-   msg+=" inputId: "+reviewSetup.getInputId;
-   this.print(msg);
-	
-	this.updateListDisplay(divReviewListId,"reviewComments",reviewSetup.filters,true);
-
-	if (! generateTableFlag) return;
-
-	
-   this.generateTable("reviewComments",divReviewId,new Object(),reviewSetup);
-}	
-
-//>>>>>>>>>>trigger visibility of additional lists
-
-crfVisit.setListVisibility=
-function(input,setup,readonlyFlag){
-	let fName="[setListVisibility/"+setup.queryName+"]";
-	this.print(fName);
-	let additionalData=crfSetup.getAdditionalData(setup.queryName);
-	
-	let x = crfHTML.getElement(additionalData.divName);
-	this.print(fName+": Div: "+x);
-	x.style.display="none";
-
-	let sText;
-	if (readonlyFlag) sText=input.innerText;
-	else sText=input.options[input.selectedIndex].text;
-			
-	this.print(fName+": Selected option text: "+sText);
-
-	if (sText == additionalData.showFlagValue){
-		let filters=new Object();
-		if ("filters" in additionalData) filters=additionalData.filters;
-		x.style.display = "block";
-		this.updateListDisplay(additionalData.divQueryName,
-			additionalData.queryName,filters,readonlyFlag);
-	}
-}
-
-//>>have list refresh when data is added (not optimal yet)
-//
-
-crfVisit.updateListDisplay=
-function(divName,queryName,filters,readonlyFlag){
-	//use Labkey.QueryWebPart to show list
-
-	let fName="[updateListDisplay]";
-
-   this.print(fName+": UpdateListDisplay: Query - "+queryName
-      +" div - "+divName);
-
-	if (divName=="NONE") return;
-
-	let crfRef=this.getCrfRef();
-	let div=crfHTML.getElement(divName);
-
-   this.print(fName+": generating WebPart: "+queryName);
-	
-	var qconfig=new Object();
-	qconfig.renderTo=divName;
-	//point to data container
-	qconfig.containerPath=this.getContainer('data');
-	qconfig.schemaName='lists'; 
-	qconfig.queryName=queryName;
-	qconfig.buttonBarPosition='top';
-	qconfig.filters=[];
-	for (f in filters){
-      let fType=LABKEY.Filter.Types.EQUAL;
-      this.print(fName+' filter ['+f+'] '+filters[f]+'/'+typeof(filters[f])+' ['+fType+']');
-     
-      if (variableList.isFilterList(filters[f])){
-         fType=LABKEY.Filter.Types.IN;
-      }
-		qconfig.filters.push(LABKEY.Filter.create(f, filters[f],fType));
-	}
-   let that=this;
-	qconfig.success=function(data){that.updateSuccess(data);};
-	qconfig.failure=function(errorInfo,options,responseObj){that.onFailure(errorInfo,options,responseObj);};
-	//show only print button
-	if (readonlyFlag){
-		qconfig.buttonBar=new Object();
-		qconfig.buttonBar.items=["print"];
-	}
-
-	LABKEY.QueryWebPart(qconfig);
-	
-}
-
-crfVisit.updateSuccess=
-function(data){
-	this.print("Update success");
-}
-
-//TODO: this should trigger a data refresh on section, ie populateData(field)
-crfVisit.toggleVisibility=
-function(sectionId,buttonName){
-	let fName='[toggleVisibility/'+sectionId+']';
-	this.print(fName);
-	let x = crfHTML.getElement(sectionId);
-	if (x.style.display === "none") {
-		//exclude non data sections (like debug)...
-		this.print(fName+': issuing setData(populateSection)');
-    		x.style.display = "block";
-		crfHTML.getElement(buttonName).value="Hide";
-      let that=this;
-		let cb=function(){that.populateSection(sectionId);};
-		crfData.setData(crfData.getCrfRefForData(),cb);
-
-  	} else {
-    		x.style.display = "none";
-		   crfHTML.getElement(buttonName).value="Show";
-
-  	}
-}
-
-crfVisit.generateButton=
-function(divName,caption,label,callbackLabel,callback=null){
-	this.print("generateButtonX");
-	
-	let tb=crfHTML.createTable(divName);
-	tb.className="t2";
-	
-	let r1=tb.insertRow();
-   let th=crfHTML.createTblHeader(null,r1);
-	th.innerHTML=caption;
-	//*!*
-	let c2=r1.insertCell();
-	let i1=crfHTML.createButton(null,c2);
-	i1.value=label;
-	i1.style.fontSize="20px";
-   let that=this;
-   if (callback)
-      i1.onclick=callback;
-   else
-	   i1.onclick=function(){that[callbackLabel]();};
-	i1.id='button_'+callbackLabel;
-
-	let c1=r1.insertCell();
-	c1.setAttribute("colspan","1");
-	//this is only for saveReview?
-	c1.id=divName+'_reportField';
-	//c1.id=config.submitReportId;
-	
-}
-
-crfVisit.generateSubQuery=
-function(input, setup, readonlyFlag){
-	let fName="[generateSubQuery]";
-	if (setup.isReview) return;
-
-	if (!(setup.queryName in crfSetup.getAdditionalDataObject())){
-		this.print(fName+': no additionalData entry (probably a subquery)');
-		return;
-	}
-
-	let additionalData=crfSetup.getAdditionalData(setup.queryName);
-	if (!("showFlag" in additionalData))
-		return;
-
-	this.print(fName);
-		
-	let expId=setup.getInputId(additionalData.showFlag);
-	if (expId!=input.id) {
-		this.print(fName+": ignoring field "+input.id+"/"+expId);
-		return;
-	}
-
-	this.print(fName+": Setting onChange to "+input.id);
-	if (readonlyFlag)
-      return;
-
-   let that=this;
-	input.onchange=function(){that.setListVisibility(input,setup,readonlyFlag)};
-}
-
-
-//>>populate fields
-//
-//
-//split to field generation and field population
-//
-crfVisit.addFieldRow=
-function(tb,field,setup,additionalData){
-
-	let fName="[addFieldRow/"+setup.queryName+':'+field.name+']';
-
-	let vName=field.name;
-	let vType=field.type;
-	let isLookup=("lookup" in field);
-	this.print(fName+": ["+vName+"/"+vType+'/'+isLookup+"]");
-
-	let row=tb.insertRow();
-	let cell=crfHTML.createTblHeader(null,row);
-   cell.style.width='300px';
-	
-	let text = crfHTML.createTextNode(field.shortCaption,null,cell);
-		
-	
-	let input=null;
-   let colSpan="3";
-	let cell1=row.insertCell();
-	cell1.colSpan=colSpan;
-	let readonlyFlag=setup.readonlyFlag(vName);
-
-
-	//set the html input object
-	while (1){
-
-		if (readonlyFlag){
-         input=crfHTML.createLabel('Loading',null,cell1);
-			break;
-		}
-	
-
-		//lookup
-		if (isLookup){
-	      let lookup=field["lookup"];
-	      //get all values from config.formConfig.lookup[X]
-	      let lObject=crfData.getLookup(lookup.queryName);
-         input = crfHTML.createSelect(lObject.LUT,null,cell1);
-			break;
-		}
-
-		//date
-	   if (vType=="date"){
-         input = crfHTML.createDate(null,cell1);
-			break;
-		}
-
-		//string
-		if (vType=="string"){
-			//we have to make sure UNDEF is carried to below
-			//since we are adapting file to either show
-			//current file or allow user to select a file
-			//
-			//TODO change this so one can always select file
-			//but also show the selected file
-
-			if(vName.search("reviewComment")>-1){
-				input = crfHTML.createTextArea(null,cell1);
-				input.cols="65";
-				input.rows="5";
-				break;
-			}
-
-			input=crfHTML.createTextInput(null,cell1);
-			
-			if (vName.search('_file_')<0) break;
-			cell1.setAttribute('colspan',"1");
-			let cell2=row.insertCell();
-			cell2.setAttribute('colspan',"2");
-			let input1=crfHTML.createFileInput(null,cell2);
-			input1.id=setup.getInputId(vName)+'_file_';
-			break;
-				
-		}
-
-
-		if (vType=="float"){
-			input = crfHTML.createTextInput(null,cell1);
-			break;
-		}	
-		
-		
-		if (vType=="boolean"){
-			input = crfHTML.createCheckbox(null,cell1);
-			this.print("Creating checkbox");
-			break;
-		}
-		break;
-	}
-	
-   input.id=setup.getInputId(vName);
-   this.print(fName+': adding element '+input.id);
-   this.print(fName+': listing element '+crfHTML.getElement(input.id));
-	
-
-	//connect associated list
-	this.generateSubQuery(input,setup,readonlyFlag);	
-
-	if (readonlyFlag) {
-		this.print(fName+': exiting(readonlyFlag)');
-		return;
-	}
-	
-}
-
-crfVisit.addSpecialFieldRows=
-function(tb,field,specFieldSetup,setup){
-   //tb is the table, specFieldSetup is a row from the table where special fields are being setup
-   //the first column is fieldUID, which is a colon joined amalgation of queryName:fieldName
-   let fieldUID=specFieldSetup["fieldUID"];
-   let x=fieldUID.split(':');
-   let fieldName=x[1];
-   let fName="[addSpecialFieldRow/"+fieldUID+"]";
-   let q=variableList.parseVariables(specFieldSetup['actionParameters']);
-   this.print(fName);
-   let type=specFieldSetup['actionType'];
-   this.print(fName+' type '+type);
-   if (type=='textArea' || type=="textAreaFromVariableDefinition"){
-      let row=tb.insertRow();
-      let cell1=row.insertCell();
-      cell1.colSpan="4";
-      cell1.style.textAlign="justify";
-      cell1.style.padding="10px";
-      cell1.style.backgroundColor="#e0e0e0";
-      cell1.innerText=q['description'];
-      if (type!='textAreaFromVariableDefinition') return;
-      let varName=q['varName'];
-      //get the value. But sometimes and particularly in this case, there are two rows for the same query
-      //one should rely on formSetup variable definition
-      let value=setup.setVariables[varName];
-      let code=q['pattern'];
-      code=code.replace(varName,value);
-      this.print(fName+' using ['+varName+'] '+value+' pattern '+q['pattern']+' code '+code);
-      cell1.innerText=q[code];
-   
-   }
-   //copyCrfEntry in populateSpecialField
-   if (specFieldSetup['actionType']=='generationObject'){
-      //only in EDIT mode!!
-      let ro=setup.readonlyFlag(fieldName);
-      if (ro) return;
-      generateRegistration.set(this);
-      q['setup']=setup;
-      let gc=generateRegistration.getObject(q,setup.getInputId(fieldName));
-      let that=this;
-      let action=function(){that.doNothing();};
-      if ('mailRecipient' in q){
-         gc.callback=function(data){that.sendEmail(data,q['mailRecipient'],action,q['subject']);};
-      }
-      else 
-         gc.callback=function(data){that.doNothing();};
-      if ("addData" in q){
-         vars=q["addData"].split(',');
-         gc.addData=new Array();
-         for (let v in vars){
-            let s=vars[v]
-            //variable name can be written as A/B where A is the name in addData and B is the variable name in crfEntry
-            //useful for mocking up crfId from daughter crf-s such as registration
-            let sArray=s.split('/');
-            let sTarget=sArray[0];
-            let sSource=sArray[sArray.length-1];
-            gc.addData[sTarget]=crfData.getCrfEntry()[sSource];
-            this.print(fName+" addData ["+sTarget+"]: "+gc.addData[sTarget]);
-         }
-      }
-      let row=tb.insertRow();
-      let cell=crfHTML.createTblHeader(null,row);
-      crfHTML.createTextNode("Automatic ID generator",null,cell);
-      let cell1=row.insertCell();
-      cell1.colSpan="3";
-      let b=crfHTML.createButton(null,cell1);
-      b.id="generateIdButton";
-      b.onclick=function(){generateRegistration.execute(gc);};
-      b.value="Generate ID";
-
-   }
-   if (specFieldSetup['actionType']=='multiChoiceButtonRow'){
-      //need all options for the field
-      if (!("lookup" in field)) {
-         this.print(fieldUID+" only enabled for lookup fields");
-         return;
-      }
-	   let lookup=field["lookup"];
-      let lObject=crfData.getLookup(lookup.queryName);
-      let row=tb.insertRow();
-      let cell=crfHTML.createTblHeader(null,row);
-      let header="All variables";
-      if ('header' in q){
-         header=q['header'];
-         header=header.replace(/_fieldCaption_/,field.shortCaption);
-         header=header.replace(/_t_/,"\t");
-
-      }
-      crfHTML.createTextNode(header,null,cell);
-      crfHTML.addStyle(cell,'center');
-      crfHTML.addStyle(cell,'topLess');
-      let cell1=row.insertCell();
-      cell1.colSpan="3";
-      for (let x in lObject.LUT){
-         let b=crfHTML.createButton(null,cell1);
-         b.id=fieldUID+':'+x;
-         b.value=lObject.LUT[x];
-         input=crfHTML.getElement(setup.getInputId(field.name));
-         b.onclick=function(){crfHTML.updateSelect(input,cell1,x,b.value);}
-      }
-      
-      
-
-   }
-}
-
-crfVisit.populateFieldRow=		
-function(entry,field,setup){
-	this.populateField(entry,field,setup);
-	this.populateSubQuery(entry,field,setup);
-   this.populateSpecialFields(entry,field,setup);
-}
-
-crfVisit.populateSubQuery=
-function(entry,field,setup){
-	let fName='[populateSubQuery/'+setup.queryName+':'+field.name+']';
-	if (setup.isReview) return;
-	
-	if (!(setup.queryName in crfSetup.getAdditionalDataObject())){
-		let msg=fName+': no additionalData entry for '+setup.queryName;
-		msg+=' (probably a subquery)';
-		this.print(msg);
-		return;
-	}
-	//find if field is connected to a sub array
-	//find queryName
-	//
-	let additionalData=crfSetup.getAdditionalData(setup.queryName);
-	this.print(fName);
-	//let flag=additionalData.showFlag;
-	
-	if (!("showFlag" in additionalData)) return;
-	let eId=setup.getInputId(additionalData.showFlag);
-	let id=setup.getInputId(field.name);
-	
-	if (eId!=id) {
-		this.print(fName+": ignoring field "+id+"/"+eId);
-		return;
-	}
-	
-	this.print(fName+': id '+id);
-	//hard to estimate readonlyFlag
-	//
-	let input=crfHTML.getElement(id);
-	let eType=input.nodeName.toLowerCase();
-	let readonlyFlag=eType!="select";
-	this.setListVisibility(input,setup,readonlyFlag);
-
-}
-
-crfVisit.clearField=
-function(field,setup){
-   let foo=new Object();
-   this.populateField(foo,field,setup);
-}
-
-crfVisit.populateField=
-function(entry,field,setup){
-
-	let vName=field.name;
-	let fName='[populateFieldName/'+vName+']';
-
-	let varValue="UNDEF";
-
-	//if (vName in setup.filters) varValue=setup.filters[vName];
-	if (vName in entry) varValue=entry[vName];
-	//if part of the filter, set it to value
-	if (vName in setup.filters) varValue=setup.filters[vName];
-	
-	let isLookup=("lookup" in field);
-	
-	this.print(fName+' v='+varValue+'/'+isLookup+' ['+
-		setup.getInputId(field.name)+']');
-	
-	let vType=field.type;
-	let id=setup.getInputId(vName);
-	let input=crfHTML.getElement(id);
-
-		
-	//date
-	if (vType=="date"){
-		if (varValue=="UNDEF") varValue=new Date();
-		else varValue=new Date(varValue);
-	}
-	
-	//lookup for readonly
-	if (isLookup && varValue!="UNDEF"){
-		let lookup=field["lookup"];
-		//get all values from config.formConfig.lookup[X]
-		let lObject=crfData.getLookup(lookup.queryName);
-		varValue=lObject.LUT[varValue];
-	}
-
-	this.print('Element: '+id+'/'+input);
-	//figure out the element type
-	let eType=input.nodeName.toLowerCase();
-	this.print('Element type: '+eType);
-
-	//change varValue for printing
-	if (varValue=="UNDEF") varValue="";
-	//HTMLTextArea, createElement(textArea)
-	if (eType==="textarea"){
-		input.value=varValue;
-		return;
-	}
-	//Text, createTextNode
-	if (eType==="#text"){
-		input.nodeValue=varValue;
-		return;
-	}
-	//HTMLLabelElement, createElement('label')
-	if (eType==="label"){
-		input.innerText=varValue;
-		return;
-	}
-
-	//HTMLSelectElement, createElement('select')
-	if (eType==="select"){
-		input.selectedIndex=0;
-		for (let i=0;i<input.options.length;i++){
-			let v=input.options[i].text;
-			if (v!=varValue) continue;
-			input.selectedIndex=i;
-			break;
-		}
-		return;
-	}
-
-	if (eType!="input"){
-		this.print('Unknown type: '+eType+' encountered, igonring');
-		return;
-	}
-	
-	//HTMLInputElement
-	let type=input.type;
-
-	if (type=="date"){
-		input.valueAsDate=varValue;
-		return;
-	}
-	//string,float
-	if (type=="text"){
-		input.value=varValue;
-		return;
-	}
-	//boolean
-	if (type=="checkbox"){
-		input.checked=varValue;
-		return;
-	}
-	this.print('Unknown input type: '+type+'. Ignoring.');
-}
-
-crfVisit.populateSpecialFields=
-function(entry,field,setup){
-   let fName='[populateSpecialFields]';
-
-   let fieldUID=setup.queryName+':'+field.name;
-   let specialFields=crfSetup.getEntryMap('specialFields:fieldUID');
-
-   if (!(fieldUID in specialFields)) return;
-
-   let specFieldSetup=specialFields[fieldUID];
-   //q is not used by copyCrfEntry, keeping it here for future reference
-   let q=variableList.parseVariables(specFieldSetup['actionParameters']);
-   let type=specFieldSetup['actionType'];
-   if (type=='copyCrfEntry'){
-      let el=crfHTML.getElement(setup.getInputId(field.name));
-      let varName=field.name;
-      if ("varName" in q)  varName=q["varName"];
-      let id=crfData.getCrfEntry()[varName];
-      el.value=id;
-      this.print(fName+' specialFields ['+field.name+'] '+id+'/'+el.value);
-   }
-
-
-}
-
-crfVisit.populateTable=
-function(listName,writeMode,setup){
-//function populateTable(formSetupEntry){
-	//let listName=config.formConfig.queryMap[formSetupEntry['queryName']];
-	//let accessMode=config.formConfig.operator+'Mode';
-	//let writeMode=formSetupEntry[accessMode]=='EDIT';
-
-	let fName='[populateTable/'+listName+']';
-
-   //should contain formSetup key
-   
-
-	
-	//data snapshot
-	let fQuery=crfData.getQuerySnapshot(listName);
-   let queryLayout=crfData.getQueryLayout(listName);
-
-	//here I assume that listName was parsed during setDataLayout and setData 
-	//so that rows was set (even if they are empty)
-	this.print(fName+"]: nrows "+fQuery.rows.length);
-	
-	let entry=this.selectEntry(fQuery.rows,setup);
-	
-   if (!entry) entry=new Object();
-	let fields=queryLayout.fields;
-		
-	for (f in fields){	
-		let field=fields[f];
-		//each field is a new row
-		this.print(fName+": Adding field: "+f+'/'+field.name+' hidden: '+field.hidden+' type:'+field.type);
-		if (field.hidden) continue;
-		if (field.name=="crfRef") continue;
-      if (field.name in setup.setVariables) continue;
-		this.populateFieldRow(entry,field,setup);
-		
-	}
-
-}
-
-crfVisit.generateTable=
-function(listName,divName,additionalData,setup){
-	let fName="[generateTable/"+listName+"]";	
-	this.print(fName);
-
-	//is listName and setup.queryName a duplicate of the same value
-	this.print(fName+': setup.queryName '+setup.queryName);	
-	//assume data is set in config.formConfig.dataQueries[data.queryName].rows;
-   let populateData=true;
-   if ("subTable" in setup){
-      this.print(fName+" is subTable");
-      populateData=false;
-   }
-
-	let entry=new Object();
-
-
-
-	//data snapshot
-	let fQuerySnapshot=crfData.getQuerySnapshot(listName);
-   let queryLayout=crfData.getQueryLayout(listName);
-	//here I assume that listName was parsed during setDataLayout and setData 
-	//so that rows was set (even if they are empty)
-	this.print(fName+": Nrows "+fQuerySnapshot.rows.length);
-	
-	if (fQuerySnapshot.rows.length>0)
-		entry=fQuerySnapshot.rows[0];
-
-   
-   if ("reviewTable" in setup){
-      entry['reviewComment']='';
-      delete entry["ModifiedBy"];
-   }
-	
-	let tb=crfHTML.createTable(divName);
-	tb.className="t2";
-
-	//this are the fields (probably constant)
-	let fields=queryLayout.fields;
-		
-	for (f in fields){
-		let field=fields[f];
-      let fieldUID=listName+":"+field.name;
-		//each field is a new row
-		this.print(fName+": Adding field: "+f+'/'+field.name+' ('+fieldUID+').');
-      //unique name
-		if (field.hidden) continue;
-		if (field.name=="crfRef") continue;
-      if (field.name in setup.setVariables) continue;
-		this.addFieldRow(tb,field,setup,additionalData);
-		if (populateData) this.populateFieldRow(entry,field,setup);
-      let specialFields=crfSetup.getEntryMap('specialFields:fieldUID');
-      if (fieldUID in specialFields){
-         let specFieldSetup=specialFields[fieldUID];
-         this.addSpecialFieldRows(tb,field,specFieldSetup,setup);
-      }
-
-		
-	}
-   //finish of if apply button is not required
-	if (!("addApply" in setup)) {
-		this.print(fName+"populateTable: done");
-		return;
-	}
-	
-	let row=tb.insertRow();
-
-	let th=crfHTML.createTblHeader(null,row);
-	th.innerHTML=setup.addApply; 
-	let cell=row.insertCell();
-	//cell.setAttribute("colspan","2");
-	let input=crfHTML.createButton(null,cell);
-	input.value=setup.addApply;
-	let cell1=row.insertCell();
-	cell1.setAttribute("colspan","2");
-	cell1.id=setup.getInputId("rerviewLastSave");
-	cell1.innerHTML="No recent update";
-	//saveReview is a generic name for saving content of the html page to a list entry
-   let that=this;
-	input.onclick=function(){that.saveReview(listName,cell1.id,setup)};
-}	
-
-crfVisit.setEntryFromElement=
-function(entry,elementId, field){
-   //set value to entry from element using representation (field) from labkey
-   //
-   //
-   
-   let fName='setEntryFromElement';
-
-   let el=crfHTML.getElement(elementId);
-				
-   if (!el) {
-      this.print(fName+" element: "+elementId+" not found");
-      return;
-   }
-   this.print(fName+" element: "+elementId);
-      
-
-   let vName=field.name;
-   let vType=field.type;
-
-   let eType=el.nodeName.toLowerCase();
-
-   if (eType==="select"){
-      entry[vName]=el.options[el.selectedIndex].value;
-      return;
-   }
-
-   if (eType==="td"){
-      entry[vName]=el.innerText;
-      return;
-   }
-   
-   if (vType=="date"){
-      let date=el.valueAsDate;
-      if (!date) return;
-
-      date.setUTCHours(12);
-      entry[vName]=date.toString();
-      this.print(fName+" setting date to "+entry[vName]);
-      return;
-   }
-
-   if (vType=="string"){
-      entry[vName]=el.value;
-      
-      if (vName.search('_file_')<0) 
-         return;
-      
-      //upload file
-      let id1=elementId+'_file_';
-      let input1=crfHTML.getElement(id1);
-      this.print(fName+' attachment field: '+input1.value);
-      //entry[vName]=el.files[0].stream();
-      let ctx=new Object();
-      ctx['dirName']='consent';
-      ctx['ID']=entry['crfRef'];
-      //should point to data container
-      ctx['project']=getContainer('data');
-      //need ID->crf!
-      //assume crfRef will get set before this
-      //element is encountered
-      this.uploadFile(input1,ctx);
-      let fv=el.value;
-      let suf=fv.split('.').pop();
-      entry[vName]=entry['crfRef']+'.'+suf;
-      return;
-      
-   }	
-   if (vType=="float" || vType=="int"){
-      entry[vName]=el.value;
-      
-      if (vName=="queryName") {
-         this.print(fName+' parsing queryName: '+el.innerText);
-         let qMapInverse=crfSetup.invertMap(crfSetup.getMap('inputLists'));
-         entry[vName]=qMapInverse[el.innerText];
-         //use queryMap lookup
-      }
-      return;
-   }	
-   if (vType=="boolean"){
-      entry[vName]=el.checked;
-      return;
-	}
-   return;
-}
-
-crfVisit.selectEntry=
-function(fRows,setup){
-   let fName='[selectEntry]';
-
-   if (!("unique" in setup)) return null;
-   if (fRows.length==0) return null;
-
-   keys=Object.keys(setup.setVariables);
-   
-   if (keys.length==0)
-      return fRows[0];
-   
-   for (let i=0;i<fRows.length;i++){
-      for (let v in setup.setVariables){
-         this.print(fName+' row '+i+' ['+v+'] '+fRows[i][v]+'/'+setup.setVariables[v]);
-         if (fRows[i][v]==setup.setVariables[v]){
-            this.print(fName+' using '+i);
-            return fRows[i];
-         }
-      }
-   }
-   return null;
-
-}
-
-crfVisit.saveReview=
-function(queryName,elementId,setup){
-	//loads any queryName
-
-   let fName='[saveReview/'+queryName+']';
-	this.print(fName+" elementId "+elementId);
-
-
-   let unique=("unique" in setup);
-	
-   //data snapshot
-	let fQuerySnapshot=crfData.getQuerySnapshot(queryName);
-   let nRows=fQuerySnapshot.rows.length;
-   
-   //data layout 
-	let queryLayout=crfData.getQueryLayout(queryName);
-
-   //determine mode based on entry uniqueness and presence of data
-   let entry=this.selectEntry(fQuerySnapshot.rows,setup);
-   let mode='update';
-
-   if (!entry){
-      entry=new Object();
-      mode='insert';
-   }
-   this.print(fName+' unique '+unique+' mode '+mode+' nRows '+nRows);
-
-	entry.crfRef=this.getCrfRefData();
-
-	this.print(fName+" set crfRef="+entry.crfRef);
-
-
-	let fields=queryLayout.fields;
-	for (f in fields){
-
-		let field=fields[f];
-		this.print(fName+" saveReview field: "+field.name);
-		if (field.hidden) continue;
-      if (field.name in setup.setVariables){
-         entry[field.name]=setup.setVariables[field.name];
-         continue;
-      }
-		
-		let vName=field.name;
-		let vType=field.type;
-
-		this.print(fName+" vType: "+vType);
-		
-		if (vName=="crfRef") continue;
-		//need to save queryName for reviewComments
-		
-		let eId=setup.getInputId(vName);
-      //copy values from form to entry
-      this.setEntryFromElement(entry,eId,field,setup);
-
-      //clear field value
-      if (!unique) this.clearField(field,setup);
-
-	}
-   let that=this;
-	let updateFlag=function(data){that.updateLastSavedFlag(data,setup,elementId)};
-   let cPath=crfSetup.getContainer('data');
-   
-   let action=updateFlag;
-   if (crfSetup.getSettings("updateRegistration")){
-      let pars=variableList.parseVariables(crfSetup.getSettings("updateRegistration"));
-      if (pars['query']==queryName){
-         action=function(data){that.updateRegistration(updateFlag,data);}
-      } 
-   }
-
-   runQuery.modifyRows(mode,'lists',queryName,[entry],action,cPath);
-
-}
-
-crfVisit.updateLastSavedFlag=
-function(data,setup,elementId){
-   let fName='[updateLastSavedFlag]';
-   this.print(fName+" update last saved flag to "+elementId);
-	let el=crfHTML.getElement(elementId);
-	let dt=new Date();
-	el.innerHTML="Last saved "+dt.toString();
-	if (data.queryName=="reviewComments"){
-		this.updateListDisplay(setup.divReviewListId,"reviewComments",setup.filters,true);
-	}	
-	//refresh stored data!
-	let writeMode=!setup.readonlyFlag();
-   let that=this;
-   let cb=function(){that.populateTable(data.queryName,writeMode,setup);};
-	if ("unique" in setup)
-		crfData.setData(crfData.getCrfRefForData(),cb);
-	if ("masterQuery" in setup){
-		let ad=crfSetup.getAdditionalData(setup.masterQuery);
-		this.print('Updating list display: '+setup.queryName+'/'+ad.queryName);
-		this.updateListDisplay(ad.divQueryName,ad.queryName,ad.filters,false);
-   }
-}
-
-//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-//generic form status switch statementes
-
-crfVisit.changeFormStatusAndNotify=
-function(actionName){
-   let fName='[changeStatusAndNotify]';
-   this.print(fName);
-   let targetStatus=crfSetup.getTargetStatus(actionName);
-   let targetRecipient=crfSetup.getTargetRecipient(actionName);
-   let actionSettings=crfSetup.getActionSettings(actionName);
-   let action=new Object();
-   action.name=actionName;
-
-   let finalStep=function(){that.redirect();};
-	if (variableList.hasVariable(actionSettings,"finalStep")){
-      this.print(fName+' adjusting finalStep');
-		//set to doNothing to remain on submit window
-		if (actionSettings.finalStep=="doNothing"){
-			finalStep=function(){that.doNothing();};
-		}
-	}
-   this.print(fName+' action '+actionName+' targetStatus '+targetStatus);
-   let that=this;	
-   action.cb=function(data){that.sendEmail(data,targetRecipient,finalStep,actionName);}
-   this.updateFlag(targetStatus,action);//Approved
-}
-
-crfVisit.updateFlag=
-function(flag,action){
-	let fName='[updateFlag]';
-
-	let entry=crfData.getCrfEntry();
-	entry.FormStatus=flag;
-	let uId=LABKEY.Security.currentUser.id;
-	entry[this.role]=uId;
-
-	this.print(fName+': Form: '+entry.Form);
-	this.print(fName+": set form status to "+entry.FormStatus);
-
-   let that=this;	
-	let cb=function(data){that.completeWithFlag(data,action);};
-   runQuery.modifyRows('update','lists','crfEntry',[entry],cb,crfSetup.getContainer('data'));
-		
-}
-
-
-crfVisit.completeWithFlag=
-function(data,action){
-	let fName='[completeWithFlag]';
-	this.print(fName+': nrows '+data.rows.length);
-
-	let fentry=data.rows[0];
-	this.print(fName+': form status '+fentry.FormStatus);
-	this.print(fName+': form '+fentry.Form);
-
-	let crfStatus=crfData.createCrfStatus(fentry);
-	crfStatus.operator=this.role;
-	crfStatus.action=action.name;
-   let that=this;
-   let cb=function(){that.doNothing();};
-   if (action.cb) cb=action.cb;
-
-   runQuery.insertRows('lists','crfStatus',[crfStatus],cb,crfSetup.getContainer('data'));
-
-}
-
-//******************************************upload to database *********************
-
-crfVisit.onDatabaseUpload=
-function(){
-   let actionName='onDatabaseUpload';
-	let fName='['+actionName+']';
-	this.print(fName);
-   let pM=this.getIdManager();
-   let participantId=participantIdManager.getParticipantIdFromCrfEntry('STUDY');
-  
-   let that=this;
-   let crfRefForData=crfData.getCrfRefForData();
-   
-   //load lists and study data
-   //check what needs to be updated and upload
-   //a (reverse) sequence of functions
-   let completeUpload=function(){that.changeFormStatusAndNotify(actionName);};
-   let uploadData=function(){crfData.uploadData(participantId,crfRefForData,completeUpload);};
-   let loadStudy=function(){crfData.setData(crfRefForData,uploadData,'study');}
-   crfData.setData(crfRefForData,loadStudy,'lists');
-}
-
-
-//*************************update for further review *************************
-
-crfVisit.onUpdateForReview=
-function(){
-   let actionName='onUpdateForReview';
-   this.changeFormStatusAndNotify(actionName);
-}
-
-//************************************************ submit *******************************************
-
-crfVisit.onSubmit=
-function(){
-	//update list storage and change status
-
-	this.hideErr();
-	this.clearErr();
-	this.printErr("onSubmit");
-   let that=this;
-   let actionName='onSubmit';
-   let action=function(){that.verifyData(actionName);};
-	crfData.setData(crfData.getCrfRefForData(),action);
-	
-
-
-}
-
-crfVisit.verifyData=
-function(actionName){
-	let fName='[verifyData/'+actionName+']';
-   let qList=crfData.getActiveQueries();
-   let that=this;
-   let doNothing=function(data){that.doNothing();};
-
-   let pM=this.getIdManager();
-   let fieldName=pM.getCrfEntryFieldName(pM.getMode());
-   let setId=crfData.getCrfEntry()[fieldName];
-
-   this.print(fName+' crfEntry ['+fieldName+'] '+crfData.getCrfEntry()[fieldName]);
-   
-   if (!setId){
-      this.printErr('Missing ID !');
-      return false;
-   }
-
-	for (let qId in qList){
-      let entry=qList[qId];
-      let q=entry['queryName'];
-		let qData=crfData.getQuerySnapshot(q);
-		if (q=="reviewComments") continue;
-		//copy snapshot to history
-      if (qData.rows.length==0){
-         this.print(fName+' no rows for '+q);
-      }
-      else
-		   runQuery.insertRows('lists',q+'History',qData.rows,doNothing,this.getContainer('data'));
-		//if it doesn't have additionalData, it is a sub query
-		if (!(q in crfSetup.getAdditionalDataObject())){
-			continue;
-		}
-		if (qData.rows.length<1){
-			this.printErr('Missing entry for query '+q);
-			return false;
-		}
-	}
-	//this is necessary only for Generated to Generation completed step
-	//let actionSettings=crfSetup.getActionSettings(actionName);	
-	//if (variableList.hasVariable(actionSettings,"updateRegistration")){
-      //if updateRegistrationFormId is set, only update when submit is used on that form
-     // if (variableList.hasVariable(actionSettings,"updateRegistrationFormId")){
-       //  let formId=crfData.getCrfEntry()['Form'];
-         //if (actionSettings['updateRegistrationFormId']==formId)
-           // this.updateRegistration();
-      //}
-      //else
-		  // this.updateRegistration();
-	//}
-   this.changeFormStatusAndNotify(actionName);
-
-}
-
-crfVisit.getEmail=
-function(recipientCode){
-
-	this.print('getEmail w/'+recipientCode);
-	let recipients=new Array();
-	let typeTo=LABKEY.Message.recipientType.to;
-	let create=LABKEY.Message.createRecipient;
-   let userMap=crfSetup.getEntryMap('users');
-	let currentUser=userMap[LABKEY.Security.currentUser.id];
-	let currentSite=this.siteEntry;
-	let formCreator=userMap[crfData.getCrfEntry()['UserId']];
-
-
-	let userRows=crfSetup.getRows('users');
-	let parentUser=null;
-   if ("parentCrfData" in crfSetup){
-		let parentCrf=crfSetup.getRows('parentCrfData');
-		parentUser=userMap[parentCrf[0].UserId];
-	}
-	
-
-	let recipientCategories=recipientCode.split(',');
-	for (let i=0;i<recipientCategories.length;i++){
-
-		let recipient=recipientCategories[i];
-		this.print('Checking '+recipient);
-		if (recipient=='crfEditor'){
-			this.print('Adding :'+formCreator.Email);
-			recipients.push(create(typeTo,formCreator.Email));
-			if (!parentUser) continue;
-			this.print('Adding :'+parentUser.Email);
-			recipients.push(create(typeTo,parentUser.Email));
-			continue;
-		}
-		//Monitor or Sponsor
-		let fList=recipient+'s';
-		let fRows=crfSetup.getRows(fList);
-		for (let i=0;i<fRows.length;i++){
-			this.print('Checking '+fRows[i].User+'/'+fRows[i].Site);
-			if (fRows[i].Site!=currentSite.siteNumber) continue;
-         let targetUser=userMap[fRows[i].User];
-         if (!targetUser) continue;
-			recipients.push(create(typeTo,targetUser.Email));
-		}
-	}
-
-	return recipients;
-}
-
-crfVisit.sendEmail=
-function(data,recipient='crfEditor',cb=null,subj='Form submitted'){
-
-	this.print('sendEmail; recipient: '+recipient);
-   let that=this;
-
-   if (!cb)
-      cb=function(){that.redirect();};
-
-   let cvar='sendEmail';
-	let cval=crfSetup.getSettings(cvar);
-	if (cval){
-
-		this.print(cvar+' set to '+cval);
-		if (cval=='FALSE'){
-			this.print('Skipping sending emails');
-			cb();
-			return;
-		}
-	}
-	if (recipient==null){
-      this.print('Skipping sending emails w/ no recipients');
-      cb();
-      return;
-   }
-
-
-	this.print('send email '+data.rows.length);
-	let crf=data.rows[0]['entryId'];
-	let formId=data.rows[0]['Form'];
-	let link=LABKEY.ActionURL.getBaseURL();
-	link+=LABKEY.ActionURL.getContainer();
-	link+='/crf_tecant-visit.view?';
-	link+='entryId='+crf;
-	link+='&formId='+formId;
-	link+='&role='+recipient;
-
-	//debug
-	let recipients=this.getEmail(recipient);
-	//from crfManagers list
-	
-	let typeHtml=LABKEY.Message.msgType.html;
-	let typePlain=LABKEY.Message.msgType.plain;
-	let msg1=LABKEY.Message.createMsgContent(typePlain,link);
-
-	//let cb=doNothing;
-	//let cb=redirect;
-	LABKEY.Message.sendMessage({
-		msgFrom:'labkey@fmf.uni-lj.si',
-		msgSubject:subj,
-		msgRecipients:recipients,
-		msgContent:[msg1],
-		success: cb
-	});
-
-}
-
-crfVisit.hideErr=
-function(){
-	let el=crfHTML.getElement("errorDiv");
-	el.style.display="none";
-}
-
-crfVisit.clearErr=
-function(){
-	let el=crfHTML.getElement("errorTxt");
-	el.value="";
-}
-
-crfVisit.showErr=
-function(){
-	let el=crfHTML.getElement("errorDiv");
-	el.style.display="block";
-}
-
-crfVisit.printErr=
-function(msg){
-	this.showErr();
-	el=crfHTML.getElement("errorTxt");
-	el.style.color="red";
-	el.value+="\n"+msg;
-}
-
-
-//**************************************************
-//
-crfVisit.onRemoveCRF=
-function(){
-   let fName='[onRemoveCRF]';
-   let crfRef=this.crfRef;
-   let crfRefForData=crfData.getCrfRefForData();
-   this.print(fName+' starting loop');
-   let actionName='onRemoveCRF';
-   let that=this;
-   let notify=function(){that.changeFormStatusAndNotify(actionName);};
-   //let removeCrfEntry=function(){crfData.removeCrfEntry(notify);}; 
-   let removeData=function(){crfData.removeData(notify);};
-   let setStudyData=function(){crfData.setData(crfRefForData,removeData,'study');};
-   let action=setStudyData;
-   let actionSettings=crfSetup.getActionSettings(actionName);
-   if (variableList.hasVariable(actionSettings,'removeWithParentCrf')){
-      //if some query needs to be deleted with parent crf, insert this as an intermediate action
-      let q=actionSettings['removeWithParentCrf'];
-      let parentCrf=crfData.getCrfEntry()['parentCrf'];
-      if (parentCrf){
-         let setParentStudyData=function(){crfData.setDataForQuery(q,parentCrf,removeData,'study');};
-         let setStudyData1=function(){crfData.setData(crfRef,setParentStudyData);}
-         action=function(){crfData.setDataForQuery(q,parentCrf,setStudyData1);};
-      }
-   }
-   crfData.setData(crfRefForData,action);
-}
-
-
-crfVisit.redirect=
-function(){
-	let formUrl="participantPortal";
-	let params=new Object();
-	params.name=formUrl;
-   params.role=this.role;
-   let crfEntry=crfData.getCrfEntry();
-   params.site=crfEntry['Site'];
-   let participantLabel=crfSetup.getParticipantLabel(crfEntry);
-   params['participantLabel']=participantLabel;
-
-	//params.pageId="CRF";
-
-	//points to crf container
-	let containerPath=crfSetup.getContainer('CRF');
-        
-	// This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-        
-	//let homeURL = LABKEY.ActionURL.buildURL("project", formUrl , containerPath, params);
-	let homeURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);
-   this.print("Redirecting to "+homeURL);
-	window.location = homeURL;
-
-}
-
-//master section, entry point from html files
-crfVisit.generateMasterForm=
-function(){
-   let that=this;
-   let action=function(){that.setFormConfig();}
-   this.init(action);
-}
-
-
-//helper function to set basic parameters on web page 
-//(fields defined in html file)
-crfVisit.populateBasicData=
-function(){
-
-   let staticData=new Object();
-   let titles=new Object();
-   staticData['version']='0.16.3'	
-   titles['version']='Software version';
-   let varRows=crfSetup.getRows('crfStaticVariables');
-   for (let i=0;i<varRows.length;i++){
-      let vName=varRows[i].staticVariable;
-      let val=crfData.getCrfEntry()[vName];
-      if (val==undefined) continue;
-      staticData[vName]=val;
-      titles[vName]=varRows[i].Title;
-   }
-	staticData['investigatorName']=this.userEntry['DisplayName'];
-   titles['investigatorName']='Investigator';
-   staticData['email']=this.userEntry['Email'];
-   titles['email']='Email';
-   staticData['siteName']=this.siteEntry['siteName'];
-   titles['siteName']='Site';
-   staticData['sitePhone']=this.siteEntry['sitePhone'];
-   titles['sitePhone']='Telephone(site)';
-
-   for (f in staticData){
-      this.addStaticData(f,titles[f],staticData[f]);
-   }
-   let formId=crfData.getCrfEntry()['Form'];
-   let formEntry=crfSetup.getEntryMap('dataForms')[formId];
-   crfHTML.getElement('formTitle').innerText=formEntry['formName'];
-}
-
-crfVisit.addStaticData=
-function(f,title,value){
-   let el=crfHTML.getElement(f);
-
-   //populate only
-   if (el!=undefined){
-      el.innerText=value;
-      return;
-   }
-   
-   //add row to table if element cannot be found
-   let table=crfHTML.getElement('staticTable');
-   let row=table.insertRow();
-   let cell=row.insertCell();
-   cell.innerText=title;
-   let cell1=row.insertCell();
-   cell1.id=f;
-   cell1.style.fontWeight='bold';
-
-   //populate
-   cell1.innerText=value;
-}
-
-//come here after the layout is read from labkey page
-//
-crfVisit.generateErrorMsg=
-function(msg){
-	let txt=crfHTML.createParagraph(msg,this.masterForm);
-	this.generateButton("submitDiv",'Exit','Exit','redirect');
-}
-
-crfVisit.checkPermissions=
-function(){
-	//check if user has permission on the form
-   let userMap=crfSetup.getEntryMap('users');
-	let currentUser=userMap[LABKEY.Security.currentUser.id];
-	let currentSite=this.siteEntry;
-	let formCreator=userMap[crfData.getCrfEntry()['UserId']];
-	let formCreatorId=formCreator.UserId;
-
-
-   //get list of sites the user can work on
-	let fList=this.role+'s';
-	let fRows=crfSetup.getRows(fList);
-   let operatorSites=new Array();
-	for (let i=0;i<fRows.length;i++){
-		if (fRows[i].User!=currentUser.UserId) continue;
-		operatorSites.push(fRows[i].Site);
-	}
-	this.print('operator Site: '+operatorSites.length);
-	if (operatorSites.length==0){
-      let msg='User '+currentUser.DisplayName;
-      msg+=' is not a '+operator;
-      this.generateErrorMsg(msg);
-      return false;
-   }
-
-	
-	//depending on operator mode, we should decide what is right
-	let operator=this.role;
-	if (this.role=='crfEditor'){
-		//editor can only edit its own forms
-		if (currentUser.UserId==formCreatorId){
-         return true;
-      }
-      //here we are if UserId and formCreatorId are not equal
-      let allowR=crfSetup.getSettings("allowFormReassignment");
-      //form reassignment is not allowed
-      if (!allowR){
-         let msg='User '+currentUser.DisplayName;
-         msg+=' has no permission on this form';
-         this.generateErrorMsg(msg);
-         return false;
-      }
-      //this is for allowed form reassignments
-      //site should still match
-      if (!operatorSites.includes(currentSite.siteNumber)){
-         let msg='User '+currentUser.DisplayName;
-         msg+=' has no permission for site '+currentSite.siteName;
-         this.generateErrorMsg(msg);
-         return false;
-      }
-      //re-assign form, leave a trace in crfStatus and change creator in crfEntry
-      let that=this;
-      let action=new Object();
-      action.name="formReassignement";
-      action.cb=function(){that.doNothing();}
-      crfData.getCrfEntry()['UserId']=currentUser.UserId;
-      let status=crfData.getCrfEntry()['FormStatus'];
-      this.updateFlag(status,action);
-      return true;
-	}
-	if (operator=='crfMonitor' || operator=='crfSponsor'){
-		//monitor can look at forms based on his site
-		//find monitor line
-      //implementation of currentSite in operatorSites
-      if (!operatorSites.includes(currentSite.siteNumber)){
-
-			let msg='User '+currentUser.DisplayName;
-			msg+=' is not a '+operator+' for site ';
-			msg+=currentSite.siteName+'('+currentSite.siteNumber+')';
-			msg+='/'+operatorSites.join(',');
-			this.generateErrorMsg(msg);
-			return false;
-		}
-	}
-
-
-	this.print('User '+currentUser.DisplayName+'/'+
-		currentSite['siteName']+
-		' acting as '+this.role);	
-   return true;
-}
-
-crfVisit.afterConfig=
-function(){
-   let fName='[afterConfig]';
-	this.print(fName);	
-   
-	this.populateBasicData();
-
-   if (!this.checkPermissions()) return;
-   crfSetup.parseButtons();
-   
-   let formStatus=crfSetup.getRows('formStatus')[0]['formStatus'];
-
-	//let functionArray=new Array();
-
-	this.print(fName+" generating buttons for formStatus \""+ formStatus+"\"");
-
-   let allButtonRows=crfSetup.getRows('crfButtons');
-	let buttonRows=new Array();
-   
-   //specifying role=X in actionSettings will limit button to that role
-   for (let i=0;i<allButtonRows.length;i++){
-      let action=allButtonRows[i]['action'];
-      //filter on actionSettings
-      let as=crfSetup.getActionSettings[action];
-      if (variableList.hasVariable(as,'role')){
-         this.print('Role['+this.role+'/'+as['role']+'] limited for action '+action);
-         //mismatch skips addition of button to buttonRows
-         if (this.role!=as['role']) continue;
-      }
-      buttonRows.push(allButtonRows[i]);
-   }
-
-
-
-	for (let i=0;i<buttonRows.length;i++){
-		let bt=buttonRows[i];
-		//if (typeof window[bt.action]==="function"){
-		this.generateButton("submitDiv",bt.caption,bt.label,bt.action,null);
-		//}
-		//else{
-		//	this.print('No match for function :'+bt.action+
-		//		' obj: '+window[bt.action]);
-		//}
-	}
-
-	this.print(fName+' buttons generated.');
-
-
-	//here we should get data. For now, just initialize objects that will hold data
-   let that=this;
-   let action=function(){that.afterDataLayout();};
-   let formId=crfData.getCrfEntry()['Form'];
-	crfData.setDataLayout(formId,this.role,action);//callback is afterDataLayout
-}
-
-crfVisit.afterDataLayout=
-function(){
-
-   let that=this;
-   let action=function(){that.afterData();};
-   //let action=function(){that.doNothing();};
-	crfData.setData(crfData.getCrfRefForData(),action);//callback is afterData
-}
-
-crfVisit.updateRegistration=
-function(cb=null,data){
-   //data is just inserted/updated registration row
-   
-	let fName="[updateRegistration]";
-	this.print(fName);
-   let pM=this.getIdManager();
-	let idFieldName=pM.getCrfEntryFieldName('STUDY');
-	//have to reload query data
-	let regEntry=data.rows[0];
-
-	for (x in regEntry){
-		this.print(fName+" ["+x+"] "+regEntry[x]);
-	}
-
-
-	let studyId=data.rows[0][idFieldName];
-	if (!studyId) {
-		this.print(fName+" study id not set ("+idFieldName+'/'+studyId+")");
-		return; //study id not set
-	}
-	
-	//set 
-	pM.setParticipantIdToCrfEntry("STUDY",studyId);
-   pM.updateCrfEntry();
-	//this will only update crfEntry in memory, but not on LabKey, 
-	//we are counting on updateFlag to follow updateRegistration
-
-	//update parentCRF as well, here we schedule update of data entry as well
-	if ("parentCrfData" in crfSetup){
-		let parentCrfEntry=crfSetup.getRows('parentCrfData')[0];
-		parentCrfEntry[idFieldName]=studyId;
-      let that=this;
-      let doNothing=function(){that.doNothing();};
-      let action={name:"updateRegistration",cb:doNothing};
-		let complete=function(data){that.completeWithFlag(data,action);};
-      runQuery.modifyRows('update','lists','crfEntry',[parentCrfEntry],complete,crfSetup.getContainer('CRF'));
-	}
-   if (cb) cb(data);
-
-}
-
-crfVisit.afterData=
-function(){
-	let fName='afterData';
-   this.configureIdManager();
-   this.generateSections();
-}
-
-
-crfVisit.configureIdManager=
-function(){
-   let fName='[configureIdManager]';
-   let idMode=this.formEntry['idMode'];
-   //set default value if no value is in the list (read value is null)
-   if (!idMode) idMode="STUDY:EDIT";
-
-   this.print(fName+': idMode '+idMode);
-   //add print to config so participantManager can use it
-   let pM=this.getIdManager();
-   //extend object
-   let that=this;
-   let action=new Object();
-   action.name='updateCrfEntry';
-   action.cb=function(){that.doNothing();};
-   let formStatus=crfData.getCrfEntry()['FormStatus'];
-   participantIdManager.updateCrfEntry=function(){that.updateFlag(formStatus,action);};   
-
-   let idModeArray=idMode.split(':');
-   pM.setMode("STUDY");
-   if (idModeArray.includes("LOCAL")) {
-      pM.setMode("LOCAL");
-   }
-   //OK, but check if CRF or registration indicate that study id is already set
-   pM.verifyCrfStudyId();
-   //still local
-   if (pM.getMode()=='LOCAL'){
-      if (idModeArray.includes("READONLY")){
-         pM.setReadonly(pM.getMode());
-         let id=pM.getParticipantIdFromCrfEntry(pM.getMode());
-         pM.setLabelMode(pM.getMode(),id);
-      }
-
-      let localId=pM.getParticipantIdFromCrfEntry('LOCAL');
-      if (localId) pM.setLabelMode('LOCAL',localId);
-      else pM.setEditMode(pM.getMode());
-      pM.setReadonly('STUDY');
-      pM.setLabelMode('STUDY','NOT SET');
-   }
-
-}
-
-crfVisit.generateSections=
-function(){
-	let accessMode=this.role+'Mode';
-   let formId=crfData.getCrfEntry()['Form'];
-   let rowsSetup=crfSetup.selectFormSetupRows(formId);
-	for (let i=0;i<rowsSetup.length;i++){
-		let entry=rowsSetup[i];
-
-      //debug
-		let queryName=crfSetup.getMap('inputLists')[entry['queryName']];
-		this.print(fName+" ["+queryName+"]: showFlag: "+entry["showFlag"]);
-		this.print(fName+" ["+queryName+"]: accessMode: "+entry[accessMode]);
-		const nData=crfData.getQuerySnapshot(queryName).rows.length;
-		this.print(fName+" ["+queryName+"]: nData: "+nData);
-
-		//skip sections
-		//also from fields
-		if (entry[accessMode]=="NONE") continue;
-			
-		//section fits one dataset/list
-		this.generateSection(entry);
-	}
-
-}
-
-crfVisit.populateSection=
-function(sectionId){
-	let fName='[populateSection/'+sectionId+']';
-	this.print(fName);
-
-   //old setting
-	let entry=crfSetup.findSetupRow(sectionId);
-
-	//ignore names without associated entry in formSetup
-	if (!entry){
-		this.print(fName+': no matching FormSetup entry found');
-		return;
-	}
-	//populate comes after generate, we should be pretty safe in taking
-	//already generated additionalData
-	let queryName=crfSetup.getMap('inputLists')[entry['queryName']];
-
-	if (!(queryName in crfSetup.getAdditionalDataObject())){
-		this.print(fName+': no additionalData generated for '+queryName);
-		return;
-	}
-	
-	let additionalData=crfSetup.getAdditionalData(queryName);
-	this.print(fName+': using additionalData '+additionalData);
-	if ("isReview" in additionalData){
-      let action=function(){crfReviewSection.CB();};
-		crfReviewSection.generateSection(queryName,queryName,action);
-		return;	
-	}
-
-	let accessMode=this.role+'Mode';
-	let aM=entry[accessMode];
-	this.print(fName+': accessMode '+aM);
-
-	if (aM!='GENERATE'){
-		let writeMode=entry[accessMode]=='EDIT';
-		this.print(fName+': mode='+writeMode);
-      let setup=this.getStoredSetup(sectionId);
-	   this.populateTable(queryName,writeMode,setup);
-		return;
-	}
-
-	//deal with generate
-	//
-	//already available -> shift to READ mode
-	let divTable=sectionId+'Table';
-	let divObj=crfHTML.getElement(divTable);
-	let divRev=crfHTML.getElement(sectionId+'Review');
-	let divRLi=crfHTML.getElement(sectionId+'ReviewList');
-	let divGBu=crfHTML.getElement(sectionId+'GenerateButton');
-
-	this.print('div GBU: '+divGBu);
-	divObj.style.display="block";
-	divRev.style.display="block";
-	divRLi.style.display="block";
-	if (divGBu!=undefined) divGBu.style.display="none";
-
-	let nData=crfData.getQuerySnapshot(queryName).rows.length;
-   let setup=this.getSetup(sectionId,queryName,0);
-	this.print('['+queryName+']: nrows '+nData);
-	if (nData>0){
-		this.populateTable(queryName,0,setup);
-		return;
-	}
-	//hide table
-	divObj.style.display="none";
-	divRev.style.display="none";
-	divRLi.style.display="none";
-	if (divGBu!=undefined) divGBu.style.display="block";
-	//add buttons?
-	//is button already generated?
-	
-	//populateTable(entry);
-	
-}		
-
-//*******    generateQuery infrastructure *********************
-
-crfVisit.onGenerateQuery=
-function(queryName){
-
-   let fName='[onGenerateQuery]';
-	this.print(fName+' '+queryName);
-//
-	let cfgRows=crfSetup.getRows('generateConfigData');
-//	//queryName to queryId?
-   let qMapInverse=crfSetup.invertMap(crfSetup.getMap('inputLists'));
-	let queryId=qMapInverse[queryName];
-
-
-	let cfgRow=crfSetup.getEntryMap('generateConfigData:queryId')[queryId];
-	
-   if (!cfgRow){
-		this.print('generateConfig for queryName['+queryId+']='+queryName+' not found');
-		return;
-	}
-
-	//let formRows=crfSetup.selectFormSetupRows(cfgRow.formId);
-//
-//	//check if all required datasets were at least saved
-	this.checkGenerationFields(cfgRow);
-}
-
-crfVisit.checkGenerationFields=
-function(entry){
-   //entry is generateConfig row
-   let fName='[checkGenerationFields]';
-	let mailRecipient=entry.emailRecipient;
-	let qMap=crfSetup.getMap('inputLists');
-   let qName=qMap[entry['queryId']];
-	//list of queries that are part of Registration form
-	this.print(fName);	
-	this.print(fName+' setRecipient: '+mailRecipient);
-	let formId=entry['formId'];
-	this.print(fName+" Checking form w/id "+formId);
-	
-   let formRows=crfSetup.selectFormSetupRows(formId);
-	//registration rows
-	for (let i=0;i<formRows.length;i++){
-		let row=formRows[i];
-		let queryId=row.queryName;
-		if (queryId==entry.queryId) continue;
-		let fQuery=crfData.getQuerySnapshot(qMap[queryId]);
-		this.print('Checking '+qMap[queryId]+' nrows: '+fQuery.rows.length);
-      //this is to check whether sufficient data was provided for monitor 
-      //to make an informed decision whether registration is in order
-		if (fQuery.rows.length==0){ 
-			this.generateError(qName,qMap[queryId]);
-			return;
-		}
-	}
-	this.generateMessage(qName,'Vailidation OK');
-   let that=this;
-	let cb=function(){that.prepareForm(entry);};
-	this.generateListEntry(entry.formId,qName,cb);
-}
-
-
-crfVisit.prepareForm=
-function(entry){
-   //entry is generateConfig row
-   let fName="[prepareForm]";
-   let formId=entry['formId'];
-
-	//this.print(fName+' recipient '+mailRecipient);
-
-	//look for existing registration entry
-   let that=this;
-	let action=function(data){that.generateForm(data,entry);};
-	let formFilter=LABKEY.Filter.create('Form',formId);
-	let parentCrfFilter=LABKEY.Filter.create('parentCrf',this.crfRef);
-   let filters=[formFilter,parentCrfFilter];
-   runQuery.selectRows('lists','crfEntry',filters,action,crfSetup.getContainer('data'));
-
-}
-
-crfVisit.generateError=
-function(queryName,fQueryName){
-	let elName=queryName+'GenerateButton'+'_reportField';
-	let el=crfHTML.getElement(elName);
-	el.innerText='Error: '+fQueryName+' was not set';
-	el.style.color='red';
-}
-
-crfVisit.generateMessage=
-function(queryName,msg){
-	let elName=queryName+'GenerateButton'+'_reportField';
-	let el=crfHTML.getElement(elName);
-	el.innerText=msg;
-	el.style.color='green';
-}
-
-crfVisit.generateForm=
-function(data,entry){
-   //entry is generateConfig entry
-   //data is a crfEntry row
-
-   let fName='[generateForm]';
-
-	const nData=data.rows.length;
-
-	let formId=entry['formId'];
-   let formEntry=crfSetup.getEntryMap('dataForms')[formId];
-   let formName=formEntry['formName'];
-	this.print(fName+' crfEntry ('+formName+'): '+nData+' rows');
-
-	//we have to generate masterQuery with parentCrf and crfRef 
-	//and crfEntry with new entryId and parentCrf equal to crfRef
-   let queryName=crfSetup.getMap('inputLists')[entry['queryId']];
-	if (nData>0) {
-		this.generateMessage(queryName,formName+' already generated.');
-		return;
-	}
-   //use current crfEntry as base
-   let crfBase=crfData.getCrfEntry();
-
-
-   let idLabel=crfSetup.getParticipantLabel(crfBase);
-   //role will appear in crfStatus and will be validated agains crfCreator entry of the form
-   let roleAndSite='generate:'+crfBase.Site;
-
-   //have to overload crfEntry
-   // - parentCrf
-   // - formStatus
-   // - UserId (set to sponsor UserId)
-   //
-   // should provide mail recipient and/or modified cb
-   //
-   //
-   let crfEntryOverload=new Object();
-
-   //parentCrf
-   crfEntryOverload.parentCrf=crfBase.entryId;
-
-   //formStatus
-	crfEntryOverload.formStatus=1;//In progress
-   //checks for both field presence (if not in query, undefined) and field value (if not set, null)
-   this.print(fName+' setup status: '+entry.formStatus);
-   if (entry.formStatus){
-      crfEntryOverload.formStatus=entry.formStatus;
-   }
-
-   //	UserId
-   //find sponsor for site
-	let site=crfBase.Site;
-	let crfSponsors=crfSetup.getRows('crfSponsors');
-	let userMap=crfSetup.getEntryMap('users');
-   let sponsorId=null;
-	for (let i=0;i<crfSponsors.length;i++){
-		//take first matching sponsor
-		if (crfSponsors[i].Site!=site) continue;
-		sponsorId=crfSponsors[i].User;
-		//finds first
-		break;
-	}
-   let sponsor=userMap[sponsorId];
-	this.print('Selecting '+sponsor.DisplayName+' as sponsor');
-	//different user than the original form...
-	//should be set to the study sponsor
-	crfEntryOverload.UserId=sponsor.UserId;
-
-   let mailRecipient=entry.mailRecipient;
-   let that=this;
-   let action=function(){that.doNothing();};
-	let cb=function(data,_crfEntry){that.sendEmail(data,mailRecipient,action,formName+' generated');}
-   formPortal.createForm(formId,roleAndSite,cb,idLabel,crfEntryOverload);
-   
-}
-
-crfVisit.generateListEntry=
-function(formId,queryName,cb){
-	//check if registration was already generated
-
-	let formRows=crfSetup.selectFormSetupRows(formId);
-
-	let nData=crfData.getQuerySnapshot(queryName).rows.length;
-
-   if (nData>0) return;
-
-
-   //create new list entry
-   let pM=this.getIdManager();
-   
-
-	let e2=new Object();
-	e2.crfRef=this.getCrfRef();
-	e2.registrationStatus=0;
-	e2.submissionDate=new Date();
-   let idLabel=crfSetup.getParticipantLabel(crfData.getCrfEntry());
-   e2[crfSetup.getLocalIdLabel()]=crfSetup.getLocalId(idLabel);
-   e2[crfSetup.getStudyIdLabel()]=crfSetup.getStudyId(idLabel);
-	this.print('set values');
-   e2.site=crfData.getCrfEntry()['Site'];
-   runQuery.insertRows('lists',queryName,[e2],cb,crfSetup.getContainer('data'));
-
-}
-		
-// ******************** end form generator (Registration) ********************
-
-//jump to populate table/generate review, etc defined at the begining of the file
-
-//entry point from generateMasterForm
-crfVisit.setFormConfig=
-function(){
-   let fName="[setFormConfig]";
-   let crfRef=this.crfRef;
-   let that=this;
-   let afterCrfEntry=function(){that.afterCrfEntry();};
-   let action=function(){crfData.setCrfEntry(crfRef,afterCrfEntry);};//afterCrfEntry
-   crfSetup.setContainers(action);
-}
-
-crfVisit.afterCrfEntry=
-function(){
-   let fName='[afterCRFEntry]';
-	this.print(fName+" setting crfEntry (x) to "+crfData.getCrfEntry()["entryId"]);
-	//for empty records or those with parentCrf not set, parentCrf comes up as null
-	//nevertheless, with two equal signs, check against undefined also works
-   crfSetup.formStatus=crfData.getCrfEntry()['FormStatus'];
-   let parentCrf=crfData.getCrfEntry()['parentCrf'];
-	this.print(fName+' parentCrf set to '+parentCrf);
-   if (parentCrf) crfSetup.parentCrf=parentCrf;
-   let that=this;
-   let action=function(){that.parseSetup();};
-   crfSetup.parseSetup(action);
-}
-
-crfVisit.parseSetup=
-function(){
-
-   //debug
-   let fName='[parseSetup]';
-   let varRows=crfSetup.getRows('crfStaticVariables');
-   let studyVars=crfSetup.getRows('studyData')[0];
-   for (let i=0;i<varRows.length;i++){
-      let vName=varRows[i].staticVariable;
-      this.print(fName+' '+vName+': '+studyVars[vName]);
-   }
-
-	//parse site
-	this.siteEntry=crfSetup.getEntryMap('siteData')[crfData.getCrfEntry()['Site']];
-	this.print("Setting site name to "+this.siteEntry['siteName']);
-	//study
-	this.print("XSetting participantField to "+studyVars["SubjectColumnName"]);
-	
-   //parse user
-   this.userEntry=crfSetup.getEntryMap('users')[crfData.getCrfEntry()['UserId']];
-	this.print("Setting user to "+this.userEntry["DisplayName"]);
-
-	this.print('Setting operator to: '+this.role);
-
-
-	
-   //point formId to point to form set in crfEntry
-   let formId=crfData.getCrfEntry()['Form'];
-	this.formEntry=crfSetup.getEntryMap('dataForms')[formId];
-
-	let accessModeColumn=this.role+'Status';
-   let targetStatus=this.formEntry[accessModeColumn];
-   let formStatus=crfData.getCrfEntry()['FormStatus'];
-
-   this.print(fName+' comparing status '+formStatus+'/'+targetStatus);
-
-   if (targetStatus!=formStatus){
-      let statusMap=crfSetup.getEntryMap('formStatusAll');
-      let targetEntry=statusMap[targetStatus];
-      let actualEntry=statusMap[formStatus];
-      alert('Form status ['+actualEntry.formStatus+'] not suitable to be operated by '+this.role+' targeting status ['+targetEntry.formStatus+']');
-      this.redirect();
-   }
-
-
-   crfSetup.setAdditionalData(this.crfRef,formId);
-	
-	this.afterConfig();
-
-}
-
-crfVisit.uploadFile=
-function(inputElement,context){
-	//context should have ID and dirName attributes; 
-	//path will be dirName/ID/fieldName_ID.suf
-	//where suf is identical to localPath content picked from
-	//inputElement
-	this.print('uploadFile: '+inputElement.value+'/');
-	if (inputElement.type=="text") return;
-	this.print('uploadFile: '+inputElement.files+'/');
-	this.print('uploadFile: '+inputElement.files.length+'/');
-	if (inputElement.files.length>0){
-		let file=inputElement.files[0];
-		this.print('uploadFile: '+inputElement.value+'/'+file.size);
-      webdav.uploadFile(file,context);
-   }
-}
-
-crfVisit.printForm=
-function(){
-   crfPrint.printForm();
-}

+ 0 - 27
web/crf/fileManager.js

@@ -1,27 +0,0 @@
-function parseResponseXML(){
-	//print(config.config,'Status:' +this.status);
-	print('Status:'+this.status);
-	if (this.status!=200) return;
-	config.loadFileConfig.json=JSON.parse(this.responseText);
-	config.loadFileConfig.cb();
-}
-
-function loadFile(){
-	print('YY: '+config.loadFileConfig.url);
-
-	let connRequest=new XMLHttpRequest();
-	connRequest.addEventListener("loadend",parseResponseXML);
-		//function(e){parseResponseXML(e,config);});
-	connRequest.open("GET", config.loadFileConfig.url);
-	connRequest.send();
-}
-
-
-function getBasePath(){
-	let server=LABKEY.ActionURL.getBaseURL();
-	let basePath=server+"_webdav";
-	basePath+=LABKEY.ActionURL.getContainer();
-	return basePath;
-}
-
-

+ 0 - 335
web/crf/formGenerator.js

@@ -1,335 +0,0 @@
-//namespace
-var formGenerator={};
-
-formGenerator.print=
-function(msg){
-   console.log(msg);
-}
-
-formGenerator.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.afterScripts(cb);};
-   let dependencies=new Array();
-   dependencies.push("crf/crfHTML.js");
-   dependencies.push("crf/crfSetup.js");
-   dependencies.push("crf/crfData.js");
-   dependencies.push("crf/runQuery.js");
-
-
-   LABKEY.requiresScript(dependencies,action);
-}
-
-formGenerator.afterScripts=
-function(cb=null){
-
-   crfData.setSetup(crfSetup);
-   let initData=function(){crfData.init(cb);};
-   crfSetup.init(initData);
-}
-
-formGenerator.setRoleAndSite=
-function(roleAndSite){
-   this.roleAndSite=roleAndSite;
-}
-
-formGenerator.showFormGenerator=
-function(){
-   if ("table" in this){
-      this.table.display='block';
-      return;
-   }
-   this.addFormGenerator();
-}
-
-formGenerator.hideFormGenerator=
-function(){
-   if (this.table){
-      this.table.display='none';
-   }
-}
-
-formGenerator.getCrfSelectRow=
-function(crfRef){
-   let rows=this.crfSelectRows;
-   for (let i=0;i<rows.length;i++){
-      if (rows[i]['crfRef']==crfRef)
-         return rows[i];
-
-   }
-   return new Object();
-}
-
-formGenerator.setOptions=
-function(fieldName,keyField,valueField){
-   let fName='[setOptions]';
-   let rows=crfSetup.getRows(fieldName);
-   //let formRows=crfSetup.getRows('generateConfigData');
-   let options=new Object();
-   for (let i=0;i<rows.length;i++){
-      let id=rows[i][keyField];
-      let name=rows[i][valueField]
-      this.print(fName+' '+rows[i][keyField]+'/'+name);
-      options[id]=name;
-      //this.addOption(fgForm.formSelect,formName,formId);
-   }
-   return options;
-}
-   
-
-formGenerator.addGenerator=
-function(){
-   let that=this;
-   let action=function(){that.addFormGenerator();};
-   let parseSetup=function(){crfSetup.parseSetup(action);};
-   crfSetup.setContainers(parseSetup);
-	
-}
-
-formGenerator.addFormGenerator=
-function(){
-   //parentClass should provide config and print and getContainer
-      
-   let fName='[addFormGenerator]';
-   this.print(fName);
-   //layout
-   this.table=crfHTML.createTable('formDiv');
-   let table=this.table;
-   table.className="t2";
-   //this is a form manipulator
-   let fgForm=new Object();
-
-   fgForm.formSelect=this.addInputRow(table,'Select form',"select");
-   fgForm.queryId=this.addInputRow(table,'Select dataset','select');
-   fgForm.crfSelect=this.addInputRow(table,'Select CRF',"select");
-   fgForm.userId=this.addInputRow(table,'Assign to user',"select");
-   fgForm.site=this.addInputRow(table,'Assign to site',"select");
-   fgForm.formStatus=this.addInputRow(table,'Select status','select');
-   fgForm.comment=this.addInputRow(table,'Enter comment','text');
-   fgForm.details=this.addInputRow(table,'Details','label');
-   fgForm.warnings=this.addInputRow(table,'Warnings','label');
-   fgForm.warnings.innerHTML='formGenerator version 3.1.0';
-
-   let formRows=crfSetup.getRows('dataForms');
-   //let formRows=crfSetup.getRows('generateConfigData');
-   let options=new Object();
-   for (let i=0;i<formRows.length;i++){
-      let formId=formRows[i]["Key"];
-      let formName=formRows[i]['formName']
-      this.print(fName+' '+formRows[i]["Key"]+'/'+formName);
-      options[formId]=formName;
-      //this.addOption(fgForm.formSelect,formName,formId);
-   }
-
-   let selOpt=this.setOptions('formStatusAll','Key','formStatus');
-   crfHTML.addSelectOptions(fgForm.formStatus,selOpt);
-   
-   let uOpt=this.setOptions('users','UserId','DisplayName');
-   crfHTML.addSelectOptions(fgForm.userId,uOpt);
-
-   let siOpt=this.setOptions('siteData','siteNumber','siteName');
-   crfHTML.addSelectOptions(fgForm.site,siOpt);
-   //callbacks should be called on copy of this
-   let that=this;
-   crfHTML.addSelectOptions(fgForm.formSelect,options);
-   fgForm.formSelect.onchange=function(){that.updateFormList(fgForm);};
-   fgForm.queryId.onchange=function(){that.updateIdList(fgForm);};
-   fgForm.crfSelect.onchange=function(){that.updateLabel(fgForm);};
-   fgForm.generateButton=this.addInputRow(table,'Generate Form','button');
-   fgForm.generateButton.value="Generate Form";
-   fgForm.generateButton.onclick=function(){that.createFormWithId(fgForm);};
-      
-}
-
-formGenerator.addInputRow=
-function(table,header,type){
-   let fName='[addInputRow]';
-   this.print(fName);
-   let row=table.insertRow();
-   let cell=crfHTML.createTblHeader(null,row);
-   crfHTML.createTextNode(header,null,cell);
-
-   cell=row.insertCell();
-   let input=null;
-      
-   if (type=="select")
-      input=crfHTML.createSelect(new Object(),null,cell);
-
-   if (type=="button")
-      input=crfHTML.createButton(null,cell);
-
-   if (type=="text"){
-      input=crfHTML.createTextArea(null,cell);
-      input.cols="65";
-      input.rows="5";
-   }
-   if (type=="label")
-      input=crfHTML.createLabel('Loading',null,cell);
-
-   return input;
-}
-
-
-formGenerator.createFormWithId=
-function(fgForm){
-   //get form id and entry id from select and create form as above
-   let fName='[createFormWithId]';
-   //let ar=roleAndSite.split(':');
-   //let role=ar[0];
-   //let siteNumber=ar[1];
-
-   this.print(fName);
-   let formId=fgForm.formSelect.options[fgForm.formSelect.selectedIndex].value;
-   let crfRef=fgForm.crfSelect.options[fgForm.crfSelect.selectedIndex].text;
-   //let configRow=crfSetup.getEntryMap('generateConfigData:formId')[formId];
-   let crfSelectRow=null;
-   
-   if (crfRef!='Add new'){
-      crfSelectRow=this.getCrfSelectRow(crfRef);
-   }
-	
-   this.print("Create form w/id "+formId);
-	
-	let crfEntry=new Object();
-	crfEntry.entryId=Date.now();
-	crfEntry["Date"]=new Date();
-	crfEntry["View"]="[VIEW]";
-   if (crfSelectRow){
-      crfEntry['participantStudyId']=crfSelectRow['participantStudyId'];
-      crfEntry['participantLocalId']=crfSelectRow['participantLocalId'];
-
-   }
-	
-   let formStatus=fgForm.formStatus.options[fgForm.formStatus.selectedIndex].value;
-   crfEntry.formStatus=formStatus;//In progress
-	//set other variables
-	//requires studyData as part of formConfig
-	let studyData=crfSetup.getRows('studyData')[0];
-   let varRows=crfSetup.getRows('crfStaticVariables');
-   for (let i=0;i<varRows.length;i++){
-      let varName=varRows[i].staticVariable;
-	   crfEntry[varName]=studyData[varName];
-   }
-   //crfEntry.UserId=LABKEY.Security.currentUser.id;
-   let userId=fgForm.userId.options[fgForm.userId.selectedIndex].value;
-   crfEntry.UserId=userId;
-
-   let site=fgForm.site.options[fgForm.site.selectedIndex].value;
-	crfEntry.Site=site;
-	this.print("Setting site to id="+crfEntry.Site);
-	//from argument list
-	crfEntry.Form=formId;
-   if (crfSelectRow){
-      crfEntry.parentCrf=crfRef;
-   }
-  
-   //
-   //compose a reviewComments entry
-   let reviewComment=new Object();
-   reviewComment['submissionDate']=crfEntry['Date'];
-   reviewComment['crfRef']=crfRef;
-   //comment length
-   let x=fgForm.comment.value;
-   this.print(fName+' comment length '+x.length);
-   if (x.length==0){
-      fgForm.warnings.innerHTML='Supply a comment';
-      return;
-   }
-   reviewComment['reviewComment']=fgForm.comment.value;
-
-   let queryId=fgForm.queryId.options[fgForm.queryId.selectedIndex].value;
-   reviewComment['queryName']=queryId;
-
-   let crfStatus=crfData.createCrfStatus(crfEntry);
-   crfStatus.operator='crfManager';
-   crfStatus.action='createFormWithId';
-   crfStatus.FormStatus=formStatus;
-
-   let that=this;
-   let containerPath=crfSetup.getContainer('data');
-   let rd=function(data){that.redirect();};
-   let pass1=function(data){runQuery.insertRows('lists','crfStatus',[crfStatus],rd,containerPath);};
-   let pass=function(data){runQuery.insertRows('lists','reviewComments',[reviewComment],pass1,containerPath);};
-   runQuery.insertRows('lists','crfEntry',[crfEntry],pass,containerPath);
-}
-
-
-formGenerator.updateFormList=
-function(fgForm){
-   let fName='[updateIdList]';
-   let formId=fgForm.formSelect.options[fgForm.formSelect.selectedIndex].value;
-   this.print(fName+' id '+formId);
-   let formRows=crfSetup.selectFormSetupRows(formId);
-   let options=new Object();
-   let qMap=crfSetup.getMap('inputLists');
-   for (let i=0;i<formRows.length;i++){
-      let key=formRows[i]['queryName'];
-      let value=qMap[key];
-      options[key]=value;
-   }
-   crfHTML.addSelectOptions(fgForm.queryId,options);
-}
-
-
-
-formGenerator.updateIdList=
-function(fgForm){
-   //get query associated with form
-   //let configRow=crfSetup.getEntryMap('generateConfigData:formId')[formId];
-   //let queryId=configRow['queryId'];
-   //this.print(fName+' queryId '+queryId);
-   let queryId=fgForm.queryId.options[fgForm.queryId.selectedIndex].value;
-   if (!queryId || queryId<0)
-      return;
-   let qMap=crfSetup.getMap('inputLists');
-   let containerPath=crfSetup.getContainer('data');
-   let that=this;
-   let success=function(data){that.updateIdListWithData(fgForm,data);};
-   runQuery.selectRows('lists',qMap[queryId],[],success,containerPath);
-}
-
-formGenerator.updateIdListWithData=
-function(fgForm,data){
-   let rows=data.rows;
-   this.crfSelectRows=data.rows;
-   let options=new Object();
-   for (let i=0;i<rows.length;i++){
-      options[i]=rows[i]['crfRef'];
-   }
-   options[100000]='Add new';
-   crfHTML.addSelectOptions(fgForm.crfSelect,options);
-   let event=new Event('change');
-   fgForm.crfSelect.dispatchEvent(event);
-}
-
-formGenerator.updateLabel=
-function(fgForm){
-   let crfRef=fgForm.crfSelect.options[fgForm.crfSelect.selectedIndex].text;
-   if (crfRef=="Add new")
-      return;
-   let crfSelectRow=this.getCrfSelectRow(crfRef);
-   fgForm.details.innerHTML='Generating for Study:'+crfSelectRow['participantStudyId']+' / Local:'+crfSelectRow['participantLocalId'];
-}
-
-formGenerator.redirect=
-function(){
-
-	let formUrl="begin";
-	let params=new Object();
-	params.name=formUrl;
-	params.pageId="CRF";
-
-	//points to crf container
-	let containerPath=crfSetup.getContainer('data');
-        
-	// This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-        
-	var homeURL = LABKEY.ActionURL.buildURL(
-			"project", formUrl , containerPath, params);
-   this.print("Redirecting to "+homeURL);
-	window.location = homeURL;
-
-	
-
-}

+ 0 - 556
web/crf/formPortal.js

@@ -1,556 +0,0 @@
-//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 getMode(){
-	if ("role" in config){
-		return config.role;
-	}
-	return "crfEditor";
-}
-
-function doNothing(){
-	print('doNothing called');
-}
-
-function makeQuery(containerName,queryName,fieldName,filterArray){
-	//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
-	
-	let e=new Object();
-	e.containerName=containerName;
-	e.queryName=queryName;
-	e.fieldName=fieldName;
-	e.filterArray=filterArray;
-	return e;
-}
-
-function getDataFromQueries(queryArray,cb){
-	afterQuery(new Object(),-1,queryArray,cb);
-}
-
-function afterQuery(data,id,queryArray,cb){
-
-	print('afterQuery['+id+']: ');
-
-	if (id>-1){
-		let fieldName=queryArray[id].fieldName;
-		print('afterQuery['+fieldName+']: '+data.rows.length);
-		//uses config.formConfig
-		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 printMessage(msg){
-	let txt=config.document.createElement("p");
-	config.document.getElementById(config.div).appendChild(txt);
-	txt.innerText=msg;
-}
-
-function userName(id){
-	let formConfig=config.formConfig;
-	for (let i=0;i<formConfig.users.rows.length;i++){
-		if (formConfig.users.rows[i].UserId!=id)
-			continue;
-		return formConfig.users.rows[i].DisplayName;
-	}
-	return "NONE";
-}
-
-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 generateFormArray(){
-	print("generateFormArray "+getMode());
-	
-	config.formConfig=new Object();
-	config.formConfig.softwareVersion='0.1.7';
-	//report software version
-	config.document.getElementById('version').innerText=config.formConfig.softwareVersion;	
-	
-	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'));
-
-
-	//setup queryArray
-	let queryArray=new Array();
-	//Forms
-	queryArray.push(makeQuery('config','Forms','dataForms',[]));
-	//users
-	queryArray.push(makeQuery('data','users','users',[]));
-	queryArray[queryArray.length-1].schemaName='core';
-	//inputLists
-	queryArray.push(makeQuery('config','inputLists','inputLists',[]));
-	//studyData
-	queryArray.push(makeQuery('data','StudyProperties','studyData',[]));
-	let e=queryArray[queryArray.length-1];
-	e.schemaName='study';
-	e.columns="StudySponsor,StudyCoordinator,EudraCTNumber";
-	e.columns+=',RegulatoryNumber,SubjectColumnName';
-	//crfEditors
-	queryArray.push(makeQuery('config','crfEditors','crfEditors',[]));
-	//crfMonitors
-	queryArray.push(makeQuery('config','crfMonitors','crfMonitors',[]));
-	//crfSponsors
-	queryArray.push(makeQuery('config','crfSponsors','crfSponsors',[]));
-	//FormStatus
-	queryArray.push(makeQuery('config','FormStatus','formStatusg',[]));
-	//site
-	queryArray.push(makeQuery('config','site','siteData',[]));
-	//crfEntry
-	queryArray.push(makeQuery('data','crfEntry','crfEntries',[]));
-
-	getDataFromQueries(queryArray,fcontinue);
-}
-
-function fcontinue(){
-	let formConfig=config.formConfig;
-
-	print("Number of study data entries: "+formConfig.studyData.rows.length);
-	print("ParticipantId: "+formConfig.studyData.rows[0].SubjectColumnName);
-
-	let qconfig=new Object();
-
-	qconfig.containerPath=getContainer('data');
-	qconfig.schemaName="study";
-	let demographicDataId=formConfig.dataForms.rows[0].masterQuery;
-	let demographicDataQuery="NONE";
-	for (let i=0;i<formConfig.inputLists.rows.length;i++){
-		let entry=formConfig.inputLists.rows[i];
-		print("inputList ["+i+"] ["+entry.Key+"] "+entry.queryName);
-		if (entry.Key==demographicDataId){
-			demographicDataQuery=entry.queryName;
-			break;
-		}
-	}
-	print('Setting demographic query to '+demographicDataQuery);
-
-
-
-	qconfig.queryName=demographicDataQuery;
-	//qconfig.queryName="demographicData";
-	
-	qconfig.success=afterPopulatingDemographicData;
-	LABKEY.Query.selectRows(qconfig);
-}
-
-function afterPopulatingDemographicData(data){	
-	let formConfig=config.formConfig;
-	formConfig.demographicData=data;
-	print("afterPopulatingDemographic");
-	print("Number of patients: "+formConfig.demographicData.rows.length);
-	
-	fcontinue2();
-
-}	
-
-function fcontinue2(){
-
-	let formConfig=config.formConfig;
-	let dataForms=formConfig.dataForms.rows;
-
-	formConfig.table=config.document.createElement("table");
-	config.document.getElementById(config.div).appendChild(formConfig.table);
-
-	let accessModeColumn=getMode()+'Status';
-	print('accessModeColumn '+accessModeColumn);
-	let creatorModeColumn=getMode()+'Creator';
-
-
-	//switch from status based to form based access
-	print("Forms: "+dataForms.length);
-	print("Entries: "+formConfig.crfEntries.rows.length);
-	let fEntries=formConfig.crfEntries.rows;
-	let users=formConfig.users.rows;
-	let currentUserId=LABKEY.Security.currentUser.id;
-	let currentUser=undefined;
-
-	for (let i=0;i<users.length;i++){
-		if (users[i].UserId!=currentUserId) continue;
-		currentUser=users[i];
-	}
-
-	let fList=config.role+'s';
-	let fRows=config.formConfig[fList].rows;
-	//current user must be in the list
-	//
-	let currentUserRoles=new Array();
-	//the same user can act for multiple sites
-	for (let i=0;i<fRows.length;i++){
-		if (fRows[i].User!=currentUser.UserId) continue;
-		currentUserRoles.push(fRows[i]);
-	}
-	if (currentUserRoles.length==0){
-		printMessage('User '+currentUser.DisplayName+" can't act as "+config.role);
-		return;
-	}
-
-	let currentSites=new Array();
-	let siteRows=config.formConfig.siteData.rows;
-	for (let i=0;i<siteRows.length;i++){
-		for (let j=0;j<currentUserRoles.length;j++){
-			if (siteRows[i].siteNumber!=currentUserRoles[j].Site) continue;
-			currentSites.push(siteRows[i]);
-		}
-	}
-
-	let msg='User '+currentUser.DisplayName+' acting as '+config.role+' for (';
-	for (let i=0;i<currentSites.length;i++){
-		if (i>0) msg+=', ';
-		msg+=currentSites[i].siteName;
-	}
-	msg+=')';
-	printMessage(msg);
-
-	for (let i=0;i<dataForms.length;i++){
-		let qForm=dataForms[i];
-		let formKey=qForm.Key;
-		
-		//figure out master query name
-		let masterQuery="NONE";
-		let mID=qForm.masterQuery;
-		for (let i2=0;i2<formConfig.inputLists.rows.length;i2++){
-			//queryName
-			if (formConfig.inputLists.rows[i2].Key!=mID)
-				continue;
-			
-			masterQuery=formConfig.inputLists.rows[i2].queryName;
-			print("Setting master query "+masterQuery);
-			break;
-		}
-		//add row for each form
-		let row=formConfig.table.insertRow(i);
-		let formName=qForm.formName;
-		print("["+i+"/"+formKey+']: '+formName);
-		let k=0;
-		let formStatus=qForm[accessModeColumn];
-		print('target formStatus '+formStatus);
-
-		for (let j=0;j<fEntries.length;j++){
-			let entry=fEntries[j];
-			let formId=entry.Form;
-			//print("Row["+j+"] formId: "+formId);
-			if (formId!=formKey)
-				continue;
-			//should we consider this form
-			
-			if (entry.FormStatus!=formStatus){
-				//print('Form status mismatch :'+entry.FormStatus);
-				continue;
-			}
-			print('Candidate '+entry.entryId);
-			//TODO: smart filter on user (now we get to see all)
-			//
-			//for editors
-			if (config.role=='crfEditor' && entry.UserId!=currentUser.UserId){
-				print('Skipping identity mismatch: '+entry.UserId+'/'+currentUser.UserId);  
-				continue;
-			}
-
-			let matchingSite=-1;
-			let potentialSiteNumbers="[";
-			for (let k=0;k<currentSites.length;k++){
-				if (k>0) potentialSiteNumbers+=',';
-				potentialSiteNumbers+=currentSites[k].siteNumber;
-				if (entry.Site!=currentSites[k].siteNumber) continue;
-				matchingSite=currentSites[k].siteNumber;
-				break;
-			}
-			potentialSiteNumbers+=']';
-			if (matchingSite==-1){
-				print('Skipping wrong site: '+entry.Site+'/'+potentialSiteNumbers);
-				continue;
-			}
-			//insert form
-			//
-
-			let fbox=config.document.createElement("div");
-			fbox.classList.add("box","gold");
-
-			let fp=config.document.createElement("p");
-			let id=entry.entryId;
-			fp.innerHTML=id;
-			//it would be great if this were patientId if available
-			//fp.classList.add("large","center");
-			fp.classList.add("center");
-			fbox.appendChild(fp);
-			
-			let fp1=config.document.createElement("p");
-			let user="NONE";
-			for (let ii=0;ii<users.length;ii++){
-				if (users[ii].UserId!=entry.UserId)
-					continue;
-				user=users[ii].DisplayName;
-				break;
-			}
-			fp1.innerHTML=user;
-			fp1.classList.add("center");
-			fbox.appendChild(fp1);
-			
-			
-			let fp2=config.document.createElement("p");
-			fp2.innerHTML=formName;
-			fp2.classList.add("center");
-			fbox.appendChild(fp2);
-			
-			let fp3=config.document.createElement("p");
-			fp3.id="pid"+id;
-			fp3.innerHTML="NONE";
-			print('Setting participant id from query: '+masterQuery);
-			if (masterQuery!="NONE"){
-				let qconfig=new Object();
-				qconfig.schemaName='lists';
-				qconfig.queryName=masterQuery;
-				qconfig.filterArray=[LABKEY.Filter.create('crfRef',id)];
-				qconfig.success=function(data){setPatientId(data,fp3.id);}
-				LABKEY.Query.selectRows(qconfig);
-			}
-			fp3.classList.add("center");
-			fbox.appendChild(fp3);
-			
-
-
-			
-			let cell=row.insertCell(k);
-			cell.classList.add("stretch");
-			cell.id="box"+entry.crfRef;
-
-			let button=config.document.createElement("button");
-			button.appendChild(fbox);
-			button.onclick=function(){openForm(entry)};
-
-			cell.appendChild(button);
-			k++;
-		}
-		print('finished checking existing forms');
-		//only those that are allowed to create formsa
-		print('Status: '+qForm[creatorModeColumn]);
-		if (qForm[creatorModeColumn]!='TRUE') continue;
-
-		let fbox=config.document.createElement("div");
-		fbox.classList.add("box","red");
-
-		let fp=config.document.createElement("p");
-		fp.innerHTML="Create new";
-		fbox.appendChild(fp);
-			
-			
-			
-		let fp2=config.document.createElement("p");
-		fp2.innerHTML=formName;
-		fp2.classList.add("center");
-		fbox.appendChild(fp2);
-			
-		let cell=row.insertCell(k);
-		cell.classList.add("stretch");
-
-		let button=config.document.createElement("button");
-		button.appendChild(fbox);
-		button.onclick=function(){createForm(formKey)};
-
-		cell.appendChild(button);
-
-	}		
-
-
-}
-
-function setPatientId(data,id){
-	let formConfig=config.formConfig;
-
-	if (data.rows.length==0) return;
-
-	//every masterQuery must have participantCode
-	let participantCode=data.rows[0].participantCode;
-	let participantField=formConfig.studyData.rows[0].SubjectColumnName;
-
-	print('setPatientId: '+data.queryName);
-	print('participantCode: '+participantCode);
-	print('participantField: '+participantField);
-	//equates to registration
-	for (let i=0;i<formConfig.demographicData.rows.length;i++){
-		let entry=formConfig.demographicData.rows[i];
-		let key=entry.lsid;
-		print('Comparing to: '+key);
-		if (key!=participantCode) continue;
-		print('Setting: ');
-		let participantId=entry[participantField];
-		config.document.getElementById(id).innerHTML=participantId;
-		break;
-	}
-	
-
-}
-
-function openForm(crfEntry){
-	let formConfig=config.formConfig;
-	let crfRef=crfEntry.entryId;
-	
-	print("Clicked for "+crfRef);
-
-	let formId=crfEntry.Form;
-	for (let i=0;i<formConfig.dataForms.rows.length;i++){
-		if (formConfig.dataForms.rows[i].Key!=formId) continue;
-		print("Setting form "+formConfig.dataForms.rows[i].formName);
-		formEntry=formConfig.dataForms.rows[i];
-		break;
-	}
-	if (formEntry==undefined) return;
-
-	//select between review and view
-	//let formUrl=formEntry["formUrl"];
-	//if ("reviewMode" in config) formUrl=formEntry["reviewFormUrl"];
-	//print("Setting url "+formUrl);
-
-	//direct all to the same html
-	let formUrl="visit";
-
-	reviewMode="EDIT";
-	if ("reviewMode" in config) reviewMode=config.reviewMode;
-	let params = {
-		"name": formUrl, 
-		// The destination wiki page. The name of this parameter is not arbitrary.
-		"entryId": crfRef,
-		"formId":formId,
-		"role" : config.role
-	};
-
-	//"formSetupQuery":formEntry["setupQuery"],
-	let containerPath= LABKEY.ActionURL.getContainer();
-        // This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-        var wikiURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);
-        print("Redirecting to "+wikiURL);
-
-		 
-	window.location = wikiURL;
-}
-
-function createForm(formId){
-	let formConfig=config.formConfig;
-
-	print("Create form w/id "+formId);
-	
-	let crfEntry=new Object();
-	crfEntry.entryId=Date.now();
-	crfEntry["Date"]=new Date();
-	crfEntry["View"]="[VIEW]";
-	crfEntry.formStatus=1;//In progress
-	//set other variables
-	//requires studyData as part of formConfig
-	let studyData=formConfig.studyData.rows[0];
-	crfEntry.EudraCTNumber=studyData.EudraCTNumber;
-	crfEntry.StudyCoordinator=studyData.StudyCoordinator;
-	crfEntry.StudySponsor=studyData.StudySponsor;
-	crfEntry.RegulatoryNumber=studyData.RegulatoryNumber;
-	crfEntry.UserId=LABKEY.Security.currentUser.id;
-	//requires crfEditors as part of formConfig
-	for (let i=0;i<formConfig.crfEditors.rows.length;i++){
-		print("Checking user "+formConfig.crfEditors.rows[i].User);
-		if (formConfig.crfEditors.rows[i].User!=crfEntry.UserId) continue;
-		print("Found user");
-		crfEntry.Site=formConfig.crfEditors.rows[i].Site;
-		print("Setting site to id="+crfEntry.Site);
-		break;
-	}	
-	//from argument list
-	crfEntry.Form=formId;
-
-	let qconfig=new Object();
-	qconfig.containerPath=getContainer('data');
-	qconfig.schemaName='lists';
-	qconfig.queryName='crfEntry';
-	qconfig.success=function(data){openForm(crfEntry)};
-	qconfig.rows=[crfEntry];
-	LABKEY.Query.insertRows(qconfig);
-}

+ 0 - 357
web/crf/formPortalNew.js

@@ -1,357 +0,0 @@
-var formPortal={};
-
-formPortal.setDebug=
-function(debug=null){
-   if (debug){
-      this.print=function(msg){debug.print(msg);};
-      this.clear=function(){debug.clear();}
-      return;
-   }
-   //provide default functions if not debug object is available
-   this.print=function(msg){console.log(msg);}
-   this.clear=function(){;}
-}
-
-
-formPortal.setDebug();
-
-formPortal.doNothing=
-function(){
-	this.print('doNothing called');
-}
-
-//load runQuery.js
-
-formPortal.printMessage=
-function(msg){
-	crfHTML.createParagraph(msg,'formDiv')
-}
-
-
-formPortal.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.scriptsLoaded(cb);};
-   LABKEY.Utils.requiresScript(["crf/runQuery.js","crf/formGenerator.js","crf/crfRoleSelector.js","crf/crfSetup.js","crf/crfData.js","crf/crfHTML.js"],action);
-}
-
-formPortal.scriptsLoaded=
-function(cb=null){
-  crfHTML.init();
-  crfRoleSelector.set(crfSetup);
-  crfData.setSetup(crfSetup);
-  let initGenerator=function(){formGenerator.init(cb);};
-  let initData=function(){crfData.init(initGenerator);};
-  crfSetup.init(initData);
-}
-
-formPortal.generateFormArray=
-function(){
-   let fName='[generateFormArray]';
-   this.print(fName);
-	this.print(fName);
-   let that=this;
-   let action=function(){that.afterSetup();};
-   let parseSetup=function(){crfSetup.parseSetup(action);};
-   crfSetup.setContainers(parseSetup);
-	
-}
-
-formPortal.filterEntry=
-function(entry,filter){
-   let fName="[filterEntry]";
-
-   //this.print(fName+' candidate '+entry.entryId);
-
-   if (entry.Form!=filter.form)
-      return false;
-
-   //only select forms where status matches the target status
-   if (entry.FormStatus!=filter.formStatus){
-      return false;
-   }
-
-   
-   if (crfSetup.getSettings("filterUser") && filter.role=='crfEditor' && entry.UserId!=filter.userId){
-      //this.print(fName+' skipping identity mismatch: '+entry.UserId+'/'+filter.userId);  
-      return false;
-   }
-
-   if (crfSetup.getSettings("filterSite") && entry.Site!=filter.siteNumber){
-      //this.print(fName+' skipping site mismatch: '+entry.Site+'/'+filter.siteNumber);  
-      return false;
-
-   }
-   return true;
-}
-
-formPortal.afterSetup=
-function(){
-   let fName='[afterSetup]';
-   this.print(fName);
-   let that=this;
-   let cb=function(){that.updateForms();};
-   crfRoleSelector.makePortal(cb);
-	this.table=crfHTML.createTable('formDiv');
-}
-
-formPortal.updateForms=
-function(){
-//this is normallz callback on role selector
-   roleAndSite=crfRoleSelector.getRoleAndSite();
-   this.drawForms(roleAndSite);
-}
-
-formPortal.drawForms=
-function(roleAndSite=null){
-   let fName="[drawForms]"; 
-
-   if (!roleAndSite){
-      alert("Please set role and site");
-      return false;
-   }
-
-   //set filter
-   let ar=roleAndSite.split(":");
-   let role=ar[0];
-   let filter=new Object();
-
-   filter.role=role;
-   filter.siteNumber=ar[1];
-   filter.userId=LABKEY.Security.currentUser.id;
-
-   let accessModeColumn=filter.role+'Status';
-
-   
-   let formRows=crfSetup.getRows('dataForms');
-   //browse through forms
-   let fEntries=crfSetup.getRows('crfEntries');
-
-   this.print(fName+' all entries '+fEntries.length);
-	for (let i=0;i<formRows.length;i++){
-
-      //dataForms is Forms
-		let formEntry=formRows[i];
-		let formId=formEntry['Key'];
-      
-      //set the status for form		
-      filter.formStatus=formEntry[accessModeColumn];
-      this.print(fName+' target formStatus ['+formEntry['formName']+'] '+filter.formStatus);
-
-		//add row for each form
-		let row=this.table.rows[i];
-      if (!row) row=this.table.insertRow(i);
-
-      let labelCell=row.cells[0];
-      let formName=formEntry['formName'];
-      if (!labelCell){
-         labelCell=row.insertCell();
-         labelCell.innerText=formName;
-         crfHTML.addStyle(labelCell,'medium');
-         crfHTML.addStyle(labelCell,'center');
-
-         //crfHTML.createParagraph(formName,null,labelCell);
-      }
-      let cell=row.cells[1];
-      if (!cell) {
-         cell=row.insertCell();
-         crfHTML.addStyle(cell,'stretch');
-      }
-      crfHTML.clear(cell);
-
-      //update the filter with form idr
-      filter.form=formId;
- 
-      let forms=new Array();
-
-		for (let j=0;j<fEntries.length;j++){
-         let entry=fEntries[j];
-			if (this.filterEntry(entry,filter))
-            forms.push(entry);
-		}
-      this.displayForms(cell,forms,roleAndSite,formId);
-		this.print(fName+' finished checking existing forms');
-
-		//only those that are allowed to create forms
-		//print('Status: '+qForm[creatorModeColumn]);
-		
-	}		  
-   if (filter.role=='crfManager')
-      //need formGenerator.js
-      formGenerator.showFormGenerator(this);
-   else
-      formGenerator.hideFormGenerator();
-
-}
-
-formPortal.displayForms=
-function(el,formList,roleAndSite,formId=null,idLabel=null,elError=null){
-   let fName='[displayForms]';
-   //formList is a list of crfEntry entries
-   
-   let table=crfHTML.createTable(null,el);
-   let row=table.insertRow();
-   let n=formList.length;
-   let that=this;
-
-   for (let i=0;i<n;i++){
-      let entry=formList[i];
-      let cell=row.insertCell(i);
-      crfHTML.addStyle(cell,'stretch');
-
-      let fbox=crfHTML.createBox(null,cell);
-      //colormap of formStatus to colors
-      let stat=entry['FormStatus'];
-
-      let style=crfSetup.getEntryMap('formStatus')[stat]['color'];
-      if (!style) style='gold';
-      crfHTML.addStyle(fbox,style);
-      this.print(fName+' setting style ['+i+'] '+style);
-
-      let user=crfSetup.getMap('users')[entry['UserId']];
-      let idLabel=crfSetup.getParticipantLabel(entry);
-      let formStatus=crfSetup.getMap('formStatus')[stat];
-      let text=[entry['entryId'],user,idLabel,formStatus];
-      fbox.onclick=function(){that.openForm(entry,roleAndSite,elError);};
-
-      for (let j=0;j<text.length;j++){
-         crfHTML.createParagraph(text[j],null,fbox);
-      }
-   }
-   if (!formId) return table;
-   let formEntry=crfSetup.getEntryMap('dataForms')[formId];
-   this.print(fName+' unique '+formEntry['unique']);
-
-   if (n>0 && formEntry['unique']=='TRUE') return table;
-
-   //add empty forms for absent records and non-unique records
-
-   //should not be allowed to create new forms
-   let regFormId=crfSetup.getSettings('registrationFormId');
-   if (regFormId==formId) return table;
-   let cell=row.insertCell(n);
-   crfHTML.addStyle(cell,'stretch');
-   let fbox=crfHTML.createBox(null,cell);
-   crfHTML.addStyle(fbox,'empty');
-   let cb=function(xdata,xcrfEntry){that.openForm(xcrfEntry,roleAndSite);};
-   fbox.onclick=function(){that.createForm(formId,roleAndSite,cb,idLabel);};
-   return table;
-   
-}
-
-formPortal.openForm=
-function(crfEntry,roleAndSite,elError=null){
-   let fName="[openForm]";
-   if (!roleAndSite){
-      if (elError) 
-         elError.innerText="Set role and site";
-      this.print(fName+' role and site not specified');
-      return;
-   }
-	let crfRef=crfEntry.entryId;
-	
-	this.print(fName+" clicked for "+crfRef);
-   let ar=roleAndSite.split(':');
-   let role=ar[0];
-   let siteNumber=ar[1];
-
-
-	//select between review and view
-	//let formUrl=formEntry["formUrl"];
-	//if ("reviewMode" in config) formUrl=formEntry["reviewFormUrl"];
-	//print("Setting url "+formUrl);
-
-	//direct all to the same html
-	let formUrl="visitNew";
-
-	reviewMode="EDIT";
-	let params = {
-		"name": formUrl, 
-		// The destination wiki page. The name of this parameter is not arbitrary.
-		"entryId": crfRef,
-		"role" : role
-	};
-
-	//"formSetupQuery":formEntry["setupQuery"],
-	let containerPath= LABKEY.ActionURL.getContainer();
-   // This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-   var wikiURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);
-   this.print(fName+" redirecting to "+wikiURL);
-
-		 
-	window.location = wikiURL;
-}
-
-formPortal.createForm=
-function(formId,roleAndSite,cb=null,idLabel=null,crfEntryOverload=null){
-   //cb takes arguments (data,crfEntry)
-   
-
-   let fName="[createForm]";
-   
-   let formRow=crfSetup.getEntryMap('dataForms')[formId];
-   let creator=formRow['creator'];
-   if (!creator) {
-      alert("Creator for form "+formRow['formName']+' not set');
-      return;
-   }
-   let ar=roleAndSite.split(':');
-   let role=ar[0];
-   let siteNumber=ar[1];
-
-   if (creator!=role){
-      alert("Can't create form as "+role+' only allowed for '+creator);
-      return;
-   }
-
-	this.print(fName+" create form w/id "+formId);
-	
-	let crfEntry=new Object();
-	crfEntry.entryId=Date.now();
-	crfEntry["Date"]=new Date();
-	crfEntry["View"]="[VIEW]";
-	crfEntry.formStatus=1;//In progress
-
-   let fStatus=formRow['initialStatus'];
-   if (fStatus)
-      crfEntry.formStatus=fStatus;
-
-
-	//set other variables
-	//requires studyData as part of formConfig
-	let studyData=crfSetup.getRows('studyData')[0];
-   let varRows=crfSetup.getRows('crfStaticVariables');
-   for (let i=0;i<varRows.length;i++){
-      let varName=varRows[i].staticVariable;
-	   crfEntry[varName]=studyData[varName];
-   }
-	crfEntry.UserId=LABKEY.Security.currentUser.id;
-	crfEntry.Site=siteNumber;
-	this.print(fName+" setting site to id="+crfEntry.Site);
-	//from argument list
-	crfEntry.Form=formId;
-   if (idLabel){
-      crfEntry[crfSetup.getLocalIdLabel()]=crfSetup.getLocalId(idLabel);
-      crfEntry[crfSetup.getStudyIdLabel()]=crfSetup.getStudyId(idLabel);
-   }
-   //overload entries
-   if (crfEntryOverload){
-      for (f in crfEntryOverload){
-         crfEntry[f]=crfEntryOverload[f];
-      }
-   }
-
-
-   let crfStatus=crfData.createCrfStatus(crfEntry);
-   crfStatus.operator=role;
-   crfStatus.action='createForm';
-   let that=this;
-   //let cb=function(data){that.openForm(crfEntry,roleAndSite);}
-   this.print(fName+' '+cb);
-   let callback=function(data){cb(data,crfEntry);};
-   let containerPath=crfSetup.getContainer('data');
-   let pass=function(data){runQuery.insertRows('lists','crfStatus',[crfStatus],callback,containerPath);};
-   runQuery.insertRows('lists','crfEntry',[crfEntry],pass,containerPath);
-}
-

+ 0 - 166
web/crf/generateRegistration.js

@@ -1,166 +0,0 @@
-let generateRegistration={};
-
-generateRegistration.fName="[generateRegistration]";
-
-generateRegistration.set=
-function(){
-   ;
-}
-
-generateRegistration.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.afterScripts(cb);}
-   LABKEY.requiresScript(["crf/crfHTML.js"],action);
-}
-
-generateRegistration.afterScripts=
-function(cb=null){
-   if (cb) cb();
-}
-
-generateRegistration.print=
-function(msg){
-   console.log(msg);
-}
-
-generateRegistration.selectRows=
-function(gObj,cb){
-   this.print(this.fName+": selectRows");
-   let xRows=new Object();
-   let that=this;
-   xRows.schemaName=gObj.schemaName;
-   xRows.queryName=gObj.queryName;
-   xRows.success=cb;
-   xRows.failure=function(errorInfo){that.fail(errorInfo);};
-   LABKEY.Query.selectRows(xRows);
-   this.print(this.fName+": selectRows completed");
-}
-
-generateRegistration.insertRows=
-function(gObj,rows){
-   this.print(this.fName+": insertRows");
-   let iRows=new Object();
-   iRows.schemaName=gObj.schemaName;
-   iRows.queryName=gObj.queryName;
-   iRows.rows=rows;
-   iRows.success=function(data){gObj.callback(data);};
-   LABKEY.Query.insertRows(iRows);
-}
- 
-generateRegistration.zeroPad=
-function(val,strLength=3){
-   let strK=val.toString();
-   return strK.padStart(strLength,'0');
-}
-
-generateRegistration.findFirstAvailableKey=
-function(rows){
-   let k=-1;
-   for (let i=0;i<rows.length;i++){
-      if (rows[i]['Key']>k){
-         k=rows[i]['Key'];
-      }
-   }
-   this.print(this.fName+': Key candidate: '+(k+1));
-   return k+1;
-}
-
-generateRegistration.generateObjectAtKey=
-function(gObj,k){
-   let regCode=gObj.codeBase+this.zeroPad(k);
-   this.print(this.fName+": regCode "+regCode);
-   let row=new Object();
-   row['Key']=k;
-   row[gObj.codeField]=regCode;
-   if ("addData" in gObj){
-      for (let q in gObj.addData){
-         row[q]=gObj.addData[q];
-      }
-   }
-   return row;
-}
-
-generateRegistration.getCode=
-function(gObj,row){
-   return row[gObj.codeField];
-}
-
-generateRegistration.updateField=
-function(gObj,text){
-   let el=crfHTML.getElement(gObj.elementId);
-   this.print(this.fName+": updateField "+gObj.elementId+'/'+el);
-   el.value=text;
-   if ('updateField' in gObj.qPar){
-      let id=gObj.setup.getInputId(gObj.qPar['updateField']);
-      crfHTML.getElement(id).value=gObj.qPar['updateValue'];
-   }
-
-}
-
-generateRegistration.generateId=
-function(gObj,data){
-   this.print(this.fName+": generateId "+data.rows.length);
-   let k=this.findFirstAvailableKey(data.rows);
-   let row=this.generateObjectAtKey(gObj,k);
-   this.updateField(gObj,this.getCode(gObj,row));
-   let rows=new Array();
-   rows.push(row);
-   this.insertRows(gObj,rows);
-}
-
-generateRegistration.doNothing=
-function(data){
-   this.print(this.fName+": doNothing() called");
-}
-
-generateRegistration.fail=
-function(errorInfo){
-   this.print(this.fName+": error "+errorInfo.exception);
-}
-
-generateRegistration.execute=
-function(gObj){
-   let that=this;
-   //this.print(this.fName+": execute "+gObj.elementId);
-   this.inspect(gObj);
-   this.selectRows(gObj,function(data){that.generateId(gObj,data);});
-}
-
-generateRegistration.inspect=
-function(gObj){
-   this.print(this.fName);
-   this.print("query: "+gObj.schemaName+'/'+gObj.queryName);
-   this.print("codeBase "+gObj.codeBase+" codeField "+gObj.codeField);
-   this.print("elementId "+gObj.elementId);
-   this.print("callback "+gObj.callback);
-   this.print("version 1.01");
-}
-
-//generic function for all functors
-//config is there by default
-//
-//pars is semicolon delimeted list of parName=value pairs;
-//required:
-//codeBase - prepend ids with this set of letters
-//schemaName - schema of queryName
-//queryName - query that keeps assigned ids
-//codeField - id field in queryName
-//
-//outputId is the field that gets updated with the button result
-//
-//object is initialized from a list in LabKey
-//
-generateRegistration.getObject=
-function(qPar,outputId){
-   let gObj=new Object();
-   gObj.codeBase=qPar["codeBase"];
-   gObj.schemaName=qPar["schemaName"];
-   gObj.queryName=qPar["queryName"];
-   gObj.codeField=qPar["codeField"];
-   gObj.setup=qPar['setup'];
-   gObj.qPar=qPar;
-   gObj.elementId=outputId;
-   //should set codeBase and elementId after initialization
-   return gObj;
-}

+ 0 - 462
web/crf/participantIdManager.js

@@ -1,462 +0,0 @@
-//all functions are based off of participantManager (print, config, etc.)
-var participantIdManager={};
-
-participantIdManager.print=
-function(msg){
-   console.log(msg);
-}
-
-participantIdManager.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.afterScripts(cb);};
-   LABKEY.requiresScript(['crf/crfHTML.js','crf/generateRegistration.js'],action);
-}
-
-participantIdManager.afterScripts=
-function(cb=null){
-   crfHTML.init();
-   generateRegistration.init(cb);
-}
-
-participantIdManager.set=
-function(setup,data){
-   this.setup=setup;
-   this.data=data;
-   this.updateCrfEntry=function(){;}
-   this.mode='STUDY';
-   //this.generateTable();
-   if (!("readonly" in this)){
-      this.readonly=new Object();
-      this.readonly['LOCAL']=false;
-      this.readonly['STUDY']=false;
-   }
-}
-
-participantIdManager.setMode=
-function(mode){
-   this.mode=mode;
-}
-
-participantIdManager.getMode=
-function(){
-   return this.mode;
-}
-
-participantIdManager.setReadonly=
-function(mode){
-   if (mode=="LOCAL"){
-      this.readonly[mode]=true;
-      return;
-   }
-   this.readonly['STUDY']=true;
-}
-
-participantIdManager.clearReadonly=
-function(mode){
-   if (mode=='LOCAL'){
-      this.readonly[mode]=false;
-      return;
-   }
-   this.readonly['STUDY']=false;
-}
-
-participantIdManager.isReadonly=
-function(mode){
-   if (mode=='LOCAL') return this.readonly['LOCAL'];
-   return this.readonly['STUDY'];
-}
-
-participantIdManager.addSelectOptions=
-function(mode=null){
-   if (mode=="LOCAL") return;
-   
-   let input=this.getInputElement(mode);
-
-   let fName='addParticipantSelectOptions';
-   this.print(fName+' input '+input);
-
-
-   //here the lookup is being populated (registrationData)
-   let demoRows=this.setup.getRows('registrationData');
-   this.print(fName+" demoRows: "+demoRows.length);
-   let opts=new Object();
-   for (let i=0;i<demoRows.length;i++){
-      opt2[i+1]=this.setup.getParticipantLabel(demoRows[i]);
-   }
-   crfHTML.addSelectOptions(input,opts);
-}
-
-participantIdManager.insertRow
-=function(label){
-	let row=this.table.insertRow();
-	
-   //label for local ID
-   let cell=crfHTML.createTblHeader(null,row);
-	cell.setAttribute("colspan","1");
-	cell.style.fontSize="20px";
-	cell.style.textAlign="left";
-   cell.innerText=label;
-
-   //value
-   row.insertCell();
-
-   //button
-   row.insertCell();
-   
-} 
- 
-
-participantIdManager.generateTable=
-function(){
-   let fName='[generateParticipantEntryField]:';
-   this.print(fName);
-
-   //this is HTML designator of area on page
-	let formName=this.masterForm;
-   this.print(fName+' master '+formName);
-
-    
-   this.table=crfHTML.createTable(formName);
-	this.table.className='t2';
-   this.insertRow('Local ID');
-   this.insertRow('Study ID');
-   this.insertRow('ID generator');
-   this.insertRow('Reset local ID');
-
-
-   this.getInputButton('LOCAL');
-   this.getInputButton('STUDY');
-
-   let sMap=this.setup.getEntryMap('siteData:siteNumber');
-   let sMapEntry=sMap[this.siteNumber];
-   let qPar=new Object();
-   qPar['queryName']='participantRegistration'+this.siteNumber;
-   qPar['codeBase']=sMapEntry['codeBase'];
-   qPar['schemaName']='lists';
-   qPar['codeField']='registrationCode';
-   let genObj=generateRegistration.getObject(qPar,'participantIdManager_localInput');
-   let that=this;
-   genObj.callback=function(){that.setId('LOCAL');};
-   //attach execute to a button 
-   let cellButton=this.table.rows[2].cells[2];
-   cellButton.style.alignItems='center';
-   this.generateButton=crfHTML.createButton(null,cellButton);
-   this.generateButton.id="participantIdManager_generateIdButton";
-   this.generateButton.onclick=function(){generateRegistration.execute(genObj);};
-   this.generateButton.value="Generate Local ID";
-  
-
-   let cellReset=this.table.rows[3].cells[2];
-   this.resetButton=crfHTML.createButton(null,cellReset);
-   this.resetButton.id='participantIdManager_resetButton';
-   this.resetButton.onclick=function(){that.resetLocal();}
-   this.resetButton.value='Reset Local ID';
-   this.print(fName+' done');
-
-
-
-}
-
-participantIdManager.getRow=
-function(mode=null){
-   let row=this.table.rows[1];
-   if (mode=="LOCAL")
-      row=this.table.rows[0];
-   return row;
-}
-
-
-participantIdManager.getValueCell=
-function(mode="NONE"){
-   return this.getRow(mode).cells[1];
-}
-
-
-participantIdManager.getButtonCell=
-function(mode="NONE"){
-   return this.getRow(mode).cells[2];
-}
-
-participantIdManager.getValueElement=
-function(mode=null){
-   return this.getValueCell(mode).firstChild;
-}
-
-
-participantIdManager.getInputElement=
-function(mode=null){
-   let fName='[getInputElement]';
-   this.print(fName);
-   let el=this.getValueElement(mode);
-   if (el) return el;
-   return this.createInputElement(mode);
-}
-
-participantIdManager.createInputElement=
-function(mode=null){
-   let elementType=this.getInputElementType(mode);
-   let cell=this.getValueCell(mode);
-   
-   if (elementType=="input") {
-      el=crfHTML.createTextInput();
-      el.id='participantIdManager_localInput';
-   }
-   if (elementType=="select") el=crfHTML.createSelect(new Object());
-   this.print(fName+' input '+el);
-
-   cell.replaceChildren(el);
-   this.addSelectOptions(mode);
- 
-   return el;
-}
-
-participantIdManager.getInputElementType=
-function(mode=null){
-   let fName='[getInputElementType]';
-   this.print(fName);
-   if (mode=="LOCAL") return "input";
-   return "select";
-}
-
-
-participantIdManager.getTextElement=
-function(mode=null){
-   let fName='[getTextElement]';
-   let el=this.getValueElement(mode);
-   if (el) return el;
-   return createTextElement(mode);
-}
-
-participantIdManager.createTextElement=
-function(mode=null){
-   let el=crfHTML.createParagraph('');
-   let cell=this.getValueCell(mode);
-   //let oldEl=pM.getInputElement(mode);
-   cell.replaceChildren(el);
-   return el;
-}
-
-
-//get the button, create if not there yet
-participantIdManager.getInputButton=
-function(mode=null){
-   let fName='[getInputManage]';
-   //this.print(fName);
-   //this prevents from having two inputs; it is either local or global from the outset
-   let cell=this.getButtonCell(mode);
-   let el=cell.firstChild;
-   if (el) return el;
-   el=crfHTML.createButton(null,cell);
-   let that=this;
-   el.onclick=function(){that.manageId(mode);};
-   return el;
-}
-
-//callback that splits to edit or set/label mode
-
-participantIdManager.manageId=
-function(mode){
-   let fName='[manageId]';
-   this.print(fName);
-   //this can happen after object was created, so make sure current
-   //elements are used
-   //this.updateElements();
-   let x=this.getInputButton(mode);
-
-   if (x.value=="Set"){
-      this.setId(mode);
-      return;
-   }
-   if (x.value=="Edit"){
-      this.editId(mode);
-      return;
-   }
-}
-
-//set mode
-participantIdManager.setId=
-function(mode=null){
-   let fName='[setId]';
-   this.print(fName);
-   let el=this.getInputElement(mode);
-
-   this.print(fName+" value: "+el.value);
-   let pId=el.value;
-   let label=pId;
-   if (mode!="LOCAL"){
-      //extract from select
-      if (el.value<0) return;
-      let opt=el.options[el.selectedIndex];
-      label=opt.text;
-      pId=crfSetup.getStudyId(label);
-      //label=label.replace(/ \(Local: /,':');
-      //label=label.replace(/\)/,'');
-   }
-   this.setParticipantIdToCrfEntry(mode,pId);//no argument (should come from mode)
-   this.print(fName+" new value "+pId);
-   this.setLabelMode(mode,label);
-   this.updateCrfEntry();
-}
-
-participantIdManager.setLabelMode=
-function(mode,label){
-   let fName='[setLabelMode1]';
-
-   this.print(fName+' id '+label);
-   //this will give two for study and one entry for local
-   //let ids=pId.split(':');
-   let id=label;
-   if (mode!='LOCAL'){
-      if (label=='NOT SET')
-         id=label;
-      else
-         id=crfSetup.getStudyId(label);
-   }
-      
-
-   let textValue=this.createTextElement(mode);
-   this.print(fName+' textElement '+textValue);
-   textValue.innerText=id;
-
-   if (mode!="LOCAL" && label!='NOT SET'){
-      let loc=crfSetup.getLocalId(label);
-      this.print(fName+' setting local id '+loc);
-      if (this.isValid(loc)){
-         //pM.getParticipantIdFromCrfEntry('LOCAL');
-         let tValLocal=this.createTextElement('LOCAL');
-         tValLocal.innerText=loc;
-      }
-      //this.setParticipantIdToCrfEntry(pM,loc,'LOCAL');
-   }
-
-   let x=this.getInputButton(mode);//getInputManage
-   let readonly=this.isReadonly(mode);
-   if (readonly){
-      x.style.display="none";
-   }
-   x.value="Edit";
-
-   if (mode=='LOCAL')
-      this.generateButton.style.display='none';
-
-   
-}
-
-//edit mode
-participantIdManager.editId=
-function(mode){
-   this.setEditMode(mode);
-}
-
-
-participantIdManager.setEditMode=
-function(mode){
-
-   let fName='[setEditMode1]';
-   this.print(fName+' pM '+this+' mode '+mode);
-   //input
-   let el=this.createInputElement(mode);
-
-   let x=this.getInputButton(mode);
-   x.value="Set";
-
-   if (mode=='LOCAL'){
-      this.generateButton.style.display='block';
-      x.style.display='block';
-   }
-
-}
-
-participantIdManager.resetLocal=
-function(){
-   this.clearReadonly('LOCAL');
-   this.setEditMode('LOCAL');
-   this.resetButton.style.display='none';
-}
-
-//manage interaction to storage/CRF and study/LabKey
-participantIdManager.getParticipantField=
-function(){
-   return this.setup.getRows('studyData')[0]['SubjectColumnName'];
-}
-
-participantIdManager.getCrfEntryFieldName=
-function(mode=null){
-   if (mode=="LOCAL") return crfSetup.getLocalIdLabel();
-   return crfSetup.getStudyIdLabel();
-}
-
-participantIdManager.setParticipantIdToCrfEntry=
-function(mode,pId){
-   let id=pId;
-   this.data.getCrfEntry()[this.getCrfEntryFieldName(mode)]=id;
-}
-
-participantIdManager.getParticipantIdFromCrfEntry=
-function(mode=null){
-   return this.data.getCrfEntry()[this.getCrfEntryFieldName(mode)];
-}
-
-participantIdManager.isValid=
-function(name){
-   if (!name) return false;
-   if (name=="null") return false;
-   return true;
-}
-
-participantIdManager.verifyCrfStudyId=
-function(){
-   let fName='[verifyCrfStatusId]';
-   //is studyId already set for the crf
-   let studyId=this.getParticipantIdFromCrfEntry('STUDY');
-   let localId=this.getParticipantIdFromCrfEntry('LOCAL');
-   this.print(fName+' studyId '+studyId+' localId '+localId);
-   this.resetButton.style.display='none';
-   if (!studyId) return;
-   let originalMode=this.getMode();
-   if (originalMode=='LOCAL' && this.setup.getSettings("allowLocalIdChange")) {
-      this.resetButton.style.display='block';
-   }
-   else{
-      this.setReadonly('LOCAL');
-   }
-   this.setReadonly('STUDY');
-   this.setMode("STUDY");
-   this.setLabelMode('STUDY',this.setup.getParticipantLabel(this.data.getCrfEntry()));
-   //get registration map to fill local id
-   let that=this;
-   let completeVerification=function(){that.completeVerification(studyId);}
-   this.data.setRegistration(completeVerification);
-}
-   
-participantIdManager.completeVerification=
-function(studyId){
-   let fName='[completeVerification]';
-   //subject to content of localId
-   let rMapEntry=this.data.getRegistrationEntryMap(this.getCrfEntryFieldName('STUDY'))[studyId];
-    //try to set it from registration
-   let localId=rMapEntry[this.getCrfEntryFieldName('LOCAL')];
-   this.print(fName+' localId '+localId+' isNull '+(localId==null)+' is"null" '+(localId=="null"));
-   
-   let localIdFromEntry=this.getParticipantIdFromCrfEntry('LOCAL');
-   if (localIdFromEntry!=localId){
-      //update mismatches
-      this.setParticipantIdToCrfEntry('LOCAL',localId);
-      this.updateCrfEntry();
-   }
-   //ignore the one set in the crfEntry, studyId prevails
-   //if (!this.isValid(localId)) {
-   //   let localId=this.getParticipantIdFromCrfEntry('LOCAL');
-   //}
-   if (this.isValid(localId)) {
-      this.setReadonly('LOCAL');
-      this.setLabelMode('LOCAL',localId);
-   }
-   else{
-      this.setEditMode('LOCAL');
-   }
-   
-}
-
-

+ 0 - 193
web/crf/participantOverview.js

@@ -1,193 +0,0 @@
-var participantOverview={};
-
-participantOverview.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.scriptsLoaded(cb);};
-   LABKEY.Utils.requiresScript(["crf/crfSetup.js","crf/crfData.js","crf/crfHTML.js"],action);
-}
-
-participantOverview.scriptsLoaded=
-function(cb=null){
-   //if other script need init, just stack the init scripts
-   //let action=function(){runQuery.init(cb);}
-   crfData.setSetup(crfSetup);
-   crfHTML.init();
-   let initData=function(){crfData.init(cb);};
-   crfSetup.init(initData);
-}
-
-participantOverview.print=
-function(msg){
-   console.log(msg);
-}
-
-participantOverview.addObjectToIdFormMap=
-function(object,map,id,form){
-
-   if (!(id in map))
-      map[id]=new Object();
-   let fMap=map[id];
-
-   if (!(form in fMap))
-      fMap[form]=new Array();
-   fMap[form].push(object);
-
-}
-
-
-participantOverview.generateParticipantArray=
-function(){
-   let fName='generateParticipantArray';
-   this.print(fName);
-   let that=this;
-   let makeArray=function(){that.makeArray();};
-   let setRegistration=function(){crfData.setRegistration(makeArray);};
-   let action=function(){crfSetup.parseSetup(setRegistration);}
-   crfSetup.setContainers(action);
-}
-
-participantOverview.matchRegistration=
-function(entry){
-   let fName='matchRegistration';
-   let sF='participantStudyId';
-   let studyRegMap=crfData.getRegistrationEntryMap(sF);//should be unique for registration
-   let nS=Object.keys(studyRegMap).length;
-   //this.print(fName+' study registration entries '+nS);
-   let lF='participantLocalId';
-   let localRegMap=crfData.getRegistrationEntryMap(lF);//should be unique for registration
-   let nL=Object.keys(localRegMap).length;
-   //this.print(fName+' local registration entries '+nL);
-   if (entry[sF]){
-      if (entry[sF] in studyRegMap){
-         return studyRegMap[entry[sF]];
-      }
-      //failed to match study id
-   }
-   if (entry[lF]){
-      if (entry[lF] in localRegMap){
-         return localRegMap[entry[lF]];
-      }
-      //failed to match local id
-   }
-   return null;
-}
-
-
-participantOverview.makeArray=
-function(){
-   let fName='makeArray';
-   let entries=crfSetup.getEntryMap('crfEntries'); 
-   let n=Object.keys(entries).length;
-   this.print(fName+' entries '+n);
-   
-   let idField='participantStudyId';
-   let entryMap=new Object();
-
-   let statusMap=crfSetup.getEntryMap('formStatusAll');
-   let i=0;
-   let site=-1;
-   if (this.searchParams.has("site")){
-      site=this.searchParams.get("site");
-   }
-
-   for (let key in entries){
-      
-      let entry=entries[key];
-
-      let formStatus=statusMap[entry['FormStatus']]['formStatus'];
-      
-      if (formStatus=='Deleted'){
-         continue;
-      }
-      
-      if (site!=-1 && entry['Site']!=site)
-         continue;
-
-      let regEntry=this.matchRegistration(entry);
-      if (!regEntry){
-         //skip mismatched crfEntry
-         this.print(fName+' ['+entry['Key']+'] no match found ');
-         i++;
-         continue;
-      }
-      //link crfEntry to registration row
-      let idLabel=crfSetup.getParticipantLabel(regEntry);
-      let form=entry['Form'];
-      this.addObjectToIdFormMap(entry,entryMap,idLabel,form);
-   }
-   this.print('Found '+(n-i)+'/'+n+' participants');
-
-   this.showArray(entryMap);
-   //for (let idLabel in entryMap){
-   
-
-}
-
-participantOverview.showArray=
-function(entryMap){
-   let table=crfHTML.createTable('formDiv');
-   crfHTML.addStyle(table,"tOverview");
-   let formRows=crfSetup.getRows('dataForms');
-   let row=table.insertRow();
-   let cell=row.insertCell();
-
-   let stMap=crfSetup.getEntryMap('formStatusAll');
-   let that=this;
-
-   for (let i=0;i<formRows.length;i++){
-      let formName=formRows[i]['formName'];
-      cell=row.insertCell();
-      let tNode=crfHTML.createTextNode(formName,null,cell);
-      crfHTML.addStyle(cell,'small');
-   }
-
-   for (let idLabel in entryMap){
-      row=table.insertRow();
-      let cell=crfHTML.createTblHeader(null,row);
-      crfHTML.createTextNode(idLabel,null,cell);
-      cell.onclick=function(){that.openParticipant(idLabel);};
-      for (let i=0;i<formRows.length;i++){
-         let form=formRows[i]['Key'];
-         let count=new Object();
-         if (form in entryMap[idLabel]){
-            let ar=entryMap[idLabel][form];
-            for (let i=0;i<ar.length;i++){
-               let entry=ar[i];
-               let st=entry['FormStatus'];
-               if (!(st in count)) count[st]=0;
-               count[st]+=1;
-            }
-         }
-         let label="";
-         for (let s in count)
-            label+=stMap[s]['formStatus']+':'+count[s]+" ";
-         cell=row.insertCell();
-         crfHTML.createTextNode(label,null,cell);
-         crfHTML.addStyle(cell,'small');
-      }
-   }
-
-}
-
-participantOverview.openParticipant=
-function(idLabel){
-	let formUrl="participantPortal";
-	let params=new Object();
-	params.name=formUrl;
-   params['participantLabel']=idLabel;
-
-	//params.pageId="CRF";
-
-	//points to crf container
-	let containerPath=crfSetup.getContainer('CRF');
-        
-	// This changes the page after building the URL. 
-	//Note that the wiki page destination name is set in params.
-        
-	//let homeURL = LABKEY.ActionURL.buildURL("project", formUrl , containerPath, params);
-	let homeURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);
-   this.print("Redirecting to "+homeURL);
-	window.location = homeURL;
-
-}

+ 0 - 222
web/crf/participantPortal.js

@@ -1,222 +0,0 @@
-var participantPortal={};
-
-participantPortal.print=function(msg){
-   console.log(msg);
-}
-
-participantPortal.idField='participantStudyId';
-participantPortal.localIdField='participantLocalId';
-
-participantPortal.init=
-function(cb=null){
-   let that=this;
-   let action=function(){that.scriptsLoaded(cb);};
-   LABKEY.Utils.requiresScript(["crf/crfSetup.js","crf/crfData.js","crf/crfHTML.js","crf/crfRoleSelector.js","crf/formPortalNew.js"],action);
-}
-
-participantPortal.scriptsLoaded=
-function(cb=null){
-   //if other script need init, just stack the init scripts
-   //let action=function(){runQuery.init(cb);}
-   crfData.setSetup(crfSetup);
-   crfRoleSelector.set(crfSetup);
-   crfHTML.init();
-   let initFormPortal=function(){formPortal.init(cb);};
-   let initData=function(){crfData.init(initFormPortal);};
-   crfSetup.init(initData);
-}
-
-participantPortal.getParticipantMap=
-function(){
-   if (!("participantMap" in this)){
-      this.participantMap=new Object();
-      this.sortByParticipantId();
-   }
-   return this.participantMap;
-}
-  
-participantPortal.clearKeyMap=
-function(){
-   if (!("participantKeyMap" in this)){
-      this.participantKeyMap=new Object();
-      return;
-   }
-   Object.keys(this.participantKeyMap).forEach(key => delete this.participantKeyMap[key]);
-}
-
-participantPortal.addToKeyMap=
-function(key,value){
-   this.participantKeyMap[value]=key;
-}
-
-participantPortal.getFromKeyMap=
-function(value){
-   return this.participantKeyMap[value];
-}
-
-participantPortal.getParticipantArray=
-function(id,formId){
-   let fName='[getParticipantArray/'+id+','+formId+']';
-   //this.print(fName);
-   let pMap=this.getParticipantMap();
-   if (!(id in pMap))
-      pMap[id]=new Object();
-   if (!(formId in pMap[id]))
-      pMap[id][formId]=new Array();
-   return pMap[id][formId];
-}
-
-
-
-participantPortal.generateFormArray=
-function(){
-   let fName='[generateFormArray]';
-   this.print(fName);
-   //gang callbacks (last to first)
-   let that=this;
-   let makePortal=function(){that.makePortal();};
-   let setRegistration=function(){crfData.setRegistration(makePortal);};
-   let action=function(){crfSetup.parseSetup(setRegistration);}
-   crfSetup.setContainers(action);
-}
-
-participantPortal.sortByParticipantId=
-function(){
-   let fName='[sortByParticipantId]';
-   //this.print(fName);
-   //let pMap=this.getParticipantMap();
-   let rows=crfSetup.getRows('crfEntries');
-   for (let i=0;i<rows.length;i++){
-      let entry=rows[i];
-      let id=crfSetup.getParticipantLabel(entry);
-      if (!id) id="NONE";
-      let formId=entry['Form'];
-      let pArray=this.getParticipantArray(id,formId);
-      pArray.push(entry);
-      this.print(fName+' pushing '+id+','+formId);
-   }
-   this.printParticipantArray();
-}
-
-participantPortal.printParticipantArray=
-function(){
-   let fName='[printParticipantMap]';
-   this.print(fName);
-   let pMap=this.getParticipantMap();
-   for (let q in pMap){
-      for (let x in pMap[q])
-         this.print(fName+' ['+q+','+x+'] '+pMap[q][x].length);
-   }
-}
-
-
-participantPortal.makePortal=
-function(){
-   let that=this;
-   let updateParticipants=function(){that.updateParticipants();};
-   crfRoleSelector.makePortal(updateParticipants);
-   this.roleError=crfHTML.createParagraph('','formDiv');
-   let txt=crfHTML.createParagraph('Select participant','formDiv');
-   crfHTML.clearStyle(txt,'center');
-   this.participantSelect=crfHTML.createSelect(new Object(),'formDiv');
-   this.displayTable=crfHTML.createTable('formDiv');
-   this.participantSelect.onchange=function(){that.displayEntries();}
-
-   //start with all patients
-   this.updateParticipants();
-   
-   if (this.searchParams.get("role") && this.searchParams.get("site")){
-      let label=this.searchParams.get("role")+':'+this.searchParams.get("site");
-      crfRoleSelector.setRoleAndSite(label);
-      crfRoleSelector.onChange(updateParticipants);
-   }
-}
-
-participantPortal.updateParticipants=
-function(){
-   let fName='[participantPortal.updateParticipants]';
-   let roleAndSite=crfRoleSelector.getRoleAndSite();
-   //clear error
-   this.roleError.innerText='';
-   let site=null;
-   if (roleAndSite){
-      let ar=roleAndSite.split(':');
-      site=ar[1];
-      this.print(fName+' site '+site);
-   }
-   let regMap=crfData.getRegistrationEntryMap();
-   this.print(fName+' registration '+Object.keys(regMap).length);
-   //let idMap=crfData.getRegistrationMap(this.idField);
-   //let idLocalMap=crfData.getRegistrationMap(this.localIdField);
-   this.clearKeyMap();
-   let updatedMap=new Object();
-   for (q in regMap){
-      let key=regMap[q]['Key'];
-      let label=crfSetup.getParticipantLabel(regMap[q]);
-      this.print(fName+' key '+key+' label '+label+' site '+site);
-      this.addToKeyMap(key,label);
-      if (site && regMap[q]['site']!=site) continue;
-      updatedMap[key]=label;
-   }
-   updatedMap[1000]='NONE';
-   updatedMap[1001]='Add new participant';
-   crfHTML.addSelectOptions(this.participantSelect,updatedMap);
-   if (this.searchParams.get('participantLabel')){
-      this.participantSelect.value=this.getFromKeyMap(this.searchParams.get('participantLabel'));
-      this.displayEntries();
-   }
-}
-
-participantPortal.displayEntries=
-function(){
-   let fName='[displayEntries]';
-   let roleAndSite=crfRoleSelector.getRoleAndSite();
-   this.print(fName);
-   let formRows=crfSetup.getRows('dataForms');
-   
-
-   //let idRows=crfData.getRegistration();
-   let selectIdText=this.participantSelect.options[this.participantSelect.selectedIndex].text;
-   if (selectIdText=='Add new participant'){
-      let formId=crfSetup.getSettings('registrationFormId');
-      if (!formId){
-         alert('registrationFormId not set in settings!');
-         return;
-      }
-      let cb=function(_data,_crfEntry){formPortal.openForm(_crfEntry,roleAndSite);};
-      formPortal.createForm(formId,roleAndSite,cb);
-      return;
-   }
-
-
-   //let selectId=crfSetup.getStudyId(selectIdText);
-   let selectId=selectIdText;
-   //let formId=formIds[Object.keys(formIds)[0]];
-   //this.printParticipantArray();
-   this.print(fName+' rows '+this.displayTable.rows.length);
-
-   for (let i=0;i<formRows.length;i++){
-      let formId=formRows[i]['Key'];
-      let row=this.displayTable.rows[i];
-      if (!row) row=this.displayTable.insertRow(i);
-      let labelCell=row.cells[0];
-      let formName=crfSetup.getMap('dataForms')[formId];
-      if (!labelCell){
-         labelCell=row.insertCell();
-         labelCell.innerText=formName;
-         crfHTML.addStyle(labelCell,'medium');
-         crfHTML.addStyle(labelCell,'center');
-
-         //crfHTML.createParagraph(formName,null,labelCell);
-      }
-      let cell=row.cells[1];
-      if (!cell) {
-         cell=row.insertCell();
-         crfHTML.addStyle(cell,'stretch');
-      }
-      crfHTML.clear(cell);
-      let forms=this.getParticipantArray(selectId,formId);
-      formPortal.displayForms(cell,forms,roleAndSite,formId,selectIdText,this.roleError);
-      this.print(fName+' ['+selectId+'/'+formId+'] forms '+forms.length);
-   }
-}

文件差异内容过多而无法显示
+ 0 - 0
web/crf/pdfkit.standalone.js


+ 0 - 8
web/crf/pdfkit.standalone.js.license

@@ -1,8 +0,0 @@
-MIT LICENSE
-Copyright (c) 2014 Devon Govett
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 206
web/crf/runQuery.js

@@ -1,206 +0,0 @@
-var runQuery={};
-
-runQuery.print=
-function(msg){
-   console.log(msg);
-}
-
-runQuery.insertRows=
-function(schema,query,rows,action=null,container=null,failure=null){
-   this.modifyRows('insert',schema,query,rows,action,container);
-}
-
-runQuery.deleteRows=
-function(schema,query,rows,action=null,container=null,failure=null){
-   this.modifyRows('delete',schema,query,rows,action,container);
-}
-
-runQuery.modifyRows=
-function(mode,schema,query,rows,action=null,container=null,failure=null){
-	//insert rows to container/schema/query and return with action
-	let fName="[cvModifyRows/"+mode+"]";
-	this.print(fName+' '+schema+'/'+query);
-	let qconfig=new Object();
-	qconfig.schemaName=schema;
-	qconfig.queryName=query;
-   if (container) qconfig.containerPath=container;
-   if (!rows) {
-      this.print(fName+' rows '+rows);
-      return;
-   }
-	qconfig.rows=rows;
-   qconfig.success=function(data){;};
-	if (action) qconfig.success=action;
-   if (mode=='insert') LABKEY.Query.insertRows(qconfig);
-   if (mode=='update') LABKEY.Query.updateRows(qconfig);
-   if (mode=='delete') LABKEY.Query.deleteRows(qconfig);
-	this.print(fName+" done");
-}
-
-runQuery.selectRows=
-function(schema,query,filters=[],action=null, container=null, failure=null, columns=null){
-	let fName="[cvSelectRows]";
-	this.print(fName+' '+schema+' '+query+' '+container);
-	let qconfig=new Object();
-	qconfig.schemaName=schema;
-	qconfig.queryName=query;
-   if (container) qconfig.containerPath=container;
-   qconfig.filterArray=filters;
-   qconfig.success=function(data){;};
-	if (action) qconfig.success=action;
-   if (failure) qconfig.failure=failure;
-   if (columns) qconfig.columns=columns;
-	LABKEY.Query.selectRows(qconfig);
-	this.print(fName+" done");
-
-}
-
-
-runQuery.makeQuery=
-function(targetObject,containerName,queryName,fieldName=null,filterArray=null,schemaName=null){
-   //call with makeQuery(config.formConfig,getContainer(name),...
-	let e=new Object();
-	e.containerName=containerName;
-	e.queryName=queryName;
-	e.fieldName=queryName;
-   if (fieldName) e.fieldName=fieldName;
-	e.filterArray=[];
-   if (filterArray) e.filterArray=filterArray;
-   e.targetObject=targetObject;
-   e.schemaName='lists';
-   if (schemaName) e.schemaName=schemaName;
-	return e;
-}
-
-runQuery.makeModification=
-function(mode,containerName,schemaName,queryName,rows){
-	let e=new Object();
-   e.mode=mode;
-	e.containerName=containerName;
-   e.schemaName=schemaName;
-	e.queryName=queryName;
-	e.rows=rows;
-   return e;
-}
-
-
-runQuery.getDataFromQueries=
-function(parentClass,queryArray,cb){
-	//queryArray should contain elements created with make query
-	//- 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
-	//
-	this.afterQuery(new Object(),-1,parentClass,queryArray,cb);
-}
-
-runQuery.modifyDataFromQueries=
-function(parentClass,queryArray,cb){
-	//queryArray should contain elements created with make query
-	//- 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
-	//
-	this.afterQueryUpload(new Object(),-1,parentClass,queryArray,cb);
-}
-
-
-
-runQuery.afterQuery=
-function(data,id,parentClass,queryArray,cb){
-   let fName='[afterQuery]';
-
-	if (id>-1){
-	   let e1=queryArray[id];
-		let fieldName=e1.fieldName;
-		parentClass.print(fName+' ['+fieldName+']: '+data.rows.length);
-		e1.targetObject[fieldName]=data;
-	}
-	id+=1;
-	if (id==queryArray.length) {
-		if (cb) cb();
-		return;
-	}
-   
-
-	let e=queryArray[id];
-   for (v in e){
-      parentClass.print(fName+' value ['+v+'] '+e[v]);
-   }
-
-	let containerPath=parentClass.getContainer(e.containerName);
-   if ("containerPath" in e){
-      parentClass.print(fName+' containerPath '+e.containerPath);
-      containerPath=e.containerPath;
-   }
-
-	let schemaName="lists";
-	if ("schemaName" in e){
-		parentClass.print(fName+' schemaName='+e.schemaName);
-		schemaName=e.schemaName;
-	}
-   let columns=null;
-	if ("columns" in e){
-		parentClass.print(fName+' columns='+e.columns);
-		columns=e.columns;
-	}
-	//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)];
-   let filterArray=[];
-	if ("filterArray" in e)
-		filterArray=e.filterArray;
-	
-	//qconfig.filterArray=[LABKEY.Filter.create('formStatus',1)]
-   let that=this;
-	let action=function(data){that.afterQuery(data,id,parentClass,queryArray,cb);};
-	let failure=function(errorInfo,responseObj){that.onTAFailure(parentClass,errorInfo,responseObj);};
-   this.selectRows(schemaName,e.queryName,filterArray,action, containerPath, failure, columns);
-
-}
-
-runQuery.afterQueryUpload=
-function(data,id,parentClass,queryArray,cb){
-   let fName='[afterQueryUpload]';
-
-	if (id>-1){
-	   let x=queryArray[id];
-		let q=x.queryName
-		parentClass.print(fName+' ['+q+']: '+data.rows.length);
-	}
-	id+=1;
-	if (id==queryArray.length) {
-		if (cb) cb();
-		return;
-	}
-   
-
-	let e=queryArray[id];
-   for (v in e){
-      parentClass.print(fName+' value ['+v+'] '+e[v]);
-   }
-	let containerPath=parentClass.getContainer(e.containerName);
-   if ("containerPath" in e){
-      parentClass.print(fName+' containerPath '+e.containerPath);
-      containerPath=e.containerPath;
-   }
-   let that=this;
-	let action=function(data){that.afterQueryUpload(data,id,parentClass,queryArray,cb);};
-	let failure=function(errorInfo,responseObj){that.onTAFailure(parentClass,errorInfo,responseObj);};
-   this.modifyRows(e.mode,e.schemaName,e.queryName,e.rows,action,containerPath,failure);
-	
-
-}
-
-
-runQuery.onTAFailure=
-function(parentClass, errorInfo, responseObj){
-   //don't have configObject to rely to
-   parentClass.print('[afterQuery]: Failure: '+errorInfo.exception);
-
-}
-

+ 0 - 59
web/crf/variableList.js

@@ -1,59 +0,0 @@
-var variableList={};
-
-variableList.parseVariables=
-function(pars){
-   if (!pars) return new Object();
-   let pA=pars.split(";");
-   let q=new Object();
-   for (let i=0;i<pA.length;i++){
-      let vA=pA[i].split('=');
-      q[vA[0]]=vA[vA.length-1];
-   }
-   return q;
-}
-
-variableList.printVariables=
-function(parentClass,q){
-	let fName="[printVariables]";
-	for (let x in q){
-		parentClass.print(fName+" ["+x+"] "+q[x]);
-	}
-}
-
-variableList.hasVariable=
-function(q,varName){
-   if (q && varName in q)
-      return true;
-
-   return false;
-}
-
-variableList.isFilterList=
-function(v){
-   if (typeof(v)!='string') return false;
-   if (v.search(';')==-1) return false;
-   return true;
-}
-
-variableList.convertToDictionary=
-function(rows){
-   let x=new Array();
-	for (let i=0;i<rows.length;i++){
-		let n=rows[i]['name'];
-		let v=rows[i]['value'];
-		x[n]=v;
-	}
-   return x;
-}
- 
-variableList.convertToAssociatedArray=
-function(rows,fieldName="name"){
-   let x=new Object();
-	for (let i=0;i<rows.length;i++){
-		let n=rows[i][fieldName];
-		x[n]=rows[i];
-	}
-   return x;
-}
-
-

+ 0 - 98
web/crf/webdav.js

@@ -1,98 +0,0 @@
-var webdav={};
-
-webdav.set=
-function(parentClass){
-   this.parent=parentClass;
-}
-   
-webdav.uploadFile=
-function(file,context){
-
-	let url=LABKEY.ActionURL.getBaseURL();
-	url+='_webdav';
-	url+=LABKEY.ActionURL.getContainer();
-	url+='/@files';
-   url+='/'+context['dirName'];
-
-	this.parent.print('uploadFile url: '+url);
-	let uploadConfig=new Object();
-	uploadConfig.file=file;
-	uploadConfig.context=context;
-	uploadConfig.url=url;
-   let that=this;
-	uploadConfig.success=function(cfg){that.afterBaseDir(cfg);};
-	uploadConfig.failure=function(cfg){that.tryMakeDir(cfg);};
-	this.webdavCheck(uploadConfig);
-}
-
-webdav.afterBaseDir=
-function(cfg){
-	this.parent.print('afterBaseDir');
-	cfg.url+='/'+cfg.context['ID'];
-   let that=this;
-	cfg.success=function(x){that.afterIDDir(x);};
-	cfg.failure=function(x){that.tryMakeDir(x);};
-	this.webdavCheck(cfg);
-}
-
-webdav.afterIDDir=
-function(cfg){
-	this.parent.print('afterIDDir');
-	this.parent.print('Uploading '+cfg.file.name);
-	let suf=cfg.file.name.split('.').pop();
-	cfg.url+='/'+cfg.context['ID']+'.'+suf;
-   cfg.data=cfg.file;
-   let that=this;
-	cfg.success=function(x){that.afterUpload(x);};
-	cfg.failure=function(x){that.onFailure(x);};
-	this.webdavPut(cfg);
-}
-
-webdav.afterUpload=
-function(cfg){
-	this.parent.print('afterUpload');
-}
-
-webdav.tryMakeDir=
-function(cfg){
-	this.parent.print('tryMakeDir '+cfg.url);
-   let that=this;
-	cfg.failure=function(x){that.onFailure(x);};
-	this.webdavMakeDir(cfg);
-}
-
-
-webdav.request=
-function (cfg,verb,data){
-	this.parent.print('request['+verb+'] '+cfg.url);
-	let connRequest=new XMLHttpRequest();
-   let that=this;
-   let action=function(connRequest,cfg){that.checkResponse(connRequest,cfg);};
-	connRequest.addEventListener("loadend",action);
-	connRequest.open(verb, cfg.url);
-	connRequest.send(data);
-	//this.print('request['+verb+'] sent');
-}
-
-webdav.checkResponse=
-function(xrq,cfg){
-	//this.print('checkResponse: readyState '+xrq.readyState);
-	//this.print('checkResponse: status '+xrq.status);
-	if (xrq.status<400) {
-		//client errors 400-499
-		//server errors 500-599
-		cfg.success(cfg);
-		return;
-	}
-	cfg.status=xrq.status;
-	cfg.failure(cfg);
-}
-
-webdav.webdavMakeDir=function(cfg){ this.request(cfg,'MKCOL',null);}
-webdav.webdavCheck=function(cfg) { this.request(cfg,'GET',null);}
-webdav.webdavPut=function(cfg) { this.request(cfg,'PUT',cfg.data);}
-
-
-webdav.onFailuer=function(cfg){
-	this.parent.print('request failed with status='+cfg.status);
-}

部分文件因为文件数量过多而无法显示