Browse Source

Fix JS to construct correct URLs when running from a subdirectory. Fixes #273

pull/287/head
Pēteris Caune 5 years ago
parent
commit
72d608902d
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
12 changed files with 24 additions and 363 deletions
  1. +3
    -0
      CHANGELOG.md
  2. +1
    -1
      hc/front/urls.py
  3. +2
    -1
      static/js/add_trello.js
  4. +7
    -6
      static/js/checks.js
  5. +0
    -204
      static/js/collapse-native.js
  6. +1
    -2
      static/js/details.js
  7. +2
    -1
      static/js/signup.js
  8. +0
    -117
      static/js/tab-native.js
  9. +5
    -29
      static/js/update-timeout-modal.js
  10. +1
    -1
      templates/base.html
  11. +1
    -0
      templates/front/details.html
  12. +1
    -1
      templates/front/my_checks_desktop.html

+ 3
- 0
CHANGELOG.md View File

@ -8,6 +8,9 @@ All notable changes to this project will be documented in this file.
- Show the number of downtimes and total downtime minutes in "Check Details" page - Show the number of downtimes and total downtime minutes in "Check Details" page
- Add the `pruneflips` management command - Add the `pruneflips` management command
## Bug Fixes
- Fix javascript code to construct correct URLs when running from a subdirectory (#273)
## 1.8.0 - 2019-07-08 ## 1.8.0 - 2019-07-08


+ 1
- 1
hc/front/urls.py View File

@ -10,7 +10,7 @@ check_urls = [
path("pause/", views.pause, name="hc-pause"), path("pause/", views.pause, name="hc-pause"),
path("remove/", views.remove_check, name="hc-remove-check"), path("remove/", views.remove_check, name="hc-remove-check"),
path("log/", views.log, name="hc-log"), path("log/", views.log, name="hc-log"),
path("status/", views.status_single),
path("status/", views.status_single, name="hc-status-single"),
path("last_ping/", views.ping_details, name="hc-last-ping"), path("last_ping/", views.ping_details, name="hc-last-ping"),
path("transfer/", views.transfer, name="hc-transfer"), path("transfer/", views.transfer, name="hc-transfer"),
path( path(


+ 2
- 1
static/js/add_trello.js View File

@ -15,9 +15,10 @@ $(function() {
$("integration-settings").text("Loading..."); $("integration-settings").text("Loading...");
token = tokenMatch[1]; token = tokenMatch[1];
var base = document.getElementById("base-url").getAttribute("href").slice(0, -1);
var csrf = $('input[name=csrfmiddlewaretoken]').val(); var csrf = $('input[name=csrfmiddlewaretoken]').val();
$.ajax({ $.ajax({
url: "/integrations/add_trello/settings/",
url: base + "/integrations/add_trello/settings/",
type: "post", type: "post",
headers: {"X-CSRFToken": csrf}, headers: {"X-CSRFToken": csrf},
data: {token: token}, data: {token: token},


+ 7
- 6
static/js/checks.js View File

@ -1,8 +1,9 @@
$(function () { $(function () {
var base = document.getElementById("base-url").getAttribute("href").slice(0, -1);
$(".my-checks-name").click(function() { $(".my-checks-name").click(function() {
var code = $(this).closest("tr.checks-row").attr("id"); var code = $(this).closest("tr.checks-row").attr("id");
var url = "/checks/" + code + "/name/";
var url = base + "/checks/" + code + "/name/";
$("#update-name-form").attr("action", url); $("#update-name-form").attr("action", url);
$("#update-name-input").val(this.dataset.name); $("#update-name-input").val(this.dataset.name);
@ -31,7 +32,7 @@ $(function () {
var checkCode = $(this).closest("tr.checks-row").attr("id"); var checkCode = $(this).closest("tr.checks-row").attr("id");
var channelCode = $("#ch-" + idx).data("code"); var channelCode = $("#ch-" + idx).data("code");
var url = "/checks/" + checkCode + "/channels/" + channelCode + "/enabled";
var url = base + "/checks/" + checkCode + "/channels/" + channelCode + "/enabled";
$.ajax({ $.ajax({
url: url, url: url,
@ -52,12 +53,12 @@ $(function () {
$('#ping-details-modal').modal("show"); $('#ping-details-modal').modal("show");
var code = $(this).closest("tr.checks-row").attr("id"); var code = $(this).closest("tr.checks-row").attr("id");
var lastPingUrl = "/checks/" + code + "/last_ping/";
var lastPingUrl = base + "/checks/" + code + "/last_ping/";
$.get(lastPingUrl, function(data) { $.get(lastPingUrl, function(data) {
$("#ping-details-body" ).html(data); $("#ping-details-body" ).html(data);
}); });
var logUrl = "/checks/" + code + "/log/";
var logUrl = base + "/checks/" + code + "/log/";
$("#ping-details-log").attr("href", logUrl); $("#ping-details-log").attr("href", logUrl);
return false; return false;
@ -79,7 +80,7 @@ $(function () {
// Update hash // Update hash
if (window.history && window.history.replaceState) { if (window.history && window.history.replaceState) {
var url = $("#checks-table").data("list-url");;
var url = $("#checks-table").data("list-url");
if (qs.length) { if (qs.length) {
url += "?" + $.param(qs); url += "?" + $.param(qs);
} }
@ -132,7 +133,7 @@ $(function () {
$(".show-log").click(function(e) { $(".show-log").click(function(e) {
var code = $(this).closest("tr.checks-row").attr("id"); var code = $(this).closest("tr.checks-row").attr("id");
var url = "/checks/" + code + "/details/";
var url = base + "/checks/" + code + "/details/";
window.location = url; window.location = url;
return false; return false;
}); });


+ 0
- 204
static/js/collapse-native.js View File

@ -1,204 +0,0 @@
// Native Javascript for Bootstrap 3 | Collapse
// by dnp_theme
(function(factory){
// CommonJS/RequireJS and "native" compatibility
if(typeof module !== "undefined" && typeof exports == "object") {
// A commonJS/RequireJS environment
if(typeof window != "undefined") {
// Window and document exist, so return the factory's return value.
module.exports = factory();
} else {
// Let the user give the factory a Window and Document.
module.exports = factory;
}
} else {
// Assume a traditional browser.
window.Collapse = factory();
}
})(function(){
// COLLAPSE DEFINITION
// ===================
var Collapse = function( element, options ) {
options = options || {};
this.btn = typeof element === 'object' ? element : document.querySelector(element);
this.accordion = null;
this.collapse = null;
this.duration = 300; // default collapse transition duration
this.options = {};
this.options.duration = /ie/.test(document.documentElement.className) ? 0 : (options.duration || this.duration);
this.init();
}
// COLLAPSE METHODS
// ================
Collapse.prototype = {
init : function() {
this.actions();
this.btn.addEventListener('click', this.toggle, false);
// allows the collapse to expand
// ** when window gets resized
// ** or via internal clicks handers such as dropwowns or any other
document.addEventListener('click', this.update, false);
window.addEventListener('resize', this.update, false)
},
actions : function() {
var self = this;
this.toggle = function(e) {
self.btn = self.getTarget(e).btn;
self.collapse = self.getTarget(e).collapse;
if (!/in/.test(self.collapse.className)) {
self.open(e)
} else {
self.close(e)
}
},
this.close = function(e) {
e.preventDefault();
self.btn = self.getTarget(e).btn;
self.collapse = self.getTarget(e).collapse;
self._close(self.collapse);
self.btn.className = self.btn.className.replace(' collapsed','');
},
this.open = function(e) {
e.preventDefault();
self.btn = self.getTarget(e).btn;
self.collapse = self.getTarget(e).collapse;
self.accordion = self.btn.getAttribute('data-parent') && self.getClosest(self.btn, self.btn.getAttribute('data-parent'));
self._open(self.collapse);
self.btn.className += ' collapsed';
if ( self.accordion !== null ) {
var active = self.accordion.querySelectorAll('.collapse.in'), al = active.length, i = 0;
for (i;i<al;i++) {
if ( active[i] !== self.collapse) self._close(active[i]);
}
}
},
this._open = function(c) {
c.className += ' in';
c.style.height = 0;
c.style.overflow = 'hidden';
c.setAttribute('area-expanded','true');
// the collapse MUST have a childElement div to wrap them all inside, just like accordion/well
var oh = this.getMaxHeight(c).oh, br = this.getMaxHeight(c).br;
c.style.height = oh + br + 'px';
setTimeout(function() {
c.style.overflow = '';
}, self.options.duration)
},
this._close = function(c) {
c.style.overflow = 'hidden';
c.style.height = 0;
setTimeout(function() {
c.className = c.className.replace(' in','');
c.style.overflow = '';
c.setAttribute('area-expanded','false');
}, self.options.duration)
},
this.update = function(e) {
var evt = e.type, tg = e.target, closest = self.getClosest(tg,'.collapse'),
itms = document.querySelectorAll('.collapse.in'), i = 0, il = itms.length;
for (i;i<il;i++) {
var itm = itms[i], oh = self.getMaxHeight(itm).oh, br = self.getMaxHeight(itm).br;
if ( evt === 'resize' && !/ie/.test(document.documentElement.className) ){
setTimeout(function() {
itm.style.height = oh + br + 'px';
}, self.options.duration)
} else if ( evt === 'click' && closest === itm ) {
itm.style.height = oh + br + 'px';
}
}
},
this.getMaxHeight = function(l) { // get collapse trueHeight and border
var t = l.children[0];
var cs = l.currentStyle || window.getComputedStyle(l);
return {
oh : getOuterHeight(t),
br : parseInt(cs.borderTop||0) + parseInt(cs.borderBottom||0)
}
},
this.getTarget = function(e) {
var t = e.currentTarget || e.srcElement,
h = t.href && t.getAttribute('href').replace('#',''),
d = t.getAttribute('data-target') && ( t.getAttribute('data-target') ),
id = h || ( d && /#/.test(d)) && d.replace('#',''),
cl = (d && d.charAt(0) === '.') && d, //the navbar collapse trigger targets a class
c = id && document.getElementById(id) || cl && document.querySelector(cl);
return {
btn : t,
collapse : c
}
},
this.getClosest = function (el, s) { //el is the element and s the selector of the closest item to find
// source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
var f = s.charAt(0);
for ( ; el && el !== document; el = el.parentNode ) {// Get closest match
if ( f === '.' ) {// If selector is a class
if ( document.querySelector(s) !== undefined ) { return el; }
}
if ( f === '#' ) { // If selector is an ID
if ( el.id === s.substr(1) ) { return el; }
}
}
return false;
}
}
}
var getOuterHeight = function (el) {
var s = el && el.currentStyle || window.getComputedStyle(el),
mtp = /px/.test(s.marginTop) ? Math.round(s.marginTop.replace('px','')) : 0,
mbp = /px/.test(s.marginBottom) ? Math.round(s.marginBottom.replace('px','')) : 0,
mte = /em/.test(s.marginTop) ? Math.round(s.marginTop.replace('em','') * parseInt(s.fontSize)) : 0,
mbe = /em/.test(s.marginBottom) ? Math.round(s.marginBottom.replace('em','') * parseInt(s.fontSize)) : 0;
return el.offsetHeight + parseInt( mtp ) + parseInt( mbp ) + parseInt( mte ) + parseInt( mbe ) //we need an accurate margin value
}
// COLLAPSE DATA API
// =================
var Collapses = document.querySelectorAll('[data-toggle="collapse"]'), i = 0, cll = Collapses.length;
for (i;i<cll;i++) {
var item = Collapses[i], options = {};
options.duration = item.getAttribute('data-duration');
new Collapse(item,options);
}
//we must add the height to the pre-opened collapses
window.addEventListener('load', function() {
var openedCollapses = document.querySelectorAll('.collapse'), i = 0, ocl = openedCollapses.length;
for (i;i<ocl;i++) {
var oc = openedCollapses[i];
if (/in/.test(oc.className)) {
var s = oc.currentStyle || window.getComputedStyle(oc);
var oh = getOuterHeight(oc.children[0]);
var br = parseInt(s.borderTop||0) + parseInt(s.borderBottom||0);
oc.style.height = oh + br + 'px';
}
}
});
return Collapse;
});

+ 1
- 2
static/js/details.js View File

@ -44,8 +44,7 @@ $(function () {
}); });
}) })
var code = document.getElementById("edit-timeout").dataset.code;
var statusUrl = "/checks/" + code + "/status/";
var statusUrl = document.getElementById("edit-timeout").dataset.statusUrl;
var lastStatusText = ""; var lastStatusText = "";
var lastUpdated = ""; var lastUpdated = "";
adaptiveSetInterval(function() { adaptiveSetInterval(function() {


+ 2
- 1
static/js/signup.js View File

@ -1,11 +1,12 @@
$(function () { $(function () {
$("#signup-go").on("click", function() { $("#signup-go").on("click", function() {
var base = document.getElementById("base-url").getAttribute("href").slice(0, -1);
var email = $("#signup-email").val(); var email = $("#signup-email").val();
var token = $('input[name=csrfmiddlewaretoken]').val(); var token = $('input[name=csrfmiddlewaretoken]').val();
$.ajax({ $.ajax({
url: "/accounts/signup/",
url: base + "/accounts/signup/",
type: "post", type: "post",
headers: {"X-CSRFToken": token}, headers: {"X-CSRFToken": token},
data: {"identity": email}, data: {"identity": email},


+ 0
- 117
static/js/tab-native.js View File

@ -1,117 +0,0 @@
// Native Javascript for Bootstrap 3 | Tab
// by dnp_theme
(function(factory){
// CommonJS/RequireJS and "native" compatibility
if(typeof module !== "undefined" && typeof exports == "object") {
// A commonJS/RequireJS environment
if(typeof window != "undefined") {
// Window and document exist, so return the factory's return value.
module.exports = factory();
} else {
// Let the user give the factory a Window and Document.
module.exports = factory;
}
} else {
// Assume a traditional browser.
window.Tab = factory();
}
})(function(){
// TAB DEFINITION
// ===================
var Tab = function( element,options ) {
options = options || {};
this.tab = typeof element === 'object' ? element : document.querySelector(element);
this.tabs = this.tab.parentNode.parentNode;
this.dropdown = this.tabs.querySelector('.dropdown');
if ( this.tabs.classList.contains('dropdown-menu') ) {
this.dropdown = this.tabs.parentNode;
this.tabs = this.tabs.parentNode.parentNode;
}
this.options = {};
// default tab transition duration
this.duration = 150;
this.options.duration = document.documentElement.classList.contains('ie') ? 0 : (options.duration || this.duration);
this.init();
}
// TAB METHODS
// ================
Tab.prototype = {
init : function() {
var self = this;
self.actions();
self.tab.addEventListener('click', self.action, false);
},
actions : function() {
var self = this;
this.action = function(e) {
e = e || window.e;
var next = e.target; //the tab we clicked is now the next tab
var nextContent = document.getElementById(next.getAttribute('href').replace('#','')); //this is the actual object, the next tab content to activate
var activeTab = self.getActiveTab();
var activeContent = self.getActiveContent();
//toggle "active" class name
activeTab.classList.remove('active');
next.parentNode.classList.add('active');
//handle dropdown menu "active" class name
if ( !self.tab.parentNode.parentNode.classList.contains('dropdown-menu')){
self.dropdown && self.dropdown.classList.remove('active');
} else {
self.dropdown && self.dropdown.classList.add('active');
}
//1. hide current active content first
activeContent.classList.remove('in');
setTimeout(function() {
//2. toggle current active content from view
activeContent.classList.remove('active');
nextContent.classList.add('active');
}, self.options.duration);
setTimeout(function() {
//3. show next active content
nextContent.classList.add('in');
}, self.options.duration*2);
e.preventDefault();
},
this.getActiveTab = function() {
var activeTabs = self.tabs.querySelectorAll('.active');
if ( activeTabs.length === 1 && !activeTabs[0].classList.contains('dropdown') ) {
return activeTabs[0]
} else if ( activeTabs.length > 1 ) {
return activeTabs[activeTabs.length-1]
}
},
this.getActiveContent = function() {
var a = self.getActiveTab().getElementsByTagName('A')[0].getAttribute('href').replace('#','');
return a && document.getElementById(a)
}
}
}
// TAB DATA API
// =================
var Tabs = document.querySelectorAll("[data-toggle='tab'], [data-toggle='pill']"), tbl = Tabs.length, i=0;
for ( i;i<tbl;i++ ) {
var tab = Tabs[i], options = {};
options.duration = tab.getAttribute('data-duration') && tab.getAttribute('data-duration') || false;
new Tab(tab,options);
}
return Tab;
});

+ 5
- 29
static/js/update-timeout-modal.js View File

@ -1,11 +1,13 @@
$(function () { $(function () {
var base = document.getElementById("base-url").getAttribute("href").slice(0, -1);
$(".timeout-grace").click(function() { $(".timeout-grace").click(function() {
var code = $(this).closest("tr.checks-row").attr("id"); var code = $(this).closest("tr.checks-row").attr("id");
if (!code) { if (!code) {
code = this.dataset.code; code = this.dataset.code;
} }
var url = "/checks/" + code + "/timeout/";
var url = base + "/checks/" + code + "/timeout/";
$("#update-timeout-form").attr("action", url); $("#update-timeout-form").attr("action", url);
$("#update-cron-form").attr("action", url); $("#update-cron-form").attr("action", url);
@ -28,32 +30,6 @@ $(function () {
return false; return false;
}); });
function init(code, kind, timeout, grace, schedule, tz) {
var url = "/checks/" + code + "/timeout/";
$("#update-timeout-form").attr("action", url);
$("#update-cron-form").attr("action", url);
// Simple
periodSlider.noUiSlider.set(timeout);
graceSlider.noUiSlider.set(grace);
// Cron
currentPreviewHash = "";
$("#cron-preview").html("<p>Updating...</p>");
$("#schedule").val(schedule);
$("#tz").selectpicker("val", tz);
var minutes = parseInt(grace / 60);
$("#update-timeout-grace-cron").val(minutes);
updateCronPreview();
kind == "simple" ? showSimple() : showCron();
$('#update-timeout-modal').modal({"show":true, "backdrop":"static"});
return false;
}
var MINUTE = {name: "minute", nsecs: 60}; var MINUTE = {name: "minute", nsecs: 60};
var HOUR = {name: "hour", nsecs: MINUTE.nsecs * 60}; var HOUR = {name: "hour", nsecs: MINUTE.nsecs * 60};
var DAY = {name: "day", nsecs: HOUR.nsecs * 24}; var DAY = {name: "day", nsecs: HOUR.nsecs * 24};
@ -166,7 +142,7 @@ $(function () {
var token = $('input[name=csrfmiddlewaretoken]').val(); var token = $('input[name=csrfmiddlewaretoken]').val();
$.ajax({ $.ajax({
url: "/checks/cron_preview/",
url: base + "/checks/cron_preview/",
type: "post", type: "post",
headers: {"X-CSRFToken": token}, headers: {"X-CSRFToken": token},
data: {schedule: schedule, tz: tz}, data: {schedule: schedule, tz: tz},


+ 1
- 1
templates/base.html View File

@ -67,7 +67,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="/">
<a id="base-url" class="navbar-brand" href="{% url 'hc-index' %}">
{% if request.user.is_authenticated and project %} {% if request.user.is_authenticated and project %}
{{ project }} {{ project }}
<span class="caret"></span> <span class="caret"></span>


+ 1
- 0
templates/front/details.html View File

@ -153,6 +153,7 @@
id="edit-timeout" id="edit-timeout"
class="btn btn-sm btn-default timeout-grace" class="btn btn-sm btn-default timeout-grace"
data-code="{{ check.code }}" data-code="{{ check.code }}"
data-status-url="{% url 'hc-status-single' check.code %}"
data-kind="{{ check.kind }}" data-kind="{{ check.kind }}"
data-timeout="{{ check.timeout.total_seconds }}" data-timeout="{{ check.timeout.total_seconds }}"
data-grace="{{ check.grace.total_seconds }}" data-grace="{{ check.grace.total_seconds }}"


+ 1
- 1
templates/front/my_checks_desktop.html View File

@ -112,7 +112,7 @@
</div> </div>
</td> </td>
<td> <td>
<div id="lpd-{{ check.code}}" class="last-ping">
<div id="lpd-{{ check.code }}" class="last-ping">
{% include "front/last_ping_cell.html" with check=check %} {% include "front/last_ping_cell.html" with check=check %}
</div> </div>
</td> </td>


Loading…
Cancel
Save