monitor.js.in 5.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
/*jslint indent: 2 */
(function () {
  "use strict";

  var monitor_title = '{{ dumps(monitor_title)[5:-1] }}';

  function loadJson(url) {
    /*global XMLHttpRequest */
    return new Promise(function (resolve, reject) {
      var xhr = new XMLHttpRequest();
      xhr.onload = function (event) {
        var response = event.target;
        if (response.status < 400) {
          try {
            resolve(JSON.parse(response.responseText));
          } catch (e) {
            reject(e);
          }
        } else {
          reject(new Error("XHR: " + response.status + ": " + response.statusText));
        }
      };
      xhr.onerror = function () {
        reject(new Error("XHR: Error"));
      };
      xhr.open("GET", url, true);
      xhr.send();
    });
  }

  ///////////////////
  // tools for HAL //

  function getProperty(object, path) {
    if (Array.isArray(path)) {
      while (path.length) {
        object = object[path.shift()];
      }
    } else {
      return object[path];
    }
    return object;
  }

  function softGetProperty(object, path) {
    try {
      return getProperty(object, path);
    } catch (ignored) {
      return undefined;
    }
  }

  function forceList(value) {
    if (Array.isArray(value)) {
      return value;
    }
    return [value];
  }

  function softGetPropertyAsList(object, path) {
    try {
      return forceList(getProperty(object, path));
    } catch (ignored) {
      return [];
    }
  }

  ///////////////////

  function htmlToElementList(html) {
    /*global document */
    var div = document.createElement("div");
    div.innerHTML = html;
    return div.querySelectorAll("*");
  }

  function resolveUrl(firstUrl) {
    /*jslint plusplus: true */
    /*global URL, location */
    var l = arguments.length, i = 1, url = new URL(firstUrl, location.href);
    while (i < l) { url = new URL(arguments[i++], url); }
    return url.href;
  }

  function escapeHtml(html) {
    return html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
  }

  function loadAndRenderMonitorSection(root, monitor_dict, monitor_url) {
    var table, service_list = softGetPropertyAsList(monitor_dict, ["_embedded", "service"]);
    if (!service_list) {
      root.textContent = "";
      return;
    }
    table = document.createElement("table");
    root.appendChild(table);
    return Promise.all(service_list.map(function (service_dict) {
      var interface_url = softGetProperty(service_dict, ["_links", "interface", "href"]),
        status_url = softGetProperty(service_dict, ["_links", "status", "href"]),
        href_html_part = (interface_url ? " href=\"" + escapeHtml(interface_url) + "\"" : ""),
        title_html_part = (service_dict.title ? escapeHtml(service_dict.title) : (service_dict.id ||"Untitled")),
        row = htmlToElementList("<table><tbody><tr><td><a" + href_html_part + ">" + title_html_part + "</a></td><td>Loading status...</td><td><a" + href_html_part + "><div style=\"height: 10mm; width: 10mm; background-color: gray;\"></div></a></td></tr></tbody></table>");
      table.appendChild(row[2]);
      if (!status_url) {
        row[5].textContent = "No status";
        return;
      }
      return loadJson(resolveUrl(monitor_url, status_url)).then(function (status_dict) {
        if (status_dict.description) {
          row[2].title = status_dict.description;
        }
        row[5].textContent = status_dict.message || "";
        row[8].style.backgroundColor = status_dict.status === "OK" ? "green" : "red";
      }).catch(function (reason) {
        row[5].textContent = (reason && (reason.name + ": " + reason.message));
        row[8].style.backgroundColor = "red";
      });
    }));
  }

  function loadAndRenderMonitorJson(root) {
    root.textContent = "Loading monitor section...";
    return loadJson("monitor.haljson").then(function (monitor_dict) {
      //monitor_json_list.push(monitor_dict);
      root.innerHTML = "";
      var loading = loadAndRenderMonitorSection(root, monitor_dict), related_monitor_list = softGetPropertyAsList(monitor_dict, ["_links", "related_monitor"]);
      if (!related_monitor_list.length) { return loading; }
      return Promise.all([loading, Promise.all(related_monitor_list.map(function (link) {
        var div = htmlToElementList("<div>Loading monitor section...</div>")[0];
        root.appendChild(div);
        if (link.href[link.href.length - 1] !== "/") {
          link.href += "/";
        }
        link.href = resolveUrl(link.href, "monitor.haljson");
        return loadJson(link.href).catch(function (reason) {
          div.textContent = (reason && (reason.name + ": " + reason.message));
        }).then(function (monitor_dict) {
          //monitor_json_list.push(monitor_dict);
          div.remove();
          return loadAndRenderMonitorSection(root, monitor_dict, link.href);
        });
      }))]);
    });
  }

  function bootstrap(root) {
    var element_list = htmlToElementList([
      "<header><a href=\"\" class=\"as-button\">Refresh</a> <a href=\"/logout\" class=\"as-button\">Logout</a></header>",
      "<h1>" + monitor_title + "</h1>",
      "<h2>System health status</h2>",
      "<p>This interface allow to see the status of several features, it may show problems and sometimes provides a way to fix them.</p>",
      "<p>Red square means the feature has a problem, green square means it is ok.</p>",
      "<p>You can click on a feature below to get more precise information.</p>"
    ].join("\n")), div = document.createElement("div"), tmp;
    [].forEach.call(element_list, function (element) {
      if (element.parentNode.parentNode) { return; }
      root.appendChild(element);
    });
    document.title = monitor_title;
    root.appendChild(div);
    /*global alert */
    tmp = loadAndRenderMonitorJson(div);
    tmp.catch(alert);
    /*global console */
    tmp.catch(console.error.bind(console));
  }

  /*global setTimeout */
  setTimeout(function () {
    /*global document */
    bootstrap(document.body);
  });
}());