Browse Source

Changed collecting data routines to recursively pick up data

Andrej Studen 3 years ago
parent
commit
adcae83557
1 changed files with 270 additions and 223 deletions
  1. 270 223
      web/crf/crfVisit.js

+ 270 - 223
web/crf/crfVisit.js

@@ -18,9 +18,15 @@ function print(msg){
 	el.value+="\n"+msg;
 }
 
+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.document.getElementById(config.crfRefId).innerHTML;
+	return	config.formConfig.crfEntry['entryId'];
 }
 
 function onFailure(errorInfo, options, responseObj){
@@ -124,119 +130,11 @@ function readonlySetup(){
 	return setup;
 }
 
-function afterFormConfig(formConfig,data){
+//afterFormConfig replaced by afterFormSetup
 
-	let debug=true;
-	if (debug) print("afterFormConfig ["+data.rows.length+"]");
-	formConfig.formSetup=data;
-
-	//get list of queries
-	let fields=formConfig.formSetup.metaData.fields;
-
-	if (debug) print("generateForm: fields: "+fields);
-	let field="NONE";
-	//if (debug) printTableSetup(config,data);
-	for (f in fields){
-		if (fields[f]['name']!='queryName') continue;
-		field=fields[f];
-		break;
-	}
-	if (debug) print("generateForm: field: "+field);
-	let lookup=field.lookup;
-	if (debug) print("generateForm: lookup: "+lookup);
-	let qconfig=new Object();
-	qconfig.containerPath=config.containerPath;
-	qconfig.schemaName=lookup.schemaName;
-	qconfig.queryName=lookup.queryName;
-		
-	//qconfig.filterArray=[LABKEY.Filter.create(lookup.keyColumn,entry['queryName'])];
-	qconfig.filterArray=[];
-	qconfig.success=function(data){afterFormSetupLookup(formConfig,data)};
-	LABKEY.Query.selectRows(qconfig);
-}
+//afterFormSetupLookup replaced by afterFormDatasets
 
-function afterFormSetupLookup(formConfig,data){
-	//walk through the list of datasets/list and generate tables for each list
-	let debug=true;
-
-	formConfig.formSetupLookup=data;
-
-	let rows=formConfig.formSetup.rows;
-	//extract list of forms from formConfig
-	for (let i=0;i<rows.length;i++){
-
-		//each from has multiple lists associated with it
-		if (debug) print("generateForm ["+i+"/"+rows.length+"]");
-
-		let entry=rows[i];
-		//this is actually a pointer into another list (==lookup)
-		//another selectRows is needed to actually get the name for the queryName
-		
-		//id : entry[queryName]
-		//name: dentry[queryName]
-	
-		let queryId=entry['queryName'];
-
-		//walk over keys to get the right lookup entry
-		let lookupRows=formConfig.formSetupLookup.rows;
-		let dentry=undefined;
-		for (let j=0;j<lookupRows.length;j++){
-			
-			if (lookupRows[j].Key!=queryId)
-				continue;
-			dentry=lookupRows[j];
-			break;
-		}
-		if (dentry===undefined){
-			print("generateForm ["+i+"] no list found");
-			return;
-		}
-		if (debug)
-			for (f in dentry) 
-				print("generateFormLookup field: "+f+" value: "+dentry[f]);
-	
-		let queryName=dentry["queryName"];
-
-		if (debug) print("generateFormLookup: ID: "+queryId+" name: "+queryName);
-	
-		//update fields for review
-		while (1){
-			//queryName already recorded
-			if (queryName in config.fields) break;
-			//reviews dont go into fields
-			if (entry['showFlag']=='REVIEW') break;
-				
-			config.fields[queryName]=new Object();
-			break;
-		}
-		
-		while(1){
-			if (queryId in config.queryMap) break;
-			//reviews dont go into fields
-			if (entry['showFlag']=='REVIEW') break;
-
-			config.queryMap[queryId]=queryName;
-			break;
-		}
-	
-		if (queryName in config.fields){
-			let field=config.fields[queryName];
-
-			field.title=entry["title"];
-			field.queryId=queryId;
-		}
-
-		if (debug) print("entry[showFlag]: "+entry["showFlag"]);
-
-		let additionalData=new Object();
-		setAdditionalData(additionalData,entry);
-		//section fits one dataset/list
-		generateSection(formConfig,queryName,entry["title"],queryName, additionalData);
-	}
-
-}
-
-function generateSection(formConfig, sectionName, sectionTitle, listName, additionalData){
+function generateSection(sectionName, sectionTitle, listName, additionalData){
 
 
 	let formName=config.masterForm;//this is HTML designator of area on page
@@ -289,9 +187,10 @@ function generateSection(formConfig, sectionName, sectionTitle, listName, additi
 
 		
 	let setup=fullAccessSetup(listName);
-	if (formConfig.formStatus=="Submitted")
+	let formStatus=config.formConfig.formStatus;
+	if (formStatus=="Submitted")
 		setup=readonlySetup();
-	if (formConfig.formStatus=="Approved")
+	if (formStatus=="Approved")
 		setup=readonlySetup();
 	
 	if ("isReview" in additionalData){
@@ -302,14 +201,14 @@ function generateSection(formConfig, sectionName, sectionTitle, listName, additi
 
 	
 	setup.unique=true;
-	generateTable(formConfig,listName,divTable.id,true,additionalData,setup);
+	generateTable(listName,divTable.id,true,additionalData,setup);
 	
 	if (debug) print("generate master table: done");
 
 	let generateSubTable=true;
-	if (formConfig.formStatus=="Submitted")
+	if (formStatus=="Submitted")
 		generateSubTable=false;
-	if (formConfig.formStatus=="Approved")
+	if (formStatus=="Approved")
 		generateSubTable=false;
 	
 	if (! ("showFlag" in additionalData) ) generateSubTable=false;
@@ -321,7 +220,7 @@ function generateSection(formConfig, sectionName, sectionTitle, listName, additi
 
 		let setup=fullAccessSetup(qName);
 		//if (readonly) setup=readonlySetup(config);
-		generateTable(formConfig,qName,dName,false,additionalData,setup);
+		generateTable(qName,dName,false,additionalData,setup);
 	}
 
 	print("generate review");
@@ -338,7 +237,7 @@ function generateSection(formConfig, sectionName, sectionTitle, listName, additi
 	//assume we already have listId (content of config.setupQueryName is listId)
 	//we need listName also
 	//qconfig.queryName=config.setupQueryName;
-	generateReview(formConfig,divReview.id,divReviewList.id,listName);
+	generateReview(divReview.id,divReviewList.id,listName);
 }
 
 
@@ -720,8 +619,8 @@ function generateReviewSection2(pid){
 	}
 }
 
-function generateReview(formConfig,divReviewId,divReviewListId, listName){
-	let listId=config.fields[listName].queryId;
+function generateReview(divReviewId,divReviewListId, listName){
+	let listId=config.formConfig.fields[listName].queryId;
 
 	let debug=true;
 	if (debug) print("Generate review for: "+listId);
@@ -735,7 +634,8 @@ function generateReview(formConfig,divReviewId,divReviewListId, listName){
 	reviewSetup.addApply="Add Review";
 
 	let generateTableFlag=true;
-	if (formConfig.formStatus == "Approved" ){
+	let formStatus=config.formConfig.formStatus;
+	if (formStatus == "Approved" ){
 		delete reviewSetup.addApply;
 		reviewSetup.readonlyFlag=function(vName){return false;}
 		generateTableFlag=false;
@@ -761,7 +661,7 @@ function generateReview(formConfig,divReviewId,divReviewListId, listName){
 	if (! generateTableFlag) return;
 
 	
-	generateTable(formConfig,"reviewComments",divReviewId,false,new Object(),reviewSetup);
+	generateTable("reviewComments",divReviewId,false,new Object(),reviewSetup);
 }	
 
 function setListVisibility(setup,additionalData,readonlyFlag){
@@ -918,7 +818,7 @@ function generateButton(divName,title,buttonName,callback){
 
 
 
-function generateTable(formConfig,listName,divName,unique,additionalData,setup){
+function generateTable(listName,divName,unique,additionalData,setup){
 
 	let debug=true;
 	
@@ -936,7 +836,7 @@ function generateTable(formConfig,listName,divName,unique,additionalData,setup){
 	for (f in setup.filters){
 		qconfig.filterArray.push(LABKEY.Filter.create(f,setup.filters[f]));
 	}
-	qconfig.success=function(data){populateTable(formConfig, data,divName,unique,additionalData,setup)};
+	qconfig.success=function(data){populateTable(data,divName,unique,additionalData,setup)};
 	LABKEY.Query.selectRows(qconfig);
 }
 
@@ -956,13 +856,13 @@ function printTableSetup(data){
 }
 
 
-function populateTable(formConfig, data,divName,unique,additionalData,setup){
+function populateTable(data,divName,unique,additionalData,setup){
 	//generate and populate table with the first suitable entry
 	let debug=true;
 	//avoid resetting of values
-	if (!(data.queryName in formConfig.dataFields))
-		formConfig.dataFields[data.queryName]=data.metaData.fields;
-
+	if (!(data.queryName in config.formConfig.dataFields))
+		config.formConfig.dataFields[data.queryName]=data.metaData.fields;
+	//changing to config.formConfig.dataQueries[data.QueryName].fields
 
 	if (debug){
 		print("populateTable Query: "+data.queryName+" divName: "+divName+" setup: "+setup);
@@ -977,12 +877,12 @@ function populateTable(formConfig, data,divName,unique,additionalData,setup){
 	if (debug)
 		print("Data: nrows "+data.rows.length);
 	
-	//copy values from queryName to formConfig.entries
-	if (data.rows.length > 0) formConfig.entries[data.queryName]=data.rows[0];
+	//copy values from queryName to formConfig.entries (if it exists)
+	if (data.rows.length > 0) config.formConfig.entries[data.queryName]=data.rows[0];
 	
 	//this is the current data snapshot
-	if (data.queryName in formConfig.entries)
-		entry=formConfig.entries[data.queryName];
+	if (data.queryName in config.formConfig.entries)
+		entry=config.formConfig.entries[data.queryName];
 	
 	
 	let tb=config.document.createElement('table');
@@ -990,7 +890,7 @@ function populateTable(formConfig, data,divName,unique,additionalData,setup){
 	config.document.getElementById(divName).appendChild(tb);
 
 	//this are the fields (probably constant)
-	let fields=formConfig.dataFields[data.queryName];
+	let fields=config.formConfig.dataFields[data.queryName];
 	for (f in fields){
 		let field=fields[f];
 		if (field.hidden) continue;
@@ -2087,7 +1987,7 @@ function generateMasterForm(){
 	setFormConfig();
 }
 
-function populateBasicData(config){
+function populateBasicData(){
 	
 	config.document.getElementById('eudraCTNumber').innerHTML=
 		config.formConfig.crfEntry.EudraCTNumber;
@@ -2108,73 +2008,26 @@ function afterConfig(){
 	let debug=true;
 
 	if (debug)
-		print("generateMasterForm");	
-	
-	let selectRows=new Object();
-	selectRows.containerPath=config.containerPath;
-	selectRows.schemaName='lists';
-	selectRows.queryName='crfEntry';
-	selectRows.filterArray=[LABKEY.Filter.create('entryId',getCRFref())];
+		print("afterConfig");	
 	
-	let formConfig=new Object();
-	//selectRows.success=function(data){populateBasicData(config,data)};
-	selectRows.success=function(data){afterCrf(formConfig,data)};
-	LABKEY.Query.selectRows(selectRows);
-}
-
-//requires populateBasicData
-function afterCrf(formConfig,data){
-	formConfig.crfEntry=data.rows[0];
 	//schedule basic data for later
-	populateBasicData(config);
+	populateBasicData();
 
-	let selectRows=new Object();
-	selectRows.containerPath=config.containerPath;
-	selectRows.schemaName='lists';
-	selectRows.queryName='FormStatus';
-	selectRows.filterArray=[];
-	
-	selectRows.success=function(data){afterFormStatus(formConfig,data)};
-	LABKEY.Query.selectRows(selectRows);	
-
-
-	//use crfEntry['FormStatus'] to determine what configuration to display
-	//reviewMode equivalence table:
-	//
-	//FormStatus	reviewMode
-	//In Progress	undefined/EDIT
-	//Review Pending undefined/EDIT
-	//Submitted	REVIEW
-	//Approved	APPROVED
-	
-	//two level indirect - 
-	//
-	//1. learn of the FormStatus options by reading in the FormStatus list
-	//
-	//2. Load the crfEntry for this crfId 
-}
-	
-
-	
-function afterFormStatus(formConfig, data){
-	print("afterFormStatus: ");
-	formConfig.formStatusData=data;
-	
-	let rows=formConfig.formStatusData.rows;
+	let rows=config.formConfig.formStatusData.rows;
 
 	for (let i=0; i<rows.length; i++){
 		let key=rows[i].Key;
-		if (formConfig.crfEntry["FormStatus"]!=key)
+		if (config.formConfig.crfEntry["FormStatus"]!=key)
 			continue;
-		formConfig.formStatus=rows[i].formStatus;
+		config.formConfig.formStatus=rows[i].formStatus;
 		break;
 	}
+	let formStatus=config.formConfig.formStatus;
 
-	print("Generating buttons for formStatus \""+
-			formConfig.formStatus+"\"");
+	print("Generating buttons for formStatus \""+ formStatus+"\"");
 	
 	let done="FALSE";
-	if (formConfig.formStatus=="Submitted"){
+	if (formStatus=="Submitted"){
 		generateButton("submitDiv","Complete submission",
 			"Upload to database",onDatabaseUpload);
 		generateButton("submitDiv","Review submission",
@@ -2183,7 +2036,7 @@ function afterFormStatus(formConfig, data){
 			"Remove CRF form",onRemoveCRF);
 		done="TRUE";
 	}
-	if (formConfig.formStatus=="Approved"){
+	if (formStatus=="Approved"){
 		generateButton("submitDiv","Review submission",
 			"Restore form for further review",onUpdateForReview);
 		generateButton("submitDiv","Print form",
@@ -2191,6 +2044,7 @@ function afterFormStatus(formConfig, data){
 		done="TRUE";
 	}
 	if (done=="FALSE"){
+		//all other states, particularly Review and In progress
 		generateButton("submitDiv","Complete submission",
 			"Submit",onSubmit);
 		generateButton("submitDiv","Remove submission",
@@ -2202,30 +2056,30 @@ function afterFormStatus(formConfig, data){
 	print('Here');
 
 
-	//schedule actual forms
-	config.fields=new Object();	
-	config.queryMap=new Object();
+	//here we should get data. For now, just initialize objects that will hold data
+	config.formConfig.dataFileds=new Object();
+	config.formConfig.entries=new Object();
+	setDataLayout(afterDataLayout);//callback is afterDataLayout
+}
+	
+function afterDataLayout(){
 
-	//data and layout of actual forms
-	//filled in generateTable
-	formConfig.entries=new Object();
-	formConfig.dataFields=new Object();
+	setData(afterData);//callback is afterData
+}
 
-	let configSelectRows=new Object();
-	configSelectRows.containerPath=config.containerPath;
-	configSelectRows.schemaName='lists';
-	configSelectRows.queryName=config.setupQueryName;
-	//this is new
-	configSelectRows.queryName="FormSetup";
-	configSelectRows.filterArray=[
-		LABKEY.Filter.create("formName",config.formId)];
+function afterData(){
 
-	print('select rows into afterFormConfig id: '+config.formId);
-	configSelectRows.success=function(data){
-		afterFormConfig(formConfig,data);};
-	configSelectRows.failure=onFailure;
-	//function(errorTxt){print("generateForm fail" + errorTxt)};
-	LABKEY.Query.selectRows(configSelectRows);
+	let rowsSetup=config.formConfig.formSetup.rows;
+	for (let i=0;i<rowsSetup.length;i++){
+		let entry=rowsSetup[i];
+		print("entry[showFlag]: "+entry["showFlag"]);
+		let queryName=config.formConfig.queryMap[entry['queryName']];
+			
+		let additionalData=new Object();
+		setAdditionalData(additionalData,entry);
+		//section fits one dataset/list
+		generateSection(queryName,entry["title"],queryName, additionalData);
+	}
 
 }
 
@@ -2245,7 +2099,8 @@ function setFormConfig(){
 	selectRows.containerPath=config.containerPath;
 	selectRows.schemaName='lists';
 	selectRows.queryName='crfEntry';
-	selectRows.filterArray=[LABKEY.Filter.create('entryId',getCRFref())];
+	//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);
@@ -2305,6 +2160,21 @@ function afterStudy(data){
 	let selectRows=new Object();
 	selectRows.containerPath=config.containerPath;
 	selectRows.schemaName='lists';
+	selectRows.queryName='FormStatus';
+	selectRows.filterArray=[];
+	
+	selectRows.success=afterFormStatus;
+	LABKEY.Query.selectRows(selectRows);	
+
+}
+
+function afterFormStatus(data){
+	print("afterFormStatus: ");
+	config.formConfig.formStatusData=data;
+	
+	let selectRows=new Object();
+	selectRows.containerPath=config.containerPath;
+	selectRows.schemaName='lists';
 	selectRows.queryName='FormSetup';
 	selectRows.filterArray=[LABKEY.Filter.create('formName',config.formId)];
 	selectRows.success=afterFormSetup;
@@ -2319,6 +2189,8 @@ function afterFormSetup(data){
 			config.formConfig.formSetup.rows.length);
 
 	let fields=config.formConfig.formSetup.metaData.fields;
+
+	//get the lookup for queryName column
 	let formQueryName='queryName';
 	let field="NONE";
 	for (f in fields){
@@ -2328,7 +2200,7 @@ function afterFormSetup(data){
 	}
 	let lookup=field.lookup;
 
-	print("Getting dataset names from :"+lookup.queryName);
+	print("Getting dataset names from "+lookup.queryName);
 	let selectRows=new Object();
 	selectRows.containerPath=config.containerPath;
 	selectRows.schemaName=lookup.schemaName;
@@ -2339,23 +2211,51 @@ function afterFormSetup(data){
 }
 
 function afterFormDatasets(data){
+	print('afterFormDatasets: '+data.rows.length);
 	config.formConfig.formDatasets=data;
 	config.formConfig.fields=new Object();
 	config.formConfig.queryMap=new Object();
-	for (let i=0;i<config.formConfig.formSetup.rows.length;i++){
-		let entry=config.formConfig.formSetup.rows[i];
+
+	let rows=config.formConfig.formSetup.rows;
+	for (let i=0;i<rows.length;i++){
+		let entry=rows[i];
 		let queryId=entry['queryName'];
-		for (let j=0;j<config.formConfig.formDatasets.rows.length;j++){
-			if (queryId!=config.formConfig.formDatasets.rows[j]['Key']) continue;
-			let qName=config.formConfig.formDatasets.rows[j]['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){
+			//already in fields
+			if (qName in config.formConfig.fields) break;
+			//review fields don't go into fields
+			if (entry['showFlag']=='REVIEW' ) break;
+			//add
 			config.formConfig.fields[qName]=new Object();
+			break;
+		}
+
+		while(1){
+			//already done
+			if (queryId in config.formConfig.queryMap) break;
+			//skip review fields
+			if (entry['showFlag']=='REVIEW' ) break;
+			//add
 			config.formConfig.queryMap[queryId]=qName;
-			let field=config.formConfig.fields[qName];
-			field.title=entry['title'];
-			field.queryId=queryId;
-			//print("     "+config.formConfig.formDatasets.rows[j]['queryName']);
 			break;
 		}
+		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){
@@ -2366,6 +2266,153 @@ function afterFormDatasets(data){
 
 }
 
+//>>>>>>>>>>>>>>>>>new>>>>>>>>>>>>
+
+function setDataLayout(cb){
+	let rowsSetup=config.formConfig.formSetup.rows;
+	config.formConfig.dataQueries=new Object();
+	config.formConfig.lookup=new Object();
+	for (let i=0;i<rowsSetup.length;i++){
+		let entry=rowsSetup[i];
+		let queryName=config.formConfig.queryMap[entry['queryName']];
+		config.formConfig.dataQueries[queryName]=new Object();
+		if (entry['showQuery']!="NONE"){
+			config.formConfig.dataQueries[entry['showQuery']]=new Object();
+		}
+	}
+	//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';
+		//we are only interested in metadata
+		selectRows.success=function(data){afterDatasets(data,cb);}
+		LABKEY.Query.selectRows(selectRows);
+	}
+}
+
+
+//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.columns=field.lookup.keyColumn+","+field.lookup.displayColumn;
+		//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 Object();//key to value
+	lObject.ValToKey=new Object();//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];
+	}
+	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){
+	//collect data and execute callback cb
+
+
+	for (q in config.formConfig.dataQueries){
+		config.formConfig.dataQueries[q].collectingData="STARTED";
+		let selectRows=new Object();
+		selectRows.queryName=q;
+		selectRows.schemaName='lists';
+		selectRows.filterArray=[LABKEY.Filter.create("crfRef",getCRFref())];
+		selectRows.success=function(data){assembleData(data,cb);};
+		LABKEY.Query.selectRows(selectRows);
+	}
+}
+
+function assembleData(data,cb){
+	config.formConfig.dataQueries[data.queryName].rows=data.rows;
+	config.formConfig.dataQueries[data.queryName].collectingData="FINISHED";
+	for (q in config.formConfig.dataQueries){
+		let dq=config.formConfig.dataQueries[q];
+		//print("assembleData ["+q+"]: "+dq.collectingData);
+		if (dq.collectingData=="STARTED") return;
+	}
+	cb();
+}
+
 //function loadFile(config){
 //
 //	let file=config.fb.files[0];