crfVisit.js 90 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276
  1. const config=new Object();
  2. function clear(){
  3. let el=config.document.getElementById(config.debugId);
  4. if (el===null) {
  5. //alert("Debug section not initialized");
  6. return;
  7. }
  8. config.document.getElementById(config.debugId).value="";
  9. }
  10. function print(msg){
  11. let el=config.document.getElementById(config.debugId);
  12. if (el===null) {
  13. //alert("Debug section not initialized. Message: "+msg);
  14. return;
  15. }
  16. el.value+="\n"+msg;
  17. }
  18. //harmonize signature
  19. //(schema,query,row,action=cvDoNothing,container=null
  20. function cvInsertRows(schema,query,rows,action=null,container=null,failure=null){
  21. cvModifyRows('insert',schema,query,rows,action,container);
  22. }
  23. function cvDeleteRows(schema,query,rows,action=null,container=null,failure=null){
  24. cvModifyRows('delete',schema,query,rows,action,container);
  25. }
  26. function cvModifyRows(mode,schema,query,rows,action=null,container=null,failure=null){
  27. //insert rows to container/schema/query and return with action
  28. let fName="[cvModifyRows/"+mode+"]";
  29. print(fName+' '+schema+'/'+query);
  30. let qconfig=new Object();
  31. qconfig.schemaName=schema;
  32. qconfig.queryName=query;
  33. if (container) qconfig.containerPath=container;
  34. if (!rows) {
  35. print(fName+' rows '+rows);
  36. return;
  37. }
  38. qconfig.rows=rows;
  39. qconfig.success=function(data){;};
  40. if (action) qconfig.success=action;
  41. if (mode=='insert') LABKEY.Query.insertRows(qconfig);
  42. if (mode=='update') LABKEY.Query.updateRows(qconfig);
  43. if (mode=='delete') LABKEY.Query.deleteRows(qconfig);
  44. print(fName+" done");
  45. }
  46. function cvSelectRows(schema,query,filters=[],action=null, container=null, failure=null, columns=null){
  47. let fName="[cvSelectRows]";
  48. print(fName+' '+schema+' '+query+' '+container);
  49. let qconfig=new Object();
  50. qconfig.schemaName=schema;
  51. qconfig.queryName=query;
  52. if (container) qconfig.containerPath=container;
  53. qconfig.filterArray=filters;
  54. qconfig.success=function(data){;};
  55. if (action) qconfig.success=action;
  56. if (failure) qconfig.failure=failure;
  57. if (columns) qconfig.columns=columns;
  58. LABKEY.Query.selectRows(qconfig);
  59. print(fName+" done");
  60. }
  61. function createCrfStatus(crfEntry){
  62. let crfStatus=new Object();
  63. crfStatus.entryId=crfEntry.entryId;
  64. crfStatus.submissionDate=new Date();
  65. crfStatus.FormStatus=crfEntry.FormStatus;
  66. crfStatus.User=crfEntry.UserId;
  67. crfStatus.Form=crfEntry.Form;
  68. return crfStatus;
  69. }
  70. function getCRFrefFirst(){
  71. //crfRef is part of html call and gets stored in the page
  72. return config.document.getElementById(config.crfRefId).innerHTML;
  73. }
  74. function getCRFref(){
  75. //'crfRefId'
  76. return config.formConfig.crfEntry['entryId'];
  77. }
  78. function getCRFrefData(){
  79. let parentCrf=config.formConfig.crfEntry['parentCrf'];
  80. if (parentCrf!=undefined) return parentCrf;
  81. return getCRFref();
  82. }
  83. function onFailure(errorInfo, options, responseObj){
  84. if (errorInfo && errorInfo.exception)
  85. alert("Failure: " + errorInfo.exception);
  86. else
  87. alert("Failure: " + responseObj.statusText);
  88. }
  89. function doNothing(){
  90. print('doNothing called');
  91. }
  92. function generateDebugSection(){
  93. //let debug=true;
  94. //if (debug) print("generateDebugSection "+sectionName);
  95. let formName=config.debugDiv;
  96. let sectionName="debugSection";
  97. let sectionTitle="Debug Messages";
  98. let tb=config.document.createElement('table');
  99. tb.className='t2';
  100. let row=tb.insertRow();
  101. let cell=config.document.createElement('th');
  102. row.appendChild(cell);
  103. cell.setAttribute("colspan","4");
  104. cell.style.fontSize="20px";
  105. cell.style.textAlign="center";
  106. let cellData=config.document.createTextNode(sectionTitle);
  107. cell.appendChild(cellData);
  108. cell=row.insertCell();
  109. let input=config.document.createElement("input");
  110. input.type="button";
  111. input.id="toggle"+sectionName+"VisbilityButton";
  112. input.onclick=function(){toggleVisibility(sectionName,input.id)};
  113. cell.appendChild(input);
  114. config.document.getElementById(formName).appendChild(tb);
  115. let div=config.document.createElement('div');
  116. div.id=sectionName;
  117. config.document.getElementById(formName).appendChild(div);
  118. //start open (for debug)
  119. //input.value="Hide";
  120. //div.style.display="block";
  121. //start hidden (for production)
  122. input.value="Show";
  123. div.style.display="none";
  124. let debugArea=config.document.createElement('textarea');
  125. debugArea.rows=10;
  126. debugArea.cols=95;
  127. debugArea.id=config.debugId;
  128. div.appendChild(debugArea);
  129. //print('ver: 0.10');
  130. }
  131. function getAdditionalData(formSetupEntry){
  132. //return information on additional data associated with the form
  133. //additionalData is a sub-list with multiple entries per patient/visit
  134. //argument is the row of the formSetup setup list
  135. let queryName=config.formConfig.queryMap[formSetupEntry['queryName']];
  136. let fName='[getAdditionalData/'+queryName+']';
  137. print(fName);
  138. //additionalData holds a reference to all queries already parsed
  139. //this helps in reducing number of calls to the database (I assume)
  140. if (queryName in config.formConfig.additionalData){
  141. print(fName+': Returning preset value');
  142. return config.formConfig.additionalData[queryName];
  143. }
  144. //first time we see this query, so we have to do the setup
  145. print(fName+': generating');
  146. config.formConfig.additionalData[queryName]=new Object();
  147. //takes address, so further changes will be to the newly created object
  148. //in fact, ad is just a short alias of the long variable name on the right
  149. let ad=config.formConfig.additionalData[queryName];
  150. //no additional data
  151. if (formSetupEntry["showFlag"]==="NONE") {
  152. print(fName+": empty");
  153. return ad;
  154. }
  155. //use showFlag to setup report section of the CRF list
  156. if (formSetupEntry["showFlag"]==="REVIEW") {
  157. //abuse additionalData to signal different segment
  158. print(fName+": generateReport");
  159. ad.isReview=true;
  160. return ad;
  161. }
  162. //setup the additionalData memory object
  163. print(fName+': setting values');
  164. ad.showFlag=formSetupEntry["showFlag"];
  165. ad.showFlagValue=formSetupEntry["showFlagValue"];
  166. ad.queryName=formSetupEntry["showQuery"];
  167. //for data queries, limit to present CRF only
  168. ad.filters=new Object();
  169. ad.filters['crfRef']=getCRFref();
  170. //compose a long debug message
  171. let msg=fName+": flag "+ad.showFlag;
  172. msg+=" value "+ad.showFlagValue;
  173. msg+=" query "+ad.queryName;
  174. print(msg);
  175. return ad;
  176. }
  177. function fullAccessSetup(listName){
  178. //generate setup object whcih should contain fields:
  179. //readonlyFlag - whether the dataset is writeable
  180. //filters - selection fields that allow creation of LABKEY.Filter.create()
  181. //getInputId - formating of unique ids for html elements
  182. //addApply - whether a submit/Save button is generated
  183. //unique - whether entries in list are unique
  184. let debug=true;
  185. if (debug) print("fullAccessSetup");
  186. let setup=new Object();
  187. setup.queryName=listName;
  188. setup.readonlyFlag=function(vName){return false};
  189. setup.filters=new Object();
  190. setup.filters['crfRef']=getCRFref();
  191. setup.getInputId=function(vName){return listName+"_"+vName;}
  192. setup.addApply="Save";
  193. setup.isReview=false;
  194. return setup;
  195. }
  196. function readonlySetup(listName){
  197. //see definition of setup object above
  198. let debug=true;
  199. if (debug) print("readonlySetup");
  200. let setup=new Object();
  201. setup.queryName=listName;
  202. setup.readonlyFlag=function(vName){return true};
  203. setup.filters=new Object();
  204. setup.filters['crfRef']=getCRFref();
  205. setup.getInputId=function(vName){return listName+'_'+vName;}
  206. setup.isReview=false;
  207. return setup;
  208. }
  209. function getSetup(listName,writeAccess=true){
  210. //change to section granulated permission of type EDIT, COMMENT, READ
  211. //let formStatus=config.formConfig.formStatus;
  212. //equivalent to READ
  213. if (!writeAccess)
  214. //if (formStatus=="Submitted")
  215. return readonlySetup(listName);
  216. //if (formStatus=="Approved")
  217. // return readonlySetup(listName);
  218. return fullAccessSetup(listName);
  219. }
  220. function generateSection(formSetupEntry){
  221. let listName=config.formConfig.queryMap[formSetupEntry['queryName']];
  222. let fName='[generateSection/'+listName+']';
  223. let sectionTitle=formSetupEntry['title'];
  224. let accessModeColumn=config.formConfig.operator+'Mode';
  225. let accessMode=formSetupEntry[accessModeColumn];
  226. //this will fix it for later use as well
  227. let additionalData=getAdditionalData(formSetupEntry);
  228. print(fName);
  229. let formName=config.masterForm;//this is HTML designator of area on page
  230. let debug=true;
  231. let tb=config.document.createElement('table');
  232. tb.className='t2';
  233. let row=tb.insertRow();
  234. let cell=config.document.createElement('th');
  235. row.appendChild(cell);
  236. cell.setAttribute("colspan","4");
  237. cell.style.fontSize="20px";
  238. cell.style.textAlign="center";
  239. let cellData=config.document.createTextNode(sectionTitle);
  240. cell.appendChild(cellData);
  241. cell=row.insertCell();
  242. let input=config.document.createElement("input");
  243. input.type="button";
  244. input.value="Show";
  245. input.id="toggle"+listName+"VisbilityButton";
  246. input.onclick=function(){toggleVisibility(listName,input.id)};
  247. cell.appendChild(input);
  248. config.document.getElementById(formName).appendChild(tb);
  249. let div=config.document.createElement('div');
  250. div.id=listName;
  251. div.style.display="none";
  252. config.document.getElementById(formName).appendChild(div);
  253. let divTable=config.document.createElement('div');
  254. divTable.id=listName+"Table";
  255. div.appendChild(divTable);
  256. if ("showFlag" in additionalData) {
  257. additionalData.divName=listName+"SubDiv";
  258. additionalData.divQueryName=listName+"SubDivList";
  259. let div1=config.document.createElement('div');
  260. div1.id=additionalData.divName;
  261. div1.style.display="none";
  262. div.appendChild(div1);
  263. let div2=config.document.createElement('div');
  264. div2.id=additionalData.divQueryName;
  265. div1.appendChild(div2);
  266. }
  267. if (debug) print("generate master table");
  268. let writeMode=accessMode=="EDIT";
  269. let setup=getSetup(listName,writeMode);
  270. if ("isReview" in additionalData){
  271. generateReviewSection(listName,div.id,generateReviewSectionCB);
  272. return;
  273. }
  274. //master table is unique per visit
  275. setup.unique=true;
  276. generateTable(listName,divTable.id,additionalData,setup);
  277. if (debug) print("generate master table: done");
  278. let generateSubTable=true;
  279. //generateSubTable equivalent to read/write access to section
  280. if (accessMode != "EDIT")
  281. generateSubTable=false;
  282. if (! ("showFlag" in additionalData) ) generateSubTable=false;
  283. if (generateSubTable){
  284. let qName=additionalData.queryName;
  285. let dName=additionalData.divName;
  286. let xsetup=fullAccessSetup(qName);
  287. //only set master query for additionalData
  288. xsetup.masterQuery=listName;
  289. //if (readonly) setup=readonlySetup(config);
  290. xsetup.subTable=true;
  291. generateTable(qName,dName,additionalData,xsetup);
  292. //generateTable(formSetupEntry,qName,dName,additionalData,setup);
  293. }
  294. print("generate review");
  295. let divReviewList=config.document.createElement('div');
  296. divReviewList.id=listName+"ReviewList";
  297. div.appendChild(divReviewList);
  298. let divReview=config.document.createElement('div');
  299. divReview.id=listName+"Review";
  300. div.appendChild(divReview);
  301. //assume we already have listId (content of config.setupQueryName is listId)
  302. //we need listName also
  303. //qconfig.queryName=config.setupQueryName;
  304. generateReview(divReview.id,divReviewList.id,listName,accessMode);
  305. if (accessMode!='GENERATE') return;
  306. print('Adding generate button');
  307. //add generateButton
  308. let divGenerateButton=config.document.createElement('div');
  309. divGenerateButton.id=listName+'GenerateButton';
  310. div.appendChild(divGenerateButton);
  311. print('Adding generate button completed to here');
  312. let cb=function(){onGenerateQuery(listName);};
  313. generateButton(divGenerateButton.id,'Generate','Generate '+listName,'XX',cb);
  314. print('Adding generate button completed');
  315. }
  316. //>>>>reviewSection associated routines
  317. function parseResponseXML(){
  318. //print(config.config,'Status:' +this.status);
  319. print('Status:'+this.status);
  320. if (this.status!=200) return;
  321. config.loadFileConfig.json=JSON.parse(this.responseText);
  322. config.loadFileConfig.cb();
  323. }
  324. function loadFile(){
  325. print('YY: '+config.loadFileConfig.url);
  326. let connRequest=new XMLHttpRequest();
  327. connRequest.addEventListener("loadend",parseResponseXML);
  328. //function(e){parseResponseXML(e,config);});
  329. connRequest.open("GET", config.loadFileConfig.url);
  330. connRequest.send();
  331. }
  332. function getBasePath(){
  333. let server=LABKEY.ActionURL.getBaseURL();
  334. let basePath=server+"_webdav";
  335. basePath+=LABKEY.ActionURL.getContainer();
  336. return basePath;
  337. }
  338. function generateErrorMessage(id,listName,msg){
  339. print('generateErrorMessage:');
  340. let eid=listName+"_errorMsg";
  341. let el=config.document.getElementById(eid);
  342. if (el===null){
  343. el=config.document.createElement("p");
  344. config.document.getElementById(id).appendChild(el);
  345. }
  346. el.innerHTML=msg;
  347. }
  348. function clearErrorMessage(listName){
  349. let eid=listName+"_errorMsg";
  350. let el=config.document.getElementById(eid);
  351. if (el===null) return;
  352. el.remove();
  353. }
  354. function generateReview(divReviewId,divReviewListId, listName, accessMode){
  355. let listId=config.formConfig.fields[listName].queryId;
  356. //listId is a number->should it be queryName?
  357. let debug=true;
  358. if (debug) print("Generate review for: "+listId+'/'+listName);
  359. let reviewSetup=new Object();
  360. reviewSetup.readonlyFlag=function(vName){
  361. if (vName=="queryName") return true;
  362. if (vName=="queryname") return true;
  363. if (vName=="ModifiedBy") return true;
  364. return false;};
  365. reviewSetup.addApply="Add Review";
  366. reviewSetup.reviewTable=true;
  367. let generateTableFlag=true;
  368. let formStatus=config.formConfig.formStatus;
  369. //COMMENTS allowed or not
  370. //three levels of access: EDIT, COMMENT, READ
  371. if (accessMode == "READ"){
  372. //if (formStatus == "Approved" ){
  373. delete reviewSetup.addApply;
  374. reviewSetup.readonlyFlag=function(vName){return false;}
  375. generateTableFlag=false;
  376. }
  377. reviewSetup.filters=new Object();
  378. reviewSetup.filters["crfRef"]=getCRFref();
  379. if (config.formConfig.crfEntry.parentCrf){
  380. reviewSetup.filters["crfRef"]=getCRFref()+";"+config.formConfig.crfEntry.parentCrf;
  381. }
  382. reviewSetup.filters["queryName"]=listId;//entry in reviewComments list is queryname, all in small caps
  383. //needs listName, in argument
  384. reviewSetup.getInputId=function(vName){return listName+"_add"+vName};
  385. reviewSetup.divReviewListId=divReviewListId;
  386. reviewSetup.isReview=true;
  387. if (debug) {
  388. let msg="Review: divId: "+divReviewId;
  389. msg+=" inputId: "+reviewSetup.getInputId;
  390. print(msg);
  391. }
  392. updateListDisplay(divReviewListId,"reviewComments",reviewSetup.filters,true);
  393. if (! generateTableFlag) return;
  394. generateTable("reviewComments",divReviewId,new Object(),reviewSetup);
  395. }
  396. //>>>>>>>>>>trigger visibility of additional lists
  397. function setListVisibility(input,setup,readonlyFlag){
  398. let debug=true;
  399. let fName="[setListVisibility/"+setup.queryName+"]";
  400. print(fName);
  401. let additionalData=config.formConfig.additionalData[setup.queryName];
  402. let x = config.document.getElementById(additionalData.divName);
  403. if (debug) print(fName+": Div: "+x);
  404. x.style.display="none";
  405. let sText;
  406. if (readonlyFlag) sText=input.innerText;
  407. else sText=input.options[input.selectedIndex].text;
  408. if (debug) print(fName+": Selected option text: "+sText);
  409. if (sText == additionalData.showFlagValue){
  410. let filters=new Object();
  411. if ("filters" in additionalData) filters=additionalData.filters;
  412. x.style.display = "block";
  413. updateListDisplay(additionalData.divQueryName,
  414. additionalData.queryName,filters,readonlyFlag);
  415. }
  416. }
  417. //>>have list refresh when data is added (not optimal yet)
  418. //
  419. function isFilterList(v){
  420. if (typeof(v)!='string') return false;
  421. if (v.search(';')==-1) return false;
  422. return true;
  423. }
  424. function updateListDisplay(divName,queryName,filters,readonlyFlag){
  425. //use Labkey.QueryWebPart to show list
  426. let debug=true;
  427. let fName="[updateListDisplay]";
  428. if (debug)
  429. print(fName+": UpdateListDisplay: Query - "+queryName
  430. +" div - "+divName);
  431. if (divName=="NONE") return;
  432. let crfRef=getCRFref();
  433. let div=config.document.getElementById(divName);
  434. if (debug)
  435. print(fName+": generating WebPart: "+queryName);
  436. var qconfig=new Object();
  437. qconfig.renderTo=divName;
  438. //point to data container
  439. qconfig.containerPath=getContainer('data');
  440. qconfig.schemaName='lists';
  441. qconfig.queryName=queryName;
  442. qconfig.buttonBarPosition='top';
  443. qconfig.filters=[];
  444. for (f in filters){
  445. let fType=LABKEY.Filter.Types.EQUAL;
  446. print(fName+' filter ['+f+'] '+filters[f]+'/'+typeof(filters[f])+' ['+fType+']');
  447. if (isFilterList(filters[f])){
  448. fType=LABKEY.Filter.Types.IN;
  449. }
  450. qconfig.filters.push(LABKEY.Filter.create(f, filters[f],fType));
  451. }
  452. qconfig.success=updateSuccess;
  453. qconfig.failure=updateFailure;
  454. //show only print button
  455. if (readonlyFlag){
  456. qconfig.buttonBar=new Object();
  457. qconfig.buttonBar.items=["print"];
  458. }
  459. LABKEY.QueryWebPart(qconfig);
  460. }
  461. function updateSuccess(data){
  462. print("Update success");
  463. }
  464. function updateFailure(data){
  465. print("Update failed");
  466. }
  467. //TODO: this should trigger a data refresh on section, ie populateData(field)
  468. function toggleVisibility(divName,buttonName){
  469. let fName='[toggleVisibility/'+divName+']';
  470. print(fName);
  471. let x = config.document.getElementById(divName);
  472. if (x.style.display === "none") {
  473. //exclude non data sections (like debug)...
  474. print(fName+': issuing setData(populateSection)');
  475. x.style.display = "block";
  476. config.document.getElementById(buttonName).value="Hide";
  477. let cb=function(){populateSection(divName);};
  478. setData(cb);
  479. } else {
  480. x.style.display = "none";
  481. config.document.getElementById(buttonName).value="Show";
  482. }
  483. }
  484. function generateButtonBU(divName,title,buttonName,callback,
  485. callbackParameters){
  486. let debug=true;
  487. if (debug) print("generateButtonBU");
  488. let tb=config.document.createElement('table');
  489. tb.className="t2";
  490. let r1=tb.insertRow();
  491. th=config.document.createElement('th');
  492. r1.appendChild(th);
  493. th.innerHTML=title;
  494. //*!*
  495. let c2=r1.insertCell();
  496. let i1=config.document.createElement("input");
  497. i1.type="button";
  498. i1.value=buttonName;
  499. i1.style.fontSize="20px";
  500. i1.onclick=function(){callback(callbackParameters);}
  501. c2.appendChild(i1);
  502. let c1=r1.insertCell();
  503. c1.setAttribute("colspan","1");
  504. c1.id=callbackParameters.submitReportId;
  505. let el=config.document.getElementById(divName);
  506. if (debug) print("generateButton: element["+divName+"]: "+el);
  507. el.appendChild(tb);
  508. }
  509. function generateButton(divName,caption,label,callbackLabel,callback){
  510. let debug=true;
  511. if (debug) print("generateButtonX");
  512. let tb=config.document.createElement('table');
  513. tb.className="t2";
  514. let r1=tb.insertRow();
  515. th=config.document.createElement('th');
  516. r1.appendChild(th);
  517. th.innerHTML=caption;
  518. //*!*
  519. let c2=r1.insertCell();
  520. let i1=config.document.createElement("input");
  521. i1.type="button";
  522. i1.value=label;
  523. i1.style.fontSize="20px";
  524. i1.onclick=callback;
  525. i1.id='button_'+callbackLabel;
  526. c2.appendChild(i1);
  527. let c1=r1.insertCell();
  528. c1.setAttribute("colspan","1");
  529. //this is only for saveReview?
  530. c1.id=divName+'_reportField';
  531. //c1.id=config.submitReportId;
  532. let el=config.document.getElementById(divName);
  533. if (debug) print("generateButton: element["+divName+"]: "+el);
  534. el.appendChild(tb);
  535. }
  536. function generateSubQuery(input, setup, readonlyFlag){
  537. let fName="[generateSubQuery]";
  538. if (setup.isReview) return;
  539. if (!(setup.queryName in config.formConfig.additionalData)){
  540. print(fName+': no additionalData entry (probably a subquery)');
  541. return;
  542. }
  543. let additionalData=config.formConfig.additionalData[setup.queryName];
  544. if (!("showFlag" in additionalData))
  545. return;
  546. print(fName);
  547. let expId=setup.getInputId(additionalData.showFlag);
  548. if (expId!=input.id) {
  549. print(fName+": ignoring field "+input.id+"/"+expId);
  550. return;
  551. }
  552. print(fName+": Setting onChange to "+input.id);
  553. if (!readonlyFlag)
  554. input.onchange=function(){setListVisibility(input,setup,readonlyFlag)};
  555. }
  556. //>>populate fields
  557. //
  558. //
  559. //split to field generation and field population
  560. //
  561. function addFieldRow(tb,field,setup,additionalData){
  562. let fName="[addFieldRow/"+setup.queryName+':'+field.name+']';
  563. let vName=field.name;
  564. let vType=field.type;
  565. let isLookup=("lookup" in field);
  566. print(fName+": ["+vName+"/"+vType+'/'+isLookup+"]");
  567. let row=tb.insertRow();
  568. let cell=config.document.createElement('th');
  569. cell.style.width='300px';
  570. row.appendChild(cell);
  571. let text = config.document.createTextNode(field.shortCaption);
  572. cell.appendChild(text);
  573. let input=null;
  574. let colSpan="3";
  575. let cell1=row.insertCell();
  576. cell1.colSpan=colSpan;
  577. let readonlyFlag=setup.readonlyFlag(vName);
  578. //set the html input object
  579. while (1){
  580. if (readonlyFlag){
  581. input=config.document.createElement('label');
  582. input.innerText='Loading';
  583. break;
  584. }
  585. //lookup
  586. if (isLookup){
  587. input = config.document.createElement("select");
  588. break;
  589. }
  590. //date
  591. if (vType=="date"){
  592. input = config.document.createElement("input");
  593. input.type="date";
  594. break;
  595. }
  596. //string
  597. if (vType=="string"){
  598. //we have to make sure UNDEF is carried to below
  599. //since we are adapting file to either show
  600. //current file or allow user to select a file
  601. //
  602. //TODO change this so one can always select file
  603. //but also show the selected file
  604. if(vName.search("reviewComment")>-1){
  605. input = config.document.createElement("textarea");
  606. input.cols="65";
  607. input.rows="5";
  608. break;
  609. }
  610. input=config.document.createElement('input');
  611. input.type="text";
  612. if (vName.search('_file_')<0) break;
  613. cell1.setAttribute('colspan',"1");
  614. let cell2=row.insertCell();
  615. cell2.setAttribute('colspan',"2");
  616. let input1=config.document.createElement('input');
  617. input1.type="file";
  618. input1.id=setup.getInputId(vName)+'_file_';
  619. cell2.appendChild(input1);
  620. break;
  621. }
  622. if (vType=="float"){
  623. input = config.document.createElement("input");
  624. input.type="text";
  625. break;
  626. }
  627. if (vType=="boolean"){
  628. input = config.document.createElement("input");
  629. input.type="checkbox";
  630. print("Creating checkbox");
  631. break;
  632. }
  633. break;
  634. }
  635. input.id=setup.getInputId(vName);
  636. cell1.appendChild(input);
  637. print(fName+': adding element '+input.id);
  638. print(fName+': listing element '+config.document.getElementById(input.id));
  639. //connect associated list
  640. generateSubQuery(input,setup,readonlyFlag);
  641. if (readonlyFlag) {
  642. print(fName+': exiting(readonlyFlag)');
  643. return;
  644. }
  645. if (!isLookup) {
  646. print(fName+': exiting (not lookup)');
  647. return;
  648. }
  649. let lookup=field["lookup"];
  650. //get all values from config.formConfig.lookup[X]
  651. let lObject=config.formConfig.lookup[lookup.queryName];
  652. //debug
  653. print(fName+": query: "+lookup.queryName);
  654. print(fName+": ElementId: "+input.id);
  655. print(fName+": No of options: " +lObject.LUT.length);
  656. print(fName+": Element: "+input);
  657. //set the lut value (input is text label) for readonly
  658. //clear existing fields from input
  659. for(let i = input.options.length; i >= 0; i--) {
  660. input.remove(i);
  661. }
  662. //create option -1
  663. let opt = config.document.createElement("option");
  664. opt.text = "<Select>";
  665. opt.value = -1;
  666. input.options[0] = opt;
  667. print(fName+": Adding <Select>");
  668. //add other, label them with LUT
  669. for (let v in lObject.LUT) {
  670. print(fName+': populating '+v+': '+lObject.LUT[v]);
  671. let opt = config.document.createElement("option");
  672. opt.text = lObject.LUT[v];
  673. opt.value = v;
  674. input.options[input.options.length] = opt;
  675. }
  676. input.selectedIndex=0;
  677. }
  678. function parseVariables(pars){
  679. let pA=pars.split(";");
  680. let q=new Object();
  681. for (let i=0;i<pA.length;i++){
  682. let vA=pA[i].split('=');
  683. q[vA[0]]=vA[vA.length-1];
  684. }
  685. return q;
  686. }
  687. function printVariables(q){
  688. let fName="[printVariables]";
  689. for (let x in q){
  690. print(fName+" ["+x+"] "+q[x]);
  691. }
  692. }
  693. function hasVariable(q,varName){
  694. if (q && varName in q)
  695. return true;
  696. return false;
  697. }
  698. function addSpecialFieldRow(tb,specFieldSetup,setup){
  699. //tb is the table, specFieldSetup is a row from the table where special fields are being setup
  700. //the first column is fieldUID, which is a colon joined amalgation of queryName:fieldName
  701. let fieldUID=specFieldSetup["fieldUID"];
  702. let x=fieldUID.split(':');
  703. let fieldName=x[1];
  704. let fName="[addSpecialFieldRow/"+fieldUID+"]";
  705. let q=parseVariables(specFieldSetup['actionParameters']);
  706. print(fName);
  707. if (specFieldSetup['actionType']=='textArea'){
  708. let row=tb.insertRow();
  709. let cell1=row.insertCell();
  710. cell1.colSpan="4";
  711. cell1.style.textAlign="justify";
  712. cell1.style.padding="10px";
  713. cell1.style.backgroundColor="#e0e0e0";
  714. cell1.innerText=q['description'];
  715. return;
  716. }
  717. if (specFieldSetup['actionType']=='generationObject'){
  718. //only in EDIT mode!!
  719. let ro=setup.readonlyFlag(fieldName);
  720. if (ro) return;
  721. config.print=print;
  722. let gc=getGenerationObject(config,q,setup.getInputId(fieldName));
  723. if ('mailRecipient' in q){
  724. gc.callback=function(data){sendEmail(data,q['mailRecipient'],doNothing,q['subject']);};
  725. }
  726. if ("addData" in q){
  727. vars=q["addData"].split(',');
  728. gc.addData=new Array();
  729. for (let v in vars){
  730. let s=vars[v]
  731. //variable name can be written as A/B where A is the name in addData and B is the variable name in crfEntry
  732. //useful for mocking up crfId from daughter crf-s such as registration
  733. let sArray=s.split('/');
  734. let sTarget=sArray[0];
  735. let sSource=sArray[sArray.length-1];
  736. gc.addData[sTarget]=config.formConfig.crfEntry[sSource];
  737. print(fName+" addData ["+sTarget+"]: "+gc.addData[sTarget]);
  738. }
  739. }
  740. let row=tb.insertRow();
  741. let cell=config.document.createElement('th');
  742. row.appendChild(cell);
  743. let text = config.document.createTextNode("Automatic ID generator");
  744. cell.appendChild(text);
  745. let cell1=row.insertCell();
  746. cell1.colSpan="3";
  747. let b=config.document.createElement("input");
  748. b.type="button";
  749. b.id="generateIdButton";
  750. b.onclick=function(){gc.execute();};
  751. b.value="Generate ID";
  752. cell1.appendChild(b);
  753. }
  754. }
  755. function populateFieldRow(entry,field,setup){
  756. populateField(entry,field,setup);
  757. populateSubQuery(entry,field,setup);
  758. }
  759. function populateSubQuery(entry,field,setup){
  760. let fName='[populateSubQuery/'+setup.queryName+':'+field.name+']';
  761. if (setup.isReview) return;
  762. if (!(setup.queryName in config.formConfig.additionalData)){
  763. let msg=fName+': no additionalData entry for '+setup.queryName;
  764. msg+=' (probably a subquery)';
  765. print(msg);
  766. return;
  767. }
  768. //find if field is connected to a sub array
  769. //find queryName
  770. //
  771. let additionalData=config.formConfig.additionalData[setup.queryName];
  772. print(fName);
  773. //let flag=additionalData.showFlag;
  774. if (!("showFlag" in additionalData)) return;
  775. let eId=setup.getInputId(additionalData.showFlag);
  776. let id=setup.getInputId(field.name);
  777. if (eId!=id) {
  778. print(fName+": ignoring field "+id+"/"+eId);
  779. return;
  780. }
  781. print(fName+': id '+id);
  782. //hard to estimate readonlyFlag
  783. //
  784. let input=config.document.getElementById(id);
  785. let eType=input.nodeName.toLowerCase();
  786. let readonlyFlag=eType!="select";
  787. setListVisibility(input,setup,readonlyFlag);
  788. }
  789. function populateField(entry,field,setup){
  790. let vName=field.name;
  791. let fName='[populateFieldName/'+vName+']';
  792. let varValue="UNDEF";
  793. //if (vName in setup.filters) varValue=setup.filters[vName];
  794. if (vName in entry) varValue=entry[vName];
  795. //if part of the filter, set it to value
  796. if (vName in setup.filters) varValue=setup.filters[vName];
  797. let isLookup=("lookup" in field);
  798. print(fName+' v='+varValue+'/'+isLookup+' ['+
  799. setup.getInputId(field.name)+']');
  800. let vType=field.type;
  801. let id=setup.getInputId(vName);
  802. let input=config.document.getElementById(id);
  803. //date
  804. if (vType=="date"){
  805. if (varValue=="UNDEF") varValue=new Date();
  806. else varValue=new Date(varValue);
  807. }
  808. //lookup for readonly
  809. if (isLookup && varValue!="UNDEF"){
  810. let lookup=field["lookup"];
  811. //get all values from config.formConfig.lookup[X]
  812. let lObject=config.formConfig.lookup[lookup.queryName];
  813. varValue=lObject.LUT[varValue];
  814. }
  815. print('Element: '+input);
  816. //figure out the element type
  817. let eType=input.nodeName.toLowerCase();
  818. print('Element type: '+eType);
  819. //change varValue for printing
  820. if (varValue=="UNDEF") varValue="";
  821. //HTMLTextArea, createElement(textArea)
  822. if (eType==="textarea"){
  823. input.value=varValue;
  824. return;
  825. }
  826. //Text, createTextNode
  827. if (eType==="#text"){
  828. input.nodeValue=varValue;
  829. return;
  830. }
  831. //HTMLLabelElement, createElement('label')
  832. if (eType==="label"){
  833. input.innerText=varValue;
  834. return;
  835. }
  836. //HTMLSelectElement, createElement('select')
  837. if (eType==="select"){
  838. input.selectedIndex=0;
  839. for (let i=0;i<input.options.length;i++){
  840. let v=input.options[i].text;
  841. if (v!=varValue) continue;
  842. input.selectedIndex=i;
  843. break;
  844. }
  845. return;
  846. }
  847. if (eType!="input"){
  848. print('Unknown type: '+eType+' encountered, igonring');
  849. return;
  850. }
  851. //HTMLInputElement
  852. let type=input.type;
  853. if (type=="date"){
  854. input.valueAsDate=varValue;
  855. return;
  856. }
  857. //string,float
  858. if (type=="text"){
  859. input.value=varValue;
  860. return;
  861. }
  862. //boolean
  863. if (type=="checkbox"){
  864. input.checked=varValue;
  865. return;
  866. }
  867. print('Unknown input type: '+type+'. Ignoring.');
  868. }
  869. function populateTable(listName,writeMode){
  870. //function populateTable(formSetupEntry){
  871. //let listName=config.formConfig.queryMap[formSetupEntry['queryName']];
  872. //let accessMode=config.formConfig.operator+'Mode';
  873. //let writeMode=formSetupEntry[accessMode]=='EDIT';
  874. let fName='[populateTable/'+listName+']';
  875. let setup=getSetup(listName,writeMode);
  876. let entry=new Object();
  877. //data snapshot
  878. let fQuery=config.formConfig.dataQueries[listName];
  879. //here I assume that listName was parsed during setDataLayout and setData
  880. //so that rows was set (even if they are empty)
  881. print(fName+"]: nrows "+fQuery.rows.length);
  882. if (fQuery.rows.length>0)
  883. entry=fQuery.rows[0];
  884. let fields=fQuery.fields;
  885. for (f in fields){
  886. let field=fields[f];
  887. //each field is a new row
  888. print(fName+": Adding field: "+f+'/'+field.name+' hidden: '+field.hidden);
  889. if (field.hidden) continue;
  890. if (field.name=="crfRef") continue;
  891. populateFieldRow(entry,field,setup);
  892. }
  893. }
  894. function generateTable(listName,divName,additionalData,setup){
  895. let debug=true;
  896. let fName="[generateTable/"+listName+"]";
  897. if (debug) print(fName);
  898. //is listName and setup.queryName a duplicate of the same value
  899. print(fName+': setup.queryName '+setup.queryName);
  900. //assume data is set in config.formConfig.dataQueries[data.queryName].rows;
  901. let populateData=true;
  902. if ("subTable" in setup){
  903. print(fName+" is subTable");
  904. populateData=false;
  905. }
  906. let entry=new Object();
  907. //data snapshot
  908. let fQuery=config.formConfig.dataQueries[listName];
  909. //here I assume that listName was parsed during setDataLayout and setData
  910. //so that rows was set (even if they are empty)
  911. print(fName+": Nrows "+fQuery.rows.length);
  912. if (fQuery.rows.length>0)
  913. entry=fQuery.rows[0];
  914. if ("reviewTable" in setup){
  915. entry['reviewComment']='';
  916. delete entry["ModifiedBy"];
  917. }
  918. let tb=config.document.createElement('table');
  919. tb.className="t2";
  920. config.document.getElementById(divName).appendChild(tb);
  921. //this are the fields (probably constant)
  922. let fields=fQuery.fields;
  923. for (f in fields){
  924. let field=fields[f];
  925. let fieldUID=listName+":"+field.name;
  926. //each field is a new row
  927. print(fName+": Adding field: "+f+'/'+field.name+' ('+fieldUID+').');
  928. //unique name
  929. if (field.hidden) continue;
  930. if (field.name=="crfRef") continue;
  931. addFieldRow(tb,field,setup,additionalData);
  932. if (populateData) populateFieldRow(entry,field,setup);
  933. if (fieldUID in config.formConfig["specialFields"]){
  934. let specFieldSetup=config.formConfig["specialFields"][fieldUID];
  935. addSpecialFieldRow(tb,specFieldSetup,setup);
  936. }
  937. }
  938. //finish of if apply button is not required
  939. if (!("addApply" in setup)) {
  940. print(fName+"populateTable: done");
  941. return;
  942. }
  943. let row=tb.insertRow();
  944. let th=config.document.createElement('th');
  945. row.appendChild(th);
  946. th.innerHTML=setup.addApply;
  947. let cell=row.insertCell();
  948. //cell.setAttribute("colspan","2");
  949. let input=config.document.createElement("input");
  950. input.type="button";
  951. input.value=setup.addApply;
  952. cell.appendChild(input);
  953. let cell1=row.insertCell();
  954. cell1.setAttribute("colspan","2");
  955. cell1.id=setup.getInputId("rerviewLastSave");
  956. cell1.innerHTML="No recent update";
  957. //saveReview is a generic name for saving content of the html page to a list entry
  958. input.onclick=function(){saveReview(listName,cell1.id,setup)};
  959. }
  960. function setEntryFromElement(entry,elementId, field){
  961. //set value to entry from element using representation (field) from labkey
  962. //
  963. //
  964. let fName='setEntryFromElement';
  965. let el=config.document.getElementById(elementId);
  966. if (!el) {
  967. print(fName+" element: "+elementId+" not found");
  968. return;
  969. }
  970. print(fName+" element: "+elementId);
  971. let vName=field.name;
  972. let vType=field.type;
  973. let eType=el.nodeName.toLowerCase();
  974. if (eType==="select"){
  975. entry[vName]=el.options[el.selectedIndex].value;
  976. return;
  977. }
  978. if (eType==="td"){
  979. entry[vName]=el.innerText;
  980. return;
  981. }
  982. if (vType=="date"){
  983. let date=el.valueAsDate;
  984. if (date==="null") return;
  985. date.setUTCHours(12);
  986. entry[vName]=date.toString();
  987. print(fName+" setting date to "+entry[vName]);
  988. return;
  989. }
  990. if (vType=="string"){
  991. entry[vName]=el.value;
  992. if (vName.search('_file_')<0)
  993. return;
  994. //upload file
  995. let id1=elementId+'_file_';
  996. let input1=config.document.getElementById(id1);
  997. print(fName+' attachment field: '+input1.value);
  998. //entry[vName]=el.files[0].stream();
  999. let ctx=new Object();
  1000. ctx['dirName']='consent';
  1001. ctx['ID']=entry['crfRef'];
  1002. //should point to data container
  1003. ctx['project']=getContainer('data');
  1004. //need ID->crf!
  1005. //assume crfRef will get set before this
  1006. //element is encountered
  1007. uploadFile(input1,ctx);
  1008. let fv=el.value;
  1009. let suf=fv.split('.').pop();
  1010. entry[vName]=entry['crfRef']+'.'+suf;
  1011. return;
  1012. }
  1013. if (vType=="float" || vType=="int"){
  1014. entry[vName]=el.value;
  1015. if (vName=="queryName") {
  1016. print(fName+' parsing queryName: '+el.innerText);
  1017. entry[vName]=config.formConfig.fields[el.innerText].queryId;
  1018. //use queryMap lookup
  1019. }
  1020. return;
  1021. }
  1022. if (vType=="boolean"){
  1023. entry[vName]=el.checked;
  1024. return;
  1025. }
  1026. return;
  1027. }
  1028. function saveReview(queryName,elementId,setup){
  1029. //loads any queryName
  1030. let debug=true;
  1031. let fName='[saveReview/'+queryName+']';
  1032. print(fName+" elementId "+elementId);
  1033. let mode='update';
  1034. let unique=("unique" in setup);
  1035. if (!unique) mode='insert';
  1036. let fQuery=config.formConfig.dataQueries[queryName];
  1037. if (fQuery.rows.length==0) useInsert=true;
  1038. let entry=new Object();
  1039. if (unique){
  1040. entry=fQuery.rows[0];
  1041. }
  1042. entry.crfRef=getCRFrefData();
  1043. if (debug) print("Set crfRef="+entry.crfRef);
  1044. //if ("queryName" in setup.filters) {
  1045. // entry.queryName=setup.filters["queryName"];
  1046. // if (debug) print("Setting queryName: "+entry.queryName);
  1047. //}
  1048. let fields=fQuery.fields;
  1049. for (f in fields){
  1050. let field=fields[f];
  1051. if (debug) print("saveReview field: "+field.name);
  1052. if (field.hidden) continue;
  1053. let vName=field.name;
  1054. let vType=field.type;
  1055. if (debug) print("vType: "+vType);
  1056. if (vName=="crfRef") continue;
  1057. //need to save queryName for reviewComments
  1058. let eId=setup.getInputId(vName);
  1059. //copy values from form to entry
  1060. setEntryFromElement(entry,eId,field);
  1061. if (!unique){
  1062. let foo=Object();
  1063. //reset the field value
  1064. populateField(foo,field,setup);
  1065. }
  1066. }
  1067. let action=function(data){updateLastSavedFlag(data,setup,elementId)};
  1068. print(fName+" mode "+mode);
  1069. cvModifyRows(mode,'lists',queryName,[entry],action,getContainer('data'));
  1070. }
  1071. function updateLastSavedFlag(data,setup,elementId){
  1072. let debug=true;
  1073. if (debug) print("Update last saved flag to "+elementId);
  1074. let el=config.document.getElementById(elementId);
  1075. let dt=new Date();
  1076. el.innerHTML="Last saved "+dt.toString();
  1077. if (data.queryName=="reviewComments"){
  1078. updateListDisplay(setup.divReviewListId,"reviewComments",setup.filters,true);
  1079. }
  1080. //refresh stored data!
  1081. let writeMode=!setup.readonlyFlag();
  1082. if ("unique" in setup)
  1083. setData(function (){populateTable(data.queryName,writeMode);});
  1084. if ("masterQuery" in setup){
  1085. let ad=config.formConfig.additionalData[setup.masterQuery];
  1086. print('Updating list display: '+setup.queryName+'/'+ad.queryName);
  1087. updateListDisplay(ad.divQueryName,ad.queryName,ad.filters,false);
  1088. }
  1089. }
  1090. //******************************************upload to database *********************
  1091. function onDatabaseUpload(){
  1092. let fName='[onDatabaseUpload]';
  1093. print(fName);
  1094. config.upload=new Object();
  1095. let fc=new Object();
  1096. let pM=getParticipantManagerObject(config);
  1097. fc.participantId=pM.getParticipantIdFromCrfEntry();
  1098. print(fName+' id '+fc.participantId);
  1099. afterParticipantId(fc);
  1100. }
  1101. function afterParticipantId(fc){
  1102. print("Setting participantId to "+fc.participantId);
  1103. config.upload.participantId=fc.participantId;
  1104. //another select rows to update all queries from setup
  1105. //just use registration for test
  1106. let formSetupRows=config.formConfig.formSetupRows;
  1107. config.upload.queries=new Array();
  1108. print("Form rows: "+formSetupRows.length);
  1109. for (let i=0;i<formSetupRows.length;i++){
  1110. let entry=formSetupRows[i];
  1111. //skip reviews
  1112. if (entry.showFlag=="REVIEW") continue;
  1113. //use lookup table to convert from id to name
  1114. let queryName=config.formConfig.queryMap[entry.queryName];
  1115. config.upload.queries.push({queryName:queryName,queryStatus:"QUEUED"});
  1116. print('form ['+i+']='+queryName+' '+entry.showFlag+'/'+entry.showQuery);
  1117. if (entry.showQuery=="NONE")
  1118. continue;
  1119. config.upload.queries.push({queryName:entry.showQuery,queryStatus:"QUEUED"});
  1120. }
  1121. //add reviews
  1122. config.upload.queries.push({queryName:"reviewComments",queryStatus:"QUEUED"});
  1123. config.upload.queryId=0;
  1124. copyToDataset();
  1125. }
  1126. function copyToDataset(){
  1127. let fName='[copyToDataset]: ';
  1128. print(fName+'['+config.upload.queryId+'/'+config.upload.queries.length+']');
  1129. //watch dog + scheduler
  1130. //
  1131. //watchdog part
  1132. if (config.upload.queryId==config.upload.queries.length) {
  1133. print(fName+'completing');
  1134. let targetStatus=config.formConfig.targetStatus['onDatabaseUpload'];
  1135. let targetRecipient=config.formConfig.targetRecipient['onDatabaseUpload'];
  1136. let action=new Object();
  1137. action.name='onDatabaseUpload';
  1138. action.cb=function(data){sendEmail(data,targetRecipient,redirect,'Form uploaded');}
  1139. updateFlag(targetStatus,action);//Approved
  1140. return;
  1141. }
  1142. //scheduler
  1143. let queryName=config.upload.queries[config.upload.queryId].queryName;
  1144. print("copyToDataset["+config.upload.queryId+"/"+
  1145. config.upload.queries.length+"]: "+queryName);
  1146. let filters=[LABKEY.Filter.create('crfRef',getCRFref())];
  1147. cvSelectRows('lists',queryName,filters,afterListData,getContainer('data'));
  1148. }
  1149. function afterListData(data){
  1150. let fName='[afterListData]: ';
  1151. let queryName=config.upload.queries[config.upload.queryId].queryName;
  1152. print(fName+" ["+queryName+"/list]: "+data.rows.length+" entries");
  1153. config.upload.queries[config.upload.queryId].listData=data;
  1154. let id=config.upload.participantId;
  1155. let filters=[LABKEY.Filter.create('crfRef',getCRFref()),LABKEY.Filter.create('ParticipantId',id)];
  1156. cvSelectRows('study',queryName,filters,afterStudyData,getContainer('data'));
  1157. }
  1158. function afterStudyData(data){
  1159. let fName='[afterStudyData]: ';
  1160. let queryObj=config.upload.queries[config.upload.queryId];
  1161. queryObj.studyData=data;
  1162. let msg=fName+"["+queryObj.queryName+"/study]: "+data.rows.length+" entries";
  1163. print(msg);
  1164. let listRows=queryObj.listData.rows;
  1165. //skip uploading an empty set
  1166. if (listRows.length==0){
  1167. printErr("List "+queryObj.queryName+" empty.");
  1168. queryObj.queryStatus="DONE";
  1169. config.upload.queryId+=1;
  1170. //back to watchdog
  1171. copyToDataset();
  1172. return;
  1173. }
  1174. let studyRows=queryObj.studyData.rows;
  1175. for (let i=0;i<studyRows.length;i++){
  1176. let entry=studyRows[i];
  1177. //
  1178. if (! (i<listRows.length) ) continue;
  1179. let entryList=listRows[i];
  1180. //keeps study only variables (ParticipantId, SequenceNum)
  1181. for (let f in entryList) {
  1182. entry[f]=entryList[f];
  1183. print(fName+"Copying ["+f+"]: "+entry[f]+"/"+entryList[f]);
  1184. }
  1185. }
  1186. print(fName+' copying completed');
  1187. if (studyRows.length>0) {
  1188. cvModifyRows('update','study',queryObj.queryName,studyRows,afterStudyUpload,getContainer('data'));
  1189. print(fName+'updateRows sent');
  1190. }
  1191. else{
  1192. let data=new Object();
  1193. data.rows=new Array();
  1194. afterStudyUpload(data);
  1195. }
  1196. }
  1197. function afterStudyUpload(data){
  1198. let fName='[afterStudyUpload] ';
  1199. print(fName);
  1200. //let participantField=config.participantField;
  1201. let participantField=config.formConfig.studyData["SubjectColumnName"];
  1202. print(fName+' participantField: '+participantField);
  1203. let queryObj=config.upload.queries[config.upload.queryId];
  1204. let queryName=queryObj.queryName;
  1205. printErr("Updated "+data.rows.length+" rows to "+queryName);
  1206. let studyRows=queryObj.studyData.rows;
  1207. let listRows=queryObj.listData.rows;
  1208. let rows=new Array();
  1209. //also updating existing rows, if they exist
  1210. for (let i=studyRows.length;i<listRows.length;i++){
  1211. let entry=listRows[i];
  1212. //make sure you have the participantField right
  1213. //
  1214. entry[participantField]=config.upload.participantId;
  1215. entry.crfRef=getCRFref();
  1216. entry.SequenceNum=getCRFref();
  1217. entry.SequenceNum=entry.SequenceNum % 1000000000;
  1218. if (listRows.length>1){
  1219. entry.SequenceNum+=i/100;
  1220. }
  1221. print( "Adding sequence number "+entry.SequenceNum);
  1222. rows.push(entry);
  1223. }
  1224. if (rows.length>0){
  1225. cvInsertRows('study',queryName,rows,afterListUpload,getContainer('data'));
  1226. }
  1227. else{
  1228. let data=new Object();
  1229. data.rows=rows;
  1230. afterListUpload(data);
  1231. }
  1232. }
  1233. function afterListUpload(data){
  1234. let queryObj=config.upload.queries[config.upload.queryId];
  1235. let queryName=queryObj.queryName;
  1236. printErr("Inserted "+data.rows.length+" rows to "+queryName);
  1237. queryObj.queryStatus="DONE";
  1238. config.upload.queryId+=1;
  1239. copyToDataset();
  1240. }
  1241. //*************************update for further review *************************
  1242. function onUpdateForReview(){
  1243. let targetStatus=config.formConfig.targetStatus['onUpdateForReview'];
  1244. let targetRecipient=config.formConfig.targetRecipient['onUpdateForReview'];
  1245. let action=new Object();
  1246. action.name='onUpdateForReview';
  1247. action.cb=function(data){sendEmail(data,targetRecipient,redirect,'Form updated for review');};
  1248. updateFlag(targetStatus,action);
  1249. }
  1250. function updateFlag(flag,action){
  1251. let fName='[updateFlag 1]';
  1252. let debug=true;
  1253. let entry=config.formConfig.crfEntry;
  1254. entry.FormStatus=flag;
  1255. let uId=config.formConfig.currentUser.UserId;
  1256. entry[config.formConfig.operator]=uId;
  1257. print(fName+': Form: '+entry.Form);
  1258. print(fName+": set form status to "+entry.FormStatus);
  1259. let cb=function(data){completeWithFlag(data,action);};
  1260. cvModifyRows('update','lists','crfEntry',[entry],cb,getContainer('data'));
  1261. }
  1262. function completeWithFlag(data,action){
  1263. let fName='[completeWithFlag]';
  1264. print(fName+': nrows '+data.rows.length);
  1265. let fentry=data.rows[0];
  1266. print(fName+': form status '+fentry.FormStatus);
  1267. print(fName+': form '+fentry.Form);
  1268. let crfStatus=createCrfStatus(fentry);
  1269. crfStatus.operator=config.formConfig.operator;
  1270. crfStatus.action=action.name;
  1271. cvInsertRows('lists','crfStatus',[crfStatus],action.cb,getContainer('data'));
  1272. }
  1273. //************************************************ submit *******************************************
  1274. function onSubmit(){
  1275. //update list storage and change status
  1276. hideErr();
  1277. clearErr();
  1278. printErr("onSubmit");
  1279. setData(verifyData);
  1280. }
  1281. function verifyData(){
  1282. return;
  1283. let fName='[verifyData]';
  1284. let queries=config.formConfig.dataQueries;
  1285. for (q in queries){
  1286. let qData=queries[q];
  1287. if (q=="reviewComments") continue;
  1288. //copy snapshot to history
  1289. cvInsertRows('lists',q+'History',qData.rows,doNothing,getContainer('data'));
  1290. //if it doesn't have additionalData, it is a sub query
  1291. if (!(q in config.formConfig.additionalData)){
  1292. continue;
  1293. }
  1294. if (qData.rows.length<1){
  1295. printErr('Missing entry for query '+q);
  1296. return false;
  1297. }
  1298. }
  1299. //this is necessary only for Generated to Generation completed step
  1300. let actionSettings=config.formConfig.actionSettings['onSubmit'];
  1301. if (hasVariable(actionSettings,"updateRegistration")){
  1302. updateRegistration();
  1303. }
  1304. let targetStatus=config.formConfig.targetStatus['onSubmit'];
  1305. let targetRecipient=config.formConfig.targetRecipient['onSubmit'];
  1306. print(fName+' targetStatus: '+targetStatus);
  1307. let finalStep=redirect;
  1308. if (hasVariable(actionSettings,"finalStep")){
  1309. //set to doNothing to remain on submit window
  1310. if (actionSettings.finalStep=="doNothing"){
  1311. finalStep=doNothing;
  1312. }
  1313. }
  1314. let action=new Object();
  1315. action.name='onSubmit';
  1316. action.cb=function(data){sendEmail(data,targetRecipient,finalStep,'Form sumbitted');};
  1317. updateFlag(targetStatus,action);
  1318. }
  1319. function getEmail(recipientCode){
  1320. print('getEmail w/'+recipientCode);
  1321. let recipients=new Array();
  1322. let typeTo=LABKEY.Message.recipientType.to;
  1323. let create=LABKEY.Message.createRecipient;
  1324. let currentUser=config.formConfig.currentUser;
  1325. let formCreator=config.formConfig.formCreator;
  1326. let currentSite=config.formConfig.currentSite;
  1327. let userRows=config.formConfig.userRows;
  1328. let parentUser=undefined;
  1329. if ("parentCrfData" in config.formConfig){
  1330. let parentCrf=config.formConfig.parentCrfData;
  1331. parentUser=getUser(parentCrf.rows[0].UserId,'parentUser');
  1332. }
  1333. let recipientCategories=recipientCode.split(',');
  1334. for (let i=0;i<recipientCategories.length;i++){
  1335. let recipient=recipientCategories[i];
  1336. print('Checking '+recipient);
  1337. if (recipient=='crfEditor'){
  1338. print('Adding :'+formCreator.Email);
  1339. recipients.push(create(typeTo,formCreator.Email));
  1340. if (parentUser==undefined) continue;
  1341. print('Adding :'+parentUser.Email);
  1342. recipients.push(create(typeTo,parentUser.Email));
  1343. continue;
  1344. }
  1345. //Monitor or Sponsor
  1346. let fList=recipient+'s';
  1347. let fRows=config.formConfig[fList];
  1348. for (let i=0;i<fRows.length;i++){
  1349. print('Checking '+fRows[i].User+'/'+fRows[i].Site);
  1350. if (fRows[i].Site!=currentSite.siteNumber) continue;
  1351. for (let j=0;j<userRows.length;j++){
  1352. if (userRows[j].UserId!=fRows[i].User) continue;
  1353. print('Adding :'+userRows[j].Email);
  1354. recipients.push(create(typeTo,userRows[j].Email));
  1355. break;
  1356. }
  1357. }
  1358. }
  1359. return recipients;
  1360. }
  1361. function sendEmail(data,recipient='crfEditor',cb=redirect,subj='Form submitted'){
  1362. print('sendEmail; recipient: '+recipient);
  1363. let st=config.formConfig.settings;
  1364. let cvar='sendEmail';
  1365. if (cvar in st){
  1366. print(cvar+' set to '+st[cvar]);
  1367. if (st[cvar]=='FALSE'){
  1368. print('Skipping sending emails');
  1369. cb();
  1370. return;
  1371. }
  1372. }
  1373. if (recipient==null){
  1374. print('Skipping sending emails w/ no recipients');
  1375. cb();
  1376. return;
  1377. }
  1378. print('send email '+data.rows.length);
  1379. let crf=data.rows[0]['entryId'];
  1380. let formId=data.rows[0]['Form'];
  1381. let link=LABKEY.ActionURL.getBaseURL();
  1382. link+=LABKEY.ActionURL.getContainer();
  1383. link+='/crf_tecant-visit.view?';
  1384. link+='entryId='+crf;
  1385. link+='&formId='+formId;
  1386. link+='&role='+recipient;
  1387. //debug
  1388. let recipients=getEmail(recipient);
  1389. //from crfManagers list
  1390. let typeHtml=LABKEY.Message.msgType.html;
  1391. let typePlain=LABKEY.Message.msgType.plain;
  1392. let msg1=LABKEY.Message.createMsgContent(typePlain,link);
  1393. //let cb=doNothing;
  1394. //let cb=redirect;
  1395. LABKEY.Message.sendMessage({
  1396. msgFrom:'labkey@fmf.uni-lj.si',
  1397. msgSubject:subj,
  1398. msgRecipients:recipients,
  1399. msgContent:[msg1],
  1400. success: cb
  1401. });
  1402. }
  1403. function hideErr(){
  1404. let el=config.document.getElementById("errorDiv");
  1405. el.style.display="none";
  1406. }
  1407. function clearErr(){
  1408. let el=config.document.getElementById("errorTxt");
  1409. el.value="";
  1410. }
  1411. function showErr(){
  1412. let el=config.document.getElementById("errorDiv");
  1413. el.style.display="block";
  1414. }
  1415. function printErr(msg){
  1416. showErr();
  1417. el=config.document.getElementById("errorTxt");
  1418. el.style.color="red";
  1419. el.value+="\n"+msg;
  1420. }
  1421. //**************************************************
  1422. //
  1423. function onRemoveCRF(){
  1424. let fName='[onRemoveCRF]';
  1425. config.inputListsIterator=0;
  1426. print(fName+' starting loop');
  1427. //let rd=function(data){redirect();};
  1428. //let cb=function(){cvInsertRows('lists','crfStatus',[crfStatus],rd,getContainer('data'));};
  1429. let cb=function(){removeCrfEntries(redirect);};
  1430. removeCRFLoop(cb);
  1431. }
  1432. function removeCRFLoop(cb){
  1433. let fName='[removeCRFLoop()]';
  1434. let debug=true;
  1435. let i=config.inputListsIterator;
  1436. let iMax=config.formConfig.inputLists.rows.length;
  1437. //in fact, we are adding two additional passages of the loop, one for
  1438. //crfEntry, the second for the same query, but using parentCrf as the
  1439. //selection variable
  1440. //let iTotal=iMax+1;
  1441. //let iTotal=iMax+1;
  1442. //
  1443. let actionSettings=config.formConfig.actionSettings['onRemoveCRF'];
  1444. let queryNameDeleteWithParentCrf='NONE';
  1445. if (hasVariable(actionSettings,'removeWithParentCrf')){
  1446. queryNameDeleteWithParentCrf=actionSettings['removeWithParentCrf'];
  1447. }
  1448. print(fName+" ["+i+"/"+iMax+"]");
  1449. if (!(i<iMax)){
  1450. if (0) return;
  1451. cb();
  1452. }
  1453. //in all but crfEntry, variable is called crfRef
  1454. let queryName=config.formConfig.inputLists.rows[i].queryName;
  1455. let idVar="crfRef";
  1456. let idValue=config.formConfig.crfEntry['entryId'];
  1457. //delete also crfEntries where parentCrf is set to crf that we are deleting
  1458. if (queryNameDeleteWithParentCrf==queryName){
  1459. idValue=config.formConfig.crfEntry['parentCrf'];
  1460. }
  1461. print(fName+" ["+i+"/"+iMax+"] "+queryName+":"+idVar+'/'+idValue);
  1462. let filters=[LABKEY.Filter.create(idVar,idValue)];
  1463. let action=function(data){removeListCRF(data,cb);};
  1464. let failure=function(errorInfo){skipListCRF(errorInfo,cb);};
  1465. cvSelectRows('lists',queryName,filters,action,getContainer('data'),failure);
  1466. //selectRows.failure=skipListCRF;
  1467. }
  1468. function removeListCRF(data,cb){
  1469. let fName="[removeListCRF]";
  1470. print(fName+" "+data.queryName+": "+data.rows.length);
  1471. config.inputListsIterator+=1;
  1472. if (data.rows.length==0){
  1473. removeCRFLoop(cb);
  1474. return;
  1475. }
  1476. let action=function(data){removeCRFLoop(cb)};
  1477. cvDeleteRows(data.schemaName,data.queryName,data.rows,action,getContainer('data'));
  1478. }
  1479. function skipListCRF(errorInfo,cb){
  1480. let fName='[skipListCRF]';
  1481. print(fName+" error in removeCRF: "+errorInfo.exception);
  1482. config.inputListsIterator+=1;
  1483. removeCRFLoop(cb);
  1484. }
  1485. function removeCrfEntries(cb){
  1486. let queryName="crfEntry";
  1487. let idVar="entryId";
  1488. let crfRef=getCRFref();
  1489. let filters=[LABKEY.Filter.create('entryId',crfRef)];
  1490. let action=function(data){deleteAndUpdateCrfStatus(data,null);}
  1491. cvSelectRows('lists',queryName,filters,action,getContainer('CRF'));
  1492. let action1=function(data){deleteAndUpdateCrfStatus(data,cb);}
  1493. let filters1=[LABKEY.Filter.create('parentCrf',crfRef)];
  1494. cvSelectRows('lists',queryName,filters1,action1,getContainer('CRF'));
  1495. }
  1496. function deleteAndUpdateCrfStatus(data,cb){
  1497. let fName='[deleteAndUpdateCrfStatus]';
  1498. let rows=data.rows;
  1499. let stack=new Array();
  1500. stack.push(cb);
  1501. for (let i=0;i<rows.length;i++){
  1502. //generate crfStatus entry out of crfEntry
  1503. let crfStatus=createCrfStatus(rows[i]);
  1504. crfStatus.action='onRemoveCRF';
  1505. crfStatus.FormStatus=config.formConfig.targetStatus[crfStatus.action];
  1506. print(fName+' status '+crfStatus.FormStatus);
  1507. crfStatus.operator=config.formConfig.operator;
  1508. let k=stack.length-1;
  1509. stack.push(function(){cvInsertRows('lists','crfStatus',[crfStatus],stack[k],getContainer('CRF'));});
  1510. let k1=k+1;
  1511. stack.push(function(){cvDeleteRows('lists','crfEntry',[rows[i]],stack[k1],getContainer('CRF'));});
  1512. }
  1513. //execute the whole stack
  1514. let m=stack.length-1;
  1515. stack[m]();
  1516. }
  1517. function redirect(){
  1518. let debug=false;
  1519. let formUrl="begin";
  1520. let params=new Object();
  1521. params.name=formUrl;
  1522. params.pageId="CRF";
  1523. //points to crf container
  1524. let containerPath=getContainer('CRF');
  1525. // This changes the page after building the URL.
  1526. //Note that the wiki page destination name is set in params.
  1527. var homeURL = LABKEY.ActionURL.buildURL(
  1528. "project", formUrl , containerPath, params);
  1529. print("Redirecting to "+homeURL);
  1530. if (debug) return;
  1531. window.location = homeURL;
  1532. }
  1533. //master section, entry point from html files
  1534. function generateMasterForm(){
  1535. generateDebugSection();
  1536. //read enviroment from lists disperesed on labkey
  1537. setFormConfig();
  1538. }
  1539. //helper function to set basic parameters on web page
  1540. //(fields defined in html file)
  1541. function populateBasicData(){
  1542. let staticData=new Object();
  1543. let titles=new Object();
  1544. staticData['version']=config.formConfig.softwareVersion;
  1545. titles['version']='Software version';
  1546. let varRows=config.formConfig['crfStaticVariables'].rows;
  1547. for (let i=0;i<varRows.length;i++){
  1548. let vName=varRows[i].staticVariable;
  1549. let val=config.formConfig.crfEntry[vName];
  1550. if (val==undefined) continue;
  1551. staticData[vName]=val;
  1552. titles[vName]=varRows[i].Title;
  1553. }
  1554. staticData['investigatorName']=config.formConfig.user['DisplayName'];
  1555. titles['investigatorName']='Investigator';
  1556. staticData['email']=config.formConfig.user['Email'];
  1557. titles['email']='Email';
  1558. staticData['siteName']=config.formConfig.currentSite['siteName'];
  1559. titles['siteName']='Site';
  1560. staticData['sitePhone']=config.formConfig.currentSite['sitePhone'];
  1561. titles['sitePhone']='Telephone(site)';
  1562. for (f in staticData){
  1563. addStaticData(f,titles[f],staticData[f]);
  1564. }
  1565. }
  1566. function addStaticData(f,title,value){
  1567. let el=config.document.getElementById(f);
  1568. //populate only
  1569. if (el!=undefined){
  1570. el.innerText=value;
  1571. return;
  1572. }
  1573. //add row to table if element cannot be found
  1574. let table=config.document.getElementById('staticTable');
  1575. let row=table.insertRow();
  1576. let cell=row.insertCell();
  1577. cell.innerText=title;
  1578. let cell1=row.insertCell();
  1579. cell1.id=f;
  1580. cell1.style.fontWeight='bold';
  1581. //populate
  1582. cell1.innerText=value;
  1583. }
  1584. //come here after the layout is read from labkey page
  1585. //
  1586. function generateErrorMsg(msg){
  1587. let txt=config.document.createElement('p');
  1588. txt.innerText=msg;
  1589. config.document.getElementById(config.masterForm).appendChild(txt);
  1590. generateButton("submitDiv",'Exit','Exit','redirect',redirect);
  1591. }
  1592. function getUser(id,field){
  1593. if (field in config.formConfig) return config.formConfig[field];
  1594. let uRows=config.formConfig.userRows;
  1595. for (let i=0;i<uRows.length;i++){
  1596. let userId=uRows[i].UserId;
  1597. if (userId!=id) continue;
  1598. config.formConfig[field]=uRows[i];
  1599. return config.formConfig[field];
  1600. }
  1601. return null;
  1602. }
  1603. function afterConfig(){
  1604. let debug=true;
  1605. if (debug)
  1606. print("afterConfig");
  1607. populateBasicData();
  1608. //check if user has permission on the form
  1609. let currentUser=getUser(LABKEY.Security.currentUser.id,'currentUser');
  1610. let currentSite=config.formConfig.currentSite;
  1611. let formCreator=getUser(config.formConfig.crfEntry.UserId,'formCreator');
  1612. let formCreatorId=formCreator.UserId;
  1613. //let formSite=config.formConfig.crfEntry.Site;
  1614. let fList=config.formConfig.operator+'s';
  1615. let fRows=config.formConfig[fList];
  1616. //let currentSiteId=-1;
  1617. //depending on operator mode, we should decide what is right
  1618. let operator=config.formConfig.operator;
  1619. if (operator=='crfEditor'){
  1620. //editor can only edit its own forms
  1621. if (currentUser.UserId!=formCreatorId){
  1622. let msg='User '+currentUser.DisplayName;
  1623. msg+=' has no permission on this form';
  1624. generateErrorMsg(msg);
  1625. return;
  1626. }
  1627. }
  1628. if (operator=='crfMonitor' || operator=='crfSponsor'){
  1629. //monitor can look at forms based on his site
  1630. //find monitor line
  1631. let operatorSites=new Array();
  1632. for (let i=0;i<fRows.length;i++){
  1633. if (fRows[i].User!=currentUser.UserId) continue;
  1634. operatorSites.push(fRows[i].Site);
  1635. }
  1636. print('operator Site: '+operatorSites.length);
  1637. if (operatorSites.length==0){
  1638. let msg='User '+currentUser.DisplayName;
  1639. msg+=' is not a '+operator;
  1640. generateErrorMsg(msg);
  1641. return;
  1642. }
  1643. let selectedSite=-1;
  1644. let siteCandidates="[";
  1645. for (let i=0;i<operatorSites.length;i++){
  1646. if (i>0) siteCandidates+=", ";
  1647. siteCandidates+=operatorSites[i];
  1648. if (operatorSites[i]!=currentSite.siteNumber) continue;
  1649. selectedSite=currentSite.siteNumber;
  1650. break;
  1651. }
  1652. siteCandidates+="]";
  1653. if (selectedSite==-1){
  1654. let msg='User '+currentUser.DisplayName;
  1655. msg+=' is not a '+operator+' for site ';
  1656. msg+=currentSite.siteName+'('+currentSite.siteNumber+')';
  1657. msg+='/'+siteCandidates;
  1658. generateErrorMsg(msg);
  1659. return;
  1660. }
  1661. }
  1662. print('User '+currentUser.DisplayName+'/'+
  1663. config.formConfig.currentSite['siteName']+
  1664. ' acting as '+config.formConfig.operator);
  1665. let rows=config.formConfig.crfButtons.rows;
  1666. config.formConfig.targetStatus=new Array();
  1667. config.formConfig.targetRecipient=new Array();
  1668. config.formConfig.actionSettings=new Array();
  1669. for (let i=0; i<rows.length; i++){
  1670. let action=rows[i].action;//String
  1671. let tstatus=rows[i].targetFormStatus;
  1672. let trecip=rows[i].targetRecipient;
  1673. config.formConfig.targetStatus[action]=tstatus;
  1674. config.formConfig.targetRecipient[action]=trecip;
  1675. //allow for settings to be promoted with each action (and potentially parsed and acted upon)
  1676. config.formConfig.actionSettings[action]=undefined;
  1677. let aSet=rows[i].actionSettings;
  1678. if (aSet){
  1679. config.formConfig.actionSettings[action]=parseVariables(aSet);
  1680. printVariables(config.formConfig.actionSettings[action]);
  1681. }
  1682. }
  1683. let formStatus=config.formConfig.formStatus;
  1684. //let functionArray=new Array();
  1685. print("Generating buttons for formStatus \""+ formStatus+"\"");
  1686. let allButtonRows=config.formConfig.crfButtons.rows;
  1687. let buttonRows=new Array();
  1688. //specifying role=X in actionSettings will limit button to that role
  1689. for (let i=0;i<allButtonRows.length;i++){
  1690. let action=allButtonRows[i]['action'];
  1691. //filter on actionSettings
  1692. let as=config.formConfig.actionSettings[action];
  1693. if (hasVariable(as,'role')){
  1694. print('Role['+config.formConfig.operator+'/'+as['role']+'] limited for action '+action);
  1695. //mismatch skips addition of button to buttonRows
  1696. if (config.formConfig.operator!=as['role']) continue;
  1697. }
  1698. buttonRows.push(allButtonRows[i]);
  1699. }
  1700. for (let i=0;i<buttonRows.length;i++){
  1701. let bt=buttonRows[i];
  1702. if (typeof window[bt.action]==="function"){
  1703. generateButton("submitDiv",bt.caption,bt.label,bt.action,
  1704. window[bt.action]);
  1705. }
  1706. else{
  1707. print('No match for function :'+bt.action+
  1708. ' obj: '+window[bt.action]);
  1709. }
  1710. }
  1711. print('Here');
  1712. //here we should get data. For now, just initialize objects that will hold data
  1713. setDataLayout(afterDataLayout);//callback is afterDataLayout
  1714. }
  1715. function afterDataLayout(){
  1716. setData(afterData);//callback is afterData
  1717. }
  1718. function verifyCrfStudyId(pM){
  1719. //is studyId already set for the crf
  1720. let studyId=pM.getParticipantIdFromCrfEntry('STUDY');
  1721. if (!studyId) return;
  1722. pM.mode="STUDY";
  1723. pM.readOnly="TRUE";
  1724. }
  1725. function verifyRegistration(pM){
  1726. //if registration is in,
  1727. //then local id should not be changed any longer
  1728. let idFieldName=pM.getCrfEntryFieldName("STUDY");
  1729. //let registrationQuery=config.formConfig.settings['registrationQuery'];
  1730. //if (!registrationQuery) return; //LOCAL is OK
  1731. //let fQuery=config.formConfig.dataQueries[registrationQuery];
  1732. //if (!fQuery) return; //no registration query, then it should be ignored
  1733. let fQuery=config.formConfig.registrationData;
  1734. if (fQuery.rows.length==0) return; //registration is empty
  1735. let studyId=fQuery.rows[0][idFieldName];
  1736. if (!studyId) return; //study id not set
  1737. //set
  1738. pM.mode="STUDY";
  1739. pM.readOnly="TRUE";
  1740. //set crf (this happens later, but probably before the form will be corrected)
  1741. pM.setParticipantIdToCrfEntry(studyId,"STUDY");
  1742. pM.updateCrfEntry();
  1743. }
  1744. function updateRegistration(){
  1745. let fName="[updateRegistration]";
  1746. print(fName);
  1747. let pM=getParticipantManagerObject(config);
  1748. let idFieldName=pM.getCrfEntryFieldName("STUDY");
  1749. //have to reload query data
  1750. let regQueryPars=parseVariables(config.formConfig.settings['registrationQuery']);
  1751. let regQuery=regQueryPars['query'];
  1752. let fQuery=config.formConfig.dataQueries[regQuery];
  1753. if (fQuery.rows.length==0) {
  1754. print(fName+" registration is empty");
  1755. return; //registration is empty
  1756. }
  1757. let regEntry=fQuery.rows[0];
  1758. for (x in regEntry){
  1759. print(fName+" ["+x+"] "+regEntry[x]);
  1760. }
  1761. let studyId=fQuery.rows[0][idFieldName];
  1762. if (!studyId) {
  1763. print(fName+" study id not set ("+idFieldName+'/'+studyId+")");
  1764. return; //study id not set
  1765. }
  1766. //set
  1767. pM.setParticipantIdToCrfEntry(studyId,"STUDY");
  1768. //this will only update crfEntry in memory, but not on LabKey,
  1769. //we are counting on updateFlag to follow updateRegistration
  1770. //update parentCRF as well, here we schedule update of data entry as well
  1771. if ("parentCrfData" in config.formConfig){
  1772. let parentCrfEntry=config.formConfig.parentCrfData.rows[0];
  1773. parentCrfEntry[idFieldName]=studyId;
  1774. let cb=function(data){completeWithFlag(data,doNothing);};
  1775. cvModifyRows('update','lists','crfEntry',[parentCrfEntry],cb,getContainer('CRF'));
  1776. }
  1777. }
  1778. function afterData(){
  1779. let fName='afterData';
  1780. //operatorBasedAccessMode
  1781. let accessMode=config.formConfig.operator+'Mode';
  1782. let rowsSetup=config.formConfig.formSetupRows;
  1783. let idMode=config.formConfig.form['idMode'];
  1784. //set default value if no value is in the list (read value is null)
  1785. if (!idMode) idMode="STUDY:EDIT";
  1786. print(fName+': idMode '+idMode);
  1787. //add print to config so participantManager can use it
  1788. config.print=print;
  1789. let pM=getParticipantManagerObject(config);
  1790. pM.updateCrfEntry=function(){updateFlag(config.formConfig.crfEntry['FormStatus'],doNothing);};
  1791. let idModeArray=idMode.split(':');
  1792. pM.mode="STUDY";
  1793. if (idModeArray.includes("LOCAL")) {
  1794. pM.mode="LOCAL";
  1795. //OK, but check if CRF or registration indicate that study id is already set
  1796. verifyCrfStudyId(pM);
  1797. //study id should already be set by updateRegistration
  1798. //verifyRegistration(pM);
  1799. }
  1800. if (idModeArray.includes("READONLY")){
  1801. pM.readOnly="TRUE";
  1802. }
  1803. let pId=pM.getParticipantIdFromCrfEntry();
  1804. if (!pId){
  1805. pM.setEditMode();
  1806. }
  1807. else{
  1808. let label=pId;
  1809. if (pM.mode=="STUDY"){
  1810. let loc=pM.getParticipantIdFromCrfEntry('LOCAL');
  1811. label=pId+':'+loc;
  1812. pM.readOnly="true";
  1813. }
  1814. pM.setLabelMode(label);
  1815. //in STUDY mode also change LOCAL ID from crfEntry
  1816. }
  1817. for (let i=0;i<rowsSetup.length;i++){
  1818. let entry=rowsSetup[i];
  1819. let queryName=config.formConfig.queryMap[entry['queryName']];
  1820. print(fName+" ["+queryName+"]: showFlag: "+entry["showFlag"]);
  1821. print(fName+" ["+queryName+"]: accessMode: "+entry[accessMode]);
  1822. const nData=config.formConfig.dataQueries[queryName].rows.length;
  1823. print(fName+" ["+queryName+"]: nData: "+nData);
  1824. //skip sections
  1825. //also from fields
  1826. if (entry[accessMode]=="NONE") continue;
  1827. //skip readonly empty records
  1828. //if (entry[accessMode]=="READ" && nData==0) continue;
  1829. //let additionalData=new Object();
  1830. //setAdditionalData(additionalData,entry);
  1831. //section fits one dataset/list
  1832. generateSection(entry);
  1833. //generateSection(queryName,entry["title"],entry[accessMode],
  1834. // additionalData);
  1835. }
  1836. }
  1837. function findSetupRow(queryName,formId){
  1838. let rowsSetup=config.formConfig.formSetupRows;
  1839. for (let i=0;i<rowsSetup.length;i++){
  1840. let e=rowsSetup[i];
  1841. let queryName1=config.formConfig.queryMap[e['queryName']];
  1842. if (e.formName!=formId) continue;
  1843. if (queryName1!=queryName) continue;
  1844. return e;
  1845. }
  1846. return null;
  1847. }
  1848. function populateSection(queryName){
  1849. let fName='[populateSection/'+queryName+']';
  1850. print(fName);
  1851. //old setting
  1852. let formId=config.formId;
  1853. //new setting
  1854. formId=config.formConfig.formId;
  1855. let entry=findSetupRow(queryName,formId);
  1856. //ignore names without associated entry in formSetup
  1857. if (entry==undefined){
  1858. print(fName+': no matching FormSetup entry found');
  1859. return;
  1860. }
  1861. //populate comes after generate, we should be pretty safe in taking
  1862. //already generated additionalData
  1863. if (!(queryName in config.formConfig.additionalData)){
  1864. print(fName+': no additionalData generated for '+queryName);
  1865. return;
  1866. }
  1867. let additionalData=config.formConfig.additionalData[queryName];
  1868. print(fName+': using additionalData '+additionalData);
  1869. if ("isReview" in additionalData){
  1870. generateReviewSection(queryName,queryName,generateReviewSectionCB);
  1871. return;
  1872. }
  1873. let accessMode=config.formConfig.operator+'Mode';
  1874. let aM=entry[accessMode];
  1875. print(fName+': accessMode '+aM);
  1876. if (aM!='GENERATE'){
  1877. let writeMode=entry[accessMode]=='EDIT';
  1878. print(fName+': mode='+writeMode);
  1879. populateTable(queryName,writeMode);
  1880. return;
  1881. }
  1882. //deal with generate
  1883. //
  1884. //already available -> shift to READ mode
  1885. let divTable=queryName+'Table';
  1886. let divObj=config.document.getElementById(divTable);
  1887. let divRev=config.document.getElementById(queryName+'Review');
  1888. let divRLi=config.document.getElementById(queryName+'ReviewList');
  1889. let divGBu=config.document.getElementById(queryName+'GenerateButton');
  1890. print('div GBU: '+divGBu);
  1891. divObj.style.display="block";
  1892. divRev.style.display="block";
  1893. divRLi.style.display="block";
  1894. if (divGBu!=undefined) divGBu.style.display="none";
  1895. let nData=config.formConfig.dataQueries[queryName].rows.length;
  1896. print('['+queryName+']: nrows '+nData);
  1897. if (nData>0){
  1898. populateTable(queryName,0);
  1899. return;
  1900. }
  1901. //hide table
  1902. divObj.style.display="none";
  1903. divRev.style.display="none";
  1904. divRLi.style.display="none";
  1905. if (divGBu!=undefined) divGBu.style.display="block";
  1906. //add buttons?
  1907. //is button already generated?
  1908. //populateTable(entry);
  1909. }
  1910. //******* generateQuery infrastructure *********************
  1911. function onGenerateQuery(queryName){
  1912. let fName='[onGenerateQuery]';
  1913. print(fName+' '+queryName);
  1914. //
  1915. let cfgRows=config.formConfig.generateConfigData.rows;
  1916. // //queryName to queryId?
  1917. let queryId=config.formConfig.fields[queryName].queryId;
  1918. let cfgRow=undefined;
  1919. for (let i=0;i<cfgRows.length;i++){
  1920. if (cfgRows[i].queryId!=queryId) continue;
  1921. cfgRow=cfgRows[i];
  1922. break;
  1923. }
  1924. if (cfgRow==undefined){
  1925. print('generateConfig for queryName['+queryId+']='+queryName+' not found');
  1926. return;
  1927. }
  1928. //add config to the list
  1929. if (!("generateConfig" in config.formConfig)){
  1930. config.formConfig.generateConfig=new Object();
  1931. }
  1932. config.formConfig.generateConfig[queryName]=cfgRow;
  1933. if (!("generateForm" in config.formConfig)){
  1934. config.formConfig.generateForm=new Object();
  1935. }
  1936. //
  1937. let formRows=config.formConfig.formRows;
  1938. let formId=cfgRow.formId;
  1939. for (let i=0;i<formRows.length;i++){
  1940. if (formRows[i].Key==formId) {
  1941. config.formConfig.generateForm[queryName]=formRows[i];
  1942. break;
  1943. }
  1944. }
  1945. //print('XcfgRow '+config.formConfig.generateForm[queryName]);
  1946. //
  1947. // //check if all required datasets were at least saved
  1948. checkGenerationFields(queryName);
  1949. }
  1950. function checkGenerationFields(queryName){
  1951. let fName='[checkGenerationFields]';
  1952. let genForm=config.formConfig.generateForm[queryName];
  1953. let genCfg=config.formConfig.generateConfig[queryName];
  1954. let mailRecipient=genCfg.emailRecipient;
  1955. //list of queries that are part of Registration form
  1956. print(fName);
  1957. print(fName+' setRecipient: '+mailRecipient);
  1958. let formId=genForm.Key;
  1959. print(fName+" Checking form w/id "+formId);
  1960. let selectGenerationRows=selectFormSetupRows(formId);
  1961. //registration rows
  1962. for (let i=0;i<selectGenerationRows.length;i++){
  1963. let row=selectGenerationRows[i];
  1964. let queryId=row.queryName;
  1965. let fQueryName=config.formConfig.queryMap[queryId];
  1966. if (fQueryName==queryName) continue;
  1967. let fQuery=config.formConfig.dataQueries[fQueryName];
  1968. print('Checking '+fQueryName+' nrows: '+fQuery.rows.length);
  1969. if (fQuery.rows.length==0){
  1970. generateError(queryName,fQueryName);
  1971. return;
  1972. }
  1973. }
  1974. generateMessage(queryName,'Vailidation OK');
  1975. print('callback: set recipient: '+mailRecipient);
  1976. let cb=function(){prepareForm(queryName,formId,mailRecipient);};
  1977. generateListEntry(formId,queryName,cb);
  1978. }
  1979. function prepareForm(queryName,formId,mailRecipient){
  1980. let fName="[prepareForm]";
  1981. print(fName+' recipient '+mailRecipient);
  1982. //look for existing registration entry
  1983. let action=function(data){generateForm(data,queryName,mailRecipient);};
  1984. let formFilter=LABKEY.Filter.create('Form',formId);
  1985. let parentCrfFilter=LABKEY.Filter.create('parentCrf',getCRFref());
  1986. let filters=[formFilter,parentCrfFilter];
  1987. cvSelectRows('lists','crfEntry',filters,action,getContainer('data'));
  1988. }
  1989. function generateError(queryName,fQueryName){
  1990. let elName=queryName+'GenerateButton'+'_reportField';
  1991. let el=config.document.getElementById(elName);
  1992. el.innerText='Error: '+fQueryName+' was not set';
  1993. el.style.color='red';
  1994. }
  1995. function generateMessage(queryName,msg){
  1996. let elName=queryName+'GenerateButton'+'_reportField';
  1997. let el=config.document.getElementById(elName);
  1998. el.innerText=msg;
  1999. el.style.color='green';
  2000. }
  2001. function generateForm(data,queryName,mailRecipient){
  2002. let fName='[generateForm]';
  2003. print(fName+' recipient: '+mailRecipient);
  2004. //
  2005. const nData=data.rows.length;
  2006. print(fName+' Registration: '+nData+' rows');
  2007. let formRow=config.formConfig.generateForm[queryName];
  2008. let formCfg=config.formConfig.generateConfig[queryName];
  2009. //we have to generate masterQuery with parentCrf and crfRef
  2010. //and crfEntry with new entryId and parentCrf equal to crfRef
  2011. if (nData>0) {
  2012. generateMessage(queryName,'Registration already generated.');
  2013. return;
  2014. }
  2015. let formId=formRow.Key;
  2016. let formName=formRow.formName;
  2017. let crfBase=config.formConfig.crfEntry;
  2018. let crfEntry=new Object();
  2019. //add new reference
  2020. crfEntry.entryId=Date.now();
  2021. crfEntry.parentCrf=getCRFref();
  2022. crfEntry["Date"]=new Date();
  2023. crfEntry["View"]="[VIEW]";
  2024. crfEntry.formStatus=1;//In progress
  2025. //checks for both field presence (if not in query, undefined) and field value (if not set, null)
  2026. print(fName+' setup status: '+formCfg.formStatus);
  2027. if (formCfg.formStatus){
  2028. crfEntry.formStatus=formCfg.formStatus;
  2029. }
  2030. //get local Id
  2031. let pM=getParticipantManagerObject(config);
  2032. crfEntry[pM.getCrfEntryFieldName()]=pM.getParticipantIdFromCrfEntry();
  2033. // //set other variables
  2034. //requires studyData as part of formConfig
  2035. // let studyData=config.formConfig.studyData;
  2036. print('Adding study: '+crfBase.EudraCTNumber);
  2037. crfEntry.EudraCTNumber=crfBase.EudraCTNumber;
  2038. crfEntry.StudyCoordinator=crfBase.StudyCoordinator;
  2039. crfEntry.StudySponsor=crfBase.StudySponsor;
  2040. crfEntry.RegulatoryNumber=crfBase.RegulatoryNumber;
  2041. //
  2042. // //find sponsor for site
  2043. let site=crfBase.Site;
  2044. let crfSponsors=config.formConfig.crfSponsors;
  2045. let users=config.formConfig.userRows;
  2046. for (let i=0;i<crfSponsors.length;i++){
  2047. //print('Checking for site '+crfSponsors[i].Site);
  2048. if (crfSponsors[i].Site!=site) continue;
  2049. config.formConfig.sponsorId=crfSponsors[i].User;
  2050. //print('Setting id '+config.formConfig.sponsorId);
  2051. //finds first
  2052. break;
  2053. }
  2054. for (let j=0;j<users.length;j++){
  2055. if (config.formConfig.sponsorId!=users[j].UserId) continue;
  2056. config.formConfig.sponsor=users[j];
  2057. //finds first (should be unique)
  2058. break;
  2059. }
  2060. print('Selecting '+config.formConfig.sponsor.DisplayName+' as sponsor');
  2061. //different user than the original form...
  2062. //should be set to the study sponsor
  2063. crfEntry.UserId=config.formConfig.sponsor.UserId;
  2064. crfEntry.Site=site;
  2065. // //set formId to one found through registration search
  2066. crfEntry.Form=formId;
  2067. ////
  2068. let crfStatus=createCrfStatus(crfEntry);
  2069. crfStatus.operator=config.formConfig.operator;
  2070. crfStatus.action='generateForm';
  2071. let cb=function(data){sendEmail(data,mailRecipient,doNothing,formName+' generated');}
  2072. let pass=function(data){cvInsertRows('lists','crfStatus',[crfStatus],cb,getContainer('data'));};
  2073. cvInsertRows('lists','crfEntry',[crfEntry],pass,getContainer('data'));
  2074. }
  2075. //
  2076. function generateListEntry(formId,queryName,cb){
  2077. //check if registration was already generated
  2078. let formRows=config.formConfig.formRows;
  2079. let qForm=undefined;
  2080. for (let i=0;i<formRows.length;i++){
  2081. if (formRows[i].Key!=formId) continue;
  2082. qForm=formRows[i];
  2083. }
  2084. let nData=config.formConfig.dataQueries[queryName].rows.length;
  2085. if (nData>0) return;
  2086. //create new list entry
  2087. let pM=getParticipantManagerObject(config);
  2088. let e2=new Object();
  2089. e2.crfRef=getCRFref();
  2090. e2.registrationStatus=0;
  2091. e2.submissionDate=new Date();
  2092. e2[pM.getCrfEntryFieldName()]=pM.getParticipantIdFromCrfEntry();
  2093. print('set values');
  2094. cvInsertRows('lists',queryName,[e2],cb,getContainer('data'));
  2095. }
  2096. // ******************** end form generator (Registration) ********************
  2097. //jump to populate table/generate review, etc defined at the begining of the file
  2098. function setContainer(label,container){
  2099. if (!(config.formConfig.hasOwnProperty('container'))){
  2100. config.formConfig.container=new Array();
  2101. }
  2102. config.formConfig.container[label]=container;
  2103. }
  2104. function getContainer(label){
  2105. return config.formConfig.container[label];
  2106. }
  2107. //entry point from generateMasterForm
  2108. function setFormConfig(){
  2109. //add object to store form related data
  2110. config.formConfig=new Object();
  2111. config.formConfig.softwareVersion='T.15.65';
  2112. let debug=true;
  2113. if (debug)
  2114. print("generateMasterForm1");
  2115. //set containers for data and configuration
  2116. //TODO: set this from a query
  2117. //
  2118. setContainer('data',LABKEY.ActionURL.getContainer());
  2119. setContainer('config',LABKEY.ActionURL.getContainer());
  2120. setContainer('CRF',LABKEY.ActionURL.getContainer());
  2121. //this is local data
  2122. cvSelectRows('lists','crfSettings',[],afterSettings,getContainer('CRF'));
  2123. //store form related data to this object
  2124. }
  2125. function convertToDictionary(rows){
  2126. let x=new Array();
  2127. for (let i=0;i<rows.length;i++){
  2128. let n=rows[i]['name'];
  2129. let v=rows[i]['value'];
  2130. x[n]=v;
  2131. }
  2132. return x;
  2133. }
  2134. function convertToAssociatedArray(rows,fieldName="name"){
  2135. let fName="[convertToAssociatedArray]";
  2136. let x=new Object();
  2137. for (let i=0;i<rows.length;i++){
  2138. let n=rows[i][fieldName];
  2139. x[n]=rows[i];
  2140. }
  2141. return x;
  2142. }
  2143. function afterSettings(data){
  2144. config.formConfig.settings=convertToDictionary(data.rows);
  2145. let st=config.formConfig.settings;
  2146. print('afterSettings');
  2147. for (let k in st){
  2148. print('\t'+k+'='+st[k]);
  2149. }
  2150. //if ('dataContainer' in st){
  2151. // setContainer('data',st['dataContainer']);
  2152. //}
  2153. let vname='configContainer';
  2154. if (vname in st){
  2155. setContainer('config',st[vname]);
  2156. }
  2157. print('Config: '+getContainer('config'));
  2158. print('Data: '+getContainer('data'));
  2159. //use first-> we must first establish link to the rigth crf entry
  2160. let filters=[LABKEY.Filter.create('entryId',getCRFrefFirst())];
  2161. cvSelectRows('lists','crfEntry',filters,afterCRFEntry,getContainer('data'));
  2162. }
  2163. function afterCRFEntry(data){
  2164. config.formConfig.crfEntry=data.rows[0];
  2165. print("Setting crfEntry (x) to "+config.formConfig.crfEntry["entryId"]);
  2166. //for empty records or those with parentCrf not set, parentCrf comes up as null
  2167. //nevertheless, with two equal signs, check against undefined also works
  2168. print('parentCrf set to '+config.formConfig.crfEntry.parentCrf);
  2169. collectData();
  2170. }
  2171. function collectData(){
  2172. let targetObject=config.formConfig;
  2173. targetObject.print=print;
  2174. targetObject.getContainer=getContainer;
  2175. let queryArray=new Array();
  2176. //k
  2177. //site
  2178. queryArray.push(makeQuery(targetObject,'config','site','siteData',[]));
  2179. //users
  2180. queryArray.push(makeQuery(targetObject,'CRF','users','userData',[]));
  2181. queryArray[queryArray.length-1].schemaName='core';
  2182. //crfEditors
  2183. queryArray.push(makeQuery(targetObject,'config','crfEditors','crfEditorsData',[]));
  2184. //crfMonitors
  2185. queryArray.push(makeQuery(targetObject,'config','crfMonitors','crfMonitorsData',[]));
  2186. //crfSponsors
  2187. queryArray.push(makeQuery(targetObject,'config','crfSponsors','crfSponsorsData',[]));
  2188. //study static data
  2189. queryArray.push(
  2190. makeQuery(targetObject,'data','crfStaticVariables','crfStaticVariables',[]));
  2191. queryArray.push(makeQuery(targetObject,'data','specialFields','specialFieldsQuery',[]));
  2192. //study
  2193. queryArray.push(makeQuery(targetObject,'data','Study','studyDataAll1',[]));
  2194. let e=queryArray[queryArray.length-1];
  2195. //overload schema name
  2196. e.schemaName='study';
  2197. //make sure variables not part of default view are loaded
  2198. //here we should already have read crfStaticVariables table
  2199. e.columns="SubjectColumnName,EudraCTNumber,StudySponsor";
  2200. e.columns+=",StudyCoordinator,RegulatoryNumber";
  2201. //formStatus
  2202. let varLabel='sourceFormStatus';
  2203. let formStatus=config.formConfig.crfEntry['FormStatus'];
  2204. let formFilter=LABKEY.Filter.create('Key',formStatus);
  2205. queryArray.push(
  2206. makeQuery(targetObject,'config','FormStatus','formStatusData',[formFilter]));
  2207. //crfButtons
  2208. let statusFilter=LABKEY.Filter.create(varLabel,formStatus);
  2209. queryArray.push(
  2210. makeQuery(targetObject,'config','crfButtons','crfButtons',[statusFilter]));
  2211. //Forms
  2212. queryArray.push(makeQuery(targetObject,'config','Forms','formData',[]));
  2213. //FormSetup
  2214. queryArray.push(makeQuery(targetObject,'config','FormSetup','formSetup',[]));
  2215. //generateConfig
  2216. queryArray.push(
  2217. makeQuery(targetObject,'config','generateConfig','generateConfigData',[]));
  2218. //inputLists
  2219. queryArray.push(
  2220. makeQuery(targetObject,'config','inputLists','inputLists',[]));
  2221. //parentCrf
  2222. let parentCrf=config.formConfig.crfEntry['parentCrf'];
  2223. if (parentCrf!=undefined){
  2224. let crfFilter=LABKEY.Filter.create('entryId',parentCrf);
  2225. queryArray.push(makeQuery(targetObject,'data','crfEntry','parentCrfData',[crfFilter]));
  2226. }
  2227. print('running getDataFromQueries');
  2228. getDataFromQueries(queryArray,addStudyData);
  2229. }
  2230. function addStudyData(){
  2231. let fName='addStudyData';
  2232. //convert specialFields to array
  2233. let q=config.formConfig["specialFieldsQuery"].rows;
  2234. config.formConfig.specialFields=convertToAssociatedArray(q,"fieldUID");
  2235. print(fName);
  2236. let queryArray=new Array();
  2237. let targetObject=config.formConfig;
  2238. targetObject.print=print;
  2239. targetObject.getContainer=getContainer;
  2240. //study
  2241. queryArray.push(makeQuery(targetObject,'data','Study','studyDataAll',[]));
  2242. //queryArray.push(makeQuery('data','Study','studyDataAll',[]));
  2243. let e=queryArray[queryArray.length-1];
  2244. //overload schema name
  2245. e.schemaName='study';
  2246. //make sure variables not part of default view are loaded
  2247. //here we should already have read crfStaticVariables table
  2248. let staticVarRows=config.formConfig['crfStaticVariables'].rows;
  2249. let columnModel=""
  2250. for (let i=0;i<staticVarRows.length;i++){
  2251. if (i>0) columnModel+=',';
  2252. columnModel+=staticVarRows[i]['staticVariable'];
  2253. }
  2254. e.columns=columnModel;
  2255. //also collect ids already in study
  2256. //registrationQuery should be a dataset
  2257. //since monitors can review late, it might be profitable to use lists
  2258. //rather than study
  2259. let regQueryPars=parseVariables(config.formConfig.settings['registrationQuery']);
  2260. let regQuery=regQueryPars['query'];
  2261. let regSchema='study';
  2262. if ('schema' in regQueryPars){
  2263. regSchema=regQueryPars['schema'];
  2264. }
  2265. queryArray.push(makeQuery(targetObject,'data',regQuery,'registrationData',[]));
  2266. queryArray[queryArray.length-1].schemaName=regSchema;
  2267. getDataFromQueries(queryArray,fcontinue);
  2268. }
  2269. function selectFormSetupRows(formId){
  2270. let formSetupRows=new Array();
  2271. let allRows=config.formConfig.formSetup.rows;
  2272. for (let i=0;i<allRows.length;i++){
  2273. let formEntry=allRows[i];
  2274. if (formEntry.formName==formId)
  2275. formSetupRows.push(formEntry);
  2276. }
  2277. return formSetupRows;
  2278. }
  2279. function fcontinue(){
  2280. //debug
  2281. let fName='[fcontinue]';
  2282. let varRows=config.formConfig['crfStaticVariables'].rows;
  2283. let studyVars=config.formConfig['studyDataAll'].rows[0];
  2284. for (let i=0;i<varRows.length;i++){
  2285. let vName=varRows[i].staticVariable;
  2286. print(fName+' '+vName+': '+studyVars[vName]);
  2287. }
  2288. //parse site
  2289. config.formConfig.siteRows=config.formConfig.siteData.rows;
  2290. let sRows=config.formConfig.siteRows;
  2291. for (let i=0;i<sRows.length;i++){
  2292. let siteId=sRows[i].siteNumber;
  2293. print('site '+siteId);
  2294. if (siteId==config.formConfig.crfEntry.Site){
  2295. config.formConfig.currentSite=sRows[i];
  2296. break;
  2297. }
  2298. }
  2299. //config.formConfig.site=data.rows[0];
  2300. print("Setting site name to "+config.formConfig.currentSite.siteName);
  2301. //study
  2302. config.formConfig.studyData=config.formConfig.studyDataAll.rows[0];
  2303. print("XSetting participantField to "+
  2304. config.formConfig.studyData["SubjectColumnName"]);
  2305. config.formConfig.crfEditors=config.formConfig.crfEditorsData.rows;
  2306. config.formConfig.crfMonitors=config.formConfig.crfMonitorsData.rows;
  2307. config.formConfig.crfSponsors=config.formConfig.crfSponsorsData.rows;
  2308. config.formConfig.userRows=config.formConfig.userData.rows;
  2309. let uRows=config.formConfig.userRows;
  2310. for (let i=0;i<uRows.length;i++){
  2311. let userId=uRows[i].UserId;
  2312. if (userId==config.formConfig.crfEntry.UserId){
  2313. config.formConfig.user=uRows[i];
  2314. break;
  2315. }
  2316. }
  2317. //config.formConfig.user=data.rows[0];
  2318. print("Setting user to "+config.formConfig.user["DisplayName"]);
  2319. let fsRows=config.formConfig.formStatusData.rows;
  2320. config.formConfig.formStatus=fsRows[0].formStatus;
  2321. config.formConfig.operator=config.role;
  2322. //config.formConfig.operator=fsRows[0].operator;
  2323. print('Setting operator to: '+config.formConfig.operator);
  2324. config.formConfig.formRows=config.formConfig.formData.rows;
  2325. //point formId to point to form set in crfEntry
  2326. config.formConfig.formId=config.formConfig.crfEntry['Form'];
  2327. //old setting, set from URL in visit.html
  2328. let formId=config.formId;
  2329. //new setting, set from crfEntry
  2330. formId=config.formConfig.formId;
  2331. let formRows=config.formConfig.formRows;
  2332. //filter out the current form
  2333. for (let i=0;i<formRows.length;i++){
  2334. if (formRows[i].Key==formId){
  2335. config.formConfig.form=formRows[i];
  2336. break;
  2337. }
  2338. }
  2339. config.formConfig.formSetupRows=selectFormSetupRows(formId);
  2340. print("Number of datasets for form ["+formId+"]: "+
  2341. config.formConfig.formSetupRows.length);
  2342. let fields=config.formConfig.formSetup.metaData.fields;
  2343. //get the lookup for queryName column
  2344. let formQueryName='queryName';
  2345. let field="NONE";
  2346. for (f in fields){
  2347. if (fields[f]['name']!=formQueryName) continue;
  2348. field=fields[f];
  2349. break;
  2350. }
  2351. let lookup=field.lookup;
  2352. print("Getting dataset names from "+lookup.queryName);
  2353. //inputLists should be in configuration container
  2354. cvSelectRows(lookup.schemaName,lookup.queryName,[],afterFormDatasets,getContainer('config'));
  2355. }
  2356. function afterFormDatasets(data){
  2357. print('afterFormDatasets: '+data.rows.length);
  2358. config.formConfig.formDatasets=data;//inputLists
  2359. config.formConfig.fields=new Object();
  2360. config.formConfig.queryMap=new Object();
  2361. config.formConfig.additionalData=new Object();
  2362. let rows=config.formConfig.formSetupRows;
  2363. //should skip report only rows
  2364. for (let i=0;i<rows.length;i++){
  2365. let entry=rows[i];
  2366. let reviewField=(entry['showFlag']=='REVIEW');
  2367. //is the operator set yet?
  2368. let accessMode=config.formConfig.operator+'Mode';
  2369. let skipField=(entry[accessMode]=="NONE");
  2370. let queryId=entry['queryName'];
  2371. let lookupRows=config.formConfig.formDatasets.rows;
  2372. print('QueryID['+i+']='+queryId);
  2373. let dentry;
  2374. for (let j=0;j<lookupRows.length;j++){
  2375. if (queryId!=lookupRows[j]['Key']) continue;
  2376. dentry=lookupRows[j];
  2377. break;
  2378. }
  2379. let qName=dentry['queryName'];
  2380. //update list of dataset formConfig is observing (fields/queryMap)
  2381. while (1){
  2382. //review contains no data
  2383. if (reviewField) break;
  2384. if (skipField) break;
  2385. //already in fields
  2386. if (qName in config.formConfig.fields) break;
  2387. config.formConfig.fields[qName]=new Object();
  2388. break;
  2389. }
  2390. while(1){
  2391. //already done
  2392. if (queryId in config.formConfig.queryMap) break;
  2393. config.formConfig.queryMap[queryId]=qName;
  2394. break;
  2395. }
  2396. if (reviewField) continue;
  2397. if (skipField) continue;
  2398. //only do this for real lists
  2399. let field=config.formConfig.fields[qName];
  2400. field.title=entry['title'];
  2401. field.queryId=queryId;
  2402. }
  2403. print("List of datasets in form : ");
  2404. for (f in config.formConfig.fields){
  2405. let field=config.formConfig.fields[f];
  2406. print("\t"+f+" ID: "+field.queryId+' title '+field.title);
  2407. }
  2408. afterConfig();
  2409. }
  2410. //>>>>>>>>>>>>>>>>>new>>>>>>>>>>>>
  2411. function setDataLayout(cb){
  2412. let rowsSetup=config.formConfig.formSetupRows;
  2413. config.formConfig.dataQueries=new Object();
  2414. let dS=config.formConfig.dataQueries;//reference only
  2415. let qMap=config.formConfig.queryMap;
  2416. config.formConfig.lookup=new Object();
  2417. for (let i=0;i<rowsSetup.length;i++){
  2418. let entry=rowsSetup[i];
  2419. //skip review rows
  2420. if (entry['showFlag']=='REVIEW')
  2421. continue;
  2422. let queryId=entry['queryName'];
  2423. let queryName=qMap[entry['queryName']];
  2424. dS[queryName]=new Object();
  2425. dS[queryName].title=entry['title'];
  2426. if (entry['showQuery']!="NONE"){
  2427. let sqName=entry['showQuery'];
  2428. dS[sqName]=new Object();
  2429. dS[sqName].title=findTitle(sqName);
  2430. }
  2431. }
  2432. //always add reviews
  2433. //
  2434. config.formConfig.dataQueries['reviewComments']=new Object();
  2435. //perhaps we will need queryId, but this is stuff for later
  2436. for (q in config.formConfig.dataQueries){
  2437. //callback will be a watchdog and will complete only
  2438. //when all data will be gathered
  2439. let dq=config.formConfig.dataQueries[q];
  2440. dq.collectingLayout="INITIALIZED";
  2441. let foo=function(data){afterDatasets(data,cb);}
  2442. cvSelectRows('lists',q,[],foo,getContainer('data'));
  2443. }
  2444. }
  2445. function findTitle(queryName){
  2446. //find by name from formDatasets
  2447. //and set associated title as title
  2448. let rows=config.formConfig.formDatasets.rows;
  2449. for (let i=0;i<rows.length;i++){
  2450. let entry=rows[i];
  2451. if (entry['queryName']!=queryName) continue;
  2452. return entry['title'];
  2453. }
  2454. return "NONE";
  2455. }
  2456. //this happens after the for loop, so all dataQueries objects are set
  2457. function afterDatasets(data,cb){
  2458. let fName='[afterDatasets]';
  2459. let qobject=config.formConfig.dataQueries[data.queryName];
  2460. print(fName+" inspecting layout for "+data.queryName+" "+qobject);
  2461. qobject.fields=data.metaData.fields;
  2462. qobject.collectingLayout="STARTED";
  2463. //qobject.started="TRUE";
  2464. qobject.lookup=new Object();//keep track of objects
  2465. let i=0;
  2466. for (let f in qobject.fields){
  2467. //anything else is simple but lookup
  2468. let field=qobject.fields[f];
  2469. if (!("lookup" in field)) continue;
  2470. qobject.lookup[f]="PENDING";
  2471. print(fName+" adding pending lookup for field "+f);
  2472. if (field.lookup.queryName in config.formConfig.lookup){
  2473. qobject.lookup[f]="DONE";
  2474. continue;
  2475. }
  2476. print(fName+" setting up query for field "+f);
  2477. config.formConfig.lookup[field.lookup.queryName]=new Object();
  2478. let lObject=config.formConfig.lookup[field.lookup.queryName];
  2479. lObject.keyColumn=field.lookup.keyColumn;
  2480. lObject.displayColumn=field.lookup.displayColumn;
  2481. let columns=field.lookup.keyColumn+","+field.lookup.displayColumn;
  2482. let action=function(data){addLookup(data,qobject,f,cb);};
  2483. let container=field.lookup.containerPath;
  2484. print(fName+" sending query: ["+
  2485. field.lookup.queryName+"] "+
  2486. field.lookup.keyColumn+'/'+
  2487. field.lookup.displayColumn);
  2488. cvSelectRows(field.lookup.schemaName,field.lookup.queryName,[],action,container,null,columns);
  2489. i+=1;
  2490. }
  2491. if (i==0){
  2492. print(fName+" no lookups for "+data.queryName);
  2493. qobject.collectingLayout="FINISHED";
  2494. }
  2495. //check if done (both here and in lookup
  2496. //this only passes if no lookups are anywhere in the dataset assembly
  2497. if (!dataLayoutSet()) return;
  2498. cb();
  2499. }
  2500. function addLookup(data,qobject,f,cb){
  2501. let fName="[addLookup]";
  2502. print(fName+" "+data.queryName+' '+qobject+' '+f);
  2503. let lObject=config.formConfig.lookup[data.queryName];
  2504. lObject.LUT=new Array();//key to value
  2505. lObject.ValToKey=new Array();//value to key
  2506. let key=lObject.keyColumn;
  2507. let val=lObject.displayColumn;
  2508. for (let i=0;i<data.rows.length;i++){
  2509. lObject.LUT[data.rows[i][key]]=data.rows[i][val];
  2510. lObject.ValToKey[data.rows[i][val]]=data.rows[i][key];
  2511. }
  2512. qobject.lookup[f]="DONE";
  2513. if (!dataLayoutSet()) return;
  2514. cb();
  2515. }
  2516. function dataLayoutSet(){
  2517. let fName="[dataLayoutSet]";
  2518. print(fName+" checking layout completeness");
  2519. let dq=config.formConfig.dataQueries;
  2520. for (f in dq){
  2521. print(fName+" ["+f+"]: "+dq[f].collectingLayout);
  2522. if (dq[f].collectingLayout=="INITIALIZED")
  2523. return 0;
  2524. if (dq[f].collectingLayout=="FINISHED")
  2525. continue; //OK
  2526. let qobject=dq[f];
  2527. for (q in qobject.lookup){
  2528. if (qobject.lookup[q]=="DONE") {
  2529. print(fName+" ["+f+"/"+q+"]: DONE");
  2530. continue;//OK
  2531. }
  2532. print(fName+" ["+f+"/"+q+"]: "+qobject.lookup[q]);
  2533. return 0;
  2534. }
  2535. dq[f].collectingLayout="FINISHED";
  2536. }
  2537. print(fName+" success");
  2538. return 1;
  2539. }
  2540. function setData(cb){
  2541. fName='[setData]';
  2542. //print(fName+': cb '+cb);
  2543. let crfMatch=getCRFref();
  2544. let parentCrf=config.formConfig.crfEntry['parentCrf'];
  2545. if (parentCrf!=undefined) crfMatch=parentCrf;
  2546. print(fName+' form crf ['+getCRFref()+'] matching for crfRef='+crfMatch);
  2547. //collect data and execute callback cb for queries in cb.queryList
  2548. for (q in config.formConfig.dataQueries){
  2549. let fQuery=config.formConfig.dataQueries[q];
  2550. fQuery.collectingData="STARTED";
  2551. let filters=[LABKEY.Filter.create("crfRef",crfMatch)];
  2552. let action=function(data){assembleData(data,cb);};
  2553. cvSelectRows('lists',q,filters,action,getContainer('data'));
  2554. }
  2555. }
  2556. function assembleData(data,cb){
  2557. let fName='[assembleData/'+data.queryName+']';
  2558. let fQuery=config.formConfig.dataQueries[data.queryName];
  2559. fQuery.rows=data.rows;
  2560. fQuery.collectingData="FINISHED";
  2561. print(fName+': adding data');
  2562. for (q in config.formConfig.dataQueries){
  2563. let dq=config.formConfig.dataQueries[q];
  2564. //print("assembleData ["+q+"]: "+dq.collectingData);
  2565. if (dq.collectingData=="STARTED") return;
  2566. }
  2567. print(fName+': completing');
  2568. cb();
  2569. }
  2570. function uploadFile(inputElement,context){
  2571. //context should have ID and dirName attributes;
  2572. //path will be dirName/ID/fieldName_ID.suf
  2573. //where suf is identical to localPath content picked from
  2574. //inputElement
  2575. print('uploadFile: '+inputElement.value+'/');
  2576. if (inputElement.type=="text") return;
  2577. print('uploadFile: '+inputElement.files+'/');
  2578. print('uploadFile: '+inputElement.files.length+'/');
  2579. if (inputElement.files.length>0){
  2580. let file=inputElement.files[0];
  2581. print('uploadFile: '+inputElement.value+'/'+file.size);
  2582. }
  2583. let url=LABKEY.ActionURL.getBaseURL();
  2584. url+='_webdav';
  2585. url+=LABKEY.ActionURL.getContainer();
  2586. url+='/@files';
  2587. url+='/'+context['dirName'];
  2588. print('uploadFile url: '+url);
  2589. let uploadConfig=new Object();
  2590. uploadConfig.inputElement=inputElement;
  2591. uploadConfig.context=context;
  2592. uploadConfig.url=url;
  2593. uploadConfig.success=afterBaseDir;
  2594. uploadConfig.failure=tryMakeDir;
  2595. webdavCheck(uploadConfig);
  2596. }
  2597. function afterBaseDir(cfg){
  2598. print('afterBaseDir');
  2599. cfg.url+='/'+cfg.context['ID'];
  2600. cfg.success=afterIDDir;
  2601. cfg.failure=tryMakeDir;
  2602. webdavCheck(cfg);
  2603. }
  2604. function afterIDDir(cfg){
  2605. print('afterIDDir');
  2606. if (cfg.inputElement.files.length==0){
  2607. print('No files found');
  2608. return;
  2609. }
  2610. let file=cfg.inputElement.files[0];
  2611. print('Uploading '+file.name);
  2612. let suf=file.name.split('.').pop();
  2613. cfg.url+='/'+cfg.context['ID']+'.'+suf;
  2614. cfg.success=afterUpload;
  2615. cfg.failure=onFailure;
  2616. cfg.data=file;
  2617. webdavPut(cfg);
  2618. }
  2619. function afterUpload(cfg){
  2620. print('afterUpload');
  2621. }
  2622. function tryMakeDir(cfg){
  2623. print('tryMakeDir '+cfg.url);
  2624. cfg.failure=onFailure;
  2625. webdavMakeDir(cfg);
  2626. }
  2627. function request(cfg,verb,data){
  2628. print('request['+verb+'] '+cfg.url);
  2629. let connRequest=new XMLHttpRequest();
  2630. connRequest.addEventListener("loadend",
  2631. function(){checkResponse(connRequest,cfg);});
  2632. connRequest.open(verb, cfg.url);
  2633. connRequest.send(data);
  2634. //print('request['+verb+'] sent');
  2635. }
  2636. function checkResponse(xrq,cfg){
  2637. //print('checkResponse: readyState '+xrq.readyState);
  2638. //print('checkResponse: status '+xrq.status);
  2639. if (xrq.status<400) {
  2640. //client errors 400-499
  2641. //server errors 500-599
  2642. cfg.success(cfg);
  2643. return;
  2644. }
  2645. cfg.status=xrq.status;
  2646. cfg.failure(cfg);
  2647. }
  2648. function webdavMakeDir(cfg){ request(cfg,'MKCOL',null);}
  2649. function webdavCheck(cfg) { request(cfg,'GET',null);}
  2650. function webdavPut(cfg) { request(cfg,'PUT',cfg.data);}
  2651. function onFailure(cfg){
  2652. print('request failed with status='+cfg.status);
  2653. }