<!DOCTYPE html> <html> <head> <title>Promise status</title> <style> input, button { min-height: 10mm; min-width: 10mm; } </style> <script> function getServiceName() { var match = /(?:&|\?)service_name=([^&]*)/.exec(location.search); if (match) { return match[1]; } throw new Error("no service name found"); } var service_name = getServiceName(), monitor_json_url = "/monitor.haljson", status_json_url = "/public/" + service_name + ".status.json", rerun_cgi_url = "/cgi-bin/monitor-run-promise.cgi?service=" + service_name; function newDeferred() { var d = { "promise": undefined, "resolve": undefined, "reject": undefined }; d.promise = new Promise(function (resolve, reject) { d.resolve = resolve; d.reject = reject; }); return d; } function xhr(param) { /*global XMLHttpRequest */ var d = newDeferred(), xhr = new XMLHttpRequest(), k, i, l, a; d.promise.cancel = function () { xhr.abort(); }; xhr.open((param.method || "GET").toUpperCase(), param.url, true); xhr.responseType = param.responseType || ""; if (param.withCredentials !== undefined) { xhr.withCredentials = param.withCredentials; } if (param.headers) { a = Object.keys(param.headers); l = a.length; for (i = 0; i < l; i += 1) { k = a[i]; xhr.setRequestHeader(k, param.headers[k]); } } xhr.addEventListener("load", function (e) { var r, t = e.target, callback; if (param.noStatusCheck) { d.resolve(t); } else if (t.status < 400) { d.resolve(t); } else { d.reject(new Error("HTTP: " + (t.status ? t.status + " " : "") + (t.statusText || "Unknown"))); } }, false); xhr.addEventListener("error", function (e) { return d.reject(new Error("HTTP: Error")); }, false); xhr.addEventListener("abort", function (e) { return d.reject(new Error("HTTP: Aborted")); }, false); xhr.send(param.data); return d.promise; } function unexpectedError(reason) { console.error(reason); alert(reason); } function PromiseStatusInterface(config) { var it = this, statusP = document.createElement("p"), descriptionH2 = document.createElement("h2"), descriptionP = document.createElement("p"), errorH2 = document.createElement("h2"), errorPre = document.createElement("pre"), header = document.createElement("header"), h1 = document.createElement("h1"), h2 = document.createElement("h2"), a = document.createElement("a"), button = document.createElement("button"); this.element = config.rootElement || document.createElement("div"); this.statusP = statusP; this.descriptionP = descriptionP; this.errorH2 = errorH2; this.errorPre = errorPre; this.element.appendChild(header); header.appendChild(a); a.setAttribute("tabindex", "-1"); a.setAttribute("href", "/"); a.appendChild(button); button.textContent = "Home"; a = document.createElement("a"); button = document.createElement("button"); header.appendChild(a); a.setAttribute("tabindex", "-1"); a.setAttribute("href", ""); a.appendChild(button); button.textContent = "Refresh"; button = document.createElement("button"); header.appendChild(button); button.textContent = "Run promise now"; button.onclick = function () { this.runPromiseNow(); }.bind(this); this.runPromiseNowButton = button; this.element.appendChild(h1); h1.textContent = "Promise status"; this.element.appendChild(statusP); this.element.appendChild(descriptionH2); descriptionH2.textContent = "Description"; this.element.appendChild(descriptionP); this.element.appendChild(errorH2); errorH2.textContent = "Error output"; errorH2.style.display = "none"; this.element.appendChild(errorPre); errorPre.style.display = "none"; this.loadStatusUi(); this.loadDescriptionUi(); this.loadErrorUi(); } PromiseStatusInterface.prototype.loadStatusJson = function () { if (this.status_json_promise) { return; } this.status_json_promise = Promise.resolve().then(function () { return xhr({url: status_json_url, withCredentials: true, responseType: "json"}); }).then(function (xhr) { return xhr.response; }); this.status_json_promise.catch(function () { return; }).then(function () { setTimeout(function () { delete this.status_json_promise; }.bind(this), 1000); }.bind(this)); return this.status_json_promise; }; PromiseStatusInterface.prototype.loadStatusUi = function () { this.loadStatusJson(); this.statusP.textContent = "Loading status..."; return this.status_json_promise.then(function (status_json) { if (status_json.status === "OK") { this.statusP.textContent = "Status: OK."; } else { this.statusP.textContent = "Status: BAD (" + status_json.status + ")."; } if (status_json.message) { this.statusP.appendChild(document.createTextNode(" " + status_json.message)); } }.bind(this), function (reason) { var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message); this.statusP.textContent = "Status Json Error: " + (message || "Unknown error"); }.bind(this)).catch(unexpectedError); }; PromiseStatusInterface.prototype.loadDescriptionUi = function () { this.loadStatusJson(); this.descriptionP.textContent = "Loading description..."; return this.status_json_promise.then(function (status_json) { if (status_json.description) { this.descriptionP.textContent = status_json.description; } else { this.descriptionP.textContent = "No description"; } }.bind(this), function (reason) { var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message); this.descriptionP.textContent = "Status Json Error: " + (message || "Unknown error"); }.bind(this)).catch(unexpectedError); }; PromiseStatusInterface.prototype.loadErrorUi = function () { this.loadStatusJson(); this.errorPre.textContent = "Loading error output..."; return this.status_json_promise.then(function (status_json) { if (status_json.error) { this.errorH2.style.display = ""; this.errorPre.style.display = ""; this.errorPre.textContent = status_json.error; } else { this.errorH2.style.display = "none"; this.errorPre.style.display = "none"; this.errorPre.textContent = ""; } }.bind(this), function (reason) { var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message); this.errorPre.textContent = "Status Json Error: " + (message || "Unknown error"); }.bind(this)).catch(unexpectedError); }; PromiseStatusInterface.prototype.runPromiseNow = function () { this.runPromiseNowButton.disabled = true; var original_text = this.runPromiseNowButton.textContent; this.runPromiseNowButton.textContent = "Sending message..."; return Promise.resolve().then(function () { return xhr({url: rerun_cgi_url, method: "POST", withCredentials: true}); }).catch(unexpectedError).then(function () { this.runPromiseNowButton.textContent = original_text; }.bind(this)); }; /*global setTimeout */ setTimeout(function () { /*global document */ document.body.innerHTML = ""; return new PromiseStatusInterface({rootElement: document.body}); }); </script> </head> <body> <h1>Promise status</h1> <noscript>Javascript should be enabled</noscript> </body> </html>