crfVisit.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. function clear(config){
  2. config.document.getElementById(config.debugId).value="";
  3. }
  4. function print(config,msg){
  5. config.document.getElementById(config.debugId).value+="\n"+msg;
  6. }
  7. function getCRFref(config){
  8. //'crfRefId'
  9. return config.document.getElementById(config.crfRefId).innerHTML;
  10. }
  11. function populateBasicData(config,data){
  12. let debug=false;
  13. if (debug)
  14. print(config,"crfRef matched entries: "+data.rows.length);
  15. if (data.rows.length!=1) { return;}
  16. config.document.getElementById('eudraCTNumber').innerHTML=data.rows[0].EudraCTNumber;
  17. config.document.getElementById('studyCoordinator').innerHTML=data.rows[0].StudyCoordinator;
  18. config.document.getElementById('studySponsor').innerHTML=data.rows[0].StudySponsor;
  19. let qconfig=new Object();
  20. qconfig.containerPath=config.containerPath;
  21. qconfig.schemaName='lists';
  22. qconfig.queryName='site';
  23. qconfig.filterArray=[LABKEY.Filter.create('siteNumber', data.rows[0].Site)];
  24. qconfig.success=function(data){setHTML(config,data,'siteName','siteName')};
  25. LABKEY.Query.selectRows(qconfig);
  26. let qconfig1=new Object();
  27. qconfig1.containerPath=config.containerPath;
  28. qconfig1.schemaName='core';
  29. qconfig1.queryName='Users';
  30. qconfig1.filterArray= [LABKEY.Filter.create('UserId',data.rows[0].UserId)];
  31. qconfig1.success= function(data){setHTML(config,data,'investigatorName','DisplayName')};
  32. LABKEY.Query.selectRows(qconfig1);
  33. }
  34. function setHTML(config,data,elementId,varName){
  35. print(config,"setHTML "+data.rows.length+" elementId: "+elementId+" varName:"+varName);
  36. if (data.rows.length>0){
  37. let entry=data.rows[0];
  38. let el=config.document.getElementById(elementId);
  39. print(config,"setHTML: Entry[" + varName + "]: " + entry[varName]);
  40. print(config,"setHTML: Element[" + elementId + "]: " + el);
  41. el.innerHTML=entry[varName];
  42. }
  43. }
  44. function setAdditionalData(config,additionalData,entry){
  45. let debug=true;
  46. if (debug) print(config,"setAdditionalData");
  47. if (entry["showFlag"]==="NONE") {
  48. if (debug) print(config,"Returning empty additionalData");
  49. return additionalData;
  50. }
  51. additionalData.showFlag=entry["showFlag"];
  52. additionalData.showFlagValue=entry["showFlagValue"];
  53. additionalData.queryName=entry["showQuery"];
  54. additionalData.filters=new Object();
  55. additionalData.filters['crfRef']=getCRFref(config);
  56. return additionalData;
  57. }
  58. function fullAccessSetup(config,listName){
  59. let debug=true;
  60. if (debug) print(config,"fullAccessSetup");
  61. let setup=new Object();
  62. setup.readonlyFlag=function(vName){return false};
  63. setup.filters=new Object();
  64. setup.filters['crfRef']=getCRFref(config);
  65. setup.getInputId=function(vName){return listName+"_"+vName;}
  66. setup.addApply="Save";
  67. setup.unique=true;
  68. //no addApply
  69. return setup;
  70. }
  71. function readonlySetup(config){
  72. let debug=true;
  73. if (debug) print(config,"readonlySetup");
  74. let setup=new Object();
  75. setup.readonlyFlag=function(vName){return true};
  76. setup.filters=new Object();
  77. setup.filters['crfRef']=getCRFref(config);
  78. setup.getInputId=function(vName){return vName;}
  79. return setup;
  80. }
  81. function generateForm(config,data){
  82. let debug=true;
  83. if (debug) print(config,"generateForm ["+data.rows.length+"]");
  84. for (let i=0;i<data.rows.length;i++){
  85. if (debug) print(config,"generateForm ["+i+"/"+data.rows.length+"]");
  86. let entry=data.rows[i];
  87. let queryName=entry["queryName"];
  88. if (debug) print(config,"entry[queryName]: "+entry["queryName"]);
  89. if (!(queryName in config.fields))
  90. config.fields[queryName]=new Object();
  91. let field=config.fields[queryName];
  92. field.title=entry["title"];
  93. if (debug) print(config,"entry[showFlag]: "+entry["showFlag"]);
  94. let additionalData=new Object();
  95. setAdditionalData(config,additionalData,entry);
  96. generateSection(config,entry["queryName"],entry["title"],
  97. entry["queryName"], additionalData);
  98. }
  99. }
  100. function generateSection(config, sectionName, sectionTitle, listName, additionalData){
  101. let formName=config.masterForm;
  102. let debug=true;
  103. if (debug) print(config,"generateSection "+sectionName);
  104. let tb=config.document.createElement('table');
  105. tb.className='t2';
  106. let row=tb.insertRow();
  107. let cell=config.document.createElement('th');
  108. row.appendChild(cell);
  109. cell.setAttribute("colspan","4");
  110. cell.style.fontSize="20px";
  111. cell.style.textAlign="center";
  112. let cellData=config.document.createTextNode(sectionTitle);
  113. cell.appendChild(cellData);
  114. cell=row.insertCell();
  115. let input=config.document.createElement("input");
  116. input.type="button";
  117. input.value="Show";
  118. input.id="toggle"+sectionName+"VisbilityButton";
  119. input.onclick=function(){toggleVisibility(config,sectionName,input.id)};
  120. cell.appendChild(input);
  121. config.document.getElementById(formName).appendChild(tb);
  122. let div=config.document.createElement('div');
  123. div.id=sectionName;
  124. div.style.display="none";
  125. config.document.getElementById(formName).appendChild(div);
  126. let divTable=config.document.createElement('div');
  127. divTable.id=sectionName+"Table";
  128. div.appendChild(divTable);
  129. if ("showFlag" in additionalData) {
  130. additionalData.divName=sectionName+"SubDiv";
  131. additionalData.divQueryName=sectionName+"SubDivList";
  132. let div1=config.document.createElement('div');
  133. div1.id=additionalData.divName;
  134. div1.style.display="none";
  135. div.appendChild(div1);
  136. let div2=config.document.createElement('div');
  137. div2.id=additionalData.divQueryName;
  138. div1.appendChild(div2);
  139. }
  140. if (debug) print(config,"generate master table");
  141. let setup=fullAccessSetup(config,listName);
  142. if (config.review)
  143. setup=readonlySetup(config);
  144. generateTable(config,listName,divTable.id,true,additionalData,setup);
  145. if (debug) print(config,"generate master table: done");
  146. if ("showFlag" in additionalData){
  147. let qName=additionalData.queryName;
  148. let dName=additionalData.divName;
  149. let setup=fullAccessSetup(config,qName);
  150. if (config.review)
  151. setup=readonlySetup(config);
  152. generateTable(config,qName,dName,false,additionalData,setup);
  153. }
  154. let divReviewList=config.document.createElement('div');
  155. divReviewList.id=sectionName+"ReviewList";
  156. div.appendChild(divReviewList);
  157. let divReview=config.document.createElement('div');
  158. divReview.id=sectionName+"Review";
  159. div.appendChild(divReview);
  160. let qconfig=new Object();
  161. qconfig.containerPath=config.containerPath;
  162. qconfig.schemaName='lists';
  163. qconfig.queryName='visitZeroSetup';
  164. qconfig.success=function(data){
  165. generateReview(config,data,divReview.id,divReviewList.id,listName)};
  166. LABKEY.Query.selectRows(qconfig);
  167. }
  168. function generateReview(config,data,divReviewId,divReviewListId, listName){
  169. let debug=true;
  170. if (debug) print(config,"Generate review for: "+listName);
  171. let listId=-1;
  172. for (let i=0;i<data.rows.length;i++){
  173. let entry=data.rows[i];
  174. if (entry["queryName"]!=listName) continue;
  175. listId=entry["Key"];
  176. break;
  177. }
  178. if (debug) print(config,"Review: setting listId: "+listId);
  179. let reviewSetup=new Object();
  180. reviewSetup.readonlyFlag=function(vName){
  181. if (vName=="queryName") return true;
  182. if (vName=="ModifiedBy") return true;
  183. return false;};
  184. reviewSetup.addApply="Add Review";
  185. reviewSetup.filters=new Object();
  186. reviewSetup.filters["crfRef"]=getCRFref(config);
  187. reviewSetup.filters["queryName"]=listId;
  188. reviewSetup.filters["ModifiedBy"]=LABKEY.Security.currentUser.id;
  189. reviewSetup.getInputId=function(vName){return listName+"_add"+vName};
  190. reviewSetup.divReviewListId=divReviewListId;
  191. if (debug) {
  192. let msg="Review: divId: "+divReviewId;
  193. msg+=" inputId: "+reviewSetup.getInputId;
  194. print(config,msg);
  195. }
  196. updateListDisplay(config,divReviewListId,"reviewComments",reviewSetup.filters,true);
  197. generateTable(config,"reviewComments",divReviewId,false,new Object(),reviewSetup);
  198. }
  199. function setListVisibility(config,setup,additionalData,readonlyFlag){
  200. let debug=true;
  201. if (debug){
  202. print(config,"Set list visibility ");
  203. for (f in additionalData){
  204. print(config,"AdditionalData["+f+"]: "+additionalData[f]);
  205. }
  206. }
  207. let x = config.document.getElementById(additionalData.divName);
  208. if (debug) print(config,"\n Div: "+x);
  209. x.style.display="none";
  210. let eId=setup.getInputId(additionalData.showFlag);
  211. let e = config.document.getElementById(eId);
  212. let sText;
  213. if (readonlyFlag) sText=e.innerHTML;
  214. else sText=e.options[e.selectedIndex].text;
  215. if (debug) print(config,"\n Selected option text: "+sText);
  216. if (sText == additionalData.showFlagValue){
  217. let filters=new Object();
  218. if ("filters" in additionalData) filters=additionalData.filters;
  219. x.style.display = "block";
  220. updateListDisplay(config,additionalData.divQueryName,additionalData.queryName,filters,readonlyFlag);
  221. }
  222. }
  223. function updateListDisplay(config,divName,queryName,filters,readonlyFlag){
  224. let debug=true;
  225. if (debug) print(config,"UpdateListDisplay: Query - "+queryName+" div - "+divName);
  226. if (divName=="NONE") return;
  227. let crfRef=getCRFref(config);
  228. let div=config.document.getElementById(divName);
  229. if (debug)
  230. print(config,"Enabling display to queryName: "+queryName);
  231. var qconfig=new Object();
  232. qconfig.renderTo=divName;
  233. qconfig.containerPath=config.containerPath;
  234. qconfig.schemaName='lists';
  235. qconfig.queryName=queryName;
  236. qconfig.buttonBarPosition='top';
  237. qconfig.filters=[];
  238. for (f in filters){
  239. qconfig.filters.push(LABKEY.Filter.create(f, filters[f]));
  240. }
  241. qconfig.success=function(data){updateSuccess(config,data)};
  242. qconfig.failure=function(data){updateFailure(config,data)};
  243. //show only print button
  244. if (readonlyFlag){
  245. qconfig.buttonBar=new Object();
  246. qconfig.buttonBar.items=["print"];
  247. }
  248. LABKEY.QueryWebPart(qconfig);
  249. }
  250. function updateSuccess(config,data){
  251. print(config,"Update success");
  252. }
  253. function updateFailure(config,data){
  254. print(config,"Update failed");
  255. }
  256. function toggleVisibility(config, divName,buttonName){
  257. let x = config.document.getElementById(divName);
  258. if (x.style.display === "none") {
  259. x.style.display = "block";
  260. config.document.getElementById(buttonName).value="Hide";
  261. } else {
  262. x.style.display = "none";
  263. config.document.getElementById(buttonName).value="Show";
  264. }
  265. }
  266. function generateButton(config,divName,buttonName,callback,callbackParameters){
  267. let debug=true;
  268. if (debug) print(config,"generateButton");
  269. let tb=config.document.createElement('table');
  270. tb.className="t2";
  271. let r1=tb.insertRow();
  272. th=config.document.createElement('th');
  273. r1.appendChild(th);
  274. th.innerHTML="Complete submission";
  275. //*!*
  276. let c2=r1.insertCell();
  277. let i1=config.document.createElement("input");
  278. i1.type="button";
  279. i1.value=buttonName;
  280. i1.style.fontSize="20px";
  281. i1.onclick=function(){callback(callbackParameters);}
  282. c2.appendChild(i1);
  283. let c1=r1.insertCell();
  284. c1.setAttribute("colspan","1");
  285. c1.id=callbackParameters.submitReportId;
  286. let el=config.document.getElementById(divName);
  287. if (debug) print(config,"generateButton: element["+divName+"]: "+el);
  288. el.appendChild(tb);
  289. }
  290. function generateTable(config,listName,divName,unique,additionalData,setup){
  291. let debug=true;
  292. if (debug) print(config,"generateTable: "+listName);
  293. //add temp variables
  294. let qconfig=new Object();
  295. qconfig.containerPath=config.containerPath;
  296. qconfig.schemaName='lists';
  297. qconfig.queryName=listName;
  298. //apply filters on data to get right entries
  299. qconfig.filterArray=[];
  300. for (f in setup.filters){
  301. qconfig.filterArray.push(LABKEY.Filter.create(f,setup.filters[f]));
  302. }
  303. qconfig.success=function(data){populateTable(config,data,divName,unique,additionalData,setup)};
  304. LABKEY.Query.selectRows(qconfig);
  305. }
  306. function populateTable(config,data,divName,unique,additionalData,setup){
  307. //generate and populate table with the first suitable entry
  308. let debug=true;
  309. if (debug){
  310. print(config,"populateTable Query: "+data.queryName+" divName: "+divName+" setup: "+setup);
  311. if (0){
  312. let obj=data.metaData.fields;
  313. for (f in obj){
  314. print(config,"Data["+f+"]: "+obj[f]);
  315. for (g in obj[f]){
  316. print(config,"Data.metaData.fields["+f+"]["+g+"]: "+obj[f][g]);
  317. }
  318. if ("lookup" in obj[f]){
  319. for (h in obj[f]["lookup"]){
  320. print(config,"Lookup["+h+"]: "+obj[f]["lookup"][h]);
  321. }
  322. }
  323. }
  324. }
  325. }
  326. let crfRef=getCRFref(config);
  327. let entry=new Object();
  328. if (debug)
  329. print(config,"Data: nrows "+data.rows.length);
  330. if (data.rows.length > 0) entry=data.rows[0];
  331. let tb=config.document.createElement('table');
  332. tb.className="t2";
  333. config.document.getElementById(divName).appendChild(tb);
  334. let fields=data.metaData.fields;
  335. for (f in fields){
  336. let field=fields[f];
  337. if (field.hidden) continue;
  338. let vName=field.name;
  339. if (debug) print(config,"Field ["+vName+"]");
  340. if (vName=="crfRef") continue;
  341. let vType=field.type;
  342. if (debug) print(config,"Field ["+vName+"/"+vType+"]");
  343. let row=tb.insertRow();
  344. let cell=config.document.createElement('th');
  345. row.appendChild(cell);
  346. let text = config.document.createTextNode(fields[f].shortCaption);
  347. cell.appendChild(text);
  348. cell=row.insertCell();
  349. let varValue="UNDEF";
  350. if (vName in setup.filters) varValue=setup.filters[vName];
  351. if (vName in entry) varValue=entry[vName];
  352. if (vType=="date"){
  353. if (varValue==="UNDEF") varValue=new Date();
  354. else varValue=new Date(varValue);
  355. }
  356. if (debug) print(config,"value: "+varValue);
  357. let input;
  358. if (setup.readonlyFlag(vName)){
  359. input=config.document.createTextNode(varValue);
  360. cell.id=setup.getInputId(vName);
  361. }
  362. else{
  363. cell.colSpan="3";
  364. let cellClass="input";
  365. let cellType="text";
  366. if ("lookup" in field){
  367. input = config.document.createElement("select");
  368. }
  369. if (vType=="date"){
  370. input = config.document.createElement("input");
  371. input.type="date";
  372. }
  373. if (vType=="string"){
  374. if(vName.search("reviewComment")>-1){
  375. input = config.document.createElement("textarea");
  376. input.cols="65";
  377. input.rows="5";
  378. }
  379. else{
  380. input = config.document.createElement("input");
  381. input.type="text";
  382. }
  383. }
  384. if (vType=="float"){
  385. input = config.document.createElement("input");
  386. input.type="text";
  387. }
  388. input.id=setup.getInputId(vName);
  389. if (vName in entry){
  390. if (vType=="string") input.value=varValue;
  391. if (vType=="float") input.value=varValue;
  392. if (vType=="date") input.valueAsDate=varValue;
  393. }
  394. }
  395. cell.appendChild(input);
  396. if ("lookup" in field){
  397. let lookup=field["lookup"];
  398. let qconfig=new Object();
  399. if (debug) print(config,"populateTable lookup: Query: "+lookup.queryName);
  400. qconfig.containerPath=config.containerPath;
  401. qconfig.schemaName=lookup.schemaName;
  402. qconfig.queryName=lookup.queryName;
  403. let parameters= new Object();
  404. parameters.elementId=setup.getInputId(vName);
  405. parameters.keyColumn=lookup.keyColumn;
  406. parameters.displayColumn=lookup.displayColumn;
  407. if (vName in setup.filters) parameters.selectedKey=setup.filters[vName];
  408. if (vName in entry) parameters.selectedKey=entry[vName];
  409. if ("showFlag" in additionalData) parameters.additionalData=additionalData;
  410. if (debug) print(config,"Populate select for "+parameters.elementId);
  411. qconfig.success=function(data){
  412. populateSelect(config,data,parameters,setup,setup.readonlyFlag(vName))
  413. };
  414. LABKEY.Query.selectRows(qconfig);
  415. }
  416. }
  417. //add comment field
  418. if (!("addApply" in setup)) {
  419. print(config,"populateTable: done");
  420. return;
  421. }
  422. let row=tb.insertRow();
  423. let th=config.document.createElement('th');
  424. row.appendChild(th);
  425. th.innerHTML=setup.addApply;
  426. let cell=row.insertCell();
  427. //cell.setAttribute("colspan","2");
  428. let input=config.document.createElement("input");
  429. input.type="button";
  430. input.value=setup.addApply;
  431. cell.appendChild(input);
  432. let cell1=row.insertCell();
  433. cell1.setAttribute("colspan","2");
  434. cell1.id=setup.getInputId("rerviewLastSave");
  435. cell1.innerHTML="No recent update";
  436. input.onclick=function(){saveReview(config,data.queryName,cell1.id,setup)};
  437. }
  438. function populateSelect(config,data,parameters,setup,readonlyFlag){
  439. let debug=true;
  440. if (debug)
  441. print(config,"populateSelect on "+data.queryName);
  442. let elementId=parameters.elementId;
  443. let keyColumn=parameters.keyColumn;
  444. let displayColumn=parameters.displayColumn;
  445. if (debug){
  446. print(config,"Query: "+data.queryName);
  447. print(config,"ElementId: "+elementId);
  448. print(config,"keyColumn: "+keyColumn);
  449. print(config,"displayColumn: "+displayColumn);
  450. if ("selectedKey" in parameters){
  451. print(config,"SelectedKey: "+parameters["selectedKey"]);
  452. }
  453. }
  454. let el = config.document.getElementById(elementId);
  455. if (debug)
  456. print(config,"Element: "+el);
  457. if (!readonlyFlag){
  458. //clear options
  459. for(i = el.options.length; i >= 0; i--) {
  460. el.remove(i);
  461. }
  462. let opt = config.document.createElement("option");
  463. opt.text = "<Select>";
  464. opt.value = -1;
  465. el.options[0] = opt;
  466. }
  467. for (let i = 0; i < data.rows.length; i++) {
  468. let displayText = data.rows[i][displayColumn];
  469. let keyValue = data.rows[i][keyColumn];
  470. if (!readonlyFlag){
  471. let opt = config.document.createElement("option");
  472. opt.text = displayText;
  473. opt.value = keyValue;
  474. el.options[el.options.length] = opt;
  475. }
  476. if (debug) print(config,"Adding: "+keyValue+" : "+displayText);
  477. let t1=checkVariable(config,el,keyValue,displayText,parameters,"selectedKey",readonlyFlag);
  478. if (t1) setup.keyValue=keyValue;
  479. }
  480. if (!("additionalData" in parameters)) return;
  481. if (debug) print(config,"\n Parsing additional data ");
  482. let additionalData=parameters["additionalData"];
  483. let expId=setup.getInputId(additionalData.showFlag);
  484. if (expId!=elementId) {
  485. print(config,"Element mismatch: got :"+expId+"/"+elementId);
  486. return;
  487. }
  488. if (debug)
  489. print(config,"Setting onChange to "+el.id);
  490. el.onchange=function(){setListVisibility(config,setup,additionalData,readonlyFlag)};
  491. setListVisibility(config,setup,additionalData,readonlyFlag);
  492. }
  493. function checkVariable(config,el,varValue,displayText, parameters,varName,readonlyFlag){
  494. let debug=true;
  495. if (!varName in parameters) return false;
  496. if (debug) print(config,"Comparing: " + varValue + "/" + parameters[varName]);
  497. if (varValue==parameters[varName]){
  498. if (readonlyFlag) el.innerHTML=displayText;
  499. else {
  500. el.selectedIndex=el.options.length-1;
  501. if (debug) print(config,"Equal; "+el.selectedIndex);
  502. }
  503. return true;
  504. }
  505. return false;
  506. }
  507. function failureSelect(config,errorInfo,resp,opt){
  508. print(config,"Error: ");
  509. }
  510. function saveReview(config,queryName,elementId,setup){
  511. let debug=true;
  512. if (debug) print(config,"saveReview: elementId "+elementId+" queryName "+queryName);
  513. let qconfig=new Object();
  514. qconfig.containerPath=config.containerPath;
  515. qconfig.schemaName='lists';//could be made more generic
  516. qconfig.queryName=queryName;
  517. if ("unique" in setup){
  518. qconfig.filterArray=[LABKEY.Filter.create("crfRef",getCRFref(config))];
  519. }
  520. qconfig.success=function(data){saveReviewToList(config,data,elementId,setup);}
  521. //to guess the fields, one must do selectRows first?
  522. LABKEY.Query.selectRows(qconfig);
  523. }
  524. function saveReviewToList(config,data,elementId,setup){
  525. let debug=true;
  526. if (debug) {
  527. let msg="saveReviewToList: "+" elementId "+elementId;
  528. msg+=" nrows "+data.rows.length;
  529. print(config,msg);
  530. }
  531. let useInsert=false;
  532. if (!("unique" in setup)) useInsert=true;
  533. if (data.rows.length==0) useInsert=true;
  534. let entry=new Object();
  535. if (!useInsert){
  536. entry=data.rows[0];
  537. }
  538. entry.crfRef=getCRFref(config);
  539. if (debug) print(config,"Set crfRef="+entry.crfRef);
  540. if ("queryName" in setup.filters) {
  541. entry.queryName=setup.filters["queryName"];
  542. if (debug) print(config,"Setting queryName: "+entry.queryName);
  543. }
  544. let fields=data.metaData.fields;
  545. for (f in fields){
  546. let field=fields[f];
  547. if (debug) print(config,"saveReview field: "+field.name);
  548. if (field.hidden) continue;
  549. let vName=fields[f].name;
  550. if (vName=="crfRef") continue;
  551. if (vName=="queryName") continue;
  552. let eId=setup.getInputId(vName);
  553. let el=config.document.getElementById(eId);
  554. if (!el) {
  555. if (debug) print(config,"saveReview element: "+eId+" not found");
  556. continue;
  557. }
  558. if (debug) print(config,"saveReview element: "+eId);
  559. let vType=fields[f].type;
  560. if (debug) print(config,"vType: "+vType);
  561. if ("lookup" in fields[f]){
  562. if (el.nodeName==="SELECT"){
  563. entry[vName]=el.options[el.selectedIndex].value;
  564. }
  565. if (el.nodeName==="TD"){
  566. entry[vName]=el.innerHTML;
  567. }
  568. print(config,"Setting lookup to "+entry[vName]);
  569. continue;
  570. }
  571. if (vType=="date"){
  572. var date=el.valueAsDate;
  573. if (date==="null") continue;
  574. date.setUTCHours(12);
  575. entry[vName]=date.toString();
  576. print(config,"Setting date to "+entry[vName]);
  577. }
  578. if (vType=="string"){
  579. entry[vName]=el.value;
  580. }
  581. if (vType=="float"){
  582. entry[vName]=el.value;
  583. }
  584. }
  585. let qconfig=new Object();
  586. qconfig.rows=[entry];
  587. qconfig.containerPath=config.containerPath;
  588. qconfig.schemaName=data.schemaName;
  589. qconfig.queryName=data.queryName;
  590. //only update comments
  591. print(config,"modifyRows: useInsert "+useInsert);
  592. qconfig.success=function(data){updateLastSavedFlag(config,data,setup,elementId)};
  593. if (!useInsert){
  594. LABKEY.Query.updateRows(qconfig);
  595. }
  596. else{
  597. LABKEY.Query.insertRows(qconfig);
  598. }
  599. }
  600. function updateLastSavedFlag(config,data,setup,elementId){
  601. let debug=true;
  602. if (debug) print(config,"Update last saved flag to "+elementId);
  603. let el=config.document.getElementById(elementId);
  604. let dt=new Date();
  605. el.innerHTML="Last saved "+dt.toString();
  606. if (data.queryName=="reviewComments"){
  607. updateListDisplay(config,setup.divReviewListId,"reviewComments",setup.filters,true);
  608. }
  609. }
  610. //******************************************upload to database *********************
  611. function onDatabaseUpload(config){
  612. print(config,"Database upload");
  613. //figure out the participantId
  614. let qconfig=new Object();
  615. qconfig.queryName=config.registrationQuery;
  616. qconfig.schemaName='lists';
  617. qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
  618. qconfig.success=function(data){updateDatabaseWithPatientId(config,data);}
  619. LABKEY.Query.selectRows(qconfig);
  620. }
  621. function updateDatabaseWithPatientId(config,data){
  622. clearErr(config);
  623. if (data.rows.length!=1){
  624. let msg="ERROR: Found "+data.rows.length;
  625. msg+=" registration entries for crfrefid "+getCRFref(config);
  626. print(config,msg);
  627. return;
  628. }
  629. participantId=data.rows[0][config.registrationParticipantIdField];
  630. print(config,"Setting participantId to "+participantId);
  631. //another select rows to update all queries from setup
  632. //just use registration for test
  633. let qconfig=new Array();
  634. qconfig.schemaName='lists';
  635. qconfig.queryName=config.setupQueryName;
  636. qconfig.success=function(data){copyDatasetsFromSetup(config,data);}
  637. LABKEY.Query.selectRows(qconfig);
  638. }
  639. function copyDatasetsFromSetup(config,data){
  640. for (let i=0;i<data.rows.length;i++){
  641. let entry=data.rows[i];
  642. copyToDataset(config,entry.queryName,participantId);
  643. if (entry.showQuery!="NONE"){
  644. copyToDataset(config,entry.showQuery,participantId);
  645. }
  646. }
  647. print(config,"Database updated");
  648. }
  649. function copyToDataset(config,queryName,participantId){
  650. print(config,"copyToDataset");
  651. let qconfig=new Object();
  652. qconfig.queryName=queryName;
  653. qconfig.schemaName="lists";
  654. qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
  655. qconfig.success=function(data){copyDataToDataset(config,queryName,participantId,data)};
  656. LABKEY.Query.selectRows(qconfig);
  657. }
  658. function copyDataToDataset(config,queryName,participantId,dataList){
  659. print(config,"copyDataToDataset");
  660. let qconfig=new Object();
  661. qconfig.queryName=queryName;
  662. qconfig.schemaName="study";
  663. qconfig.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
  664. qconfig.filterArray.push(LABKEY.Filter.create('ParticipantId',participantId));
  665. qconfig.success=function(data){copyDataToDatasetChecked(config,queryName,participantId,dataList,data)};
  666. LABKEY.Query.selectRows(qconfig);
  667. }
  668. function copyDataToDatasetChecked(config,queryName,participantId,dataList,dataStudy){
  669. print(config,"copyDataToDatasetChecked");
  670. if (dataStudy.rows.lentgh>0){
  671. clearErr(config);
  672. let msg="Dataset "+queryName+" already filled for participant "+participantId;
  673. printErr(config,msg);
  674. //rows with the same crfRef and patientId already inserted - skip
  675. return;
  676. }
  677. //update non-list elements
  678. let seqNumber=getCRFref(config);
  679. let rows=new Array();
  680. for (let i=0;i<dataList.rows.length;i++){
  681. let entry=dataList.rows[i];
  682. entry.ParticipantId=participantId;
  683. entry.crfRef=getCRFref(config);
  684. entry.SequenceNum=getCRFref(config);
  685. entry.SequenceNum=entry.SequenceNum % 1000000000;
  686. if (dataList.rows.length>1){
  687. entry.SequenceNum+=i/10;
  688. }
  689. print(config, "Adding sequence number "+entry.SequenceNum);
  690. rows.push(entry);
  691. }
  692. let qconfig=new Object();
  693. qconfig.queryName=queryName;
  694. qconfig.schemaName="study";
  695. qconfig.success=function(data){
  696. reportCopyDataToDatasetChecked(config,queryName,participantId,data)};
  697. qconfig.rows=rows;
  698. LABKEY.Query.insertRows(qconfig);
  699. }
  700. function reportCopyDataToDatasetChecked(config,queryName,participantId,data){
  701. printErr(config,"Inserted "+data.rows.length+" rows to "+queryName);
  702. }
  703. //*************************update for further review *************************
  704. function onUpdateForReview(config){
  705. print(config,"Sent to further review");
  706. let qconfig=new Object();
  707. qconfig.schemaName='lists';
  708. qconfig.queryName='crfEntry';
  709. qconfig.success=function(data){setFlagToReview(config,data);}
  710. qconfig.filterArray=[LABKEY.Filter.create("entryId",getCRFref(config))];
  711. LABKEY.Query.selectRows(qconfig);
  712. }
  713. function setFlagToReview(config,data){
  714. let debug=true;
  715. print(config,"setFlagToReview");
  716. if (data.rows.length!=1){
  717. let msg="ERROR: Found "+data.rows.length;
  718. msg+=" entries for crfrefid "+getCRFref(config);
  719. print(config,msg);
  720. return;
  721. }
  722. let entry=data.rows[0];
  723. entry.FormStatus=4;//Pending Review
  724. if (debug)
  725. print(config,"Set form status to "+entry.FormStatus);
  726. let qconfig=new Object();
  727. qconfig.schemaName='lists';
  728. qconfig.queryName='crfEntry';
  729. qconfig.rows=[entry];
  730. qconfig.success=function(data){completeWithReview(config,data);}
  731. LABKEY.Query.updateRows(qconfig);
  732. }
  733. function completeWithReview(config,data){
  734. let debug=true;
  735. if (debug)
  736. print(config,"complete with review");
  737. let formUrl="begin";
  738. var params = {
  739. "name": formUrl, // The destination wiki page. The name of this parameter is not arbitrary.
  740. };
  741. let containerPath= LABKEY.ActionURL.getContainer();
  742. // This changes the page after building the URL.
  743. //Note that the wiki page destination name is set in params.
  744. var homeURL = LABKEY.ActionURL.buildURL("project", formUrl , containerPath, params);
  745. print(config,"Redirecting to "+homeURL);
  746. window.location = homeURL;
  747. }
  748. //************************************************ submit *******************************************
  749. function onSubmit(config){
  750. let debug=true;
  751. hideErr(config);
  752. clearErr(config);
  753. printErr(config,"onSubmit");
  754. checkForm(config);
  755. let cb=new Object();
  756. cb.success=finalValidation;
  757. cb.failure=function(config){printErr(config,"waitForCheckForm failed")};
  758. waitForCheckForm(config,cb);
  759. }
  760. function finalValidation(config){
  761. let debug=true;
  762. if (debug) print(config,"validate");
  763. let completed=true;
  764. for (f in config.fields){
  765. let field=config.fields[f];
  766. if (field.status!="DONE") {
  767. printErr(config,"Missing entry for "+field.title);
  768. completed=false;
  769. }
  770. }
  771. if (debug) print(config,"valid: "+completed);
  772. if (completed){
  773. finalRedirect(config);
  774. }
  775. else{
  776. updateSubmitStatus(config,"Form invalid");
  777. }
  778. }
  779. function finalRedirect(config){
  780. printErr(config,"Form valid");
  781. let c1=new Object();
  782. c1.schemaName='lists';
  783. c1.queryName='crfEntry';
  784. c1.filterArray=[LABKEY.Filter.create('crfRef',getCRFref(config))];
  785. c1.success=function(data){setSubmitStatus(config,data)};
  786. LABKEY.Query.selectRows(c1);
  787. }
  788. function setSubmitStatus(config,data){
  789. let entry=data.rows[0];
  790. entry.formStatus=2;//Submitted
  791. let c1=new Object();
  792. c1.schemaName=data.schemaName;
  793. c1.queryName=data.queryName;
  794. c1.containerPath=config.containerPath;
  795. c1.rows=[entry];
  796. c1.success=function(data){updateSubmitStatus(config,"Form submitted")};
  797. LABKEY.Query.updateRows(c1);
  798. }
  799. function updateSubmitStatus(config,msg){
  800. let el=document.getElementById(config.submitReportId);
  801. el.innerHTML=msg;
  802. }
  803. function hideErr(config){
  804. let el=config.document.getElementById("errorDiv");
  805. el.style.display="none";
  806. }
  807. function clearErr(config){
  808. let el=config.document.getElementById("errorTxt");
  809. el.value="";
  810. }
  811. function showErr(config){
  812. let el=config.document.getElementById("errorDiv");
  813. el.style.display="block";
  814. }
  815. function printErr(config,msg){
  816. showErr(config);
  817. el=config.document.getElementById("errorTxt");
  818. el.style.color="red";
  819. el.value+="\n"+msg;
  820. }
  821. function checkForm(config){
  822. let debug=false;
  823. let crfRef=getCRFref(config)
  824. config.status="UNKNOWN";
  825. for (f in config.fields){
  826. let field=config.fields[f];
  827. field.status="UNKNOWN";
  828. if (debug)
  829. print(config,"Setting status for "+f+" to "+ field.status);
  830. let selectRows=new Object();
  831. selectRows.containerPath=config.containerPath;
  832. selectRows.schemaName="lists";
  833. selectRows.queryName=f;
  834. selectRows.filterArray=[LABKEY.Filter.create('crfRef',crfRef)];
  835. selectRows.success=function(data){checkData(data,config)};
  836. selectRows.failure=function(errorObj){print(config,"checkData failed.")};
  837. LABKEY.Query.selectRows(selectRows);
  838. }
  839. }
  840. function waitForCheckForm(config,cb){
  841. let debug=true;
  842. if (!("i" in config)) config.i=0;
  843. if (debug) print(config,"["+config.i+"] checkForm status "+config.status);
  844. if (config.i>100) {
  845. if (debug) print(config,"executing failure");
  846. cb.failure(config);
  847. return;
  848. }
  849. if (config.status=="DONE") {
  850. if (debug) print(config,"executing success");
  851. cb.success(config);
  852. if (debug) print(config,"success executed");
  853. return;
  854. }
  855. config.i+=1;
  856. setTimeout(function(){waitForCheckForm(config,cb);},1000);
  857. }
  858. function checkData(data,config){
  859. let debug=false;
  860. if (debug) print(config,"checkData ");
  861. let field=config.fields[data.queryName];
  862. field.status="NONE";
  863. if (debug) print(config,"Setting status for "+data.queryName+" to "+field.status);
  864. if (data.rows.length>0)
  865. field.status="DONE";
  866. if (debug)
  867. print(config,"checkData set status for "+data.queryName+" to "+field.status);
  868. for (f in config.fields){
  869. let subField=config.fields[f];
  870. if (debug)
  871. print(config,"checkData status["+f+"]: "+subField.status);
  872. if (subField.status=="UNKNOWN") {
  873. if (debug) print(config,"\t Status for "+f+" not set ["+ subField.status+"]");
  874. return;
  875. }
  876. }
  877. config.status="DONE";
  878. }
  879. function generateMasterForm(config){
  880. let debug=true;
  881. if (debug)
  882. print(config,"generateMasterForm");
  883. let selectRows=new Object();
  884. selectRows.containerPath=config.containerPath;
  885. selectRows.schemaName='lists';
  886. selectRows.queryName='crfEntry';
  887. selectRows.filterArray=[LABKEY.Filter.create('entryId',getCRFref(config))];
  888. selectRows.success=function(data){populateBasicData(config,data)};
  889. //requires populateBasicData
  890. LABKEY.Query.selectRows(selectRows);
  891. config.fields=new Object();
  892. let configSelectRows=new Object();
  893. configSelectRows.containerPath=config.containerPath;
  894. configSelectRows.schemaName='lists';
  895. configSelectRows.queryName=config.setupQueryName;
  896. configSelectRows.success=function(data){generateForm(config,data);};
  897. configSelectRows.failure=function(errorTxt){print(config,"generateForm fail")};
  898. LABKEY.Query.selectRows(configSelectRows);
  899. if (debug)
  900. print(config,"Generating buttons");
  901. //requires onSubmit
  902. if (config.review){
  903. generateButton(config,"submitDiv","Upload to database",onDatabaseUpload,config);
  904. generateButton(config,"submitDiv","Ask for further review",onUpdateForReview,config);
  905. }
  906. else{
  907. generateButton(config,"submitDiv","Submit",onSubmit,config);
  908. }
  909. }