Переглянути джерело

Adding display of competing entries in crfVisitNew.js

Andrej 3 днів тому
батько
коміт
b196329b0f
1 змінених файлів з 138 додано та 59 видалено
  1. 138 59
      web/crf/crfVisitNew.js

+ 138 - 59
web/crf/crfVisitNew.js

@@ -66,7 +66,6 @@ function(){
 
 crfVisit.getCrfRef=
 function (){
-	//'crfRefId'
 	return crfData.getCrfEntry()['entryId'];
 }
 
@@ -137,6 +136,7 @@ function(sectionId,listName){
 	setup.filters=new Object();
 	setup.filters['crfRef']=this.getCrfRef();
 	setup.getInputId=function(vName){return sectionId+"_"+vName;}
+	setup.getLabelId=function(vName){return sectionId+"_"+vName+"_label";}
    setup.sectionId=sectionId;
 	setup.isReview=false;
    this.addSetup(sectionId,setup);
@@ -181,34 +181,54 @@ function(sectionId,listName,writeAccess=true){
 
 crfVisit.generateSection=
 function(formSetupEntry){
+
+   //generate section, ie. part that corresponds to a single row from FormSetup
+   //<div> hierarchy
+   //this.masterForm -> X -> [ XTable, XSubDiv -> XSubDivList, XReviewList, XReview ]
+   //visibility is toggled on X
+   //X is a shorthand for sectionId
+
    let that=this;
 	let listName=crfSetup.getMap('inputLists')[formSetupEntry['queryName']];
    let sectionId="section"+formSetupEntry['Key'];
-   //if (!listName) is for debugSection
+
+//section is also generated for debug
    if (!listName){
       listName="debugSection";
    }
+
+
 	let fName='[generateSection/'+listName+']';
 	let sectionTitle=formSetupEntry['title'];	
+
+   //role dictates how the section is displayed (EDIT, COMMENT, READ)
 	let accessModeColumn=this.role+'Mode';
-	let accessMode=formSetupEntry[accessModeColumn];
+   let accessMode=formSetupEntry[accessModeColumn];
+
 	//this will fix it for later use as well
 	this.print(fName+' title '+sectionTitle);
 
+   //js <table> commands
 	let tb=crfHTML.createTable(this.masterForm);
 	tb.className='t2';
+
+   //generate header
 	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);
+
+   //toggle visibility button (Show/Hide)
 	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)};
 
+
+   //js <div> under this.masterForm
 	let div=crfHTML.createDiv(sectionId,this.masterForm);
 	div.style.display="none";
 
@@ -221,47 +241,47 @@ function(formSetupEntry){
       return;
    }
 
-	let additionalData=crfSetup.getAdditionalData(listName);
+   //js <div> for table
 	let divTable=crfHTML.createDiv(sectionId+"Table",null,div);
 	
+   //check for sub-queries 
+	let additionalData=crfSetup.getAdditionalData(listName);
 	if ("showFlag" in additionalData) {
 		additionalData.divName=sectionId+"SubDiv";
 		additionalData.divQueryName=sectionId+"SubDivList";
-
+//[XSubDiv]
 		let div1=crfHTML.createDiv(additionalData.divName,null,div);
 		div1.style.display="none";
+//[XSubDiv->XSubDivList]
 		let div2=crfHTML.createDiv(additionalData.divQueryName,null,div1);
 
 	}
 	this.print(fName+" generate master table");
 
+   //convert from accessMode to setup
 	let writeMode=accessMode=="EDIT";	
 	let setup=this.getSetup(sectionId,listName,writeMode);
    setup.setVariables=variableList.parseVariables(formSetupEntry['variableDefinition']);
 	
-
+//special case for providing review sections (not used in hypoAfrica)
    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
 
 	
+	//main table is unique per visit
 	setup.unique=true;
 	this.generateTable(listName,divTable.id,additionalData,setup);
 	
-	this.print("generate master table: done");
+	this.print("generate main 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){
+	//subTable is the editable interface to data,
+   //only generate for write/EDIT access to section
+
+   if (accessMode == "EDIT" && ("showFlag" in additionalData)){
 		let qName=additionalData.queryName;
 		let dName=additionalData.divName;
 		
@@ -269,24 +289,20 @@ function(formSetupEntry){
 		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");
 
+	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;
+
+//special provisions for GENERATE (typically associated with Registration section/table)
 	this.print('Adding generate button');	
 	//add generateButton
 	let divGenerateButton=crfHTML.createDiv(listName+"GenerateButton",null,div);
@@ -336,6 +352,7 @@ function(divReviewId,divReviewListId, listName, accessMode){
 	//needs listName, in argument
 	
 	reviewSetup.getInputId=function(vName){return listName+"_add"+vName};
+	reviewSetup.getLabelId=function(vName){return listName+"_add"+vName+"_label";};
 	reviewSetup.divReviewListId=divReviewListId;
 	reviewSetup.isReview=true;	
    this.addSetup(divReviewId,reviewSetup);
@@ -534,8 +551,9 @@ function(tb,field,setup,additionalData){
 	let row=tb.insertRow();
 	let cell=crfHTML.createTblHeader(null,row);
    cell.style.width='300px';
-	
+   cell.id=setup.getLabelId(vName);
 	let text = crfHTML.createTextNode(field.shortCaption,null,cell);
+
 		
 	
 	let input=null;
@@ -789,6 +807,21 @@ function(entry,field,setup){
 	let vName=field.name;
 	let fName='[populateFieldName/'+vName+']';
 
+   //this.print(fName+" label element: "+labelElement);
+   //this.print(fName+" label element: "+labelElement.childNodes.length);
+   if ("_mergeData" in entry){
+      let dataArray=entry["_mergeData"][vName];
+      this.print(fName+" vals "+dataArray);
+      let label=field.shortCaption+" [";
+      for (let i=0;i<dataArray.length;i++){
+         if (i) label+="/";
+         label+=dataArray[i].toString();
+      }
+      label+="]";
+      crfHTML.setTextNode(crfHTML.getElement(setup.getLabelId(vName)).childNodes[0],label);
+   }
+   //this.print(fName+" label "+label);
+
 	let varValue="UNDEF";
 
 	//if (vName in setup.filters) varValue=setup.filters[vName];
@@ -803,6 +836,7 @@ function(entry,field,setup){
 	
 	let vType=field.type;
 	let id=setup.getInputId(vName);
+   //here I would also need the label to update in case of multiple matches
 	let input=crfHTML.getElement(id);
 
 		
@@ -907,29 +941,21 @@ function(entry,field,setup){
 
 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);
+	let fields=queryLayout.fields;
 
 	//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);
+	let entry=this.selectEntry(fQuery.rows,setup,fields);
 	
    if (!entry) entry=new Object();
-	let fields=queryLayout.fields;
 		
 	for (f in fields){	
 		let field=fields[f];
@@ -946,31 +972,33 @@ function(listName,writeMode,setup){
 
 crfVisit.generateTable=
 function(listName,divName,additionalData,setup){
+   //generate table for query(listName)
 	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;
+   //populate old data for main query, but not subqueries (since one assumess distinct data in each row)
    let populateData=true;
    if ("subTable" in setup){
       this.print(fName+" is subTable");
       populateData=false;
    }
 
-	let entry=new Object();
-
-
+	//this are the fields (probably constant)
+   let queryLayout=crfData.getQueryLayout(listName);
+	let fields=queryLayout.fields;
 
 	//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];
+
+   entry=this.selectEntry(fQuerySnapshot.rows,setup,fields);
+   if (!entry) entry=new Object();
+   //fQuerySnapshot.rows[0];
 
    
    if ("reviewTable" in setup){
@@ -981,8 +1009,6 @@ function(listName,divName,additionalData,setup){
 	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];
@@ -1113,30 +1139,75 @@ function(entry,elementId, field){
 }
 
 crfVisit.selectEntry=
-function(fRows,setup){
+function(fRows,setup,fields){
+   //out of potentially many entries, prepare a combined entry and 
+   //fill the _mergeData field with observations during merge
+   //where each field gets a comment that will be displayed
+   //with instructions of the field
    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];
+      return this.mergeEntries(fRows,setup,fields);
+
    
+   candidates=new Array();
    for (let i=0;i<fRows.length;i++){
+      let entryOK=true;
       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];
+         if (fRows[i][v]!=setup.setVariables[v]){
+            entryOK=false;
+            break;
          }
+         
+      }
+      if (!entryOK){
+         this.print(fName+' skipping '+i);
+         continue;
       }
+      this.print(fName+' adding '+i);
+      candidates.push(fRows[i])
    }
-   return null;
+   return this.mergeEntries(candidates,setup,fields);
 
 }
 
+crfVisit.mergeEntries=
+function(fRows,setup,fields){
+   let fName="[mergeEntries]";
+   this.print(fName+" entries["+fRows.length+"]");
+   let entry=fRows[0];
+   if (fRows.length==1){
+      return entry
+   }
+   let mergeData=new Object();
+
+   for (let k=0;k<fields.length;k++){
+      let field=fields[k];
+      let LUT=null;
+      if ("lookup" in field) 
+         LUT=crfData.getLookup(field.lookup.queryName).LUT;
+      let v=new Array();
+      for (let i=0;i<fRows.length;i++){
+         let varValue=fRows[i][field.name];
+         if (LUT!=null) varValue=LUT[varValue];
+         v.push(varValue)
+      }
+
+      this.print(fName+" "+field.name+" "+v);
+      mergeData[field.name]=v;
+   }
+
+
+   entry["_mergeData"]=mergeData;
+   return entry;
+}
+
+
 crfVisit.saveReview=
 function(queryName,elementId,setup){
 	//loads any queryName
@@ -1153,9 +1224,10 @@ function(queryName,elementId,setup){
    
    //data layout 
 	let queryLayout=crfData.getQueryLayout(queryName);
+	let fields=queryLayout.fields;
 
    //determine mode based on entry uniqueness and presence of data
-   let entry=this.selectEntry(fQuerySnapshot.rows,setup);
+   let entry=this.selectEntry(fQuerySnapshot.rows,setup,fields);
    let mode='update';
 
    if (!entry){
@@ -1169,7 +1241,6 @@ function(queryName,elementId,setup){
 	this.print(fName+" set crfRef="+entry.crfRef);
 
 
-	let fields=queryLayout.fields;
 	for (f in fields){
 
 		let field=fields[f];
@@ -1912,7 +1983,9 @@ function(){
 	let accessMode=this.role+'Mode';
    let formId=crfData.getCrfEntry()['Form'];
    let rowsSetup=crfSetup.selectFormSetupRows(formId);
+//go through formSetup and generate section for each entry
 	for (let i=0;i<rowsSetup.length;i++){
+//row in FormSetup
 		let entry=rowsSetup[i];
 
       //debug
@@ -1924,6 +1997,7 @@ function(){
 
 		//skip sections
 		//also from fields
+      //this can be crfEditorMode, crfMonitorMode or crfSponsorMode
 		if (entry[accessMode]=="NONE") continue;
 			
 		//section fits one dataset/list
@@ -2001,10 +2075,6 @@ function(sectionId){
 	divRev.style.display="none";
 	divRLi.style.display="none";
 	if (divGBu!=undefined) divGBu.style.display="block";
-	//add buttons?
-	//is button already generated?
-	
-	//populateTable(entry);
 	
 }		
 
@@ -2266,7 +2336,6 @@ function(){
       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']);
@@ -2340,3 +2409,13 @@ crfVisit.printForm=
 function(){
    crfPrint.printForm();
 }
+
+crfVisit.getFieldNames=
+function(fields){
+   //fields is an array of items with attribute name
+   let fieldNames=new Array();
+   for (let i=0;i<fields.length;i++){
+      fieldNames.push(fields[i].name);
+   }
+   return fieldNames;
+}