Proyecto en colaboración con OPASO

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /* Authors : Carlos C. Corrada-Bravo
  2. David J. Ortiz-Rivera
  3. Organization : Centro de Desarrollo y Consultoria Computacional
  4. Project : OPASO Material Registry
  5. File : inventory.js
  6. Description : Generate inventory table */
  7. /* save inventory data globally */
  8. var editing,inventory,form,text,timeout,i,next;
  9. var sort_key = "material";
  10. /* fetch inventory */
  11. $(document).ready(function(){
  12. link_gen();
  13. fetch_inventory();
  14. });
  15. /* display_form() - animate form */
  16. function display_form(){
  17. $(".form-shader").addClass("fade-in");
  18. $(".edit-form").addClass("slide-down");
  19. }
  20. /* hide_form() - hide form */
  21. function hide_form(){
  22. $(".edit-form").removeClass("slide-down");
  23. setTimeout(function(){
  24. $(".form-shader").removeClass("fade-in");
  25. },250);
  26. }
  27. /* set_listeners() - listen for events */
  28. function set_listeners(){
  29. /* option queries */
  30. $(".action").click(function(){
  31. /* extract args */
  32. var option = $(this).attr("id");
  33. i = $(this).parent().parent().attr("id");
  34. /* handle by option */
  35. switch(option){
  36. case "edit": /* edit row, populate row */
  37. set_form();
  38. break;
  39. case "remove": /* delete row, confirm */
  40. set_confirm("Do you wish to delete entry from inventory?",option);
  41. break;
  42. default: /* undefined, display alert */
  43. set_alert("error","Invalid option")
  44. break;
  45. }
  46. });
  47. /* submit query */
  48. $("#yes").click(function(){
  49. hide_confirm();
  50. $.post("/scripts/opaso",{query: 8,lab_id: get_arg("lab_id"),data: JSON.stringify(inventory[i])},function(data){
  51. // console.log(data);
  52. /* extract response */
  53. let response = JSON.parse(data);
  54. let status = response["status"];
  55. /* handle by status */
  56. switch(status){
  57. case "expired": /* on expired, redirect to index */
  58. window.location.href = "/?error=session_expired";
  59. break;
  60. case "success": /* on success, generate table body */
  61. $(`#${i}`).remove();
  62. next -= 1;
  63. $(".table-total").text(`Total: ${next}`);
  64. default: /* on success/error, display message */
  65. set_alert(status,response["message"]);
  66. break;
  67. }
  68. });
  69. });
  70. /* cancel query */
  71. $("#no").click(hide_confirm);
  72. /* set listener for form submit button */
  73. $(".submit").click(function(){
  74. if(get_form()){
  75. /* submit query */
  76. hide_form();
  77. $.post("/scripts/opaso",{query: 6,lab_id: get_arg("lab_id"),mat_id: inventory[i]["material"]["mat_id"],man_id: inventory[i]["manufacturer"]["man_id"],uom: inventory[i]["uom"],capacity: inventory[i]["capacity"],data: JSON.stringify(form)},function(data){
  78. // console.log(data);
  79. /* extract response */
  80. let response = JSON.parse(data);
  81. let status = response["status"];
  82. /* handle by status */
  83. switch(status){
  84. case "expired": /* on expired, redirect to index */
  85. window.location.href = "/?error=session_expired";
  86. break;
  87. case "success": /* on success, update inventory */
  88. // console.log(inventory[i],form);
  89. for(var field in form){
  90. if(field === "mat_name"){
  91. inventory[i]["material"][field] = form[field];
  92. }
  93. else if(field === "man_name"){
  94. inventory[i]["manufacturer"][field] = form[field];
  95. }
  96. else{
  97. inventory[i][field] = form[field];
  98. }
  99. if(field === "sds"){
  100. $(`#${i}`).find(`td[value=${field}]`).find("span").attr("href",form[field]);
  101. }
  102. else{
  103. $(`#${i}`).find(`td[value=${field}]`).text(form[field]);
  104. }
  105. }
  106. // console.log(inventory[i]);
  107. default: /* on success/error, display message */
  108. set_alert(status,response["message"]);
  109. break;
  110. }
  111. });
  112. }
  113. /* invalid form, display warning */
  114. else{
  115. set_alert("error","All fields required");
  116. }
  117. });
  118. /* edit cell */
  119. $(".entry-cell").dblclick(function(){
  120. /* verify if user is editing */
  121. if(!editing){
  122. $(this).height($(this).height());
  123. $(this).css("padding","0px");
  124. if($(this).attr("value") === "sds"){
  125. text = $(this).find("span").attr("href");
  126. }
  127. else{
  128. text = $(this).text();
  129. }
  130. i = $(this).parent().attr("id");
  131. var textarea = element_gen("textarea",{class: "edit",text: text});
  132. $(this).html(textarea);
  133. editing = true;
  134. }
  135. });
  136. /* submit cell edit */
  137. $("body").click(function(event){
  138. var t = $(event.target).attr("class");
  139. if(editing && t !== "edit"){
  140. edit_field();
  141. }
  142. });
  143. /* submit cell edit */
  144. $(document).on("keypress",function(event){
  145. if(event.which == 13 && editing){
  146. event.preventDefault();
  147. edit_field();
  148. }
  149. });
  150. /* hide form */
  151. $(".close-form").click(function(e){
  152. if(e.target === e.currentTarget){
  153. hide_form();
  154. }
  155. });
  156. /* hide confirm alert */
  157. $(".hide-confirm").click(function(e){
  158. if(e.target === e.currentTarget){
  159. hide_confirm();
  160. }
  161. });
  162. }
  163. /* edit_field() - update material field */
  164. function edit_field(){
  165. /* extract text */
  166. var delta = $(".edit").val();
  167. var field = $(".edit").parent().attr("value");
  168. if(text != delta){
  169. // console.log(inventory,i,inventory[i]);
  170. let data = {mat_id: inventory[i]["material"]["mat_id"],man_id: inventory[i]["manufacturer"]["man_id"],capacity: inventory[i]["capacity"], uom: inventory[i]["uom"]};
  171. if(field === "capacity"){
  172. data["prev_capacity"] = text;
  173. data["new_capacity"] = delta;
  174. total = inventory[i]["total"];
  175. data["quantity"] = Math.ceil(total/delta);
  176. }
  177. else if(field === "total"){
  178. data["total"] = delta;
  179. data["quantity"] = Math.ceil(delta/data["capacity"]);
  180. }
  181. else if(field === "quantity"){
  182. data["quantity"] = delta;
  183. data["total"] = delta * data["capacity"];
  184. }
  185. else if(field === "uom"){
  186. data["prev_uom"] = text;
  187. data["new_uom"] = delta;
  188. }
  189. else{
  190. data[field] = delta;
  191. }
  192. /* update field */
  193. $.post("/scripts/opaso",{query: 5,lab_id: get_arg("lab_id"),data: JSON.stringify(data),field: field},function(data){
  194. // console.log(data);
  195. /* extract response */
  196. let response = JSON.parse(data);
  197. let status = response["status"];
  198. /* handle by status */
  199. switch(status){
  200. case "expired": /* on expired, redirect to index */
  201. window.location.href = "/?error=session_expired";
  202. break;
  203. case "success": /* on success, update entry */
  204. if(field === "mat_name"){
  205. inventory[i]["material"][field] = delta;
  206. }
  207. else if(field === "man_name"){
  208. inventory[i]["manufacturer"][field] = delta;
  209. }
  210. else if(field === "total"){
  211. inventory[i]["quantity"] = Math.ceil(delta/inventory[i]["capacity"]);
  212. $(`#${i}`).find("td[value=quantity]").text(inventory[i]["quantity"]);
  213. }
  214. else if(field === "capacity"){
  215. total = inventory[i]["total"];
  216. inventory[i]["quantity"] = Math.ceil(total/delta);
  217. $(`#${i}`).find("td[value=quantity]").text(inventory[i]["quantity"]);
  218. }
  219. else if(field === "quantity"){
  220. inventory[i]["total"] = delta * inventory[i]["capacity"];
  221. $(`#${i}`).find("td[value=total]").text(inventory[i]["total"]);
  222. }
  223. if(field === "sds"){
  224. var icon = element_gen("i",{class: "fas fa-link"});
  225. var link = element_gen("span",{class: "sds",href: decodeURI(delta),target: "_blank",rel: "noopener noreferrer",childs: {icon}});
  226. $(".edit").parent().html(link);
  227. }
  228. else{
  229. $(".edit").parent().html(delta);
  230. }
  231. if(field !== "mat_name" && field !== "man_name"){
  232. inventory[i][field] = delta;
  233. }
  234. $(".edit").parent().removeAttr("style");
  235. default: /* on error, display message */
  236. if(field === "sds"){
  237. var icon = element_gen("i",{class: "fas fa-link"});
  238. var link = element_gen("span",{class: "sds",href: decodeURI(text),target: "_blank",rel: "noopener noreferrer",childs: {icon}});
  239. $(".edit").parent().html(link);
  240. }
  241. else{
  242. $(".edit").parent().html(text);
  243. }
  244. /* reset styling */
  245. $(".edit").parent().removeAttr("style");
  246. set_alert(status,response["message"]);
  247. break;
  248. }
  249. });
  250. }
  251. else{
  252. if(field === "sds"){
  253. var icon = element_gen("i",{class: "fas fa-link"});
  254. var link = element_gen("span",{class: "sds",href: decodeURI(text),target: "_blank",rel: "noopener noreferrer",childs: {icon}});
  255. $(".edit").parent().html(link);
  256. }
  257. else{
  258. $(".edit").parent().html(text);
  259. $(".edit").parent().removeAttr("style");
  260. }
  261. }
  262. editing = false;
  263. }
  264. /* get_form(row: string) - get form data from row */
  265. function get_form(){
  266. form = {};
  267. var valid = true;
  268. $(".material-input").each(function(){
  269. var id = $(this).attr("id");
  270. // var s = `.${id}`;
  271. var field = $(this).attr("name");
  272. /* highlight */
  273. if(!is_valid($(this).val())){
  274. // $(s).show();
  275. valid = false;
  276. $(this).addClass("invalid");
  277. }
  278. /* unhighlight */
  279. else{
  280. // $(s).hide();
  281. $(this).removeClass("invalid");
  282. }
  283. form[field] = $(this).val();
  284. });
  285. return valid;
  286. }
  287. /* set_form() - populate form using inventory data */
  288. function set_form(){
  289. for(var field in inventory[i]){
  290. if(field === "material"){
  291. var s = "mat_name";
  292. var val = inventory[i][field][s];
  293. }
  294. else if(field === "manufacturer"){
  295. var s = "man_name";
  296. var val = inventory[i][field][s]
  297. }
  298. else{
  299. var s = field;
  300. var val = inventory[i][field];
  301. }
  302. $(`input[name=${s}]`).val(val);
  303. }
  304. display_form();
  305. }
  306. /* table_gen(inventory: dictionary) - generate table body */
  307. function table_gen(data){
  308. /* extract entries */
  309. for(var d in data){
  310. /* generate table row */
  311. let tr = element_gen("tr",{class: "entry-row",id: d});
  312. for(var field in data[d]){
  313. switch(field){
  314. case "material": /* material, extract id */
  315. var link = element_gen("a",{class: "mat-link",text: data[d][field]["mat_name"],href: `materials?mat_id=${data[d][field]["mat_id"]}`,target: "_blank",rel: "noopener noreferrer"});
  316. var attributes = {class: "entry-cell",value: "mat_name",mat_id: data[d][field]["mat_id"],childs: {link}};
  317. break;
  318. case "manufacturer": /* manufacturer, extract id */
  319. var attributes ={class: "entry-cell",value: "man_name",man_id: data[d][field]["man_id"],text: data[d][field]["man_name"]};
  320. break;
  321. case "sds": /* generate sds link */
  322. if(!data[d][field]){
  323. data[d][field] = "-";
  324. }
  325. var icon = element_gen("i",{class: "fas fa-link"});
  326. var link = element_gen("span",{class: "sds",href: decodeURI(data[d][field]),target: "_blank",rel: "noopener noreferrer",childs: {icon}});
  327. var attributes = {class: "entry-cell",value: field,childs: {link}};
  328. break;
  329. default: /* default */
  330. if(!data[d][field]){
  331. data[d][field] = "-";
  332. }
  333. var attributes = {class: "entry-cell",value: field,text: data[d][field]};
  334. break;
  335. }
  336. var td = element_gen("td",attributes);
  337. tr.append(td);
  338. }
  339. /* generate actions cell */
  340. let actions = {edit:{class: "t-icon material-icons",icon: "notes"},remove: {class: "t-icon material-icons",icon: "close"}};
  341. var td = element_gen("td",{class: "actions-cell"});
  342. /* generate actions */
  343. for(var action in actions){
  344. var icon = element_gen("i",{class: actions[action]["class"],text: actions[action]["icon"]});
  345. var button = element_gen("button",{class: "button action",id: action,value: d,title: action,childs: {icon}});
  346. td.append(button);
  347. }
  348. /* append */
  349. tr.append(td);
  350. $("tbody").append(tr);
  351. }
  352. /* display inventory */
  353. $(".processing").hide();
  354. setTimeout(function(){
  355. set_listeners();
  356. $(".main-wrapper").show();
  357. },250);
  358. }
  359. /* fetch_inventory() - fetch lab inventory */
  360. function fetch_inventory(){
  361. /* extract lab id */
  362. let lab_id = get_arg("lab_id");
  363. if(is_valid(lab_id)){
  364. $.post("/scripts/opaso",{query: 4,lab_id: lab_id},function(data){
  365. // console.log(data);
  366. /* extract response */
  367. response = JSON.parse(data);
  368. status = response["status"];
  369. /* handle by status */
  370. switch(status){
  371. case "success": /* on success, generate table */
  372. inventory = response["lab"]["inventory"];
  373. /* generate inventory table */
  374. table_gen(inventory);
  375. next = Object.keys(inventory).length;
  376. $(".table-total").text(`Total: ${next}`);
  377. break;
  378. case "expired": /* on expired, redirect */
  379. window.location.href = "/?error=session_expired";
  380. break;
  381. default: /* on error, display message */
  382. set_alert(status,response["message"]);
  383. break;
  384. }
  385. });
  386. }
  387. /* missing args */
  388. else{
  389. set_alert("error","One or more arguments missing");
  390. }
  391. }