1
0
Fork 0

Rework PageRouter, Page, pageContent and SecretTitleElement.

This commit is contained in:
Kitteh 2021-05-15 10:54:39 +01:00
parent 8f448b80fc
commit 67bd89db1a
36 changed files with 515 additions and 532 deletions

View file

@ -1,4 +1,4 @@
import { Page } from "./types/Page"; import { Page } from "./PageSystem/Page";
import { allPages } from "./allPages"; import { allPages } from "./allPages";
import { getKeyByObjectPropertyValue } from "./utils"; import { getKeyByObjectPropertyValue } from "./utils";

29
src/PageSystem/Page.ts Normal file
View file

@ -0,0 +1,29 @@
import { PageRouter } from "./PageRouter";
import { PageState } from "../PageState";
export class Page {
constructor() {
// Do Nothing
}
public router: PageRouter;
public state: PageState;
async render(): Promise<void> {}
get name(): string {
return "Page";
}
async getPageTitle(): Promise<Element | string> {
return this.name;
}
async goBack(): Promise<void> {
await this.router.changePage("HOME");
}
async cleanup(): Promise<void> {
// Do Nothing
}
async setRouterAndState(router: PageRouter, state: PageState): Promise<void> {
this.router = router;
this.state = state;
}
}

View file

@ -1,5 +1,6 @@
import { Page } from "./types/Page"; import { Page } from "./Page";
import { getObjectKeys } from "./utils"; import { PageState } from "../PageState";
import { getObjectKeys } from "../utils";
type pageList = { type pageList = {
[key: string]: Page; [key: string]: Page;
@ -9,9 +10,15 @@ const PageDoesNotExistError = new Error("Page does not exist.");
const PageHasNotBeenSetError = new Error("Page has not been set."); const PageHasNotBeenSetError = new Error("Page has not been set.");
export class PageRouter extends EventTarget { export class PageRouter extends EventTarget {
constructor(pages: pageList, pageContentElement: HTMLElement, pageTitleElement: HTMLElement) { constructor(
pages: pageList,
state: PageState,
pageContentElement: HTMLElement,
pageTitleElement: HTMLElement,
) {
super(); super();
this.pages = pages; this.pages = pages;
this.state = state;
this.pageContentElement = pageContentElement; this.pageContentElement = pageContentElement;
this.pageTitleElement = pageTitleElement; this.pageTitleElement = pageTitleElement;
} }
@ -20,6 +27,7 @@ export class PageRouter extends EventTarget {
private currentPageID: string; private currentPageID: string;
private currentPage: Page; private currentPage: Page;
public state: PageState;
public pageContentElement: HTMLElement; public pageContentElement: HTMLElement;
public pageTitleElement: HTMLElement; public pageTitleElement: HTMLElement;
@ -27,10 +35,23 @@ export class PageRouter extends EventTarget {
return getObjectKeys(this.pages); return getObjectKeys(this.pages);
} }
public async getCurrentPage(): Promise<Page> {
return this.currentPage;
}
public async getCurrentPageID(): Promise<string> { public async getCurrentPageID(): Promise<string> {
return this.currentPageID; return this.currentPageID;
} }
public async setPageContent(content: string | HTMLElement): Promise<void> {
if (typeof content === "string") {
this.pageContentElement.innerHTML = content;
} else {
this.pageContentElement.innerHTML = "";
this.pageContentElement.appendChild(content);
}
}
public async changePage(pageID: string): Promise<void> { public async changePage(pageID: string): Promise<void> {
if (!(await this.getPageIDs()).includes(pageID)) throw PageDoesNotExistError; if (!(await this.getPageIDs()).includes(pageID)) throw PageDoesNotExistError;
@ -43,6 +64,8 @@ export class PageRouter extends EventTarget {
this.currentPageID = pageID; this.currentPageID = pageID;
this.currentPage = this.pages[pageID]; this.currentPage = this.pages[pageID];
await this.currentPage.setRouterAndState(this, this.state);
// Dispatch an event saying the page has been changed. // Dispatch an event saying the page has been changed.
this.dispatchEvent(new CustomEvent("pageChanged")); this.dispatchEvent(new CustomEvent("pageChanged"));
@ -57,8 +80,12 @@ export class PageRouter extends EventTarget {
this.pageContentElement.innerHTML = ""; this.pageContentElement.innerHTML = "";
this.pageTitleElement.innerHTML = ""; this.pageTitleElement.innerHTML = "";
// TODO: Make Page have a getTitle method. const pageTitle = await this.currentPage.getPageTitle();
this.pageTitleElement.innerText = this.currentPage.name; if (typeof pageTitle === "string") {
this.pageTitleElement.innerText = pageTitle;
} else {
this.pageTitleElement.appendChild(pageTitle);
}
await this.currentPage.render(); await this.currentPage.render();
} }

View file

@ -13,7 +13,7 @@ import { NewTOTPEnginePage } from "./pages/NewEngines/NewTOTPEngine";
import { NewTOTPPage } from "./pages/TOTP/NewTOTP"; import { NewTOTPPage } from "./pages/TOTP/NewTOTP";
import { NewTransitEnginePage } from "./pages/NewEngines/NewTransitEngine"; import { NewTransitEnginePage } from "./pages/NewEngines/NewTransitEngine";
import { NewTransitKeyPage } from "./pages/Transit/NewTransitKey"; import { NewTransitKeyPage } from "./pages/Transit/NewTransitKey";
import { Page } from "./types/Page"; import { Page } from "./PageSystem/Page";
import { PwGenPage } from "./pages/PwGen"; import { PwGenPage } from "./pages/PwGen";
import { SetLanguagePage } from "./pages/SetLanguage"; import { SetLanguagePage } from "./pages/SetLanguage";
import { SetVaultURLPage } from "./pages/SetVaultURL"; import { SetVaultURLPage } from "./pages/SetVaultURL";

View file

@ -1,9 +1,9 @@
import { ListItem } from "./ListItem"; import { ListItem } from "./ListItem";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageRouter } from "../globalPageRouter";
import i18next from "i18next"; import i18next from "i18next";
import { PageRouter } from "../PageSystem/PageRouter";
export function NavBar(): HTMLElement { export function NavBar(router: PageRouter): HTMLElement {
return makeElement({ return makeElement({
id: "navBar", id: "navBar",
tag: "nav", tag: "nav",
@ -21,7 +21,7 @@ export function NavBar(): HTMLElement {
tag: "a", tag: "a",
text: i18next.t("home_btn"), text: i18next.t("home_btn"),
onclick: async () => { onclick: async () => {
await pageRouter.changePage("HOME"); await router.changePage("HOME");
}, },
}), }),
), ),
@ -30,7 +30,7 @@ export function NavBar(): HTMLElement {
tag: "a", tag: "a",
text: i18next.t("back_btn"), text: i18next.t("back_btn"),
onclick: async () => { onclick: async () => {
await pageRouter.goBack(); await router.goBack();
}, },
}), }),
), ),
@ -39,7 +39,7 @@ export function NavBar(): HTMLElement {
tag: "a", tag: "a",
text: i18next.t("refresh_btn"), text: i18next.t("refresh_btn"),
onclick: async () => { onclick: async () => {
await pageRouter.refresh(); await router.refresh();
}, },
}), }),
), ),
@ -58,7 +58,7 @@ export function NavBar(): HTMLElement {
tag: "a", tag: "a",
text: i18next.t("me_btn"), text: i18next.t("me_btn"),
onclick: async () => { onclick: async () => {
await pageRouter.changePage("ME"); await router.changePage("ME");
}, },
}), }),
), ),
@ -69,6 +69,6 @@ export function NavBar(): HTMLElement {
}); });
} }
export function reloadNavBar(): void { export function reloadNavBar(router: PageRouter): void {
document.querySelector("#navBar").replaceWith(NavBar()); document.querySelector("#navBar").replaceWith(NavBar(router));
} }

View file

@ -0,0 +1,57 @@
import { PageRouter } from "../PageSystem/PageRouter";
import { makeElement } from "../htmlUtils";
function currentTitleSecretText(router: PageRouter, suffix = ""): string {
let currentSecretText = router.state.currentSecret;
currentSecretText += suffix;
if (router.state.currentSecretVersion !== null)
currentSecretText += ` (v${router.state.currentSecretVersion})`;
return currentSecretText;
}
export async function SecretTitleElement(router: PageRouter, suffix = ""): Promise<HTMLElement> {
const titleElement = makeElement({
tag: "div",
children: [
makeElement({
tag: "a",
text: router.state.currentBaseMount + " ",
onclick: async () => {
router.state.currentSecretPath = [];
router.state.currentSecret = "";
router.state.currentSecretVersion = null;
if (
router.state.currentMountType.startsWith("kv") ||
router.state.currentMountType == "cubbyhole"
) {
await router.changePage("KEY_VALUE_VIEW");
} else if (router.state.currentMountType == "totp") {
await router.changePage("TOTP");
} else if (router.state.currentMountType == "transit") {
await router.changePage("TRANSIT_VIEW");
}
},
}),
...router.state.currentSecretPath.map((secretPath, index, secretPaths) => {
return makeElement({
tag: "a",
text: secretPath + " ",
onclick: async () => {
router.state.currentSecretVersion = null;
if (router.state.currentMountType.startsWith("kv")) {
router.state.currentSecretPath = secretPaths.slice(0, index + 1);
await router.changePage("KEY_VALUE_VIEW");
}
},
});
}),
makeElement({
tag: "span",
condition: router.state.currentSecret.length != 0,
text: currentTitleSecretText(router, suffix),
}),
],
});
return titleElement;
}

View file

@ -1,6 +0,0 @@
import { PageRouter } from "./PageRouter";
export let pageRouter: PageRouter;
export function setPageRouter(router: PageRouter): void {
pageRouter = router;
}

View file

@ -20,14 +20,13 @@ Prism.highlightAll();
// Actual Imports // Actual Imports
import { NavBar } from "./elements/NavBar"; import { NavBar } from "./elements/NavBar";
import { PageRouter } from "./PageRouter"; import { PageRouter } from "./PageSystem/PageRouter";
import { allPages } from "./allPages"; import { allPages } from "./allPages";
import { formatDistance } from "./formatDistance"; import { formatDistance } from "./formatDistance";
import { getSealStatus } from "./api/sys/getSealStatus"; import { getSealStatus } from "./api/sys/getSealStatus";
import { makeElement } from "./htmlUtils"; import { makeElement } from "./htmlUtils";
import { pageState } from "./globalPageState"; import { pageState } from "./globalPageState";
import { playground } from "./playground"; import { playground } from "./playground";
import { setPageRouter } from "./globalPageRouter";
import i18next from "i18next"; import i18next from "i18next";
// @ts-ignore // @ts-ignore
@ -41,7 +40,7 @@ declare global {
async function onLoad(): Promise<void> { async function onLoad(): Promise<void> {
document.body.innerHTML = ""; document.body.innerHTML = "";
document.body.appendChild(NavBar()); document.body.appendChild(makeElement({tag: "div", id: "navBarReplace"}));
document.body.appendChild( document.body.appendChild(
makeElement({ makeElement({
tag: "div", tag: "div",
@ -69,10 +68,12 @@ async function onLoad(): Promise<void> {
const pageRouter = new PageRouter( const pageRouter = new PageRouter(
allPages, allPages,
pageState,
document.getElementById("pageContent"), document.getElementById("pageContent"),
document.getElementById("pageTitle"), document.getElementById("pageTitle"),
); );
setPageRouter(pageRouter);
document.querySelector("#navBarReplace").replaceWith(NavBar(pageRouter));
pageRouter.addEventListener("pageChanged", async function (_) { pageRouter.addEventListener("pageChanged", async function (_) {
pageState.currentPage = await pageRouter.getCurrentPageID(); pageState.currentPage = await pageRouter.getCurrentPageID();
@ -80,7 +81,7 @@ async function onLoad(): Promise<void> {
}); });
if (process.env.NODE_ENV == "development") { if (process.env.NODE_ENV == "development") {
await playground(); await playground(pageRouter);
} }
await pageRouter.changePage(pageState.currentPageString); await pageRouter.changePage(pageState.currentPageString);

View file

@ -1,41 +1,37 @@
import { Page } from "./types/Page"; import { PageRouter } from "./PageSystem/PageRouter";
import { PageState } from "./PageState";
import { getSealStatus } from "./api/sys/getSealStatus"; import { getSealStatus } from "./api/sys/getSealStatus";
import { lookupSelf } from "./api/sys/lookupSelf"; import { lookupSelf } from "./api/sys/lookupSelf";
import { makeElement } from "./htmlUtils";
import { pageRouter } from "./globalPageRouter";
import { pageState } from "./globalPageState";
import ClipboardJS from "clipboard"; import ClipboardJS from "clipboard";
import UIkit from "uikit"; import UIkit from "uikit";
import i18next from "i18next"; import i18next from "i18next";
async function prePageChecksReal() { async function prePageChecksReal(router: PageRouter) {
if (pageState.language.length == 0) { if (router.state.language.length == 0) {
await changePage("SET_LANGUAGE"); await router.changePage("SET_LANGUAGE");
throw new Error("Language Not Set"); throw new Error("Language Not Set");
} }
if (!pageState.apiURL) { if (!router.state.apiURL) {
await changePage("SET_VAULT_URL"); await router.changePage("SET_VAULT_URL");
throw new Error("Vault URL Not Set"); throw new Error("Vault URL Not Set");
} }
const sealStatus = await getSealStatus(); const sealStatus = await getSealStatus();
if (sealStatus.sealed) { if (sealStatus.sealed) {
await changePage("UNSEAL"); await router.changePage("UNSEAL");
throw new Error("Vault Sealed"); throw new Error("Vault Sealed");
} }
try { try {
await lookupSelf(); await lookupSelf();
} catch (e) { } catch (e) {
await changePage("LOGIN"); await router.changePage("LOGIN");
throw e; throw e;
} }
} }
export async function prePageChecks(): Promise<boolean> { export async function prePageChecks(router: PageRouter): Promise<boolean> {
try { try {
await prePageChecksReal(); await prePageChecksReal(router);
} catch (e) { } catch (e) {
console.log("OHNO", e); console.log("OHNO", e);
return false; return false;
@ -78,82 +74,3 @@ export function setErrorText(text: string): void {
timeout: 2000, timeout: 2000,
}); });
} }
export async function changePage(page: string): Promise<void> {
await pageRouter.changePage(page);
}
export function setPageTitle(title: string | HTMLElement): void {
const pageTitle = document.getElementById("pageTitle");
pageTitle.innerHTML = "";
if (typeof title === "string") {
pageTitle.innerText = title.toString();
} else {
pageTitle.appendChild(title);
}
}
function currentTitleSecretText() {
let currentSecretText = pageState.currentSecret;
currentSecretText += (pageState.currentPage as Page).titleSuffix;
if (pageState.currentSecretVersion !== null)
currentSecretText += ` (v${pageState.currentSecretVersion})`;
return currentSecretText;
}
export function setTitleElement(pageState: PageState): void {
const titleElement = makeElement({
tag: "div",
children: [
makeElement({
tag: "a",
text: pageState.currentBaseMount + " ",
onclick: async () => {
pageState.currentSecretPath = [];
pageState.currentSecret = "";
pageState.currentSecretVersion = null;
if (
pageState.currentMountType.startsWith("kv") ||
pageState.currentMountType == "cubbyhole"
) {
await changePage("KEY_VALUE_VIEW");
} else if (pageState.currentMountType == "totp") {
await changePage("TOTP");
} else if (pageState.currentMountType == "transit") {
await changePage("TRANSIT_VIEW");
}
},
}),
...pageState.currentSecretPath.map(function (secretPath, index, secretPaths) {
return makeElement({
tag: "a",
text: secretPath + " ",
onclick: async () => {
pageState.currentSecretVersion = null;
if (pageState.currentMountType.startsWith("kv")) {
pageState.currentSecretPath = secretPaths.slice(0, index + 1);
await changePage("KEY_VALUE_VIEW");
}
},
});
}),
makeElement({
tag: "span",
condition: pageState.currentSecret.length != 0,
text: currentTitleSecretText(),
}),
],
});
setPageTitle(titleElement);
}
export function setPageContent(content: string | HTMLElement): void {
const pageContent = document.getElementById("pageContent");
if (typeof content === "string") {
pageContent.innerHTML = content;
} else {
pageContent.innerHTML = "";
pageContent.appendChild(content);
}
}

View file

@ -1,10 +1,9 @@
import { MountType, getMounts } from "../api/sys/getMounts"; import { MountType, getMounts } from "../api/sys/getMounts";
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils";
import { getCapabilitiesPath } from "../api/sys/getCapabilities"; import { getCapabilitiesPath } from "../api/sys/getCapabilities";
import { lookupSelf } from "../api/sys/lookupSelf"; import { lookupSelf } from "../api/sys/lookupSelf";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState"; import { prePageChecks, setErrorText } from "../pageUtils";
import { sortedObjectMap } from "../utils"; import { sortedObjectMap } from "../utils";
import i18next from "i18next"; import i18next from "i18next";
@ -13,11 +12,11 @@ export class HomePage extends Page {
super(); super();
} }
async render(): Promise<void> { async render(): Promise<void> {
setPageContent(""); await this.router.setPageContent("");
if (!(await prePageChecks())) return; if (!(await prePageChecks(this.router))) return;
const homePageContent = makeElement({ tag: "div" }); const homePageContent = makeElement({ tag: "div" });
setPageContent(homePageContent); await this.router.setPageContent(homePageContent);
const textList = makeElement({ const textList = makeElement({
tag: "ul", tag: "ul",
class: "uk-nav", class: "uk-nav",
@ -26,7 +25,7 @@ export class HomePage extends Page {
tag: "li", tag: "li",
children: makeElement({ children: makeElement({
tag: "span", tag: "span",
html: i18next.t("vaulturl_text", { text: pageState.apiURL }), html: i18next.t("vaulturl_text", { text: this.state.apiURL }),
}), }),
}), }),
makeElement({ makeElement({
@ -35,7 +34,7 @@ export class HomePage extends Page {
tag: "a", tag: "a",
text: i18next.t("password_generator_btn"), text: i18next.t("password_generator_btn"),
onclick: async () => { onclick: async () => {
await changePage("PW_GEN"); await this.router.changePage("PW_GEN");
}, },
}), }),
}), }),
@ -57,8 +56,8 @@ export class HomePage extends Page {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);
if (error.message == "permission denied") { if (error.message == "permission denied") {
pageState.token = ""; this.state.token = "";
await changePage("LOGIN"); await this.router.changePage("LOGIN");
} }
} }
@ -70,16 +69,16 @@ export class HomePage extends Page {
text: i18next.t("home_new_secrets_engine_button"), text: i18next.t("home_new_secrets_engine_button"),
class: ["uk-button", "uk-button-primary", "uk-margin-top"], class: ["uk-button", "uk-button-primary", "uk-margin-top"],
onclick: async () => { onclick: async () => {
await changePage("NEW_SECRETS_ENGINE"); await this.router.changePage("NEW_SECRETS_ENGINE");
}, },
}), }),
); );
} }
pageState.currentBaseMount = ""; this.state.currentBaseMount = "";
pageState.currentSecretPath = []; this.state.currentSecretPath = [];
pageState.currentSecret = ""; this.state.currentSecret = "";
pageState.currentSecretVersion = null; this.state.currentSecretVersion = null;
const navList = makeElement({ const navList = makeElement({
tag: "ul", tag: "ul",
@ -91,7 +90,7 @@ export class HomePage extends Page {
// sort it by secretPath so it's in alphabetical order consistantly. // sort it by secretPath so it's in alphabetical order consistantly.
const mountsMap = sortedObjectMap(mounts); const mountsMap = sortedObjectMap(mounts);
mountsMap.forEach(function (mount: MountType, baseMount) { mountsMap.forEach((mount: MountType, baseMount) => {
if (typeof mount != "object") return; if (typeof mount != "object") return;
if (mount == null) return; if (mount == null) return;
if (!("type" in mount)) return; if (!("type" in mount)) return;
@ -122,9 +121,9 @@ export class HomePage extends Page {
tag: "a", tag: "a",
text: linkText, text: linkText,
onclick: async () => { onclick: async () => {
pageState.currentBaseMount = baseMount; this.state.currentBaseMount = baseMount;
pageState.currentMountType = mountType; this.state.currentMountType = mountType;
await changePage(linkPage); await this.router.changePage(linkPage);
}, },
}), }),
}), }),

View file

@ -1,8 +1,7 @@
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { deleteSecret } from "../../api/kv/deleteSecret"; import { deleteSecret } from "../../api/kv/deleteSecret";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState";
import i18next from "i18next"; import i18next from "i18next";
export class KeyValueDeletePage extends Page { export class KeyValueDeletePage extends Page {
@ -10,17 +9,16 @@ export class KeyValueDeletePage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
if (pageState.currentSecretVersion != null) { if (this.state.currentSecretVersion != null) {
pageState.currentSecretVersion = null; this.state.currentSecretVersion = null;
await changePage("KEY_VALUE_SECRET"); await this.router.changePage("KEY_VALUE_SECRET");
} else { } else {
pageState.currentSecret = ""; this.state.currentSecret = "";
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} }
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); await this.router.setPageContent(
setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -34,11 +32,11 @@ export class KeyValueDeletePage extends Page {
text: i18next.t("kv_delete_btn"), text: i18next.t("kv_delete_btn"),
onclick: () => { onclick: () => {
void deleteSecret( void deleteSecret(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentMountType, this.state.currentMountType,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
pageState.currentSecretVersion, this.state.currentSecretVersion,
).then(() => { ).then(() => {
void this.goBack(); void this.goBack();
}); });
@ -48,9 +46,11 @@ export class KeyValueDeletePage extends Page {
}), }),
); );
} }
get titleSuffix(): string {
return i18next.t("kv_delete_suffix"); async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router, i18next.t("kv_delete_suffix"));
} }
get name(): string { get name(): string {
return i18next.t("kv_delete_title"); return i18next.t("kv_delete_title");
} }

View file

@ -1,8 +1,8 @@
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class KeyValueNewPage extends Page { export class KeyValueNewPage extends Page {
@ -11,13 +11,12 @@ export class KeyValueNewPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} }
addKVNewForm: HTMLFormElement; addKVNewForm: HTMLFormElement;
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
this.addKVNewForm = makeElement({ this.addKVNewForm = makeElement({
tag: "form", tag: "form",
id: "addKVNewForm", id: "addKVNewForm",
@ -51,7 +50,7 @@ export class KeyValueNewPage extends Page {
}), }),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.addKVNewForm); await this.router.setPageContent(this.addKVNewForm);
this.addKVNewForm.addEventListener("submit", async (e: Event) => { this.addKVNewForm.addEventListener("submit", async (e: Event) => {
e.preventDefault(); e.preventDefault();
@ -64,27 +63,27 @@ export class KeyValueNewPage extends Page {
const path = formData.get("path") as string; const path = formData.get("path") as string;
let keyData = {}; let keyData = {};
if (["kv-v1", "cubbyhole"].includes(pageState.currentMountType)) { if (["kv-v1", "cubbyhole"].includes(this.state.currentMountType)) {
keyData = { key: "value" }; keyData = { key: "value" };
} }
try { try {
await createOrUpdateSecret( await createOrUpdateSecret(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentMountType, this.state.currentMountType,
pageState.currentSecretPath, this.state.currentSecretPath,
path, path,
keyData, keyData,
); );
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} catch (e: unknown) { } catch (e: unknown) {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);
} }
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("kv_new_suffix"); return await SecretTitleElement(this.router, i18next.t("kv_new_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,10 +1,9 @@
import { CopyableInputBox } from "../../elements/CopyableInputBox"; import { CopyableInputBox } from "../../elements/CopyableInputBox";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getCapabilities } from "../../api/sys/getCapabilities"; import { getCapabilities } from "../../api/sys/getCapabilities";
import { getSecret } from "../../api/kv/getSecret"; import { getSecret } from "../../api/kv/getSecret";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState";
import { sortedObjectMap } from "../../utils"; import { sortedObjectMap } from "../../utils";
import { undeleteSecret } from "../../api/kv/undeleteSecret"; import { undeleteSecret } from "../../api/kv/undeleteSecret";
import Prism from "prismjs"; import Prism from "prismjs";
@ -15,17 +14,16 @@ export class KeyValueSecretPage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
if (pageState.currentSecretVersion != null) { if (this.state.currentSecretVersion != null) {
pageState.currentSecretVersion = null; this.state.currentSecretVersion = null;
await changePage("KEY_VALUE_VERSIONS"); await this.router.changePage("KEY_VALUE_VERSIONS");
} else { } else {
pageState.currentSecret = ""; this.state.currentSecret = "";
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} }
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); await this.router.setPageContent(
setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -50,17 +48,20 @@ export class KeyValueSecretPage extends Page {
const kvList = document.querySelector("#kvList"); const kvList = document.querySelector("#kvList");
let isSecretNestedJson = false; let isSecretNestedJson = false;
const caps = await getCapabilities( const caps = await getCapabilities(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
); );
if (caps.includes("delete")) { if (caps.includes("delete")) {
let deleteButtonText = i18next.t("kv_secret_delete_btn"); let deleteButtonText = i18next.t("kv_secret_delete_btn");
if (pageState.currentMountType == "kv-v2" && pageState.currentSecretVersion == null) { if (this.state.currentMountType == "kv-v2" && this.state.currentSecretVersion == null) {
deleteButtonText = i18next.t("kv_secret_delete_all_btn"); deleteButtonText = i18next.t("kv_secret_delete_all_btn");
} else if (pageState.currentMountType == "kv-v2" && pageState.currentSecretVersion != null) { } else if (
this.state.currentMountType == "kv-v2" &&
this.state.currentSecretVersion != null
) {
deleteButtonText = i18next.t("kv_secret_delete_version_btn", { deleteButtonText = i18next.t("kv_secret_delete_version_btn", {
version: pageState.currentSecretVersion, version: this.state.currentSecretVersion,
}); });
} }
buttonsBlock.appendChild( buttonsBlock.appendChild(
@ -69,49 +70,49 @@ export class KeyValueSecretPage extends Page {
id: "deleteButton", id: "deleteButton",
class: ["uk-button", "uk-button-danger"], class: ["uk-button", "uk-button-danger"],
onclick: async () => { onclick: async () => {
await changePage("KEY_VALUE_DELETE"); await this.router.changePage("KEY_VALUE_DELETE");
}, },
text: deleteButtonText, text: deleteButtonText,
}), }),
); );
} }
if (caps.includes("update")) { if (caps.includes("update")) {
if (pageState.currentSecretVersion == null) { if (this.state.currentSecretVersion == null) {
buttonsBlock.appendChild( buttonsBlock.appendChild(
makeElement({ makeElement({
tag: "button", tag: "button",
id: "editButton", id: "editButton",
class: ["uk-button", "uk-margin", "uk-button-primary"], class: ["uk-button", "uk-margin", "uk-button-primary"],
onclick: async () => { onclick: async () => {
await changePage("KEY_VALUE_SECRET_EDIT"); await this.router.changePage("KEY_VALUE_SECRET_EDIT");
}, },
text: i18next.t("kv_secret_edit_btn"), text: i18next.t("kv_secret_edit_btn"),
}), }),
); );
} }
} }
if (pageState.currentMountType == "kv-v2") { if (this.state.currentMountType == "kv-v2") {
buttonsBlock.appendChild( buttonsBlock.appendChild(
makeElement({ makeElement({
tag: "button", tag: "button",
id: "versionsButton", id: "versionsButton",
class: ["uk-button", "uk-button-secondary"], class: ["uk-button", "uk-button-secondary"],
onclick: async () => { onclick: async () => {
await changePage("KEY_VALUE_VERSIONS"); await this.router.changePage("KEY_VALUE_VERSIONS");
}, },
text: i18next.t("kv_secret_versions_btn"), text: i18next.t("kv_secret_versions_btn"),
}), }),
); );
} }
void getSecret( const secretInfo = await getSecret(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentMountType, this.state.currentMountType,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
pageState.currentSecretVersion, this.state.currentSecretVersion,
).then((secretInfo) => { );
if (secretInfo == null && pageState.currentMountType == "kv-v2") { if (secretInfo == null && this.state.currentMountType == "kv-v2") {
document.querySelector("#buttonsBlock").remove(); document.querySelector("#buttonsBlock").remove();
document.getElementById("loadingText").remove(); document.getElementById("loadingText").remove();
@ -128,15 +129,14 @@ export class KeyValueSecretPage extends Page {
text: i18next.t("kv_secret_restore_btn"), text: i18next.t("kv_secret_restore_btn"),
id: "restoreButton", id: "restoreButton",
class: ["uk-button", "uk-button-primary"], class: ["uk-button", "uk-button-primary"],
onclick: () => { onclick: async () => {
void undeleteSecret( await undeleteSecret(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
pageState.currentSecretVersion, this.state.currentSecretVersion,
).then((_) => { );
void changePage(pageState.currentPageString); await this.router.changePage(this.state.currentPageString);
});
}, },
}), }),
); );
@ -169,7 +169,6 @@ export class KeyValueSecretPage extends Page {
}, this); }, this);
} }
document.getElementById("loadingText").remove(); document.getElementById("loadingText").remove();
});
} }
makeKVListElement(key: string, value: string): HTMLElement { makeKVListElement(key: string, value: string): HTMLElement {
return makeElement({ return makeElement({
@ -179,6 +178,10 @@ export class KeyValueSecretPage extends Page {
}); });
} }
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string { get name(): string {
return i18next.t("kv_secret_title"); return i18next.t("kv_secret_title");
} }

View file

@ -1,10 +1,10 @@
import { CodeJar } from "codejar"; import { CodeJar } from "codejar";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret";
import { getSecret } from "../../api/kv/getSecret"; import { getSecret } from "../../api/kv/getSecret";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import { sortedObjectMap, verifyJSONString } from "../../utils"; import { sortedObjectMap, verifyJSONString } from "../../utils";
import i18next from "i18next"; import i18next from "i18next";
@ -13,10 +13,9 @@ export class KeyValueSecretEditPage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("KEY_VALUE_SECRET"); await this.router.changePage("KEY_VALUE_SECRET");
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
const loadingText = makeElement({ const loadingText = makeElement({
tag: "p", tag: "p",
text: i18next.t("kv_sec_edit_loading"), text: i18next.t("kv_sec_edit_loading"),
@ -30,7 +29,7 @@ export class KeyValueSecretEditPage extends Page {
class: ["uk-button", "uk-button-primary"], class: ["uk-button", "uk-button-primary"],
text: i18next.t("kv_sec_edit_btn"), text: i18next.t("kv_sec_edit_btn"),
}); });
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -45,44 +44,43 @@ export class KeyValueSecretEditPage extends Page {
], ],
}), }),
); );
void getSecret( const secretInfo = await getSecret(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentMountType, this.state.currentMountType,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
).then((secretInfo) => { );
loadingText.remove(); loadingText.remove();
const secretsJSON = JSON.stringify(sortedObjectMap(secretInfo), null, 4); const secretsJSON = JSON.stringify(sortedObjectMap(secretInfo), null, 4);
const jar = CodeJar(editor, () => {}, { tab: " ".repeat(4) }); const jar = CodeJar(editor, () => {}, { tab: " ".repeat(4) });
jar.updateCode(secretsJSON); jar.updateCode(secretsJSON);
saveButton.onclick = function () { saveButton.onclick = async () => {
if (!verifyJSONString(jar.toString())) { if (!verifyJSONString(jar.toString())) {
setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); setErrorText(i18next.t("kv_sec_edit_invalid_json_err"));
return; return;
} }
createOrUpdateSecret( try {
pageState.currentBaseMount, await createOrUpdateSecret(
pageState.currentMountType, this.state.currentBaseMount,
pageState.currentSecretPath, this.state.currentMountType,
pageState.currentSecret, this.state.currentSecretPath,
this.state.currentSecret,
JSON.parse(jar.toString()), JSON.parse(jar.toString()),
) );
.then((_) => { await this.router.changePage("KEY_VALUE_SECRET");
void changePage("KEY_VALUE_SECRET"); } catch (e: unknown) {
return; const error = e as Error;
}) setErrorText(error.message);
.catch((e: Error) => { }
setErrorText(e.message);
});
}; };
});
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("kv_sec_edit_suffix"); return await SecretTitleElement(this.router, i18next.t("kv_sec_edit_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,9 +1,8 @@
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getSecretMetadata } from "../../api/kv/getSecretMetadata"; import { getSecretMetadata } from "../../api/kv/getSecretMetadata";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { objectToMap } from "../../utils"; import { objectToMap } from "../../utils";
import { pageState } from "../../globalPageState";
import i18next from "i18next"; import i18next from "i18next";
export class KeyValueVersionsPage extends Page { export class KeyValueVersionsPage extends Page {
@ -11,25 +10,23 @@ export class KeyValueVersionsPage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
if (pageState.currentSecretVersion != null) { if (this.state.currentSecretVersion != null) {
pageState.currentSecretVersion = null; this.state.currentSecretVersion = null;
} }
await changePage("KEY_VALUE_SECRET"); await this.router.changePage("KEY_VALUE_SECRET");
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
const versionsList = makeElement({ const versionsList = makeElement({
tag: "ul", tag: "ul",
id: "versionsList", id: "versionsList",
class: ["uk-nav", "uk-nav-default"], class: ["uk-nav", "uk-nav-default"],
}); });
setPageContent(versionsList); await this.router.setPageContent(versionsList);
const metadata = await getSecretMetadata( const metadata = await getSecretMetadata(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentSecretPath, this.state.currentSecretPath,
pageState.currentSecret, this.state.currentSecret,
); );
objectToMap(metadata.versions).forEach((_, ver) => { objectToMap(metadata.versions).forEach((_, ver) => {
@ -40,8 +37,8 @@ export class KeyValueVersionsPage extends Page {
tag: "a", tag: "a",
text: `v${ver}`, text: `v${ver}`,
onclick: async () => { onclick: async () => {
pageState.currentSecretVersion = ver; this.state.currentSecretVersion = ver;
await changePage("KEY_VALUE_SECRET"); await this.router.changePage("KEY_VALUE_SECRET");
}, },
}), }),
}), }),
@ -49,8 +46,8 @@ export class KeyValueVersionsPage extends Page {
}); });
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("kv_sec_versions_suffix"); return await SecretTitleElement(this.router, i18next.t("kv_sec_versions_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,9 +1,9 @@
import { DoesNotExistError } from "../../types/internalErrors"; import { DoesNotExistError } from "../../types/internalErrors";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getSecrets } from "../../api/kv/getSecrets"; import { getSecrets } from "../../api/kv/getSecrets";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class KeyValueViewPage extends Page { export class KeyValueViewPage extends Page {
@ -11,22 +11,20 @@ export class KeyValueViewPage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
if (pageState.currentSecretPath.length != 0) { if (this.state.currentSecretPath.length != 0) {
pageState.popCurrentSecretPath(); this.state.popCurrentSecretPath();
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} else { } else {
await changePage("HOME"); await this.router.changePage("HOME");
} }
} }
async render(): Promise<void> { async render(): Promise<void> {
pageState.currentSecret = ""; this.state.currentSecret = "";
setTitleElement(pageState);
const kvViewPageContent = makeElement({ tag: "div" }); const kvViewPageContent = makeElement({ tag: "div" });
setPageContent(kvViewPageContent); await this.router.setPageContent(kvViewPageContent);
if (pageState.currentMountType == "cubbyhole") { if (this.state.currentMountType == "cubbyhole") {
kvViewPageContent.appendChild( kvViewPageContent.appendChild(
makeElement({ makeElement({
tag: "p", tag: "p",
@ -40,16 +38,16 @@ export class KeyValueViewPage extends Page {
text: i18next.t("kv_view_new_btn"), text: i18next.t("kv_view_new_btn"),
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
onclick: async () => { onclick: async () => {
await changePage("KEY_VALUE_NEW_SECRET"); await this.router.changePage("KEY_VALUE_NEW_SECRET");
}, },
}); });
kvViewPageContent.appendChild(newButton); kvViewPageContent.appendChild(newButton);
try { try {
const res = await getSecrets( const res = await getSecrets(
pageState.currentBaseMount, this.state.currentBaseMount,
pageState.currentMountType, this.state.currentMountType,
pageState.currentSecretPath, this.state.currentSecretPath,
); );
kvViewPageContent.appendChild( kvViewPageContent.appendChild(
@ -57,7 +55,7 @@ export class KeyValueViewPage extends Page {
tag: "ul", tag: "ul",
class: ["uk-nav", "uk-nav-default"], class: ["uk-nav", "uk-nav-default"],
children: [ children: [
...res.map(function (secret) { ...res.map((secret) => {
return makeElement({ return makeElement({
tag: "li", tag: "li",
children: makeElement({ children: makeElement({
@ -65,11 +63,11 @@ export class KeyValueViewPage extends Page {
text: secret, text: secret,
onclick: async () => { onclick: async () => {
if (secret.endsWith("/")) { if (secret.endsWith("/")) {
pageState.pushCurrentSecretPath(secret); this.state.pushCurrentSecretPath(secret);
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} else { } else {
pageState.currentSecret = secret; this.state.currentSecret = secret;
await changePage("KEY_VALUE_SECRET"); await this.router.changePage("KEY_VALUE_SECRET");
} }
}, },
}), }),
@ -82,7 +80,7 @@ export class KeyValueViewPage extends Page {
const error = e as Error; const error = e as Error;
if (error == DoesNotExistError) { if (error == DoesNotExistError) {
// getSecrets also 404's on no keys so dont go all the way back. // getSecrets also 404's on no keys so dont go all the way back.
if (pageState.currentSecretPath.length != 0) { if (this.state.currentSecretPath.length != 0) {
return this.goBack(); return this.goBack();
} else { } else {
kvViewPageContent.appendChild( kvViewPageContent.appendChild(
@ -98,6 +96,10 @@ export class KeyValueViewPage extends Page {
} }
} }
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string { get name(): string {
return i18next.t("kv_view_title"); return i18next.t("kv_view_title");
} }

View file

@ -1,10 +1,9 @@
import { Margin } from "../elements/Margin"; import { Margin } from "../elements/Margin";
import { MarginInline } from "../elements/MarginInline"; import { MarginInline } from "../elements/MarginInline";
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { changePage, setErrorText, setPageContent } from "../pageUtils";
import { lookupSelf } from "../api/sys/lookupSelf"; import { lookupSelf } from "../api/sys/lookupSelf";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState"; import { setErrorText } from "../pageUtils";
import { usernameLogin } from "../api/auth/usernameLogin"; import { usernameLogin } from "../api/auth/usernameLogin";
import i18next from "i18next"; import i18next from "i18next";
@ -83,7 +82,7 @@ export class LoginPage extends Page {
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -132,15 +131,15 @@ export class LoginPage extends Page {
}), }),
); );
tokenLoginForm.addEventListener("submit", async function (e) { tokenLoginForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(tokenLoginForm); const formData = new FormData(tokenLoginForm);
const token = formData.get("token"); const token = formData.get("token");
pageState.token = token as string; this.state.token = token as string;
try { try {
await lookupSelf(); await lookupSelf();
await changePage("HOME"); await this.router.changePage("HOME");
} catch (e: unknown) { } catch (e: unknown) {
const error = e as Error; const error = e as Error;
document.getElementById("tokenInput").classList.add("uk-form-danger"); document.getElementById("tokenInput").classList.add("uk-form-danger");
@ -151,7 +150,7 @@ export class LoginPage extends Page {
} }
} }
}); });
usernameLoginForm.addEventListener("submit", async function (e) { usernameLoginForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(usernameLoginForm); const formData = new FormData(usernameLoginForm);
@ -160,8 +159,8 @@ export class LoginPage extends Page {
formData.get("username") as string, formData.get("username") as string,
formData.get("password") as string, formData.get("password") as string,
); );
pageState.token = res; this.state.token = res;
await changePage("HOME"); await this.router.changePage("HOME");
} catch (e: unknown) { } catch (e: unknown) {
const error = e as Error; const error = e as Error;
document.getElementById("usernameInput").classList.add("uk-form-danger"); document.getElementById("usernameInput").classList.add("uk-form-danger");

View file

@ -1,14 +1,7 @@
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { import { addClipboardNotifications, prePageChecks, setErrorText } from "../pageUtils";
addClipboardNotifications,
changePage,
prePageChecks,
setErrorText,
setPageContent,
} from "../pageUtils";
import { getCapabilitiesPath } from "../api/sys/getCapabilities"; import { getCapabilitiesPath } from "../api/sys/getCapabilities";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState";
import { renewSelf } from "../api/sys/renewSelf"; import { renewSelf } from "../api/sys/renewSelf";
import { sealVault } from "../api/sys/sealVault"; import { sealVault } from "../api/sys/sealVault";
import ClipboardJS from "clipboard"; import ClipboardJS from "clipboard";
@ -20,8 +13,8 @@ export class MePage extends Page {
} }
async render(): Promise<void> { async render(): Promise<void> {
if (!(await prePageChecks())) return; if (!(await prePageChecks(this.router))) return;
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "ul", tag: "ul",
class: "uk-nav", class: "uk-nav",
@ -32,8 +25,8 @@ export class MePage extends Page {
tag: "a", tag: "a",
text: i18next.t("log_out_btn"), text: i18next.t("log_out_btn"),
onclick: async () => { onclick: async () => {
pageState.token = ""; this.state.token = "";
await changePage("HOME"); await this.router.changePage("HOME");
}, },
}), }),
}), }),
@ -43,7 +36,7 @@ export class MePage extends Page {
tag: "a", tag: "a",
text: i18next.t("copy_token_btn"), text: i18next.t("copy_token_btn"),
attributes: { attributes: {
"data-clipboard-text": pageState.token, "data-clipboard-text": this.state.token,
}, },
thenRun: (e) => { thenRun: (e) => {
const clipboard = new ClipboardJS(e); const clipboard = new ClipboardJS(e);
@ -59,7 +52,7 @@ export class MePage extends Page {
onclick: () => { onclick: () => {
renewSelf() renewSelf()
.then(() => { .then(() => {
void changePage("HOME"); void this.router.changePage("HOME");
}) })
.catch((e: Error) => { .catch((e: Error) => {
setErrorText(e.message); setErrorText(e.message);
@ -82,7 +75,7 @@ export class MePage extends Page {
text: i18next.t("seal_vault_btn"), text: i18next.t("seal_vault_btn"),
onclick: async () => { onclick: async () => {
await sealVault(); await sealVault();
await changePage("UNSEAL_VAULT"); await this.router.changePage("UNSEAL_VAULT");
}, },
}), }),
}), }),
@ -92,7 +85,7 @@ export class MePage extends Page {
tag: "a", tag: "a",
text: i18next.t("change_language_btn"), text: i18next.t("change_language_btn"),
onclick: async () => { onclick: async () => {
await changePage("SET_LANGUAGE"); await this.router.changePage("SET_LANGUAGE");
}, },
}), }),
}), }),

View file

@ -1,10 +1,9 @@
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Option } from "../../elements/Option"; import { Option } from "../../elements/Option";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent } from "../../pageUtils";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { newMount } from "../../api/sys/newMount"; import { newMount } from "../../api/sys/newMount";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class NewKVEnginePage extends Page { export class NewKVEnginePage extends Page {
@ -56,9 +55,9 @@ export class NewKVEnginePage extends Page {
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(newEngineForm); await this.router.setPageContent(newEngineForm);
newEngineForm.addEventListener("submit", async function (e) { newEngineForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(newEngineForm); const formData = new FormData(newEngineForm);
@ -73,9 +72,9 @@ export class NewKVEnginePage extends Page {
version: version, version: version,
}, },
}); });
pageState.currentMountType = "kv-v" + version; this.state.currentMountType = "kv-v" + version;
pageState.currentBaseMount = name + "/"; this.state.currentBaseMount = name + "/";
await changePage("KEY_VALUE_VIEW"); await this.router.changePage("KEY_VALUE_VIEW");
} catch (e) { } catch (e) {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);

View file

@ -1,9 +1,8 @@
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent } from "../../pageUtils";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { newMount } from "../../api/sys/newMount"; import { newMount } from "../../api/sys/newMount";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class NewTOTPEnginePage extends Page { export class NewTOTPEnginePage extends Page {
@ -42,9 +41,9 @@ export class NewTOTPEnginePage extends Page {
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(newEngineForm); await this.router.setPageContent(newEngineForm);
newEngineForm.addEventListener("submit", async function (e) { newEngineForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(newEngineForm); const formData = new FormData(newEngineForm);
@ -55,9 +54,9 @@ export class NewTOTPEnginePage extends Page {
name: name, name: name,
type: "totp", type: "totp",
}); });
pageState.currentMountType = "totp"; this.state.currentMountType = "totp";
pageState.currentBaseMount = name + "/"; this.state.currentBaseMount = name + "/";
await changePage("TOTP"); await this.router.changePage("TOTP");
} catch (e) { } catch (e) {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);

View file

@ -1,9 +1,8 @@
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent } from "../../pageUtils";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { newMount } from "../../api/sys/newMount"; import { newMount } from "../../api/sys/newMount";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class NewTransitEnginePage extends Page { export class NewTransitEnginePage extends Page {
@ -42,9 +41,9 @@ export class NewTransitEnginePage extends Page {
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(newEngineForm); await this.router.setPageContent(newEngineForm);
newEngineForm.addEventListener("submit", async function (e) { newEngineForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(newEngineForm); const formData = new FormData(newEngineForm);
@ -55,9 +54,9 @@ export class NewTransitEnginePage extends Page {
name: name, name: name,
type: "transit", type: "transit",
}); });
pageState.currentMountType = "transit"; this.state.currentMountType = "transit";
pageState.currentBaseMount = name + "/"; this.state.currentBaseMount = name + "/";
await changePage("TRANSIT_VIEW"); await this.router.changePage("TRANSIT_VIEW");
} catch (e) { } catch (e) {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);

View file

@ -1,6 +1,5 @@
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { Tile } from "../elements/Tile"; import { Tile } from "../elements/Tile";
import { changePage, setPageContent } from "../pageUtils";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import i18next from "i18next"; import i18next from "i18next";
@ -10,7 +9,7 @@ export class NewSecretsEnginePage extends Page {
} }
async render(): Promise<void> { async render(): Promise<void> {
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
class: "uk-child-width-1-1@s uk-child-width-1-2@m uk-grid-small uk-grid-match", class: "uk-child-width-1-1@s uk-child-width-1-2@m uk-grid-small uk-grid-match",
@ -19,22 +18,22 @@ export class NewSecretsEnginePage extends Page {
Tile({ Tile({
title: i18next.t("new_secrets_engine_kv_title"), title: i18next.t("new_secrets_engine_kv_title"),
description: i18next.t("new_secrets_engine_kv_description"), description: i18next.t("new_secrets_engine_kv_description"),
onclick: () => { onclick: async () => {
void changePage("NEW_KV_ENGINE"); await this.router.changePage("NEW_KV_ENGINE");
}, },
}), }),
Tile({ Tile({
title: i18next.t("new_secrets_engine_totp_title"), title: i18next.t("new_secrets_engine_totp_title"),
description: i18next.t("new_secrets_engine_totp_description"), description: i18next.t("new_secrets_engine_totp_description"),
onclick: () => { onclick: async () => {
void changePage("NEW_TOTP_ENGINE"); await this.router.changePage("NEW_TOTP_ENGINE");
}, },
}), }),
Tile({ Tile({
title: i18next.t("new_secrets_engine_transit_title"), title: i18next.t("new_secrets_engine_transit_title"),
description: i18next.t("new_secrets_engine_transit_description"), description: i18next.t("new_secrets_engine_transit_description"),
onclick: () => { onclick: async () => {
void changePage("NEW_TRANSIT_ENGINE"); await this.router.changePage("NEW_TRANSIT_ENGINE");
}, },
}), }),
], ],

View file

@ -1,9 +1,8 @@
import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox"; import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox";
import { Margin } from "../elements/Margin"; import { Margin } from "../elements/Margin";
import { Option } from "../elements/Option"; import { Option } from "../elements/Option";
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { setPageContent } from "../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
const passwordLengthMin = 1; const passwordLengthMin = 1;
@ -59,7 +58,7 @@ export class PwGenPage extends Page {
passwordForm: HTMLFormElement; passwordForm: HTMLFormElement;
async render(): Promise<void> { async render(): Promise<void> {
setPageContent(""); await this.router.setPageContent("");
this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault)); this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault));
this.passwordLengthTitle = makeElement({ this.passwordLengthTitle = makeElement({
@ -110,7 +109,7 @@ export class PwGenPage extends Page {
}) as HTMLFormElement; }) as HTMLFormElement;
this.passwordForm.addEventListener("submit", (e) => this.formEvent(e)); this.passwordForm.addEventListener("submit", (e) => this.formEvent(e));
setPageContent(this.passwordForm); await this.router.setPageContent(this.passwordForm);
} }
getPasswordLengthText(): string { getPasswordLengthText(): string {

View file

@ -1,8 +1,6 @@
import { Margin } from "../elements/Margin"; import { Margin } from "../elements/Margin";
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { changePage, setPageContent } from "../pageUtils";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState";
import { reloadNavBar } from "../elements/NavBar"; import { reloadNavBar } from "../elements/NavBar";
import i18next from "i18next"; import i18next from "i18next";
@ -51,18 +49,18 @@ export class SetLanguagePage extends Page {
}), }),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(setLanguageForm); await this.router.setPageContent(setLanguageForm);
setLanguageForm.addEventListener("submit", async function (e) { setLanguageForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(setLanguageForm); const formData = new FormData(setLanguageForm);
const language = formData.get("language") as string; const language = formData.get("language") as string;
pageState.language = language; this.state.language = language;
const t = await i18next.changeLanguage(language); const t = await i18next.changeLanguage(language);
pageState.pageDirection = t("language_direction"); this.state.pageDirection = t("language_direction");
reloadNavBar(); reloadNavBar(this.router);
await changePage("HOME"); await this.router.changePage("HOME");
}); });
} }
get name(): string { get name(): string {

View file

@ -1,14 +1,12 @@
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { changePage, setPageContent } from "../pageUtils";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState";
export class SetVaultURLPage extends Page { export class SetVaultURLPage extends Page {
constructor() { constructor() {
super(); super();
} }
async render(): Promise<void> { async render(): Promise<void> {
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "form", tag: "form",
id: "setVaultURLForm", id: "setVaultURLForm",
@ -43,11 +41,11 @@ export class SetVaultURLPage extends Page {
], ],
}), }),
); );
document.getElementById("setVaultURLForm").addEventListener("submit", async function (e) { document.getElementById("setVaultURLForm").addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(document.querySelector("#setVaultURLForm")); const formData = new FormData(document.querySelector("#setVaultURLForm"));
pageState.apiURL = formData.get("vaultURL") as string; this.state.apiURL = formData.get("vaultURL") as string;
await changePage("HOME"); await this.router.changePage("HOME");
}); });
} }
get name(): string { get name(): string {

View file

@ -1,10 +1,10 @@
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { MarginInline } from "../../elements/MarginInline"; import { MarginInline } from "../../elements/MarginInline";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { addNewTOTP } from "../../api/totp/addNewTOTP"; import { addNewTOTP } from "../../api/totp/addNewTOTP";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
function replaceAll(str: string, replace: string, replaceWith: string): string { function replaceAll(str: string, replace: string, replaceWith: string): string {
@ -21,11 +21,9 @@ export class NewTOTPPage extends Page {
super(); super();
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("TOTP"); await this.router.changePage("TOTP");
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
const totpForm = makeElement({ const totpForm = makeElement({
tag: "form", tag: "form",
children: [ children: [
@ -84,9 +82,9 @@ export class NewTOTPPage extends Page {
), ),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(totpForm); await this.router.setPageContent(totpForm);
totpForm.addEventListener("submit", async function (e) { totpForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(totpForm); const formData = new FormData(totpForm);
@ -99,8 +97,8 @@ export class NewTOTPPage extends Page {
}; };
try { try {
await addNewTOTP(pageState.currentBaseMount, parms); await addNewTOTP(this.state.currentBaseMount, parms);
await changePage("TOTP"); await this.router.changePage("TOTP");
} catch (e: unknown) { } catch (e: unknown) {
const error = e as Error; const error = e as Error;
setErrorText(`API Error: ${error.message}`); setErrorText(`API Error: ${error.message}`);
@ -108,8 +106,8 @@ export class NewTOTPPage extends Page {
}); });
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("totp_new_suffix"); return await SecretTitleElement(this.router, i18next.t("totp_new_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,12 +1,12 @@
import { CopyableInputBox } from "../../elements/CopyableInputBox"; import { CopyableInputBox } from "../../elements/CopyableInputBox";
import { DoesNotExistError } from "../../types/internalErrors"; import { DoesNotExistError } from "../../types/internalErrors";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getTOTPCode } from "../../api/totp/getTOTPCode"; import { getTOTPCode } from "../../api/totp/getTOTPCode";
import { getTOTPKeys } from "../../api/totp/getTOTPKeys"; import { getTOTPKeys } from "../../api/totp/getTOTPKeys";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { objectToMap } from "../../utils"; import { objectToMap } from "../../utils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export interface TOTPListElement extends HTMLElement { export interface TOTPListElement extends HTMLElement {
@ -24,9 +24,8 @@ export class TOTPViewPage extends Page {
totpListElements: Record<string, TOTPListElement>; totpListElements: Record<string, TOTPListElement>;
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
const totpList = makeElement({ tag: "div" }); const totpList = makeElement({ tag: "div" });
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -35,7 +34,7 @@ export class TOTPViewPage extends Page {
text: i18next.t("totp_view_new_btn"), text: i18next.t("totp_view_new_btn"),
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
onclick: async () => { onclick: async () => {
await changePage("NEW_TOTP"); await this.router.changePage("NEW_TOTP");
}, },
}), }),
makeElement({ makeElement({
@ -51,7 +50,7 @@ export class TOTPViewPage extends Page {
); );
try { try {
const res = await getTOTPKeys(pageState.currentBaseMount); const res = await getTOTPKeys(this.state.currentBaseMount);
for (const totpKeyName of res) { for (const totpKeyName of res) {
const totpListElement = this.makeTOTPListElement(totpKeyName); const totpListElement = this.makeTOTPListElement(totpKeyName);
totpList.appendChild(totpListElement); totpList.appendChild(totpListElement);
@ -88,7 +87,7 @@ export class TOTPViewPage extends Page {
} }
async updateTOTPElement(totpKeyName: string, totpListElement: TOTPListElement): Promise<void> { async updateTOTPElement(totpKeyName: string, totpListElement: TOTPListElement): Promise<void> {
totpListElement.setCode(await getTOTPCode(pageState.currentBaseMount, totpKeyName)); totpListElement.setCode(await getTOTPCode(this.state.currentBaseMount, totpKeyName));
} }
makeTOTPListElement(totpKeyName: string): TOTPListElement { makeTOTPListElement(totpKeyName: string): TOTPListElement {
@ -106,6 +105,10 @@ export class TOTPViewPage extends Page {
return gridElement; return gridElement;
} }
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string { get name(): string {
return i18next.t("totp_view_title"); return i18next.t("totp_view_title");
} }

View file

@ -1,10 +1,10 @@
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Option } from "../../elements/Option"; import { Option } from "../../elements/Option";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { newTransitKey } from "../../api/transit/newTransitKey"; import { newTransitKey } from "../../api/transit/newTransitKey";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class NewTransitKeyPage extends Page { export class NewTransitKeyPage extends Page {
@ -12,8 +12,6 @@ export class NewTransitKeyPage extends Page {
super(); super();
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState);
const newTransitKeyForm = makeElement({ const newTransitKeyForm = makeElement({
tag: "form", tag: "form",
children: [ children: [
@ -66,9 +64,9 @@ export class NewTransitKeyPage extends Page {
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(newTransitKeyForm); await this.router.setPageContent(newTransitKeyForm);
newTransitKeyForm.addEventListener("submit", async function (e) { newTransitKeyForm.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
const formData = new FormData(newTransitKeyForm); const formData = new FormData(newTransitKeyForm);
@ -76,12 +74,12 @@ export class NewTransitKeyPage extends Page {
const type = formData.get("type") as string; const type = formData.get("type") as string;
try { try {
await newTransitKey(pageState.currentBaseMount, { await newTransitKey(this.state.currentBaseMount, {
name: name, name: name,
type: type, type: type,
}); });
pageState.currentSecret = name; this.state.currentSecret = name;
await changePage("TRANSIT_VIEW_SECRET"); await this.router.changePage("TRANSIT_VIEW_SECRET");
} catch (e) { } catch (e) {
const error = e as Error; const error = e as Error;
setErrorText(error.message); setErrorText(error.message);
@ -89,8 +87,8 @@ export class NewTransitKeyPage extends Page {
}); });
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("transit_new_key_suffix"); return await SecretTitleElement(this.router, i18next.t("transit_new_key_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,10 +1,10 @@
import { CopyableModal } from "../../elements/CopyableModal"; import { CopyableModal } from "../../elements/CopyableModal";
import { FileUploadInput } from "../../elements/FileUploadInput"; import { FileUploadInput } from "../../elements/FileUploadInput";
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { fileToBase64, makeElement } from "../../htmlUtils"; import { fileToBase64, makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import { transitDecrypt } from "../../api/transit/transitDecrypt"; import { transitDecrypt } from "../../api/transit/transitDecrypt";
import i18next from "i18next"; import i18next from "i18next";
@ -14,14 +14,13 @@ export class TransitDecryptPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("TRANSIT_VIEW_SECRET"); await this.router.changePage("TRANSIT_VIEW_SECRET");
} }
transitDecryptForm: HTMLFormElement; transitDecryptForm: HTMLFormElement;
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); await this.router.setPageContent(
setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
}), }),
@ -74,7 +73,7 @@ export class TransitDecryptPage extends Page {
}), }),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.transitDecryptForm); await this.router.setPageContent(this.transitDecryptForm);
this.transitDecryptForm.addEventListener("submit", async (e: Event) => { this.transitDecryptForm.addEventListener("submit", async (e: Event) => {
e.preventDefault(); e.preventDefault();
await this.transitDecryptFormHandler(); await this.transitDecryptFormHandler();
@ -96,7 +95,7 @@ export class TransitDecryptPage extends Page {
} }
try { try {
const res = await transitDecrypt(pageState.currentBaseMount, pageState.currentSecret, { const res = await transitDecrypt(this.state.currentBaseMount, this.state.currentSecret, {
ciphertext: ciphertext, ciphertext: ciphertext,
}); });
let plaintext = res.plaintext; let plaintext = res.plaintext;
@ -115,8 +114,8 @@ export class TransitDecryptPage extends Page {
} }
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("transit_decrypt_suffix"); return await SecretTitleElement(this.router, i18next.t("transit_decrypt_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,10 +1,10 @@
import { CopyableModal } from "../../elements/CopyableModal"; import { CopyableModal } from "../../elements/CopyableModal";
import { FileUploadInput } from "../../elements/FileUploadInput"; import { FileUploadInput } from "../../elements/FileUploadInput";
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { fileToBase64, makeElement } from "../../htmlUtils"; import { fileToBase64, makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import { transitEncrypt } from "../../api/transit/transitEncrypt"; import { transitEncrypt } from "../../api/transit/transitEncrypt";
import i18next from "i18next"; import i18next from "i18next";
@ -14,14 +14,13 @@ export class TransitEncryptPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("TRANSIT_VIEW_SECRET"); await this.router.changePage("TRANSIT_VIEW_SECRET");
} }
transitEncryptForm: HTMLFormElement; transitEncryptForm: HTMLFormElement;
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); await this.router.setPageContent(
setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
}), }),
@ -74,7 +73,7 @@ export class TransitEncryptPage extends Page {
}), }),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.transitEncryptForm); await this.router.setPageContent(this.transitEncryptForm);
this.transitEncryptForm.addEventListener("submit", async (e: Event) => { this.transitEncryptForm.addEventListener("submit", async (e: Event) => {
e.preventDefault(); e.preventDefault();
@ -98,7 +97,7 @@ export class TransitEncryptPage extends Page {
} }
try { try {
const res = await transitEncrypt(pageState.currentBaseMount, pageState.currentSecret, { const res = await transitEncrypt(this.state.currentBaseMount, this.state.currentSecret, {
plaintext: plaintext, plaintext: plaintext,
}); });
const modal = CopyableModal( const modal = CopyableModal(
@ -113,8 +112,8 @@ export class TransitEncryptPage extends Page {
} }
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("transit_encrypt_suffix"); return await SecretTitleElement(this.router, i18next.t("transit_encrypt_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,12 +1,12 @@
import { CopyableModal } from "../../elements/CopyableModal"; import { CopyableModal } from "../../elements/CopyableModal";
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Option } from "../../elements/Option"; import { Option } from "../../elements/Option";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getTransitKey } from "../../api/transit/getTransitKey"; import { getTransitKey } from "../../api/transit/getTransitKey";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { objectToMap } from "../../utils"; import { objectToMap } from "../../utils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import { transitRewrap } from "../../api/transit/transitRewrap"; import { transitRewrap } from "../../api/transit/transitRewrap";
import i18next from "i18next"; import i18next from "i18next";
@ -18,14 +18,13 @@ export class TransitRewrapPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("TRANSIT_VIEW_SECRET"); await this.router.changePage("TRANSIT_VIEW_SECRET");
} }
transitRewrapForm: HTMLFormElement; transitRewrapForm: HTMLFormElement;
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); const transitKey = await getTransitKey(this.state.currentBaseMount, this.state.currentSecret);
const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret);
const stringVersions = Array.from( const stringVersions = Array.from(
objectToMap(transitKey.keys).keys(), objectToMap(transitKey.keys).keys(),
@ -47,7 +46,7 @@ export class TransitRewrapPage extends Page {
}; };
}); });
setPageContent(""); await this.router.setPageContent("");
this.transitRewrapForm = makeElement({ this.transitRewrapForm = makeElement({
tag: "form", tag: "form",
children: [ children: [
@ -82,7 +81,7 @@ export class TransitRewrapPage extends Page {
}), }),
], ],
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.transitRewrapForm); await this.router.setPageContent(this.transitRewrapForm);
this.transitRewrapForm.addEventListener("submit", async (e: Event) => { this.transitRewrapForm.addEventListener("submit", async (e: Event) => {
e.preventDefault(); e.preventDefault();
@ -93,7 +92,7 @@ export class TransitRewrapPage extends Page {
async transitRewrapFormHandler(): Promise<void> { async transitRewrapFormHandler(): Promise<void> {
const formData = new FormData(this.transitRewrapForm); const formData = new FormData(this.transitRewrapForm);
try { try {
const res = await transitRewrap(pageState.currentBaseMount, pageState.currentSecret, { const res = await transitRewrap(this.state.currentBaseMount, this.state.currentSecret, {
ciphertext: formData.get("ciphertext") as string, ciphertext: formData.get("ciphertext") as string,
key_version: parseInt(formData.get("version") as string, 10), key_version: parseInt(formData.get("version") as string, 10),
}); });
@ -106,8 +105,8 @@ export class TransitRewrapPage extends Page {
} }
} }
get titleSuffix(): string { async getPageTitle(): Promise<Element | string> {
return i18next.t("transit_rewrap_suffix"); return await SecretTitleElement(this.router, i18next.t("transit_rewrap_suffix"));
} }
get name(): string { get name(): string {

View file

@ -1,9 +1,9 @@
import { DoesNotExistError } from "../../types/internalErrors"; import { DoesNotExistError } from "../../types/internalErrors";
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { getTransitKeys } from "../../api/transit/getTransitKeys"; import { getTransitKeys } from "../../api/transit/getTransitKeys";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { setErrorText } from "../../pageUtils";
import i18next from "i18next"; import i18next from "i18next";
export class TransitViewPage extends Page { export class TransitViewPage extends Page {
@ -12,44 +12,42 @@ export class TransitViewPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("HOME"); await this.router.changePage("HOME");
} }
async render(): Promise<void> { async render(): Promise<void> {
pageState.currentSecret = ""; this.state.currentSecret = "";
setTitleElement(pageState);
const transitViewContent = makeElement({ tag: "div" }); const transitViewContent = makeElement({ tag: "div" });
setPageContent(transitViewContent); await this.router.setPageContent(transitViewContent);
const newButton = makeElement({ const newButton = makeElement({
tag: "button", tag: "button",
text: "New", text: "New",
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
onclick: () => { onclick: async () => {
void changePage("TRANSIT_NEW_KEY"); await this.router.changePage("TRANSIT_NEW_KEY");
}, },
}); });
transitViewContent.appendChild(newButton); transitViewContent.appendChild(newButton);
try { try {
const res = await getTransitKeys(pageState.currentBaseMount); const res = await getTransitKeys(this.state.currentBaseMount);
transitViewContent.appendChild( transitViewContent.appendChild(
makeElement({ makeElement({
tag: "ul", tag: "ul",
class: ["uk-nav", "uk-nav-default"], class: ["uk-nav", "uk-nav-default"],
children: [ children: [
...res.map(function (secret) { ...res.map((secret) => {
return makeElement({ return makeElement({
tag: "li", tag: "li",
children: makeElement({ children: makeElement({
tag: "a", tag: "a",
text: secret, text: secret,
onclick: () => { onclick: async () => {
pageState.currentSecret = secret; this.state.currentSecret = secret;
void changePage("TRANSIT_VIEW_SECRET"); await this.router.changePage("TRANSIT_VIEW_SECRET");
}, },
}), }),
}); });
@ -72,6 +70,10 @@ export class TransitViewPage extends Page {
} }
} }
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string { get name(): string {
return i18next.t("transit_view_title"); return i18next.t("transit_view_title");
} }

View file

@ -1,9 +1,8 @@
import { Page } from "../../types/Page"; import { Page } from "../../PageSystem/Page";
import { SecretTitleElement } from "../../elements/SecretTitleElement";
import { Tile } from "../../elements/Tile"; import { Tile } from "../../elements/Tile";
import { changePage, setPageContent, setTitleElement } from "../../pageUtils";
import { getTransitKey } from "../../api/transit/getTransitKey"; import { getTransitKey } from "../../api/transit/getTransitKey";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState";
import i18next from "i18next"; import i18next from "i18next";
export class TransitViewSecretPage extends Page { export class TransitViewSecretPage extends Page {
@ -12,15 +11,13 @@ export class TransitViewSecretPage extends Page {
} }
async goBack(): Promise<void> { async goBack(): Promise<void> {
await changePage("TRANSIT_VIEW"); await this.router.changePage("TRANSIT_VIEW");
} }
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); const transitKey = await getTransitKey(this.state.currentBaseMount, this.state.currentSecret);
const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); await this.router.setPageContent(
setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
class: "uk-child-width-1-1@s uk-child-width-1-2@m uk-grid-small uk-grid-match", class: "uk-child-width-1-1@s uk-child-width-1-2@m uk-grid-small uk-grid-match",
@ -32,8 +29,8 @@ export class TransitViewSecretPage extends Page {
description: i18next.t("transit_view_encrypt_description"), description: i18next.t("transit_view_encrypt_description"),
icon: "lock", icon: "lock",
iconText: i18next.t("transit_view_encrypt_icon_text"), iconText: i18next.t("transit_view_encrypt_icon_text"),
onclick: () => { onclick: async () => {
void changePage("TRANSIT_ENCRYPT"); await this.router.changePage("TRANSIT_ENCRYPT");
}, },
}), }),
Tile({ Tile({
@ -42,8 +39,8 @@ export class TransitViewSecretPage extends Page {
description: i18next.t("transit_view_decrypt_description"), description: i18next.t("transit_view_decrypt_description"),
icon: "mail", icon: "mail",
iconText: i18next.t("transit_view_decrypt_icon_text"), iconText: i18next.t("transit_view_decrypt_icon_text"),
onclick: () => { onclick: async () => {
void changePage("TRANSIT_DECRYPT"); await this.router.changePage("TRANSIT_DECRYPT");
}, },
}), }),
Tile({ Tile({
@ -52,8 +49,8 @@ export class TransitViewSecretPage extends Page {
description: i18next.t("transit_view_rewrap_description"), description: i18next.t("transit_view_rewrap_description"),
icon: "code", icon: "code",
iconText: i18next.t("transit_view_rewrap_icon_text"), iconText: i18next.t("transit_view_rewrap_icon_text"),
onclick: () => { onclick: async () => {
void changePage("TRANSIT_REWRAP"); await this.router.changePage("TRANSIT_REWRAP");
}, },
}), }),
], ],
@ -61,6 +58,10 @@ export class TransitViewSecretPage extends Page {
); );
} }
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string { get name(): string {
return i18next.t("transit_view_secret_title"); return i18next.t("transit_view_secret_title");
} }

View file

@ -1,9 +1,9 @@
import { MarginInline } from "../elements/MarginInline"; import { MarginInline } from "../elements/MarginInline";
import { Page } from "../types/Page"; import { Page } from "../PageSystem/Page";
import { QRScanner, QRScannerType } from "../elements/QRScanner"; import { QRScanner, QRScannerType } from "../elements/QRScanner";
import { SealStatusType, getSealStatus } from "../api/sys/getSealStatus"; import { SealStatusType, getSealStatus } from "../api/sys/getSealStatus";
import { changePage, setErrorText, setPageContent } from "../pageUtils";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { setErrorText } from "../pageUtils";
import { submitUnsealKey } from "../api/sys/submitUnsealKey"; import { submitUnsealKey } from "../api/sys/submitUnsealKey";
import i18next from "i18next"; import i18next from "i18next";
@ -68,7 +68,7 @@ export class UnsealPage extends Page {
this.unsealInputContent = makeElement({ this.unsealInputContent = makeElement({
tag: "div", tag: "div",
}); });
setPageContent( await this.router.setPageContent(
makeElement({ makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -169,7 +169,7 @@ export class UnsealPage extends Page {
progressBar.max = keysNeeded; progressBar.max = keysNeeded;
if (!data.sealed) { if (!data.sealed) {
progressBar.value = keysNeeded; progressBar.value = keysNeeded;
await changePage("HOME"); await this.router.changePage("HOME");
} }
} }

View file

@ -1,7 +1,5 @@
import { PageRouter } from "./PageRouter"; import { PageRouter } from "./PageSystem/PageRouter";
import { PageState } from "./PageState"; import { PageState } from "./PageState";
import { pageRouter } from "./globalPageRouter";
import { pageState } from "./globalPageState";
import i18next from "i18next"; import i18next from "i18next";
// Playground is a way to debug and test things. // Playground is a way to debug and test things.
@ -18,9 +16,9 @@ declare global {
} }
// Please empty this function before committing. // Please empty this function before committing.
export async function playground(): Promise<void> { export async function playground(router: PageRouter): Promise<void> {
console.log("Welcome to Playground!"); console.log("Welcome to Playground!");
window.pageState = pageState; window.pageState = router.state;
window.i18next = i18next; window.i18next = i18next;
window.router = pageRouter; window.router = router;
} }

View file

@ -1,20 +0,0 @@
import { changePage } from "../pageUtils";
export class Page {
constructor() {
// Do Nothing
}
async render(): Promise<void> {}
get name(): string {
return "Page";
}
get titleSuffix(): string {
return "";
}
async goBack(): Promise<void> {
await changePage("HOME");
}
async cleanup(): Promise<void> {
// Do Nothing
}
}