var formPortal={}; //global config variable formPortal.config=new Object(); 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.getMode= function(){ if ("role" in this.config){ return this.config.role; } return "crfEditor"; } formPortal.doNothing= function(){ this.print('doNothing called'); } //load runQuery.js formPortal.printMessage= function(msg){ let txt=this.config.document.createElement("p"); this.config.document.getElementById(this.config.div).appendChild(txt); txt.innerText=msg; } formPortal.userName= function(id){ let formConfig=this.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"; } formPortal.setContainer= function(label,container){ let config=this.config; if (!(config.formConfig.hasOwnProperty('container'))){ config.formConfig.container=new Array(); } config.formConfig.container[label]=container; } formPortal.getContainer= function(label){ return this.config.formConfig.container[label]; } formPortal.init= function(cb=null){ let that=this; let action=function(){that.scriptsLoaded(cb);}; LABKEY.Utils.requiresScript(["crfTecant/runQuery.js","crfTecant/formGenerator.js","crfTecant/variableList.js"],action); } formPortal.scriptsLoaded= function(cb=null){ formGenerator.set(this); if (cb) cb(); } formPortal.generateFormArray= function(){ let that=this; let action=function(){that.fcontinue0();}; this.init(action); } formPortal.fcontinue0= function(){ this.print("generateFormArray "+this.getMode()); let config=this.config; config.formConfig=new Object(); config.formConfig.softwareVersion='T.2.01'; //report software version //report software version config.document.getElementById('version').innerText=config.formConfig.softwareVersion; 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.afterSettings(data);}; LABKEY.Query.selectRows(selectRows); } formPortal.afterSettings= function(data){ let fName="[afterSettings]"; let config=this.config; 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; this.print(fName); for (let k in st){ this.print(fName+'\t'+k+'='+st[k]); } //if ('dataContainer' in st){ // setContainer('data',st['dataContainer']); //} let vname='configContainer'; if (vname in st){ this.setContainer('config',st[vname]); } this.print(fName+' config: '+this.getContainer('config')); this.print(fName+' data: '+this.getContainer('data')); //setup queryArray let queryArray=new Array(); //targetObject let targetObject=config.formConfig; //static variables queryArray.push(runQuery.makeQuery(targetObject,'data','crfStaticVariables','crfStaticVariables',[])); //Forms queryArray.push(runQuery.makeQuery(targetObject,'config','Forms','dataForms',[])); //users queryArray.push(runQuery.makeQuery(targetObject,'data','users','users',[])); queryArray[queryArray.length-1].schemaName='core'; //inputLists queryArray.push(runQuery.makeQuery(targetObject,'config','inputLists','inputLists',[])); //crfEditors queryArray.push(runQuery.makeQuery(targetObject,'config','crfEditors','crfEditors',[])); //crfMonitors queryArray.push(runQuery.makeQuery(targetObject,'config','crfMonitors','crfMonitors',[])); //crfSponsors queryArray.push(runQuery.makeQuery(targetObject,'config','crfSponsors','crfSponsors',[])); //crfManagers queryArray.push(runQuery.makeQuery(targetObject,'config','crfManagers','crfManagers',[])); //FormStatus queryArray.push(runQuery.makeQuery(targetObject,'config','FormStatus','formStatusg',[])); //site queryArray.push(runQuery.makeQuery(targetObject,'config','site','siteData',[])); //crfEntry queryArray.push(runQuery.makeQuery(targetObject,'data','crfEntry','crfEntries',[])); queryArray.push( runQuery.makeQuery(targetObject,'config','generateConfig','generateConfigData',[])); let that=this; let action=function(){that.addStudyData();}; runQuery.getDataFromQueries(this,queryArray,action); //getDataFromQueries(queryArray,fcontinue); } formPortal.addStudyData= function(){ let config=this.config; //setup queryArray let queryArray=new Array(); let targetObject=config.formConfig; queryArray.push(runQuery.makeQuery(targetObject,'data','StudyProperties','studyData',[])); let e=queryArray[queryArray.length-1]; e.schemaName='study'; let columnModel=""; let varRows=config.formConfig['crfStaticVariables'].rows; 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();}; runQuery.getDataFromQueries(this,queryArray,action); } formPortal.filterEntry= function(entry,filter,settings){ let fName="[filterEntry]"; if (entry.Form!=filter.form) return false; //only select forms where status matches the target status if (entry.FormStatus!=filter.formStatus){ //check for additionalStates let addStates=filter.additionalVisibilityStates[filter.role]; this.print(fName+' addState['+filter.role+'] '+addStates); if (!addStates) return false; if (entry.FormStatus!=addStates) return false; } this.print(fName+' candidate '+entry.entryId); //TODO: smart filter on user (now we get to see all) // //for editors if ("filterUser" in settings && filter.role=='crfEditor' && entry.UserId!=filter.userId){ this.print(fName+' skipping identity mismatch: '+entry.UserId+'/'+filter.userId); return false; } //for others let matchingSite=-1; let potentialSiteNumbers="["; for (let k=0;k<filter.sites.length;k++){ if (k>0) potentialSiteNumbers+=','; potentialSiteNumbers+=filter.sites[k].siteNumber; //skip mismatching sites if (entry.Site!=filter.sites[k].siteNumber) continue; matchingSite=filter.sites[k].siteNumber; break; } potentialSiteNumbers+=']'; if (matchingSite==-1){ this.print(fName+' skipping wrong site: '+entry.Site+'/'+potentialSiteNumbers); return false; } return true; } formPortal.fcontinue= function(){ let fName='[fcontinue]'; let config=this.config; let formConfig=config.formConfig; this.print(fName+" number of study data entries: "+formConfig.studyData.rows.length); this.print(fName+" participantId: "+formConfig.studyData.rows[0].SubjectColumnName); let dataForms=formConfig.dataForms.rows; formConfig.table=config.document.createElement("table"); config.document.getElementById(config.div).appendChild(formConfig.table); let accessModeColumn=this.getMode()+'Status'; this.print(fName+' accessModeColumn '+accessModeColumn); //cutting down on number of fields //let creatorModeColumn=getMode()+'Creator'; //switch from status based to form based access this.print(fName+" forms: "+dataForms.length); this.print(fName+" 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]; } //determine the role filter let fList=config.role+'s'; //check for users that fit the role, //fRows lists all users for role let fRows=config.formConfig[fList].rows; this.print(fName+' candidates: '+fRows.length) //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]); } //cludge for public sites where all users can act as anything let sts=config.formConfig.settings; let vName='allowAllForSite'; if (vName in sts){ let tempUserRole=new Object(); tempUserRole.User=currentUser.UserId; tempUserRole.Site=parseInt(sts[vName]); currentUserRoles.push(tempUserRole); } //currentUser was not matched in fRows if (currentUserRoles.length==0){ this.printMessage('User '+currentUser.DisplayName+" can't act as "+config.role); return; } //currentUser should be also attached to the site of the document 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]); } } config.formConfig.currentSites=currentSites; 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+=')'; this.printMessage(msg); let filter=new Object(); filter.role=config.role; filter.userId=currentUser.UserId; filter.sites=currentSites; //make a formStatus map let formStatusMap=new Object(); this.print(fName+' formStatusMap: '+config.formConfig.formStatusg.rows.length); for (let i=0;i<config.formConfig.formStatusg.rows.length;i++){ let fs=config.formConfig.formStatusg.rows[i]; let s=fs['Key']; formStatusMap[s]=fs; this.print(fName+' formStatusMap adding '+s); } this.print(fName+' formStatusMap '+Object.keys(formStatusMap).length+'/'+config.formConfig.formStatusg.rows.length); //browse through forms for (let i=0;i<dataForms.length;i++){ //dataForms is Forms let qForm=dataForms[i]; let formKey=qForm.Key; filter.form=qForm.Key; //add row for each form let row=formConfig.table.insertRow(i); let formName=qForm.formName; this.print(fName+" ["+i+"/"+formKey+']: '+formName); //column counter let k=0; //get the target status let formStatus=qForm[accessModeColumn]; filter.formStatus=qForm[accessModeColumn]; this.print(fName+' target formStatus '+formStatus); filter.additionalVisibilityStates=new Object(); let as=qForm["additionalVisibilityStates"]; if (as){ filter.additionalVisibilityStates=variableList.parseVariables(as); } for (let j=0;j<fEntries.length;j++){ let entry=fEntries[j]; if (!this.filterEntry(entry,filter,config.formConfig.settings)) continue; //insert form // let fbox=config.document.createElement("div"); let color='gold'; this.print(fName+' status '+entry.FormStatus+' obj '+formStatusMap[entry.FormStatus]); if (formStatusMap[entry.FormStatus]){ let c=formStatusMap[entry.FormStatus]['color']; if (c) color=c; this.print(fName+' status '+entry.FormStatus+' color '+c); } fbox.classList.add("box",color); 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; let pid=entry['participantStudyId']; let loc=entry['participantLocalId']; let label=''; if (pid) label+=pid+' '; if (loc) label+='(Local: '+loc+')'; if (label.length==0) label="NONE"; fp3.innerHTML=label; 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); let that=this; button.onclick=function(){that.openForm(entry)}; cell.appendChild(button); k++; } this.print(fName+' finished checking existing forms'); //only those that are allowed to create forms //print('Status: '+qForm[creatorModeColumn]); let creator=qForm['creator']; if (!creator) continue; if (creator!=this.getMode()) continue; //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); let that=this; button.onclick=function(){that.createForm(formKey)}; cell.appendChild(button); } if (config.role=='crfManager') this.print('Skipping form generator'); //need formGenerator.js //formGenerator.addFormGenerator(this); } formPortal.openForm= function(crfEntry){ let fName="[openForm]"; let config=this.config; let formConfig=config.formConfig; let crfRef=crfEntry.entryId; this.print(fName+" 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; this.print(fName+" 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_tecant", formUrl , containerPath, params); this.print(fName+" redirecting to "+wikiURL); window.location = wikiURL; } formPortal.createForm= function(formId){ let fName="[createForm]"; let config=this.config; let formConfig=config.formConfig; let dataForms=formConfig.dataForms.rows; let qForm=null; for (let i=0;i<dataForms.length;i++){ if (dataForms[i].Key==formId){ qForm=dataForms[i]; break; } } 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=qForm["initialStatus"];//In progress this.print(fName+" setting status to "+crfEntry.FormStatus); //set other variables //requires studyData as part of formConfig let studyData=formConfig.studyData.rows[0]; let varRows=formConfig['crfStaticVariables'].rows; 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=config.formConfig.currentSites[0].siteNumber; this.print(fName+" setting site to id="+crfEntry.Site); //from argument list crfEntry.Form=formId; let crfStatus=new Object(); crfStatus.entryId=crfEntry.entryId; crfStatus.submissionDate=new Date(); crfStatus.FormStatus=crfEntry.FormStatus; crfStatus.User=crfEntry.UserId; crfStatus.Form=crfEntry.Form; crfStatus.operator=config.role; crfStatus.action='createForm'; let that=this; let cb=function(data){that.openForm(crfEntry);}; //this is for debug //let cb=function(data){;}; let containerPath=this.getContainer('data'); let pass=function(data){formGenerator.insertRow('lists','crfStatus',crfStatus,cb,containerPath);}; formGenerator.insertRow('lists','crfEntry',crfEntry,pass,this.getContainer('data')); }