Skip to content

Commit

Permalink
Merge pull request #339 from erwindon/singlepage
Browse files Browse the repository at this point in the history
Singlepage
  • Loading branch information
erwindon authored Dec 28, 2020
2 parents cb75527 + a37147b commit 5ee55bf
Show file tree
Hide file tree
Showing 21 changed files with 471 additions and 299 deletions.
14 changes: 10 additions & 4 deletions saltgui/static/scripts/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ export class API {
const loginResponseStr = Utils.getStorageItem("session", "login-response");
if (!loginResponseStr) {
this.logout().then(() => {
window.location.replace(config.NAV_URL + "/login?reason=no-session");
this.router.goTo("login", {"reason": "no-session"});
return true;
}, () => {
window.location.replace(config.NAV_URL + "/login?reason=no-session");
this.router.goTo("login", {"reason": "no-session"});
return false;
});
}
Expand All @@ -280,10 +280,10 @@ export class API {
const expireValue = loginResponse.expire;
if (now > expireValue) {
this.logout().then(() => {
window.location.replace(config.NAV_URL + "/login?reason=expired-session");
this.router.goTo("login", {"reason": "expired-session"});
return true;
}, () => {
window.location.replace(config.NAV_URL + "/login?reason=expired-session");
this.router.goTo("login", {"reason": "expired-session"});
return false;
});
}
Expand All @@ -303,6 +303,12 @@ export class API {
return;
}

// allow only one event-stream
if (API.eventsOK) {
return;
}
API.eventsOK = true;

let source;
try {
/* eslint-disable compat/compat */
Expand Down
5 changes: 5 additions & 0 deletions saltgui/static/scripts/DropDown.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,9 @@ export class DropDownMenu {
this.menuDropdown.style.display = "none";
}

clearMenu () {
while (this.menuDropdownContent.firstChild) {
this.menuDropdownContent.removeChild(this.menuDropdownContent.firstChild);
}
}
}
135 changes: 94 additions & 41 deletions saltgui/static/scripts/Router.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global config document window */
/* global document window */

import {API} from "./Api.js";
import {BeaconsMinionPage} from "./pages/BeaconsMinion.js";
Expand Down Expand Up @@ -29,6 +29,7 @@ export class Router {
Character.init();

this.api = new API();
this.api.router = this;
this.commandbox = new CommandBox(this, this.api);
this.currentPage = undefined;
this.pages = [];
Expand All @@ -52,16 +53,20 @@ export class Router {
this._registerPage(this.optionsPage = new OptionsPage(this));
this._registerPage(new LogoutPage(this));

Router._registerRouterEventListeners();
this._registerRouterEventListeners();

this.updateMainMenu();

// This URL already has its prefix added
// therefore is must not be added again
this.goTo(window.location.pathname + window.location.search, true);
const hash = window.location.hash.replace(/^#/, "");
const search = window.location.search;
/* eslint-disable compat/compat */
/* URLSearchParams.entries() is not supported in IE 11 */
/* URLSearchParams is not supported in op_mini all, IE 11, Baidu 7.12 */
this.goTo(hash, Object.fromEntries(new URLSearchParams(search)));
/* eslint-enable compat/compat */
}

static _registerMenuItem (pButtonId, pUrl) {
_registerMenuItem (pButtonId, pHash) {
for (const nr of ["1", "2"]) {
document.getElementById("button-" + pButtonId + nr).
addEventListener("click", (pClickEvent) => {
Expand All @@ -75,32 +80,42 @@ export class Router {
panel.style.display = "";
}, 500);
}
window.location.replace(config.NAV_URL + pUrl);
this.goTo(pHash);
});
}
}

static _registerRouterEventListeners () {
_registerRouterEventListeners () {
document.getElementById("logo").
addEventListener("click", () => {
if (window.event.ctrlKey) {
window.location.assign(config.NAV_URL + "/options");
this.goTo("options");
} else {
window.location.assign(config.NAV_URL + "/");
this.goTo("");
}
});

Router._registerMenuItem("minions", "/");
Router._registerMenuItem("grains", "/grains");
Router._registerMenuItem("schedules", "/schedules");
Router._registerMenuItem("pillars", "/pillars");
Router._registerMenuItem("beacons", "/beacons");
Router._registerMenuItem("keys", "/keys");
Router._registerMenuItem("jobs", "/jobs");
Router._registerMenuItem("templates", "/templates");
Router._registerMenuItem("events", "/eventsview");
Router._registerMenuItem("reactors", "/reactors");
Router._registerMenuItem("logout", "/logout");
addEventListener("popstate", (popstate) => {
const hash = popstate.target.location.hash.replace(/^#/, "");
const search = popstate.target.location.search;
/* eslint-disable compat/compat */
/* URLSearchParams.entries() is not supported in IE 11 */
/* URLSearchParams is not supported in op_mini all, IE 11, Baidu 7.12 */
this.goTo(hash, Object.fromEntries(new URLSearchParams(search)), 2);
/* eslint-enable compat/compat */
});

this._registerMenuItem("minions", "");
this._registerMenuItem("grains", "grains");
this._registerMenuItem("schedules", "schedules");
this._registerMenuItem("pillars", "pillars");
this._registerMenuItem("beacons", "beacons");
this._registerMenuItem("keys", "keys");
this._registerMenuItem("jobs", "jobs");
this._registerMenuItem("templates", "templates");
this._registerMenuItem("events", "eventsview");
this._registerMenuItem("reactors", "reactors");
this._registerMenuItem("logout", "logout");
}

_registerPage (pPage) {
Expand All @@ -126,36 +141,77 @@ export class Router {
}
}

goTo (pPath, hasPathPrefix = false) {
if (this.switchingPage) {
return;
}
if (window.location.pathname === config.NAV_URL + pPath && this.currentPage) {
return;
}
if (pPath === "/" && Utils.getStorageItem("session", "login-response") === null) {
// pForward = 0 --> normal navigation
// pForward = 1 --> back navigation using regular gui
// pForward = 2 --> back navigation using browser
goTo (pHash, pQuery = {}, pForward = 0) {

if (Utils.getStorageItem("session", "login-response") === null) {
// the fact that we don't have a session will be caught later
// but this was shows less error messages on the console
pPath = "/login";
pHash = "login";
pQuery = {"reason": "no-session"};
}
const pathUrl = (hasPathPrefix ? "" : config.NAV_URL) + pPath.split("?")[0];

// save the details from the parent
const parentHash = document.location.hash.replace(/^#/, "");
const search = window.location.search;
/* eslint-disable compat/compat */
/* URLSearchParams.entries() is not supported in IE 11 */
/* URLSearchParams is not supported in op_mini all, IE 11, Baidu 7.12 */
const parentQuery = Object.fromEntries(new URLSearchParams(search));
/* eslint-enable compat/compat */

for (const route of this.pages) {
if (!route.path.test(pathUrl)) {
if (route.path !== pHash) {
continue;
}
// push history state for login (including redirect to /)
if (pathUrl === config.NAV_URL + "/login" || pathUrl === config.NAV_URL + "/") {
window.history.pushState({}, undefined, pPath);
// push history state, so that the address bar holds the correct
// deep-link; and so that we can use the back-button
let url = "/";
let sep = "?";
for (const key in pQuery) {
const value = pQuery[key];
if (!value || value === "undefined") {
continue;
}
url += sep + key + "=" + encodeURIComponent(value);
sep = "&";
}
url += "#" + pHash;
if (parentHash === route.path) {
// page refresh
// prevents being detected as "forward navigation"
// do nothing
} else if (pForward === 0) {
// forward navigation
window.history.pushState({}, undefined, url);
route.parentHash = parentHash;
route.parentQuery = parentQuery;
} else if (pForward === 1) {
// close-icon on a panel
// do not save parent details
// these were already registered on the way forward
window.history.pushState({}, undefined, url);
} else if (pForward === 2) {
// backward navigation from browser
// do nothing extra
}
this._showPage(route);
return;
}
// route could not be found
// just go to the main page
this.goTo("/");
if (pHash === "") {
console.log("cannot find default page");
return;
}
this.goTo("");
}

_showPage (pPage) {
pPage.clearPage();

pPage.pageElement.style.display = "";

const activeMenuItems = Array.from(document.querySelectorAll(".menu-item-active"));
Expand Down Expand Up @@ -191,21 +247,18 @@ export class Router {
elem2.classList.add("menu-item-active");
}

this.switchingPage = true;

pPage.onShow();

// start the event-pipe (again)
// it is either not started, or needs restarting
API.getEvents(this);

if (this.currentPage) {
if (this.currentPage && this.currentPage !== pPage) {
Router._hidePage(this.currentPage);
}

this.currentPage = pPage;

this.currentPage.pageElement.classList.add("current");
this.switchingPage = false;
}

static _hidePage (pPage) {
Expand Down
4 changes: 4 additions & 0 deletions saltgui/static/scripts/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export class Utils {
// functions for URL parameters

static _getQueryParam2 (pUrl, pName) {
const hashPos = pUrl.indexOf("#");
if (hashPos > 0) {
pUrl = pUrl.substring(0, hashPos);
}
const questionmarkPos = pUrl.indexOf("?");
if (questionmarkPos < 0) {
return undefined;
Expand Down
4 changes: 2 additions & 2 deletions saltgui/static/scripts/output/Output.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global config document MouseEvent window */
/* global document MouseEvent window */

import {Character} from "../Character.js";
import {OutputDocumentation} from "./OutputDocumentation.js";
Expand Down Expand Up @@ -80,7 +80,7 @@ export class Output {
// typically found in the output of an async job
if (pMinionResponse.match(ParseCommandLine.getPatJid())) {
const link = document.createElement("a");
link.href = config.NAV_URL + "/job?id=" + encodeURIComponent(pMinionResponse);
link.href = "#job?id=" + encodeURIComponent(pMinionResponse);
link.innerText = pMinionResponse;
return link;
}
Expand Down
10 changes: 5 additions & 5 deletions saltgui/static/scripts/pages/Logout.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global config */
/* global window */

import {Page} from "./Page.js";
import {Utils} from "../Utils.js";
Expand All @@ -24,7 +24,7 @@ export class LogoutPage extends Page {

onShow () {
this.api.logout().then(() => {
window.location.replace(config.NAV_URL + "/login?reason=logout");
this.router.goTo("login", {"reason": "logout"});
});
}

Expand All @@ -44,7 +44,7 @@ export class LogoutPage extends Page {
// Api.apiRequest will do all the work
statsPromise.then(() => true, () => {
this.api.logout().then(() => {
window.location.replace(config.NAV_URL + "/login?reason=no-session");
this.router.goTo("login", {"reason": "no-session"});
return false;
});
});
Expand All @@ -69,10 +69,10 @@ export class LogoutPage extends Page {
warning.innerText = "Logout";
// logout, and redirect to login screen
this.api.logout().then(() => {
window.location.replace(config.NAV_URL + "/login?reason=expired-session");
this.router.goTo("login", {"reason": "expired-session"});
return true;
}, () => {
window.location.replace(config.NAV_URL + "/login?reason=expired-session");
this.router.goTo("login", {"reason": "expired-session"});
return false;
});
return;
Expand Down
10 changes: 8 additions & 2 deletions saltgui/static/scripts/pages/Page.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* global config */
/* global */

import {Utils} from "../Utils.js";

export class Page {

constructor (pPath, pPageName, pPageSelector, pMenuItemSelector, pRouter) {
this.path = new RegExp("^" + config.NAV_URL.replace(/\//, "[/]") + "[/]" + pPath + "$");
this.path = pPath;
this.name = pPageName;

// <div class='route' id='page-keys'>
Expand Down Expand Up @@ -130,4 +130,10 @@ export class Page {
panel.onShow();
}
}

clearPage () {
for (const panel of this.panels) {
panel.clearPanel();
}
}
}
10 changes: 3 additions & 7 deletions saltgui/static/scripts/panels/Beacons.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global config window */
/* global */

import {DropDownMenu} from "../DropDown.js";
import {Panel} from "./Panel.js";
Expand Down Expand Up @@ -96,7 +96,7 @@ export class BeaconsPanel extends Panel {
BeaconsPanel._addMenuItemShowBeacons(menu, minionId);

minionTr.addEventListener("click", () => {
window.location.assign(config.NAV_URL + "/beacons-minion?minionid=" + encodeURIComponent(minionId));
this.router.goTo("beacons-minion", {"minionid": minionId});
});
}

Expand Down Expand Up @@ -141,15 +141,11 @@ export class BeaconsPanel extends Panel {

const menu = new DropDownMenu(minionTr);
BeaconsPanel._addMenuItemShowBeacons(menu, pMinionId);

minionTr.addEventListener("click", () => {
window.location.assign(config.NAV_URL + "/beacons-minion?minionid=" + encodeURIComponent(pMinionId));
});
}

static _addMenuItemShowBeacons (pMenu, pMinionId) {
pMenu.addMenuItem("Show beacons", () => {
window.location.assign(config.NAV_URL + "/beacons-minion?minionid=" + encodeURIComponent(pMinionId));
this.router.goTo("beacons-minion", {"minionid": pMinionId});
});
}
}
Loading

0 comments on commit 5ee55bf

Please sign in to comment.