otsdaq_utilities  v2_04_02
SystemStatus.js
1 
3 var _allAppsArray = new Array();
4 var _allContextNames = new Array();
5 var _allClassNames = new Array();
6 var _arrayOnDisplayTable = new Array(); // has the array values currently displayed on the table
7 var intersectionArray = new Array();
8 
9 //functions:
10  // init()
11  // ========= server calls ====================
12  // getContextNames()
13  // getAppsArray()
14  // updateAppsArray()
15  // ========== Display functions ==============
16  // displayTable() -> Inside this function, you can change the color of the cells depending on the state of the app
17  // ========= filtering functions =============
18  // createFilterList()
19  // collapsibleList()
20  // selectAll()
21  // filterUsingCheckBox()
22  // filter()
23  // getFilteredArray()
24  // isEquivalent()
25 
26 
29 
30 //init called once body has loaded
31 function init() {
32  Debug.log("Calibrations init");
33 
34  collapsibleList();
35 
36  // Use promises to make code execute in an intutive manner
37  // 1. Get context names into an array...then
38  // 2. Get app names into an array ....then
39  // 3. display the table of array names and call filtering functions
40  // 4. repeatedly update the _allAppsArray values
41  getContextNames().
42  then(getAppsArray).
43  then(function(result){
44  // display table of apps
45  displayTable(result);
46 
47  // populate filterDiv
48  createFilterList();
49 
50  // if user clicks on list item instead, tick the checkbox and call filter function
51  filterByClickingOnItem();
52 
53  // update the _allAppsArray variable with repeated calls to server
54  // setTimeout(updateAppsArray, 4000);
55  setTimeout(function(){
56  updateAppsArray();
57  }, 4000);
58 
59 
60  });
61 
62 
63  return;
64 } // end of init()
65 
66 
67 // The function below gets the available context names from the server
68 function getContextNames(){
69 
70  return new Promise(function(resolve, reject){
71  //get context
72  DesktopContent.XMLHttpRequest("Request?RequestType=getContextMemberNames", "",
73  function (req)
74  {
75  var memberNames = req.responseXML.getElementsByTagName("ContextMember");
76  _allContextNames = new Array(); //reset
77 
78  for(var i=0;i<memberNames.length;++i)
79  {
80  _allContextNames.push(memberNames[i].getAttribute("value"));
81  }
82  // Debug.log(_allContextNames);
83  if(_allContextNames.length == 0)
84  {
85  Debug.log("Empty context member list found!",Debug.HIGH_PRIORITY);
86  reject("Empty context member list found!");
87  }
88 
89 
90  // return _allContextNames
91  resolve(_allContextNames);
92  }); //end request handler
93 
94  }); // end of Promise
95 
96 }// end of getContextNames()
97 
98 
99 // This function makes a call to the server and returns an array of objects
100 // each object contains the details of an application such as the id, name, status etc.
101 function getAppsArray(){
102 
103  return new Promise(function(resolve, reject){
104  DesktopContent.XMLHttpRequest("Request?RequestType=getAppStatus", "",
105  function (req)
106  {
107  var appNames, appUrls, appIds, appStatus, appTime, appClasses, appProgress, appContexts;
108 
109 
110  _allAppsArray = new Array();
111  _allClassNames = new Array();
112 
113  appNames = req.responseXML.getElementsByTagName("name");
114  appIds = req.responseXML.getElementsByTagName("id");
115  appStatus = req.responseXML.getElementsByTagName("status");
116  appTime = req.responseXML.getElementsByTagName("time");
117  appProgress = req.responseXML.getElementsByTagName("progress");
118  appClasses = req.responseXML.getElementsByTagName("class");
119  appUrls = req.responseXML.getElementsByTagName("url");
120  appContexts = req.responseXML.getElementsByTagName("context");
121 
122  var i;
123  for (i = 0; i< appNames.length; i++)
124  {
125  _allAppsArray.push({
126  "name" : appNames[i].getAttribute("value"),
127  "id" : appIds[i].getAttribute("value"),
128  "status" : appStatus[i].getAttribute("value"),
129  "time" : appTime[i].getAttribute("value"),
130  "progress" : appProgress[i].getAttribute("value"),
131  "class" : appClasses[i].getAttribute("value"),
132  "url" : appUrls[i].getAttribute("value"),
133  "context" : appContexts[i].getAttribute("value")
134  });
135 
136  // populate the array of classes
137  _allClassNames.push(appClasses[i].getAttribute("value"));
138  }
139 
140  if(_allAppsArray.length == 0)
141  {
142  Debug.log("Empty apps array!",Debug.HIGH_PRIORITY);
143  reject("Empty Empty apps array!");
144  }
145 
146  //return _allAppsArray;
147  resolve(_allAppsArray);
148 
149  }, 0,0,0,true);// end of request handler
150  });// end of Promise
151 
152 }// end of getAppsArray()
153 
154 
155 
156 // this function updates the _allAppsArray by making repeated requests to the server
157 // at specific time intervals. The function is recursive and makes use of setTimeout()
158 // because setInterval() can overload the server if a request fails.
159 function updateAppsArray() {
160  {
161  getAppsArray();
162  // intersectionArray = setIntersection(_allAppsArray, _arrayOnDisplayTable); // should return updated array for display
163  _arrayOnDisplayTable = setIntersection(_allAppsArray, _arrayOnDisplayTable);
164  displayTable(_arrayOnDisplayTable);
165  }
166  setTimeout(updateAppsArray, 4000);
167 }; // end of updateAppsArray()
168 
169 
170 
171 // this function displays a table with the app array passed into it
172 function displayTable(appsArray){
173 
174  // clear the statusDiv
175  var statusDivElement = document.getElementById("statusDiv");
176  statusDivElement.innerHTML = "";
177 
178  //Create a HTML Table element.
179  var table = document.createElement("TABLE");
180  table.border = "1";
181 
182  //Get the count of columns.
183  var columnNames = ["Name", "App ID", "Status", "Time", "Progress", "Class", "Application Url", "Context"];
184  var columnCount = columnNames.length;
185 
186  //Add the header row.
187  var row = table.insertRow(-1);
188  for (var i = 0; i < columnCount; i++) {
189  var headerCell = document.createElement("TH");
190  headerCell.innerHTML = columnNames[i];
191  row.appendChild(headerCell);
192  }
193 
194  //Add the data rows.
195  for (var i = 0; i < appsArray.length; i++) {
196  row = table.insertRow(-1);
197  for (var key in appsArray[i]) {
198  var cell = row.insertCell(-1);
199  cell.innerHTML = appsArray[i][key];
200  if (key == "status")
201  {
202  switch(appsArray[i][key]) {
203  case "Initial":
204  cell.style.backgroundColor = "#77D0FF"// rgb(119, 208, 255); -> colors obtained from state machine
205  break;
206  case "Halted":
207  cell.style.backgroundColor = "#4AB597"; // rgb(74, 181, 151);
208  break;
209  case "Failed":
210  cell.style.backgroundColor = "red";
211  break;
212  default:
213  } // end of switch
214 
215  }// end of if statement
216  }
217  }// done with adding data rows
218 
219  // add table to statusDiv
220  statusDivElement.appendChild(table);
221 
222  // keep record of current array on display. This variable is later used to redisplay table after user does filtering
223  _arrayOnDisplayTable = appsArray;
224 
225  return 1;
226 
227 }// end of displayTable()
228 
229 
230 // this function creates list elements and checkboxes to
231 // be displayed in the filterDiv
232 function createFilterList() {
233  var contextUl = document.getElementById('contextUl');
234  var classUl = document.getElementById('classUl');
235 
236  renderFilterList(_allContextNames, contextUl, "contextName");
237  renderFilterList(_allClassNames, classUl, "className");
238 
239  function renderFilterList(elemArray, ulelem, cbName) {
240 
241  for (var i = 0; i < elemArray.length; i++)
242  {
243  var li = document.createElement('li'); // create a list element
244  var cb_input = document.createElement('input'); // create a checkbox
245  cb_input.setAttribute("type", "checkbox");
246  cb_input.setAttribute("class", cbName);
247  cb_input.checked = false; // set checkboxes to false
248  cb_input.setAttribute("value", elemArray[i]);
249 
250 
251  li.setAttribute('class','item');
252  li.appendChild(cb_input);
253  var textnode;
254 
255  if (cbName == "className")
256  {
257  textnode = document.createTextNode(elemArray[i].slice(5));// remove "ots::" in display text
258  }
259  else
260  {
261  textnode = document.createTextNode(elemArray[i]);
262  }
263 
264  li.appendChild(textnode);
265  ulelem.appendChild(li);
266 
267  }
268  }// end of renderFilterList()
269 
270 }// end of createFilterList()
271 
272 
273 // this function creates a collapsible menu in the filterDiv
274 // from the available context names, and class names
275 function collapsibleList(){
276 
277  var collapsible = document.getElementsByClassName("collapsible");
278 
279  for (var i = 0; i < collapsible.length; i++)
280  {
281  collapsible[i].addEventListener("click", function() {
282 
283  this.firstElementChild.style.visibility = "hidden"; // make help tooltip hidden
284 
285  this.classList.toggle("active");
286  var content = this.nextElementSibling;
287  if (content.style.display === "block") {
288  content.style.display = "none";
289  } else {
290  content.style.display = "block";
291  }
292  });
293 
294  }
295 }// end of collapsibleList()
296 
297 
298 function filterByClickingOnItem() {
299 
300  var listElements = document.getElementsByTagName("li");
301 
302  for (let i = 0; i < listElements.length; i++) {
303  listElements[i].addEventListener("click", function() {
304 
305  // tick the checkbox and call filter function
306  var listChildren = listElements[i].childNodes;
307  // console.log(listChildren);
308  for (let j = 0; j < listChildren.length; j++) {
309 
310  if(listChildren[j].className == "selectAll"){
311  if(listChildren[j].checked)
312  {
313  listChildren[j].checked = false;
314  }
315  else
316  {
317  listChildren[j].checked = true;
318  }
319 
320  checkAllBoxes(listChildren[j].checked);
321 
322  function checkAllBoxes(cbvalue){
323  var parentUl = listChildren[j].parentElement.parentElement;
324  var listSiblings = parentUl.childNodes;
325 
326  for (let k = 0; k < listSiblings.length; k++) {
327  if(listSiblings[k].nodeName == "LI"){
328  listSiblings[k].firstChild.checked = cbvalue;
329  }
330  }
331  filter();
332  }// end of checkAllBoxes()
333  return;
334  }
335 
336  if(listChildren[j].nodeName == "INPUT")
337  {
338  listChildren[j].checked = true;
339  }
340 
341 
342  } // end of for loop
343  filter();
344  });
345 
346  }
347 }// end of filterByClickingOnItem()
348 
349 
350 function filter() {
351 
352 
353  var filteredClass = getFilteredArray("className"); // filter by class
354  var filteredContext = getFilteredArray("contextName"); // filter by context
355 
356  // if filterByClass and filterByContext return empty arrays, display the full table
357  if (filteredClass.length == 0 && filteredContext.length == 0) {
358  displayTable(_allAppsArray);
359  return;
360  }
361 
362  // merge the two arrays
363 
364  // 1. get apps in filteredContext that are not in filteredClass
365  var notInFilteredClass = new Array();
366  var common;
367 
368  for (let i = 0; i < filteredContext.length; i++) {
369  common = false;
370 
371  for (let j = 0; j < filteredClass.length; j++) {
372  if (isEquivalent(filteredContext[i], filteredClass[j])) {
373  common = true;
374  continue;
375  }
376 
377  }
378  if (common == false) {
379  notInFilteredClass.push(filteredContext[i]);
380  }
381 
382  }
383 
384  // 2. concatenate the two arrays
385  var result = filteredClass.concat(notInFilteredClass);
386 
387  // display the table
388  displayTable(result);
389 } // end of filter()
390 
391 
392 function getFilteredArray(className){
393 
394  var filterobjects = document.getElementsByClassName(className);
395  var checkedItems = new Array();
396 
397  // loop through elements and find those that are checked
398  for(var i = 0; i < filterobjects.length; i++)
399  {
400  if (filterobjects[i].checked == true)
401  {
402  var val = filterobjects[i].getAttribute("value");
403  checkedItems.push(val);
404  }
405  }
406 
407  // loop through _allAppsArray and get apps that match checked values
408  var filtered = _allAppsArray.filter(function(app) {
409  // returns apps that have class/context values in checkedItems array
410  return checkedItems.includes(app.class) || checkedItems.includes(app.context); // if value is in checkedItems
411  });
412 
413  return filtered;
414 } // end of getFilteredArray()
415 
416 
417 // compares two objects by value to see if they are the same
418 function isEquivalent(a, b) {
419  // Create arrays of property names
420  var aProps = Object.getOwnPropertyNames(a);
421  var bProps = Object.getOwnPropertyNames(b);
422 
423  // If number of properties is different,
424  // objects are not equivalent
425  if (aProps.length != bProps.length) {
426  return false;
427  }
428 
429  for (var i = 0; i < aProps.length; i++) {
430  var propName = aProps[i];
431 
432  // If values of same property are not equal,
433  // objects are not equivalent
434  if (a[propName] !== b[propName]) {
435  return false;
436  }
437  }
438 
439  // If we made it this far, objects
440  // are considered equivalent
441  return true;
442 } // end of isEquivalent()
443 
444 
445 // generic function that can be used to get union/intersection of two arrays of objects
446 function setIntersection(list1, list2) {
447 
448  result = [];
449  for (let i = 0; i < list1.length; i++) {
450 
451  for(let j = 0; j < list2.length; j++){
452  if (list1[i].id == list2[j].id)
453  {
454  result.push(list1[i]);
455  break;
456  }
457  }// inner for loop
458 
459  }// outer for loop
460  return result;
461 } // end of setIntersection()