Procházet zdrojové kódy

Adding storage to datasets

Andrej Studen před 5 roky
rodič
revize
c4eb652066

+ 83 - 0
views/reviewVisit0.html

@@ -0,0 +1,83 @@
+<style>
+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}
+
+div.d1 {text-align:center; width=400px; background-color:#e0e0e0;
+        font-size:      20px; margin-bottom:20px}
+</style>
+
+<table cellspacing="2" cellpadding="5" border="0">
+<tr><td>CRF ID: </td><td><strong id="crfRefId">1583163135258</strong></td></tr>
+<tr><td>Eudra CT Number: </td><td><strong id="eudraCTNumber">Loading</strong></td></tr>
+<tr><td>Study Sponsor: </td><td><strong id="studySponsor">Loading</strong></td></tr>
+<tr><td>Study Coordinator: </td><td><strong id="studyCoordinator">Loading</strong></td></tr>
+<tr><td>Site: </td><td><strong id="siteName">Loading</strong></td></tr>
+<tr><td>Investigator: </td><td><strong id="investigatorName">Loading</strong></td></tr>
+</table>
+
+<form name="visitForm" id="visitForm">
+
+</form>
+
+<div id="submitDiv"/>
+
+
+<div id="errorDiv" style="display:none">
+<textarea id="errorTxt" cols="95" rows="10"></textarea>
+</div>
+
+<div id="debug" style="display:block">
+<textarea cols="95" rows="10" name="formStatus" id="formStatus">
+Loading
+</textarea>
+</div>
+
+
+
+<script type="text/javascript">
+
+window.onload = init();
+
+function init(){
+		
+	var searchParams = new URLSearchParams(window.location.search);
+	
+	//update this to pick crfRef from url
+	let crfRef=searchParams.get('entryId');
+	document.getElementById("crfRefId").innerHTML=crfRef;
+	//let crfRef=document.getElementById("crfRefId").innerHTML;
+	
+
+
+	let config=new Object();
+	//will this change if we are in views?
+	config.review=true;
+	//where to get ParticipantId
+	config.registrationQuery="registration";
+	config.registrationParticipantIdField="participantCode";
+	config.masterForm="visitForm";
+	
+	config.document=document;
+	config.debugId="formStatus";
+	config.crfRefId="crfRefId";
+	config.containerPath= LABKEY.ActionURL.getContainer();
+	config.setupQueryName="visitZeroSetup";
+	config.submitReportId="submitReport";
+	
+	
+	clear(config);
+	print(config,"Container path"+config.containerPath);
+
+
+	generateMasterForm(config);
+
+
+	
+
+}
+</script>

+ 6 - 0
views/reviewVisit0.view.xml

@@ -0,0 +1,6 @@
+<view xmlns="http://labkey.org/data/xml/view" title="Review Visit #0">
+	<dependencies>
+			<dependency path="crf/crfVisit.js"/>
+	</dependencies>
+</view>
+<!-- need to restart labkey to add new files -->

+ 5 - 24
views/visit0.html

@@ -45,7 +45,7 @@ window.onload = init();
 
 
 function init(){
 function init(){
 		
 		
-	var searchParams = new URLSearchParams(window.location.search);
+	let searchParams = new URLSearchParams(window.location.search);
 	
 	
 	//update this to pick crfRef from url
 	//update this to pick crfRef from url
 	let crfRef=searchParams.get('entryId');
 	let crfRef=searchParams.get('entryId');
@@ -61,35 +61,16 @@ function init(){
 	config.document=document;
 	config.document=document;
 	config.debugId="formStatus";
 	config.debugId="formStatus";
 	config.crfRefId="crfRefId";
 	config.crfRefId="crfRefId";
-	config.containerPath="TECANT/Data";
-	
+	config.containerPath= LABKEY.ActionURL.getContainer();
+	config.setupQueryName="visitZeroSetup";
+	config.submitReportId="submitReport";
 	
 	
 	clear(config);
 	clear(config);
 	print(config,"Container path"+config.containerPath);
 	print(config,"Container path"+config.containerPath);
 
 
+	generateMasterForm(config);
 
 
-	let selectRows=new Object();
-	selectRows.containerPath=config.containerPath;
-	selectRows.schemaName='lists';
-	selectRows.queryName='crfEntry';
-	selectRows.filterArray=[LABKEY.Filter.create('entryId',crfRef)];
-	selectRows.success=function(data){populateBasicData(config,data)};
-	//requires populateBasicData
-	LABKEY.Query.selectRows(selectRows);
-
-	config.fields=new Object();	
 
 
-	let configSelectRows=new Object();
-	configSelectRows.containerPath=config.containerPath;
-	configSelectRows.schemaName='lists';
-	configSelectRows.queryName='visitZeroSetup';
-	configSelectRows.success=function(data){generateForm(config,data);};
-	configSelectRows.failure=function(errorTxt){print(config,"generateForm fail")};
-	LABKEY.Query.selectRows(configSelectRows);
-
-	config.submitReportId="submitReport";
-	//requires onSubmit
-	generateButton(config,"submitDiv","Submit",onSubmit,config);
 
 
 	
 	
 
 

+ 9 - 5
web/crf/crfPortal.js

@@ -35,7 +35,7 @@ function drawForm(par){
 
 
 function generateQConfig(listName){
 function generateQConfig(listName){
     let qConfig=new Object();
     let qConfig=new Object();
-    qConfig.containerPath="TECANT/Data";
+    //qConfig.containerPath="TECANT/Data";
     qConfig.schemaName="lists";
     qConfig.schemaName="lists";
     qConfig.queryName=listName;
     qConfig.queryName=listName;
     return qConfig;
     return qConfig;
@@ -300,8 +300,11 @@ function populateTableRow(data,par,rowId){
 function populateSelect(data,selectedData, par, rowId){
 function populateSelect(data,selectedData, par, rowId){
 	//data is the set of lookup entries, selectedData is a subset of entries valued at lookup.keyColumn 
 	//data is the set of lookup entries, selectedData is a subset of entries valued at lookup.keyColumn 
 	let debug=true;
 	let debug=true;
-	if (debug)
-		print(par.config,"populateSelect Data: "+data.queryName+" selectedData:"+selectedData.queryName);
+	if (debug){
+		let msg="populateSelect Data: "+data.queryName;
+		msg+=" selectedData:"+selectedData.queryName;
+		print(par.config,msg);
+	}
 	let row=par.vars[rowId];
 	let row=par.vars[rowId];
 	let selectId=row.selectId; 
 	let selectId=row.selectId; 
 	
 	
@@ -321,7 +324,7 @@ function populateSelect(data,selectedData, par, rowId){
 		print(par.config,"displayColumn: "+displayColumn);
 		print(par.config,"displayColumn: "+displayColumn);
 	
 	
 	}
 	}
-	let el = document.getElementById(selectId);
+	let el = par.config.document.getElementById(selectId);
 	
 	
 	if (debug)
 	if (debug)
 		print(par.config,"Element: "+el);
 		print(par.config,"Element: "+el);
@@ -698,7 +701,8 @@ function finalRedirect(data,entry,par){
 		"entryId": entry[par.vars["Crf"].masterSelectVarName]
 		"entryId": entry[par.vars["Crf"].masterSelectVarName]
 	};
 	};
 
 
-	let containerPath="TECANT";//part of data?
+	let containerPath= LABKEY.ActionURL.getContainer();
+	//"TECANT";//part of data?
         // This changes the page after building the URL. 
         // This changes the page after building the URL. 
 	//Note that the wiki page destination name is set in params.
 	//Note that the wiki page destination name is set in params.
         var wikiURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);
         var wikiURL = LABKEY.ActionURL.buildURL("crf", formUrl , containerPath, params);

+ 260 - 10
web/crf/crfVisit.js

@@ -77,6 +77,19 @@ function fullAccessSetup(config,listName){
 	setup.unique=true;
 	setup.unique=true;
 	//no addApply
 	//no addApply
 	return setup;
 	return setup;
+
+}
+
+function readonlySetup(config){
+	let debug=true;
+	if (debug) print(config,"readonlySetup");
+
+	let setup=new Object();
+	setup.readonlyFlag=function(vName){return true};
+	setup.filters=new Object();
+	setup.filters['crfRef']=getCRFref(config);
+	setup.getInputId=function(vName){return vName;}
+	return setup;
 }
 }
 
 
 function generateForm(config,data){
 function generateForm(config,data){
@@ -158,14 +171,20 @@ function generateSection(config, sectionName, sectionTitle, listName, additional
 	}
 	}
 	if (debug) print(config,"generate master table");
 	if (debug) print(config,"generate master table");
 	
 	
-	generateTable(config,listName,divTable.id,true,additionalData,fullAccessSetup(config,listName));
+	let setup=fullAccessSetup(config,listName);
+	if (config.review) 
+		setup=readonlySetup(config);
+	generateTable(config,listName,divTable.id,true,additionalData,setup);
 	
 	
 	if (debug) print(config,"generate master table: done");
 	if (debug) print(config,"generate master table: done");
 	
 	
 	if ("showFlag" in additionalData){
 	if ("showFlag" in additionalData){
 		let qName=additionalData.queryName;
 		let qName=additionalData.queryName;
 		let dName=additionalData.divName;
 		let dName=additionalData.divName;
-		generateTable(config,qName,dName,false,additionalData,fullAccessSetup(config,qName));
+		let setup=fullAccessSetup(config,qName);
+		if (config.review)
+			setup=readonlySetup(config);
+		generateTable(config,qName,dName,false,additionalData,setup);
 	}
 	}
 
 
 	let divReviewList=config.document.createElement('div');
 	let divReviewList=config.document.createElement('div');
@@ -180,7 +199,8 @@ function generateSection(config, sectionName, sectionTitle, listName, additional
 	qconfig.containerPath=config.containerPath;
 	qconfig.containerPath=config.containerPath;
 	qconfig.schemaName='lists';
 	qconfig.schemaName='lists';
 	qconfig.queryName='visitZeroSetup';
 	qconfig.queryName='visitZeroSetup';
-	qconfig.success=function(data){generateReview(config,data,divReview.id,divReviewList.id,listName)};
+	qconfig.success=function(data){
+		generateReview(config,data,divReview.id,divReviewList.id,listName)};
 	LABKEY.Query.selectRows(qconfig);
 	LABKEY.Query.selectRows(qconfig);
 }
 }
 
 
@@ -210,8 +230,11 @@ function generateReview(config,data,divReviewId,divReviewListId, listName){
 	reviewSetup.divReviewListId=divReviewListId;
 	reviewSetup.divReviewListId=divReviewListId;
 		
 		
 
 
-	if (debug) print(config,"Review: divId: "+divReviewId+" inputId: "+reviewSetup.getInputId);
-	
+	if (debug) {
+		let msg="Review: divId: "+divReviewId;
+		msg+=" inputId: "+reviewSetup.getInputId;
+		print(config,msg);
+	}
 	updateListDisplay(config,divReviewListId,"reviewComments",reviewSetup.filters,true);
 	updateListDisplay(config,divReviewListId,"reviewComments",reviewSetup.filters,true);
 	generateTable(config,"reviewComments",divReviewId,false,new Object(),reviewSetup);
 	generateTable(config,"reviewComments",divReviewId,false,new Object(),reviewSetup);
 }	
 }	
@@ -623,8 +646,11 @@ function saveReview(config,queryName,elementId,setup){
 
 
 function saveReviewToList(config,data,elementId,setup){
 function saveReviewToList(config,data,elementId,setup){
 	let debug=true;
 	let debug=true;
-	if (debug) print(config,"saveReviewToList: "+" elementId "+elementId+ " nrows "+data.rows.length);
-	
+	if (debug) {
+		let msg="saveReviewToList: "+" elementId "+elementId;
+		msg+=" nrows "+data.rows.length;
+		print(config,msg);
+	}
 	let useInsert=false;
 	let useInsert=false;
 	if (!("unique" in setup)) useInsert=true;
 	if (!("unique" in setup)) useInsert=true;
 	if (data.rows.length==0) useInsert=true;
 	if (data.rows.length==0) useInsert=true;
@@ -637,8 +663,10 @@ function saveReviewToList(config,data,elementId,setup){
 
 
 	if (debug) print(config,"Set crfRef="+entry.crfRef);
 	if (debug) print(config,"Set crfRef="+entry.crfRef);
 
 
-	if ("queryName" in setup.filters) entry.queryName=setup.filters["queryName"];
-	
+	if ("queryName" in setup.filters) {
+		entry.queryName=setup.filters["queryName"];
+		if (debug) print(config,"Setting queryName: "+entry.queryName);
+	}
 	let fields=data.metaData.fields;
 	let fields=data.metaData.fields;
 	for (f in fields){
 	for (f in fields){
 
 
@@ -663,6 +691,8 @@ function saveReviewToList(config,data,elementId,setup){
 		
 		
 		let vType=fields[f].type;
 		let vType=fields[f].type;
 
 
+		if (debug) print(config,"vType: "+vType);
+
 		if ("lookup" in fields[f]){
 		if ("lookup" in fields[f]){
 			if (el.nodeName==="SELECT"){
 			if (el.nodeName==="SELECT"){
 				entry[vName]=el.options[el.selectedIndex].value;
 				entry[vName]=el.options[el.selectedIndex].value;
@@ -698,7 +728,7 @@ function saveReviewToList(config,data,elementId,setup){
 	qconfig.queryName=data.queryName;
 	qconfig.queryName=data.queryName;
 
 
 	//only update comments
 	//only update comments
-
+	print(config,"modifyRows: useInsert "+useInsert);
 	qconfig.success=function(data){updateLastSavedFlag(config,data,setup,elementId)};
 	qconfig.success=function(data){updateLastSavedFlag(config,data,setup,elementId)};
 	if (!useInsert){
 	if (!useInsert){
 		LABKEY.Query.updateRows(qconfig);
 		LABKEY.Query.updateRows(qconfig);
@@ -719,6 +749,184 @@ function updateLastSavedFlag(config,data,setup,elementId){
 	}	
 	}	
 }
 }
 
 
+//******************************************upload to database *********************
+
+
+function onDatabaseUpload(config){
+	print(config,"Database upload");
+	//figure out the participantId
+	
+	let qconfig=new Object();
+	qconfig.queryName=config.registrationQuery;
+	qconfig.schemaName='lists';
+	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
+	qconfig.success=function(data){updateDatabaseWithPatientId(config,data);}
+	LABKEY.Query.selectRows(qconfig);
+
+}
+
+function updateDatabaseWithPatientId(config,data){
+	clearErr(config);
+	if (data.rows.length!=1){
+		let msg="ERROR: Found "+data.rows.length;
+		msg+=" registration entries for crfrefid "+getCRFref(config);
+		print(config,msg);
+		return;
+	}
+	participantId=data.rows[0][config.registrationParticipantIdField];
+	print(config,"Setting participantId to "+participantId);
+	//another select rows to update all queries from setup
+	//just use registration for test
+	let qconfig=new Array();
+	qconfig.schemaName='lists';
+	qconfig.queryName=config.setupQueryName;
+	qconfig.success=function(data){copyDatasetsFromSetup(config,data);}
+	LABKEY.Query.selectRows(qconfig);
+}
+
+function copyDatasetsFromSetup(config,data){
+
+	for (let i=0;i<data.rows.length;i++){
+		let entry=data.rows[i];
+		copyToDataset(config,entry.queryName,participantId);
+		if (entry.showQuery!="NONE"){
+			copyToDataset(config,entry.showQuery,participantId);
+		}
+	}
+	print(config,"Database updated");
+}
+
+
+
+function copyToDataset(config,queryName,participantId){
+	print(config,"copyToDataset");
+	let qconfig=new Object();
+	qconfig.queryName=queryName;
+	qconfig.schemaName="lists";
+	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
+	qconfig.success=function(data){copyDataToDataset(config,queryName,participantId,data)};
+	LABKEY.Query.selectRows(qconfig);
+}
+
+function copyDataToDataset(config,queryName,participantId,dataList){
+	print(config,"copyDataToDataset");
+
+	let qconfig=new Object();
+	qconfig.queryName=queryName;
+	qconfig.schemaName="study";
+	qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
+	qconfig.filterArray.push(LABKEY.Filter.create('ParticipantId',participantId));
+	qconfig.success=function(data){copyDataToDatasetChecked(config,queryName,participantId,dataList,data)};
+	LABKEY.Query.selectRows(qconfig);
+}
+
+
+function copyDataToDatasetChecked(config,queryName,participantId,dataList,dataStudy){
+
+	print(config,"copyDataToDatasetChecked");
+	if (dataStudy.rows.lentgh>0){
+		clearErr(config);
+		let msg="Dataset "+queryName+" already filled for participant "+participantId;
+		printErr(config,msg);
+		//rows with the same crfRef and patientId already inserted - skip
+		return;
+	}
+	
+	//update non-list elements
+	let seqNumber=getCRFref(config);
+
+	let rows=new Array();
+	for (let i=0;i<dataList.rows.length;i++){
+		let entry=dataList.rows[i];
+		entry.ParticipantId=participantId;
+		entry.crfRef=getCRFref(config);
+		entry.SequenceNum=getCRFref(config);
+		entry.SequenceNum=entry.SequenceNum % 1000000000;
+		
+		if (dataList.rows.length>1){
+			entry.SequenceNum+=i/10;
+		}
+		print(config, "Adding sequence number "+entry.SequenceNum);
+		rows.push(entry);
+	}
+	
+	let qconfig=new Object();
+	qconfig.queryName=queryName;
+	qconfig.schemaName="study";
+	qconfig.success=function(data){
+		reportCopyDataToDatasetChecked(config,queryName,participantId,data)};
+	qconfig.rows=rows;
+	LABKEY.Query.insertRows(qconfig);
+}
+
+function reportCopyDataToDatasetChecked(config,queryName,participantId,data){
+	printErr(config,"Inserted "+data.rows.length+" rows to "+queryName);
+
+}
+
+
+
+
+//*************************update for further review *************************
+
+function onUpdateForReview(config){
+	print(config,"Sent to further review");
+	let qconfig=new Object();
+	qconfig.schemaName='lists';
+	qconfig.queryName='crfEntry';
+	qconfig.success=function(data){setFlagToReview(config,data);}
+	qconfig.filterArray=[LABKEY.Filter.create("entryId",getCRFref(config))];
+	LABKEY.Query.selectRows(qconfig);
+}
+
+function setFlagToReview(config,data){
+	let debug=true;
+	print(config,"setFlagToReview");
+	if (data.rows.length!=1){
+		let msg="ERROR: Found "+data.rows.length;
+		msg+=" entries for crfrefid "+getCRFref(config);
+		print(config,msg);
+		return;
+	}
+	let entry=data.rows[0];
+	entry.FormStatus=4;//Pending Review
+	if (debug)
+		print(config,"Set form status to "+entry.FormStatus);
+	
+	let qconfig=new Object();
+	qconfig.schemaName='lists';
+	qconfig.queryName='crfEntry';
+	qconfig.rows=[entry];
+	qconfig.success=function(data){completeWithReview(config,data);}
+	LABKEY.Query.updateRows(qconfig);
+	
+}
+
+function completeWithReview(config,data){
+	let debug=true;
+
+	if (debug)
+		print(config,"complete with review");
+	let formUrl="begin";
+	var params = {
+		"name": formUrl, // The destination wiki page. The name of this parameter is not arbitrary.
+	};
+
+	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 homeURL = LABKEY.ActionURL.buildURL("project", formUrl , containerPath, params);
+        print(config,"Redirecting to "+homeURL);
+		 
+	window.location = homeURL;
+
+	
+
+}
+
+//************************************************ submit *******************************************
+
+
 function onSubmit(config){
 function onSubmit(config){
 	let debug=true;
 	let debug=true;
 	hideErr(config);
 	hideErr(config);
@@ -870,3 +1078,45 @@ function checkData(data,config){
 	config.status="DONE";
 	config.status="DONE";
 }
 }
 
 
+
+function generateMasterForm(config){
+	let debug=true;
+
+	if (debug)
+		print(config,"generateMasterForm");	
+	
+	let selectRows=new Object();
+	selectRows.containerPath=config.containerPath;
+	selectRows.schemaName='lists';
+	selectRows.queryName='crfEntry';
+	selectRows.filterArray=[LABKEY.Filter.create('entryId',getCRFref(config))];
+	selectRows.success=function(data){populateBasicData(config,data)};
+	//requires populateBasicData
+	LABKEY.Query.selectRows(selectRows);
+
+
+	config.fields=new Object();	
+
+	let configSelectRows=new Object();
+	configSelectRows.containerPath=config.containerPath;
+	configSelectRows.schemaName='lists';
+	configSelectRows.queryName=config.setupQueryName;
+	configSelectRows.success=function(data){generateForm(config,data);};
+	configSelectRows.failure=function(errorTxt){print(config,"generateForm fail")};
+	LABKEY.Query.selectRows(configSelectRows);
+
+	if (debug)
+		print(config,"Generating buttons");
+
+	//requires onSubmit
+	if (config.review){
+	
+		generateButton(config,"submitDiv","Upload to database",onDatabaseUpload,config);
+		generateButton(config,"submitDiv","Ask for further review",onUpdateForReview,config);
+	}	
+	else{
+		generateButton(config,"submitDiv","Submit",onSubmit,config);
+	}
+
+}
+

+ 0 - 831
web/crf/crfVisitAll.js

@@ -1,831 +0,0 @@
-function myprint(config, msg){
-	config.document.getElementById(config.debugId).value+="\n"+msg;
-}
-
-function print(config,msg){myprint(config,msg);}
-
-function getCRFref(config){
-	//'crfRefId'
-	return config.document.getElementById(config.crfRefId).innerHTML;
-}
-
-function populateBasicData(config,data){
-	let debug=false;
-	if (debug)
-		print(config,"crfRef matched entries: "+data.rows.length);
-	if (data.rows.length!=1) { return;}
-	config.document.getElementById('eudraCTNumber').innerHTML=data.rows[0].EudraCTNumber;
-	config.document.getElementById('studyCoordinator').innerHTML=data.rows[0].StudyCoordinator;
-	config.document.getElementById('studySponsor').innerHTML=data.rows[0].StudySponsor;
-	LABKEY.Query.selectRows({schemaName: 'lists',queryName: 'site', 
-		filterArray: [LABKEY.Filter.create('siteNumber', data.rows[0].Site)],
-		success: function(data){setHTML(config,data,'siteName','siteName')};
-	});	
-	LABKEY.Query.selectRows({schemaName: 'core',queryName: 'Users',
-		filterArray: [LABKEY.Filter.create('UserId',data.rows[0].UserId)],
-		success: function(data){setHTML(config,data,'investigatorName','DisplayName')}
-	});
-}
-
-function setHTML(config,data,elementId,varName){
-	print(config,"\nsetHTML "+data.rows.length+" elementId: "+elementId+" varName:"+varName);
-	if (data.rows.length>0){
-		let entry=data.rows[0];
-		let el=config.document.getElementById(elementId);
-		
-		print(config,"\nsetHTML: Entry[" + varName + "]: " + entry[varName]);
-		print(config,"\nsetHTML: Element[" + elementId + "]: " + el;
-		el.innerHTML=entry[varName];
-	}
-
-}
-
-function setAdditionalData(config,additionalData,entry){
-	let debug=true;
-	if (debug) print(config,"setAdditionalData");
-	if (entry["showFlag"]==="NONE") {
-		if (debug) print(config,"Returning empty additionalData");
-		return additionalData;
-	}
-	additionalData.showFlag=entry["showFlag"];
-	additionalData.showFlagValue=entry["showFlagValue"];
-	additionalData.queryName=entry["showQuery"];
-	additionalData.filters=new Object();
-	additionalData.filters['crfRef']=getCRFref();
-	return additionalData;
-}
-
-function fullAccessSetup(listName){
-	let setup=new Object();
-	setup.readonlyFlag=function(vName){return false};
-	setup.filters=new Object();
-	setup.filters['crfRef']=getCRFref();
-	setup.getInputId=function(vName){return listName+"_"+vName;}
-	setup.addApply="Save";
-	setup.unique=true;
-	//no addApply
-	return setup;
-}
-
-function generateForm(config,data){
-
-	let debug=true;
-	if (debug) print(config,"generateForm ["+data.rows.length+"]");
-	for (let i=0;i<data.rows.length;i++){
-		let entry=data.rows[i];
-		let queryName=entry["queryName"];
-
-		if (!(queryName in config.fields))
-			 config.fields[queryName]=new Object();
-		let field=config.fields[queryName];
-		field.title=entry["title"];
-
-		if (debug) print(config,"generateForm ["+i+"/"+data.rows.length+"]");
-		if (debug) print(config,"entry[queryName]: "+entry["queryName"]);
-		if (debug) print(config,"entry[showFlag]: "+entry["showFlag"]);
-		let additionalData=new Object();
-		setAdditionalData(config,additionalData,entry);
-		generateSection(config,entry["queryName"],entry["title"],
-				entry["queryName"], additionalData);
-
-	}
-}
-
-function generateSection(config, sectionName, sectionTitle, listName, additionalData){
-	let formName=config.masterForm;
-	let debug=true;
-	if (debug) print(config,"generateSection");
-	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"+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;
-	div.style.display="none";
-	config.document.getElementById(formName).appendChild(div);	
-
-	let divTable=config.document.createElement('div');
-	divTable.id=sectionName+"Table";
-	div.appendChild(divTable);
-	
-	if ("showFlag" in additionalData) {
-
-		additionalData.divName=sectionName+"SubDiv";
-		additionalData.divQueryName=sectionName+"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(config,"generate master table");
-	generateTable(config,listName,divTable.id,true,additionalData,fullAccessSetup(listName));
-	if (debug) print(config,"generate master table: done");
-	if ("showFlag" in additionalData){
-		let qName=additionalData.queryName;
-		let dName=additionalData.divName;
-		generateTable(config,qName,dName,false,additionalData,fullAccessSetup(qName));
-	}
-
-	let divReviewList=config.document.createElement('div');
-	divReviewList.id=sectionName+"ReviewList";
-	div.appendChild(divReviewList);
-	
-	let divReview=config.document.createElement('div');
-	divReview.id=sectionName+"Review";
-	div.appendChild(divReview);
-
-	let config=new Object();	
-	config.schemaName='lists';
-	config.queryName='visitZeroSetup';
-	config.success=function(data){generateReview(config,data,divReview.id,divReviewList.id,listName)};
-	LABKEY.Query.selectRows(config);
-}
-
-function generateReview(config,data,divReviewId,divReviewListId, listName){
-	let debug=true;
-	let listId=-1;
-	for (let i=0;i<data.rows.length;i++){
-		let entry=data.rows[i];
-		if (entry["queryName"]!=listName) continue;
-		listId=entry["Key"];
-		break;
-	}
-	
-	let reviewSetup=new Object();
-	reviewSetup.readonlyFlag=function(vName){if (vName=="queryName") return true; return false;};
-	reviewSetup.addApply="Add Review";
-	reviewSetup.filters=new Object();
-	reviewSetup.filters["crfRef"]=getCRFref(config);
-	reviewSetup.filters["queryName"]=listId;
-	reviewSetup.getInputId=function(vName){return listName+"_"+vName;}	
-	reviewSetup.divReviewListId=divReviewListId;	
-
-	if (debug) print(config,"update list display");
-	updateListDisplay(config,divReviewListId,"reviewComments",reviewSetup.filters,true);
-	generateTable(config,"reviewComments",divReviewId,false,new Object(),reviewSetup);
-}	
-
-function setListVisibility(config,setup,additionalData,readonlyFlag){
-	let debug=true;
-	if (debug){
-		print(config,"Set list visibility ");
-		for (f in additionalData){
-			print(config,"AdditionalData["+f+"]: "+additionalData[f]);
-		}
-	}
-	let x = config.document.getElementById(additionalData.divName);
-	if (debug) print("\n Div: "+x);
-	x.style.display="none";
-	let eId=setup.getInputId(additionalData.showFlag);
-	let e = config.document.getElementById(eId);
-	
-	let sText;
-	if (readonlyFlag) sText=e.innerHTML;
-	else sText=e.options[e.selectedIndex].text;
-	
-	if (debug) print(config,"\n Selected option text: "+sText);
-
-	if (sText == additionalData.showFlagValue){
-		let filters=new Object();
-		if ("filters" in additionalData) filters=additionalData.filters;
-		x.style.display = "block";
-		updateListDisplay(config,additionalData.divQueryName,additionalData.queryName,filters,readonlyFlag);
-	}
-}
-
-function updateListDisplay(config,divName,queryName,filters,readonlyFlag){
-	let debug=true;
-
-	if (debug) print(config,"UpdateListDisplay: Query - "+queryName+" div - "+divName);
-
-	if (divName=="NONE") return;
-	let crfRef=getCRFref(config);
-	let div=config.document.getElementById(divName);
-
-	if (debug)
-		print(config,"Enabling display to queryName: "+queryName);
-	
-	var qconfig=new Object();
-	qconfig.renderTo=divName;
-	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=function(data){updateSuccess(config,data)};
-	qconfig.failure=function(data){updateFailure(config,data)};
-	//show only print button
-	if (readonlyFlag){
-		qconfig.buttonBar=new Object();
-		qconfig.buttonBar.items=["print"];
-	}
-
-	LABKEY.QueryWebPart(qconfig);
-	
-}
-
-function updateSuccess(config,data){
-	print(config,"Update success");
-}
-
-function updateFailure(config,data){
-	print(config,"Update failed");
-}
-
-function toggleVisibility(config, divName,buttonName){
-
-	let x = config.document.getElementById(divName);
-	if (x.style.display === "none") {
-    		x.style.display = "block";
-		config.document.getElementById(buttonName).value="Hide";
-
-  	} else {
-    		x.style.display = "none";
-		config.document.getElementById(buttonName).value="Show";
-
-  	}
-}
-
-function generateButton(config,divName,buttonName,callback,callbackParameters){
-	let debug=true;
-	if (debug) print(config,"generateButton");
-	
-	let tb=config.document.createElement('table');
-	tb.className="t2";
-	
-	let r1=tb.insertRow();
-	th=config.document.createElement('th');
-	r1.appendChild(th);
-	th.innerHTML="Complete submission";
-	//*!*
-	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 generateTable(config,listName,divName,unique,additionalData,setup){
-	let debug=true;
-	
-	//add temp variables
-	let qconfig=new Object();
-	qconfig.schemaName='lists';
-	qconfig.queryName=listName;
-	//apply filters on data to get right entries
-	qconfig.filterArray=[];
-	for (f in setup.filters){
-		qconfig.filterArray.push(LABKEY.Filter.create(f,setup.filters[f]));
-	}
-	qconfig.success=function(data){populateTable(config,data,divName,unique,additionalData,setup)};
-	LABKEY.Query.selectRows(qconfig);
-}
-
-function populateTable(config,data,divName,unique,additionalData,setup){
-	//generate and populate table with the first suitable entry
-	let debug=true;
-
-	if (debug){
-		print(config,"populateTable Query: "+data.queryName+" divName: "+divName+" setup: "+setup);
-
-
-		if (0){
-			let obj=data.metaData.fields;
-			for (f in obj){	
-				print(config,"Data["+f+"]: "+obj[f]);
-				for (g in obj[f]){
-					print(config,"Data.metaData.fields["+f+"]["+g+"]: "+obj[f][g]);
-				}
-				if ("lookup" in obj[f]){
-					for (h in obj[f]["lookup"]){
-						print(config,"Lookup["+h+"]: "+obj[f]["lookup"][h]);
-	
-					}
-				}
-
-			}
-		}
-	}
-	let crfRef=getCRFref(config);
-	let entry=new Object();
-
-	if (debug)
-		print(config,"Data: nrows "+data.rows.length);
-
-	if (data.rows.length > 0) entry=data.rows[0];
-	
-	let tb=config.document.createElement('table');
-	tb.className="t2";
-	config.document.getElementById(divName).appendChild(tb);
-
-	let fields=data.metaData.fields;
-	for (f in fields){
-		let field=fields[f];
-		if (field.hidden) continue;
-		
-		let vName=field.name;
-		
-		if (debug) print(config,"Field ["+vName+"]");
-		if (vName=="crfRef") continue;		
-
-		let vType=field.type;
-		if (debug) print(config,"Field ["+vName+"/"+vType+"]");
-		let row=tb.insertRow();
-		let cell=config.document.createElement('th');
-		row.appendChild(cell);
-		let text = config.document.createTextNode(fields[f].shortCaption);
-		cell.appendChild(text);
-		cell=row.insertCell();
-		
-		let varValue="UNDEF";
-		if (vName in setup.filters) varValue=setup.filters[vName];
-		if (vName in entry) varValue=entry[vName];
-		if (vType=="date"){
-			if (varValue==="UNDEF") varValue=new Date();
-			else varValue=new Date(varValue);
-		}
-		if (debug) print("value: "+varValue);		
-		let input;
-		if (setup.readonlyFlag(vName)){
-			input=config.document.createTextNode(varValue);
-			cell.id=setup.getInputId(vName);
-		}
-		else{
-			cell.colSpan="3";
-
-			let cellClass="input";
-			let cellType="text";
-			if ("lookup" in field){
-				input = config.document.createElement("select");
-			}
-			if (vType=="date"){ 
-				input = config.document.createElement("input");
-				input.type="date";
-			}
-			if (vType=="string"){
-				if(vName.search("reviewComment")>-1){
-					input = config.document.createElement("textarea");
-					input.cols="65";
-					input.rows="5";
-				}
-				else{
-					input = config.document.createElement("input");
-					input.type="text";
-				}
-			}
-			if (vType=="float"){
-				input = config.document.createElement("input");
-				input.type="text";
-			}	
-		
-			input.id=setup.getInputId(vName);
-			if (vName in entry){
-				if (vType=="string") input.value=varValue;
-				if (vType=="float")  input.value=varValue;
-				if (vType=="date") input.valueAsDate=varValue;
-			}
-		}
-
-	
-		cell.appendChild(input);
-		
-		if ("lookup" in field){
-			let lookup=field["lookup"];
-			let qconfig=new Object();
-			if (debug) print(config,"Query: "+lookup.queryName);
-			qconfig.schemaName=lookup.schemaName;
-			qconfig.queryName=lookup.queryName;
-			let parameters= new Object();
-			parameters.elementId=setup.getInputId(vName);
-			parameters.keyColumn=lookup.keyColumn;
-			parameters.displayColumn=lookup.displayColumn;
-			
-			if (vName in setup.filters) parameters.selectedKey=setup.filters[vName];
-			if (vName in entry) parameters.selectedKey=entry[vName];
-			
-			if ("showFlag" in additionalData) parameters.additionalData=additionalData;
-			if (debug) print("Populate select for "+parameters.elementId);
-			qconfig.success=function(data){populateSelect(config,data,parameters,setup,setup.readonlyFlag(vName))};
-			LABKEY.Query.selectRows(qconfig);
-		}
-		
-	}
-	//add comment field	
-	if (!("addApply" in setup)) {
-		print(config,"populateTable: 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("rewievLastSave");
-	cell1.innerHTML="No recent update";
-	input.onclick=function(){saveReview(config,data.queryName,cell1.id,setup)};
-}	
-	
-
-function populateSelect(config,data,parameters,setup,readonlyFlag){
-	let debug=true;
-	if (debug)
-		print(config,"populateSelect on "+data.queryName);
-	let elementId=parameters.elementId;
-	let keyColumn=parameters.keyColumn;
-	let displayColumn=parameters.displayColumn;
-	if (debug){
-		print(config,"Query: "+data.queryName);
-		print(config,"ElementId: "+elementId);
-		print(config,"keyColumn: "+keyColumn);
-		print(config,"displayColumn: "+displayColumn);
-	
-		if ("selectedKey" in parameters){
-			print(config,"SelectedKey: "+parameters["selectedKey"]);
-		}
-	}
-	let el = config.document.getElementById(elementId);
-	
-	if (debug)
-		print(config,"Element: "+el);
-   	
-	if (!readonlyFlag){
-		//clear options
-		for(i = el.options.length; i >= 0; i--) {
-			el.remove(i);
-   		}
-	
-		let opt = config.document.createElement("option");
-		opt.text = "<Select>";
-		opt.value = -1;
-		el.options[0] = opt;
-
-	}
-
-	for (let i = 0; i < data.rows.length; i++) {
-		let displayText = data.rows[i][displayColumn];
-		let keyValue = data.rows[i][keyColumn];
-
-		if (!readonlyFlag){
-			let opt = config.document.createElement("option");
-
-			opt.text = displayText;
-			opt.value = keyValue;
-			el.options[el.options.length] = opt;
-		
-		}
-		if (debug) print("Adding: "+keyValue+" : "+displayText);
-		
-		let t1=checkVariable(config,el,keyValue,displayText,parameters,"selectedKey",readonlyFlag);
-		if (t1) setup.keyValue=keyValue;
-
-		
-	}
-	
-	if (!("additionalData" in parameters)) return;
-
-	if (debug) print(config,"\n Parsing additional data ");
-
-	let additionalData=parameters["additionalData"];	
-
-	let expId=setup.getInputId(additionalData.showFlag);
-	if (expId!=elementId) {
-		print(config,"Element mismatch: got :"+expId+"/"+elementId);
-		return;
-	}
-
-	if (debug)
-		print(config,"Setting onChange to "+el.id);
-	
-	el.onchange=function(){setListVisibility(config,setup,additionalData,readonlyFlag)};
-	setListVisibility(config,setup,additionalData,readonlyFlag);
-
-}	
-
-function checkVariable(config,el,varValue,displayText, parameters,varName,readonlyFlag){
-	let debug=true;
-	if (!varName in parameters) return false;
-	if (debug) print(config,"Comparing: " + varValue  + "/" + parameters[varName]);
-			
-        if (varValue==parameters[varName]){
-		if (readonlyFlag) el.innerHTML=displayText;
-		else {
-			el.selectedIndex=el.options.length-1;
-			if (debug) print(" Equal; "+el.selectedIndex);
-		}
-		return true;
-	}
-	return false;
-	
-}
-
-
-function failureSelect(config,errorInfo,resp,opt){
-	document.getElementById('formStatus').value+="\n Error: ";
-
-}
-
-function saveReview(config,queryName,elementId,setup){
-	let debug=true;
-	if (debug) print(config,"saveReview: elementId "+elementId);
-	let qconfig=new Object();
-	qconfig.schemaName='lists';//could be made more generic
-	qconfig.queryName=queryName;
-	if ("unique" in setup){
-		qconfig.filterArray=[LABKEY.Filter.create("crfRef",getCRFref())];
-	}
-	qconfig.success=function(data){saveReviewToList(config,data,elementId,setup);}
-	//to guess the fields, one must do selectRows first?
-	LABKEY.Query.selectRows(qconfig);
-}
-
-function saveReviewToList(config,data,elementId,setup){
-	let debug=true;
-	if (debug) print(config,"saveReviewToList: "+" elementId "+elementId+ " nrows "+data.rows.length);
-	
-	let useInsert=false;
-	if (!("unique" in setup)) useInsert=true;
-	if (data.rows.length==0) useInsert=true;
-	let entry=new Object();
-	
-	if (!useInsert){
-		entry=data.rows[0];
- 	}
-	entry.crfRef=getCRFref();
-	
-	if ("keyValue" in setup) entry.queryName=setup.keyValue;
-	
-	let fields=data.metaData.fields;
-	for (f in fields){
-
-		let field=fields[f];
-		if (debug) print(config,"saveReview field: "+field.name);
-		if (field.hidden) continue;
-		
-		let vName=fields[f].name;
-
-		if (vName=="crfRef") continue;
-		if (vName=="queryName") continue;
-		
-		let eId=setup.getInputId(vName);
-		
-		let el=config.document.getElementById(eId);
-				
-		if (!el) {
-			if (debug) print(config,"saveReview element: "+eId+" not found");
-			continue;
-		}
-		if (debug) print(config,"saveReview element: "+eId);
-		
-		let vType=fields[f].type;
-
-		if ("lookup" in fields[f]){
-			if (el.nodeName==="SELECT"){
-				entry[vName]=el.options[el.selectedIndex].value;
-			}
-			if (el.nodeName==="TD"){
-				entry[vName]=el.innerHTML;	
-			}
-
-			print(config,"Setting lookup to "+entry[vName]);
-			continue;
-		}
-		if (vType=="date"){
-			var date=el.valueAsDate;
-			if (date==="null") continue;
-			date.setUTCHours(12);
-			entry[vName]=date.toString();
-			print(config,"Setting date to "+entry[vName]);
-		}	
-		if (vType=="string"){
-			entry[vName]=el.value;
-		}	
-		if (vType=="float"){
-			entry[vName]=el.value;
-		}	
-
-
-	}
-	
-	let qconfig=new Object();
-	qconfig.rows=[entry];
-	qconfig.schemaName=data.schemaName;
-	qconfig.queryName=data.queryName;
-
-	//only update comments
-
-	qconfig.success=function(data){updateLastSavedFlag(config,data,setup,elementId)};
-	if (!useInsert){
-		LABKEY.Query.updateRows(qconfig);
-	}
-	else{
-		LABKEY.Query.insertRows(qconfig);
-	}
-}
-
-function updateLastSavedFlag(config,data,setup,elementId){
-	let debug=true;
-	if (debug) print(config,"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(config,setup.divReviewListId,"reviewComments",setup.filters,true);
-	}	
-}
-
-function onSubmit(config){
-	let debug=true;
-	hideErr(config);
-	clearErr(config);
-	printErr(config,"onSubmit");
-	checkForm(config);
-	let cb=new Object();
-	cb.success=finalValidation;
-	cb.failure=function(config){printErr("waitForCheckForm failed")};
-	waitForCheckForm(config,cb);
-}
-
-function finalValidation(config){
-	let debug=true;
-	if (debug) print(config,"validate");
-	
-	let completed=true;
-	for (f in config.fields){
-		let field=config.fields[f];
-		if (field.status!="DONE") {
-			printErr(config,"Missing entry for "+field.title);
-			completed=false;
-		}
-	}
-	if (debug) print(config,"valid: "+completed);
-
-	if (completed){
-		finalRedirect(config);
-	}
-	else{
-		updateSubmitStatus(config,"Form invalid");
-	}
-}
-
-function finalRedirect(config){
-	printErr(config,"Form valid");
-	let c1=new Object();
-	c1.schemaName='lists';
-	c1.queryName='crfEntry';
-	c1.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
-	c1.success=function(data){setSubmitStatus(config,data)};
-	LABKEY.Query.selectRows(c1);
-}
-
-function setSubmitStatus(config,data){
-	let entry=data.rows[0];
-	entry.formStatus=2;//Submitted
-	let c1=new Object();
-	c1.schemaName=data.schemaName;
-	c1.queryName=data.queryName;
-	c1.rows=[entry];
-	c1.success=function(data){updateSubmitStatus(config,"Form submitted")};
-	LABKEY.Query.updateRows(c1);
-}
-
-function updateSubmitStatus(config,msg){
-	let el=document.getElementById(config.submitReportId);
-	el.innerHTML=msg;
-}
-
-function hideErr(config){
-	let el=config.document.getElementById("errorDiv");
-	el.style.display="none";
-}
-
-function clearErr(config){
-	let el=config.document.getElementById("errorTxt");
-	el.value="";
-}
-
-function showErr(config){
-	let el=config.document.getElementById("errorDiv");
-	el.style.display="block";
-}
-
-
-function printErr(config,msg){
-	showErr(config);
-	el=config.document.getElementById("errorTxt");
-	el.style.color="red";
-	el.value+="\n"+msg;
-}
-
-function checkForm(config){
-	let debug=false;
-	let crfRef=getCRFref(config)
-	
-	
-	config.status="UNKNOWN";
-	for (f in config.fields){
-		let field=config.fields[f];
-		field.status="UNKNOWN";
-
-		if (debug) 
-			print(config,"Setting status for "+f+" to "+ field.status);
-
-		let selectRows=new Object();
-		selectRows.schemaName="lists";
-		selectRows.queryName=f;
-		selectRows.filterArray=[LABKEY.Filter.create('crfRef',crfRef)];
-		selectRows.success=function(data){checkData(data,config)};
-		selectRows.failure=function(errorObj){print(config,"checkData failed.")};
-		LABKEY.Query.selectRows(selectRows);
-	}
-}
-
-function waitForCheckForm(config,cb){
-	let debug=true;
-	if (!("i" in config)) config.i=0;
-	if (debug) print(config,"["+config.i+"] checkForm status "+config.status);
-	if (config.i>100) {
-		if (debug) print(config,"executing failure");	
-		cb.failure(config);
-		return;
-	}
-	if (config.status=="DONE") {
-		if (debug) print(config,"executing success");	
-		cb.success(config);
-		if (debug) print(config,"success executed");	
-		return;
-	}
-	config.i+=1;
-	setTimeout(function(){waitForCheckForm(config,cb);},1000);
-}
-
-function checkData(data,config){
-	let debug=false;
-	if (debug) print(config,"checkData ");
-	let field=config.fields[data.queryName];
-	field.status="NONE";
-	if (debug) print(config,"Setting status for "+data.queryName+" to "+field.status);
-	if (data.rows.length>0)
-		field.status="DONE";
-	
-	if (debug)
-		print(config,"checkData set status for "+data.queryName+" to "+field.status);
-	
-	for (f in config.fields){
-		let subField=config.fields[f];
-		if (debug) 
-			print(config,"checkData status["+f+"]: "+subField.status);	
-		if (subField.status=="UNKNOWN") {
-			if (debug) print(config,"\t Status for "+f+" not set ["+ subField.status+"]");
-			return;
-		}
-		
-	}
-	config.status="DONE";
-}
-