From 67bd89db1af7c27839f441746e487f1aad927484 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Sat, 15 May 2021 10:54:39 +0100 Subject: [PATCH] Rework PageRouter, Page, pageContent and SecretTitleElement. --- src/PageState.ts | 2 +- src/PageSystem/Page.ts | 29 ++++ src/{ => PageSystem}/PageRouter.ts | 37 ++++- src/allPages.ts | 2 +- src/elements/NavBar.ts | 16 +- src/elements/SecretTitleElement.ts | 57 +++++++ src/globalPageRouter.ts | 6 - src/main.ts | 11 +- src/pageUtils.ts | 103 ++----------- src/pages/Home.ts | 37 +++-- src/pages/KeyValue/KeyValueDelete.ts | 34 ++--- src/pages/KeyValue/KeyValueNew.ts | 25 ++-- src/pages/KeyValue/KeyValueSecret.ts | 175 +++++++++++----------- src/pages/KeyValue/KeyValueSecretsEdit.ts | 74 +++++---- src/pages/KeyValue/KeyValueVersions.ts | 29 ++-- src/pages/KeyValue/KeyValueView.ts | 46 +++--- src/pages/Login.ts | 19 ++- src/pages/Me.ts | 27 ++-- src/pages/NewEngines/NewKVEngine.ts | 15 +- src/pages/NewEngines/NewTOTPEngine.ts | 15 +- src/pages/NewEngines/NewTransitEngine.ts | 15 +- src/pages/NewSecretsEngine.ts | 17 +-- src/pages/PwGen.ts | 7 +- src/pages/SetLanguage.ts | 16 +- src/pages/SetVaultURL.ts | 12 +- src/pages/TOTP/NewTOTP.ts | 22 ++- src/pages/TOTP/TOTPView.ts | 19 ++- src/pages/Transit/NewTransitKey.ts | 22 ++- src/pages/Transit/TransitDecrypt.ts | 19 ++- src/pages/Transit/TransitEncrypt.ts | 19 ++- src/pages/Transit/TransitRewrap.ts | 21 ++- src/pages/Transit/TransitView.ts | 32 ++-- src/pages/Transit/TransitViewSecret.ts | 29 ++-- src/pages/Unseal.ts | 8 +- src/playground.ts | 10 +- src/types/Page.ts | 20 --- 36 files changed, 515 insertions(+), 532 deletions(-) create mode 100644 src/PageSystem/Page.ts rename src/{ => PageSystem}/PageRouter.ts (64%) create mode 100644 src/elements/SecretTitleElement.ts delete mode 100644 src/globalPageRouter.ts delete mode 100644 src/types/Page.ts diff --git a/src/PageState.ts b/src/PageState.ts index 7105515..80c6c19 100644 --- a/src/PageState.ts +++ b/src/PageState.ts @@ -1,4 +1,4 @@ -import { Page } from "./types/Page"; +import { Page } from "./PageSystem/Page"; import { allPages } from "./allPages"; import { getKeyByObjectPropertyValue } from "./utils"; diff --git a/src/PageSystem/Page.ts b/src/PageSystem/Page.ts new file mode 100644 index 0000000..a617808 --- /dev/null +++ b/src/PageSystem/Page.ts @@ -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 {} + get name(): string { + return "Page"; + } + async getPageTitle(): Promise { + return this.name; + } + async goBack(): Promise { + await this.router.changePage("HOME"); + } + async cleanup(): Promise { + // Do Nothing + } + async setRouterAndState(router: PageRouter, state: PageState): Promise { + this.router = router; + this.state = state; + } +} diff --git a/src/PageRouter.ts b/src/PageSystem/PageRouter.ts similarity index 64% rename from src/PageRouter.ts rename to src/PageSystem/PageRouter.ts index 77b8572..555d895 100644 --- a/src/PageRouter.ts +++ b/src/PageSystem/PageRouter.ts @@ -1,5 +1,6 @@ -import { Page } from "./types/Page"; -import { getObjectKeys } from "./utils"; +import { Page } from "./Page"; +import { PageState } from "../PageState"; +import { getObjectKeys } from "../utils"; type pageList = { [key: string]: Page; @@ -9,9 +10,15 @@ const PageDoesNotExistError = new Error("Page does not exist."); const PageHasNotBeenSetError = new Error("Page has not been set."); export class PageRouter extends EventTarget { - constructor(pages: pageList, pageContentElement: HTMLElement, pageTitleElement: HTMLElement) { + constructor( + pages: pageList, + state: PageState, + pageContentElement: HTMLElement, + pageTitleElement: HTMLElement, + ) { super(); this.pages = pages; + this.state = state; this.pageContentElement = pageContentElement; this.pageTitleElement = pageTitleElement; } @@ -20,6 +27,7 @@ export class PageRouter extends EventTarget { private currentPageID: string; private currentPage: Page; + public state: PageState; public pageContentElement: HTMLElement; public pageTitleElement: HTMLElement; @@ -27,10 +35,23 @@ export class PageRouter extends EventTarget { return getObjectKeys(this.pages); } + public async getCurrentPage(): Promise { + return this.currentPage; + } + public async getCurrentPageID(): Promise { return this.currentPageID; } + public async setPageContent(content: string | HTMLElement): Promise { + if (typeof content === "string") { + this.pageContentElement.innerHTML = content; + } else { + this.pageContentElement.innerHTML = ""; + this.pageContentElement.appendChild(content); + } + } + public async changePage(pageID: string): Promise { if (!(await this.getPageIDs()).includes(pageID)) throw PageDoesNotExistError; @@ -43,6 +64,8 @@ export class PageRouter extends EventTarget { this.currentPageID = pageID; this.currentPage = this.pages[pageID]; + await this.currentPage.setRouterAndState(this, this.state); + // Dispatch an event saying the page has been changed. this.dispatchEvent(new CustomEvent("pageChanged")); @@ -57,8 +80,12 @@ export class PageRouter extends EventTarget { this.pageContentElement.innerHTML = ""; this.pageTitleElement.innerHTML = ""; - // TODO: Make Page have a getTitle method. - this.pageTitleElement.innerText = this.currentPage.name; + const pageTitle = await this.currentPage.getPageTitle(); + if (typeof pageTitle === "string") { + this.pageTitleElement.innerText = pageTitle; + } else { + this.pageTitleElement.appendChild(pageTitle); + } await this.currentPage.render(); } diff --git a/src/allPages.ts b/src/allPages.ts index 175beee..829842a 100644 --- a/src/allPages.ts +++ b/src/allPages.ts @@ -13,7 +13,7 @@ import { NewTOTPEnginePage } from "./pages/NewEngines/NewTOTPEngine"; import { NewTOTPPage } from "./pages/TOTP/NewTOTP"; import { NewTransitEnginePage } from "./pages/NewEngines/NewTransitEngine"; import { NewTransitKeyPage } from "./pages/Transit/NewTransitKey"; -import { Page } from "./types/Page"; +import { Page } from "./PageSystem/Page"; import { PwGenPage } from "./pages/PwGen"; import { SetLanguagePage } from "./pages/SetLanguage"; import { SetVaultURLPage } from "./pages/SetVaultURL"; diff --git a/src/elements/NavBar.ts b/src/elements/NavBar.ts index 3931990..667f81c 100644 --- a/src/elements/NavBar.ts +++ b/src/elements/NavBar.ts @@ -1,9 +1,9 @@ import { ListItem } from "./ListItem"; import { makeElement } from "../htmlUtils"; -import { pageRouter } from "../globalPageRouter"; import i18next from "i18next"; +import { PageRouter } from "../PageSystem/PageRouter"; -export function NavBar(): HTMLElement { +export function NavBar(router: PageRouter): HTMLElement { return makeElement({ id: "navBar", tag: "nav", @@ -21,7 +21,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("home_btn"), onclick: async () => { - await pageRouter.changePage("HOME"); + await router.changePage("HOME"); }, }), ), @@ -30,7 +30,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("back_btn"), onclick: async () => { - await pageRouter.goBack(); + await router.goBack(); }, }), ), @@ -39,7 +39,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("refresh_btn"), onclick: async () => { - await pageRouter.refresh(); + await router.refresh(); }, }), ), @@ -58,7 +58,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("me_btn"), onclick: async () => { - await pageRouter.changePage("ME"); + await router.changePage("ME"); }, }), ), @@ -69,6 +69,6 @@ export function NavBar(): HTMLElement { }); } -export function reloadNavBar(): void { - document.querySelector("#navBar").replaceWith(NavBar()); +export function reloadNavBar(router: PageRouter): void { + document.querySelector("#navBar").replaceWith(NavBar(router)); } diff --git a/src/elements/SecretTitleElement.ts b/src/elements/SecretTitleElement.ts new file mode 100644 index 0000000..d827a37 --- /dev/null +++ b/src/elements/SecretTitleElement.ts @@ -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 { + 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; +} diff --git a/src/globalPageRouter.ts b/src/globalPageRouter.ts deleted file mode 100644 index 5ee44ca..0000000 --- a/src/globalPageRouter.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PageRouter } from "./PageRouter"; - -export let pageRouter: PageRouter; -export function setPageRouter(router: PageRouter): void { - pageRouter = router; -} diff --git a/src/main.ts b/src/main.ts index a8523f8..ee4bf48 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,14 +20,13 @@ Prism.highlightAll(); // Actual Imports import { NavBar } from "./elements/NavBar"; -import { PageRouter } from "./PageRouter"; +import { PageRouter } from "./PageSystem/PageRouter"; import { allPages } from "./allPages"; import { formatDistance } from "./formatDistance"; import { getSealStatus } from "./api/sys/getSealStatus"; import { makeElement } from "./htmlUtils"; import { pageState } from "./globalPageState"; import { playground } from "./playground"; -import { setPageRouter } from "./globalPageRouter"; import i18next from "i18next"; // @ts-ignore @@ -41,7 +40,7 @@ declare global { async function onLoad(): Promise { document.body.innerHTML = ""; - document.body.appendChild(NavBar()); + document.body.appendChild(makeElement({tag: "div", id: "navBarReplace"})); document.body.appendChild( makeElement({ tag: "div", @@ -69,10 +68,12 @@ async function onLoad(): Promise { const pageRouter = new PageRouter( allPages, + pageState, document.getElementById("pageContent"), document.getElementById("pageTitle"), ); - setPageRouter(pageRouter); + + document.querySelector("#navBarReplace").replaceWith(NavBar(pageRouter)); pageRouter.addEventListener("pageChanged", async function (_) { pageState.currentPage = await pageRouter.getCurrentPageID(); @@ -80,7 +81,7 @@ async function onLoad(): Promise { }); if (process.env.NODE_ENV == "development") { - await playground(); + await playground(pageRouter); } await pageRouter.changePage(pageState.currentPageString); diff --git a/src/pageUtils.ts b/src/pageUtils.ts index 0c65458..174900b 100644 --- a/src/pageUtils.ts +++ b/src/pageUtils.ts @@ -1,41 +1,37 @@ -import { Page } from "./types/Page"; -import { PageState } from "./PageState"; +import { PageRouter } from "./PageSystem/PageRouter"; import { getSealStatus } from "./api/sys/getSealStatus"; import { lookupSelf } from "./api/sys/lookupSelf"; -import { makeElement } from "./htmlUtils"; -import { pageRouter } from "./globalPageRouter"; -import { pageState } from "./globalPageState"; import ClipboardJS from "clipboard"; import UIkit from "uikit"; import i18next from "i18next"; -async function prePageChecksReal() { - if (pageState.language.length == 0) { - await changePage("SET_LANGUAGE"); +async function prePageChecksReal(router: PageRouter) { + if (router.state.language.length == 0) { + await router.changePage("SET_LANGUAGE"); throw new Error("Language Not Set"); } - if (!pageState.apiURL) { - await changePage("SET_VAULT_URL"); + if (!router.state.apiURL) { + await router.changePage("SET_VAULT_URL"); throw new Error("Vault URL Not Set"); } const sealStatus = await getSealStatus(); if (sealStatus.sealed) { - await changePage("UNSEAL"); + await router.changePage("UNSEAL"); throw new Error("Vault Sealed"); } try { await lookupSelf(); } catch (e) { - await changePage("LOGIN"); + await router.changePage("LOGIN"); throw e; } } -export async function prePageChecks(): Promise { +export async function prePageChecks(router: PageRouter): Promise { try { - await prePageChecksReal(); + await prePageChecksReal(router); } catch (e) { console.log("OHNO", e); return false; @@ -78,82 +74,3 @@ export function setErrorText(text: string): void { timeout: 2000, }); } - -export async function changePage(page: string): Promise { - 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); - } -} diff --git a/src/pages/Home.ts b/src/pages/Home.ts index a8ba99a..d3c47bd 100644 --- a/src/pages/Home.ts +++ b/src/pages/Home.ts @@ -1,10 +1,9 @@ import { MountType, getMounts } from "../api/sys/getMounts"; -import { Page } from "../types/Page"; -import { changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils"; +import { Page } from "../PageSystem/Page"; import { getCapabilitiesPath } from "../api/sys/getCapabilities"; import { lookupSelf } from "../api/sys/lookupSelf"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; +import { prePageChecks, setErrorText } from "../pageUtils"; import { sortedObjectMap } from "../utils"; import i18next from "i18next"; @@ -13,11 +12,11 @@ export class HomePage extends Page { super(); } async render(): Promise { - setPageContent(""); - if (!(await prePageChecks())) return; + await this.router.setPageContent(""); + if (!(await prePageChecks(this.router))) return; const homePageContent = makeElement({ tag: "div" }); - setPageContent(homePageContent); + await this.router.setPageContent(homePageContent); const textList = makeElement({ tag: "ul", class: "uk-nav", @@ -26,7 +25,7 @@ export class HomePage extends Page { tag: "li", children: makeElement({ tag: "span", - html: i18next.t("vaulturl_text", { text: pageState.apiURL }), + html: i18next.t("vaulturl_text", { text: this.state.apiURL }), }), }), makeElement({ @@ -35,7 +34,7 @@ export class HomePage extends Page { tag: "a", text: i18next.t("password_generator_btn"), 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; setErrorText(error.message); if (error.message == "permission denied") { - pageState.token = ""; - await changePage("LOGIN"); + this.state.token = ""; + await this.router.changePage("LOGIN"); } } @@ -70,16 +69,16 @@ export class HomePage extends Page { text: i18next.t("home_new_secrets_engine_button"), class: ["uk-button", "uk-button-primary", "uk-margin-top"], onclick: async () => { - await changePage("NEW_SECRETS_ENGINE"); + await this.router.changePage("NEW_SECRETS_ENGINE"); }, }), ); } - pageState.currentBaseMount = ""; - pageState.currentSecretPath = []; - pageState.currentSecret = ""; - pageState.currentSecretVersion = null; + this.state.currentBaseMount = ""; + this.state.currentSecretPath = []; + this.state.currentSecret = ""; + this.state.currentSecretVersion = null; const navList = makeElement({ tag: "ul", @@ -91,7 +90,7 @@ export class HomePage extends Page { // sort it by secretPath so it's in alphabetical order consistantly. const mountsMap = sortedObjectMap(mounts); - mountsMap.forEach(function (mount: MountType, baseMount) { + mountsMap.forEach((mount: MountType, baseMount) => { if (typeof mount != "object") return; if (mount == null) return; if (!("type" in mount)) return; @@ -122,9 +121,9 @@ export class HomePage extends Page { tag: "a", text: linkText, onclick: async () => { - pageState.currentBaseMount = baseMount; - pageState.currentMountType = mountType; - await changePage(linkPage); + this.state.currentBaseMount = baseMount; + this.state.currentMountType = mountType; + await this.router.changePage(linkPage); }, }), }), diff --git a/src/pages/KeyValue/KeyValueDelete.ts b/src/pages/KeyValue/KeyValueDelete.ts index d1bca45..80ae119 100644 --- a/src/pages/KeyValue/KeyValueDelete.ts +++ b/src/pages/KeyValue/KeyValueDelete.ts @@ -1,8 +1,7 @@ -import { Page } from "../../types/Page"; -import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { deleteSecret } from "../../api/kv/deleteSecret"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; import i18next from "i18next"; export class KeyValueDeletePage extends Page { @@ -10,17 +9,16 @@ export class KeyValueDeletePage extends Page { super(); } async goBack(): Promise { - if (pageState.currentSecretVersion != null) { - pageState.currentSecretVersion = null; - await changePage("KEY_VALUE_SECRET"); + if (this.state.currentSecretVersion != null) { + this.state.currentSecretVersion = null; + await this.router.changePage("KEY_VALUE_SECRET"); } else { - pageState.currentSecret = ""; - await changePage("KEY_VALUE_VIEW"); + this.state.currentSecret = ""; + await this.router.changePage("KEY_VALUE_VIEW"); } } async render(): Promise { - setTitleElement(pageState); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -34,11 +32,11 @@ export class KeyValueDeletePage extends Page { text: i18next.t("kv_delete_btn"), onclick: () => { void deleteSecret( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, - pageState.currentSecret, - pageState.currentSecretVersion, + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, + this.state.currentSecret, + this.state.currentSecretVersion, ).then(() => { void this.goBack(); }); @@ -48,9 +46,11 @@ export class KeyValueDeletePage extends Page { }), ); } - get titleSuffix(): string { - return i18next.t("kv_delete_suffix"); + + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("kv_delete_suffix")); } + get name(): string { return i18next.t("kv_delete_title"); } diff --git a/src/pages/KeyValue/KeyValueNew.ts b/src/pages/KeyValue/KeyValueNew.ts index 2a1b67a..7d2c384 100644 --- a/src/pages/KeyValue/KeyValueNew.ts +++ b/src/pages/KeyValue/KeyValueNew.ts @@ -1,8 +1,8 @@ -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class KeyValueNewPage extends Page { @@ -11,13 +11,12 @@ export class KeyValueNewPage extends Page { } async goBack(): Promise { - await changePage("KEY_VALUE_VIEW"); + await this.router.changePage("KEY_VALUE_VIEW"); } addKVNewForm: HTMLFormElement; async render(): Promise { - setTitleElement(pageState); this.addKVNewForm = makeElement({ tag: "form", id: "addKVNewForm", @@ -51,7 +50,7 @@ export class KeyValueNewPage extends Page { }), ], }) as HTMLFormElement; - setPageContent(this.addKVNewForm); + await this.router.setPageContent(this.addKVNewForm); this.addKVNewForm.addEventListener("submit", async (e: Event) => { e.preventDefault(); @@ -64,27 +63,27 @@ export class KeyValueNewPage extends Page { const path = formData.get("path") as string; let keyData = {}; - if (["kv-v1", "cubbyhole"].includes(pageState.currentMountType)) { + if (["kv-v1", "cubbyhole"].includes(this.state.currentMountType)) { keyData = { key: "value" }; } try { await createOrUpdateSecret( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, path, keyData, ); - await changePage("KEY_VALUE_VIEW"); + await this.router.changePage("KEY_VALUE_VIEW"); } catch (e: unknown) { const error = e as Error; setErrorText(error.message); } } - get titleSuffix(): string { - return i18next.t("kv_new_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("kv_new_suffix")); } get name(): string { diff --git a/src/pages/KeyValue/KeyValueSecret.ts b/src/pages/KeyValue/KeyValueSecret.ts index 1bc1027..7caf891 100644 --- a/src/pages/KeyValue/KeyValueSecret.ts +++ b/src/pages/KeyValue/KeyValueSecret.ts @@ -1,10 +1,9 @@ import { CopyableInputBox } from "../../elements/CopyableInputBox"; -import { Page } from "../../types/Page"; -import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getCapabilities } from "../../api/sys/getCapabilities"; import { getSecret } from "../../api/kv/getSecret"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; import { sortedObjectMap } from "../../utils"; import { undeleteSecret } from "../../api/kv/undeleteSecret"; import Prism from "prismjs"; @@ -15,17 +14,16 @@ export class KeyValueSecretPage extends Page { super(); } async goBack(): Promise { - if (pageState.currentSecretVersion != null) { - pageState.currentSecretVersion = null; - await changePage("KEY_VALUE_VERSIONS"); + if (this.state.currentSecretVersion != null) { + this.state.currentSecretVersion = null; + await this.router.changePage("KEY_VALUE_VERSIONS"); } else { - pageState.currentSecret = ""; - await changePage("KEY_VALUE_VIEW"); + this.state.currentSecret = ""; + await this.router.changePage("KEY_VALUE_VIEW"); } } async render(): Promise { - setTitleElement(pageState); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -50,17 +48,20 @@ export class KeyValueSecretPage extends Page { const kvList = document.querySelector("#kvList"); let isSecretNestedJson = false; const caps = await getCapabilities( - pageState.currentBaseMount, - pageState.currentSecretPath, - pageState.currentSecret, + this.state.currentBaseMount, + this.state.currentSecretPath, + this.state.currentSecret, ); if (caps.includes("delete")) { 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"); - } 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", { - version: pageState.currentSecretVersion, + version: this.state.currentSecretVersion, }); } buttonsBlock.appendChild( @@ -69,107 +70,105 @@ export class KeyValueSecretPage extends Page { id: "deleteButton", class: ["uk-button", "uk-button-danger"], onclick: async () => { - await changePage("KEY_VALUE_DELETE"); + await this.router.changePage("KEY_VALUE_DELETE"); }, text: deleteButtonText, }), ); } if (caps.includes("update")) { - if (pageState.currentSecretVersion == null) { + if (this.state.currentSecretVersion == null) { buttonsBlock.appendChild( makeElement({ tag: "button", id: "editButton", class: ["uk-button", "uk-margin", "uk-button-primary"], onclick: async () => { - await changePage("KEY_VALUE_SECRET_EDIT"); + await this.router.changePage("KEY_VALUE_SECRET_EDIT"); }, text: i18next.t("kv_secret_edit_btn"), }), ); } } - if (pageState.currentMountType == "kv-v2") { + if (this.state.currentMountType == "kv-v2") { buttonsBlock.appendChild( makeElement({ tag: "button", id: "versionsButton", class: ["uk-button", "uk-button-secondary"], onclick: async () => { - await changePage("KEY_VALUE_VERSIONS"); + await this.router.changePage("KEY_VALUE_VERSIONS"); }, text: i18next.t("kv_secret_versions_btn"), }), ); } - void getSecret( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, - pageState.currentSecret, - pageState.currentSecretVersion, - ).then((secretInfo) => { - if (secretInfo == null && pageState.currentMountType == "kv-v2") { - document.querySelector("#buttonsBlock").remove(); - document.getElementById("loadingText").remove(); - - kvList.appendChild( - makeElement({ - tag: "p", - text: i18next.t("kv_secret_deleted_text"), - }), - ); - - kvList.appendChild( - makeElement({ - tag: "button", - text: i18next.t("kv_secret_restore_btn"), - id: "restoreButton", - class: ["uk-button", "uk-button-primary"], - onclick: () => { - void undeleteSecret( - pageState.currentBaseMount, - pageState.currentSecretPath, - pageState.currentSecret, - pageState.currentSecretVersion, - ).then((_) => { - void changePage(pageState.currentPageString); - }); - }, - }), - ); - return; - } - - const secretsMap = sortedObjectMap(secretInfo); - - for (const value of secretsMap.values()) { - if (typeof value == "object") isSecretNestedJson = true; - } - - if (isSecretNestedJson) { - const jsonText = JSON.stringify( - sortedObjectMap(secretsMap as unknown as Record), - null, - 4, - ); - kvList.appendChild( - makeElement({ - tag: "pre", - class: ["code-block", "language-json", "line-numbers"], - html: Prism.highlight(jsonText, Prism.languages.json, "json"), - }), - ); - } else { - secretsMap.forEach((value: string, key: string) => { - const kvListElement = this.makeKVListElement(key, value); - kvList.appendChild(kvListElement); - }, this); - } + const secretInfo = await getSecret( + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, + this.state.currentSecret, + this.state.currentSecretVersion, + ); + if (secretInfo == null && this.state.currentMountType == "kv-v2") { + document.querySelector("#buttonsBlock").remove(); document.getElementById("loadingText").remove(); - }); + + kvList.appendChild( + makeElement({ + tag: "p", + text: i18next.t("kv_secret_deleted_text"), + }), + ); + + kvList.appendChild( + makeElement({ + tag: "button", + text: i18next.t("kv_secret_restore_btn"), + id: "restoreButton", + class: ["uk-button", "uk-button-primary"], + onclick: async () => { + await undeleteSecret( + this.state.currentBaseMount, + this.state.currentSecretPath, + this.state.currentSecret, + this.state.currentSecretVersion, + ); + await this.router.changePage(this.state.currentPageString); + }, + }), + ); + return; + } + + const secretsMap = sortedObjectMap(secretInfo); + + for (const value of secretsMap.values()) { + if (typeof value == "object") isSecretNestedJson = true; + } + + if (isSecretNestedJson) { + const jsonText = JSON.stringify( + sortedObjectMap(secretsMap as unknown as Record), + null, + 4, + ); + kvList.appendChild( + makeElement({ + tag: "pre", + class: ["code-block", "language-json", "line-numbers"], + html: Prism.highlight(jsonText, Prism.languages.json, "json"), + }), + ); + } else { + secretsMap.forEach((value: string, key: string) => { + const kvListElement = this.makeKVListElement(key, value); + kvList.appendChild(kvListElement); + }, this); + } + document.getElementById("loadingText").remove(); } makeKVListElement(key: string, value: string): HTMLElement { return makeElement({ @@ -179,6 +178,10 @@ export class KeyValueSecretPage extends Page { }); } + async getPageTitle(): Promise { + return await SecretTitleElement(this.router); + } + get name(): string { return i18next.t("kv_secret_title"); } diff --git a/src/pages/KeyValue/KeyValueSecretsEdit.ts b/src/pages/KeyValue/KeyValueSecretsEdit.ts index 302286c..855fa07 100644 --- a/src/pages/KeyValue/KeyValueSecretsEdit.ts +++ b/src/pages/KeyValue/KeyValueSecretsEdit.ts @@ -1,10 +1,10 @@ import { CodeJar } from "codejar"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; import { getSecret } from "../../api/kv/getSecret"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import { sortedObjectMap, verifyJSONString } from "../../utils"; import i18next from "i18next"; @@ -13,10 +13,9 @@ export class KeyValueSecretEditPage extends Page { super(); } async goBack(): Promise { - await changePage("KEY_VALUE_SECRET"); + await this.router.changePage("KEY_VALUE_SECRET"); } async render(): Promise { - setTitleElement(pageState); const loadingText = makeElement({ tag: "p", text: i18next.t("kv_sec_edit_loading"), @@ -30,7 +29,7 @@ export class KeyValueSecretEditPage extends Page { class: ["uk-button", "uk-button-primary"], text: i18next.t("kv_sec_edit_btn"), }); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -45,44 +44,43 @@ export class KeyValueSecretEditPage extends Page { ], }), ); - void getSecret( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, - pageState.currentSecret, - ).then((secretInfo) => { - loadingText.remove(); + const secretInfo = await getSecret( + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, + this.state.currentSecret, + ); - const secretsJSON = JSON.stringify(sortedObjectMap(secretInfo), null, 4); + loadingText.remove(); - const jar = CodeJar(editor, () => {}, { tab: " ".repeat(4) }); - jar.updateCode(secretsJSON); - saveButton.onclick = function () { - if (!verifyJSONString(jar.toString())) { - setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); - return; - } + const secretsJSON = JSON.stringify(sortedObjectMap(secretInfo), null, 4); - createOrUpdateSecret( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, - pageState.currentSecret, + const jar = CodeJar(editor, () => {}, { tab: " ".repeat(4) }); + jar.updateCode(secretsJSON); + saveButton.onclick = async () => { + if (!verifyJSONString(jar.toString())) { + setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); + return; + } + + try { + await createOrUpdateSecret( + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, + this.state.currentSecret, JSON.parse(jar.toString()), - ) - .then((_) => { - void changePage("KEY_VALUE_SECRET"); - return; - }) - .catch((e: Error) => { - setErrorText(e.message); - }); - }; - }); + ); + await this.router.changePage("KEY_VALUE_SECRET"); + } catch (e: unknown) { + const error = e as Error; + setErrorText(error.message); + } + }; } - get titleSuffix(): string { - return i18next.t("kv_sec_edit_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("kv_sec_edit_suffix")); } get name(): string { diff --git a/src/pages/KeyValue/KeyValueVersions.ts b/src/pages/KeyValue/KeyValueVersions.ts index 3040628..7df4fba 100644 --- a/src/pages/KeyValue/KeyValueVersions.ts +++ b/src/pages/KeyValue/KeyValueVersions.ts @@ -1,9 +1,8 @@ -import { Page } from "../../types/Page"; -import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getSecretMetadata } from "../../api/kv/getSecretMetadata"; import { makeElement } from "../../htmlUtils"; import { objectToMap } from "../../utils"; -import { pageState } from "../../globalPageState"; import i18next from "i18next"; export class KeyValueVersionsPage extends Page { @@ -11,25 +10,23 @@ export class KeyValueVersionsPage extends Page { super(); } async goBack(): Promise { - if (pageState.currentSecretVersion != null) { - pageState.currentSecretVersion = null; + if (this.state.currentSecretVersion != null) { + this.state.currentSecretVersion = null; } - await changePage("KEY_VALUE_SECRET"); + await this.router.changePage("KEY_VALUE_SECRET"); } async render(): Promise { - setTitleElement(pageState); - const versionsList = makeElement({ tag: "ul", id: "versionsList", class: ["uk-nav", "uk-nav-default"], }); - setPageContent(versionsList); + await this.router.setPageContent(versionsList); const metadata = await getSecretMetadata( - pageState.currentBaseMount, - pageState.currentSecretPath, - pageState.currentSecret, + this.state.currentBaseMount, + this.state.currentSecretPath, + this.state.currentSecret, ); objectToMap(metadata.versions).forEach((_, ver) => { @@ -40,8 +37,8 @@ export class KeyValueVersionsPage extends Page { tag: "a", text: `v${ver}`, onclick: async () => { - pageState.currentSecretVersion = ver; - await changePage("KEY_VALUE_SECRET"); + this.state.currentSecretVersion = ver; + await this.router.changePage("KEY_VALUE_SECRET"); }, }), }), @@ -49,8 +46,8 @@ export class KeyValueVersionsPage extends Page { }); } - get titleSuffix(): string { - return i18next.t("kv_sec_versions_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("kv_sec_versions_suffix")); } get name(): string { diff --git a/src/pages/KeyValue/KeyValueView.ts b/src/pages/KeyValue/KeyValueView.ts index ec93bc6..16b3e1b 100644 --- a/src/pages/KeyValue/KeyValueView.ts +++ b/src/pages/KeyValue/KeyValueView.ts @@ -1,9 +1,9 @@ import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getSecrets } from "../../api/kv/getSecrets"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class KeyValueViewPage extends Page { @@ -11,22 +11,20 @@ export class KeyValueViewPage extends Page { super(); } async goBack(): Promise { - if (pageState.currentSecretPath.length != 0) { - pageState.popCurrentSecretPath(); - await changePage("KEY_VALUE_VIEW"); + if (this.state.currentSecretPath.length != 0) { + this.state.popCurrentSecretPath(); + await this.router.changePage("KEY_VALUE_VIEW"); } else { - await changePage("HOME"); + await this.router.changePage("HOME"); } } async render(): Promise { - pageState.currentSecret = ""; - - setTitleElement(pageState); + this.state.currentSecret = ""; const kvViewPageContent = makeElement({ tag: "div" }); - setPageContent(kvViewPageContent); + await this.router.setPageContent(kvViewPageContent); - if (pageState.currentMountType == "cubbyhole") { + if (this.state.currentMountType == "cubbyhole") { kvViewPageContent.appendChild( makeElement({ tag: "p", @@ -40,16 +38,16 @@ export class KeyValueViewPage extends Page { text: i18next.t("kv_view_new_btn"), class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], onclick: async () => { - await changePage("KEY_VALUE_NEW_SECRET"); + await this.router.changePage("KEY_VALUE_NEW_SECRET"); }, }); kvViewPageContent.appendChild(newButton); try { const res = await getSecrets( - pageState.currentBaseMount, - pageState.currentMountType, - pageState.currentSecretPath, + this.state.currentBaseMount, + this.state.currentMountType, + this.state.currentSecretPath, ); kvViewPageContent.appendChild( @@ -57,7 +55,7 @@ export class KeyValueViewPage extends Page { tag: "ul", class: ["uk-nav", "uk-nav-default"], children: [ - ...res.map(function (secret) { + ...res.map((secret) => { return makeElement({ tag: "li", children: makeElement({ @@ -65,11 +63,11 @@ export class KeyValueViewPage extends Page { text: secret, onclick: async () => { if (secret.endsWith("/")) { - pageState.pushCurrentSecretPath(secret); - await changePage("KEY_VALUE_VIEW"); + this.state.pushCurrentSecretPath(secret); + await this.router.changePage("KEY_VALUE_VIEW"); } else { - pageState.currentSecret = secret; - await changePage("KEY_VALUE_SECRET"); + this.state.currentSecret = secret; + await this.router.changePage("KEY_VALUE_SECRET"); } }, }), @@ -82,7 +80,7 @@ export class KeyValueViewPage extends Page { const error = e as Error; if (error == DoesNotExistError) { // 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(); } else { kvViewPageContent.appendChild( @@ -98,6 +96,10 @@ export class KeyValueViewPage extends Page { } } + async getPageTitle(): Promise { + return await SecretTitleElement(this.router); + } + get name(): string { return i18next.t("kv_view_title"); } diff --git a/src/pages/Login.ts b/src/pages/Login.ts index 6698487..5756a58 100644 --- a/src/pages/Login.ts +++ b/src/pages/Login.ts @@ -1,10 +1,9 @@ import { Margin } from "../elements/Margin"; import { MarginInline } from "../elements/MarginInline"; -import { Page } from "../types/Page"; -import { changePage, setErrorText, setPageContent } from "../pageUtils"; +import { Page } from "../PageSystem/Page"; import { lookupSelf } from "../api/sys/lookupSelf"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; +import { setErrorText } from "../pageUtils"; import { usernameLogin } from "../api/auth/usernameLogin"; import i18next from "i18next"; @@ -83,7 +82,7 @@ export class LoginPage extends Page { ], }) as HTMLFormElement; - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -132,15 +131,15 @@ export class LoginPage extends Page { }), ); - tokenLoginForm.addEventListener("submit", async function (e) { + tokenLoginForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(tokenLoginForm); const token = formData.get("token"); - pageState.token = token as string; + this.state.token = token as string; try { await lookupSelf(); - await changePage("HOME"); + await this.router.changePage("HOME"); } catch (e: unknown) { const error = e as Error; 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(); const formData = new FormData(usernameLoginForm); @@ -160,8 +159,8 @@ export class LoginPage extends Page { formData.get("username") as string, formData.get("password") as string, ); - pageState.token = res; - await changePage("HOME"); + this.state.token = res; + await this.router.changePage("HOME"); } catch (e: unknown) { const error = e as Error; document.getElementById("usernameInput").classList.add("uk-form-danger"); diff --git a/src/pages/Me.ts b/src/pages/Me.ts index b2dece8..deab685 100644 --- a/src/pages/Me.ts +++ b/src/pages/Me.ts @@ -1,14 +1,7 @@ -import { Page } from "../types/Page"; -import { - addClipboardNotifications, - changePage, - prePageChecks, - setErrorText, - setPageContent, -} from "../pageUtils"; +import { Page } from "../PageSystem/Page"; +import { addClipboardNotifications, prePageChecks, setErrorText } from "../pageUtils"; import { getCapabilitiesPath } from "../api/sys/getCapabilities"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; import { renewSelf } from "../api/sys/renewSelf"; import { sealVault } from "../api/sys/sealVault"; import ClipboardJS from "clipboard"; @@ -20,8 +13,8 @@ export class MePage extends Page { } async render(): Promise { - if (!(await prePageChecks())) return; - setPageContent( + if (!(await prePageChecks(this.router))) return; + await this.router.setPageContent( makeElement({ tag: "ul", class: "uk-nav", @@ -32,8 +25,8 @@ export class MePage extends Page { tag: "a", text: i18next.t("log_out_btn"), onclick: async () => { - pageState.token = ""; - await changePage("HOME"); + this.state.token = ""; + await this.router.changePage("HOME"); }, }), }), @@ -43,7 +36,7 @@ export class MePage extends Page { tag: "a", text: i18next.t("copy_token_btn"), attributes: { - "data-clipboard-text": pageState.token, + "data-clipboard-text": this.state.token, }, thenRun: (e) => { const clipboard = new ClipboardJS(e); @@ -59,7 +52,7 @@ export class MePage extends Page { onclick: () => { renewSelf() .then(() => { - void changePage("HOME"); + void this.router.changePage("HOME"); }) .catch((e: Error) => { setErrorText(e.message); @@ -82,7 +75,7 @@ export class MePage extends Page { text: i18next.t("seal_vault_btn"), onclick: async () => { await sealVault(); - await changePage("UNSEAL_VAULT"); + await this.router.changePage("UNSEAL_VAULT"); }, }), }), @@ -92,7 +85,7 @@ export class MePage extends Page { tag: "a", text: i18next.t("change_language_btn"), onclick: async () => { - await changePage("SET_LANGUAGE"); + await this.router.changePage("SET_LANGUAGE"); }, }), }), diff --git a/src/pages/NewEngines/NewKVEngine.ts b/src/pages/NewEngines/NewKVEngine.ts index 260930a..fa2ff26 100644 --- a/src/pages/NewEngines/NewKVEngine.ts +++ b/src/pages/NewEngines/NewKVEngine.ts @@ -1,10 +1,9 @@ import { Margin } from "../../elements/Margin"; import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; import { makeElement } from "../../htmlUtils"; import { newMount } from "../../api/sys/newMount"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class NewKVEnginePage extends Page { @@ -56,9 +55,9 @@ export class NewKVEnginePage extends Page { ], }) as HTMLFormElement; - setPageContent(newEngineForm); + await this.router.setPageContent(newEngineForm); - newEngineForm.addEventListener("submit", async function (e) { + newEngineForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(newEngineForm); @@ -73,9 +72,9 @@ export class NewKVEnginePage extends Page { version: version, }, }); - pageState.currentMountType = "kv-v" + version; - pageState.currentBaseMount = name + "/"; - await changePage("KEY_VALUE_VIEW"); + this.state.currentMountType = "kv-v" + version; + this.state.currentBaseMount = name + "/"; + await this.router.changePage("KEY_VALUE_VIEW"); } catch (e) { const error = e as Error; setErrorText(error.message); diff --git a/src/pages/NewEngines/NewTOTPEngine.ts b/src/pages/NewEngines/NewTOTPEngine.ts index 3f95239..c70111e 100644 --- a/src/pages/NewEngines/NewTOTPEngine.ts +++ b/src/pages/NewEngines/NewTOTPEngine.ts @@ -1,9 +1,8 @@ import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; import { makeElement } from "../../htmlUtils"; import { newMount } from "../../api/sys/newMount"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class NewTOTPEnginePage extends Page { @@ -42,9 +41,9 @@ export class NewTOTPEnginePage extends Page { ], }) as HTMLFormElement; - setPageContent(newEngineForm); + await this.router.setPageContent(newEngineForm); - newEngineForm.addEventListener("submit", async function (e) { + newEngineForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(newEngineForm); @@ -55,9 +54,9 @@ export class NewTOTPEnginePage extends Page { name: name, type: "totp", }); - pageState.currentMountType = "totp"; - pageState.currentBaseMount = name + "/"; - await changePage("TOTP"); + this.state.currentMountType = "totp"; + this.state.currentBaseMount = name + "/"; + await this.router.changePage("TOTP"); } catch (e) { const error = e as Error; setErrorText(error.message); diff --git a/src/pages/NewEngines/NewTransitEngine.ts b/src/pages/NewEngines/NewTransitEngine.ts index 26e810b..79ae03e 100644 --- a/src/pages/NewEngines/NewTransitEngine.ts +++ b/src/pages/NewEngines/NewTransitEngine.ts @@ -1,9 +1,8 @@ import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; import { makeElement } from "../../htmlUtils"; import { newMount } from "../../api/sys/newMount"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class NewTransitEnginePage extends Page { @@ -42,9 +41,9 @@ export class NewTransitEnginePage extends Page { ], }) as HTMLFormElement; - setPageContent(newEngineForm); + await this.router.setPageContent(newEngineForm); - newEngineForm.addEventListener("submit", async function (e) { + newEngineForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(newEngineForm); @@ -55,9 +54,9 @@ export class NewTransitEnginePage extends Page { name: name, type: "transit", }); - pageState.currentMountType = "transit"; - pageState.currentBaseMount = name + "/"; - await changePage("TRANSIT_VIEW"); + this.state.currentMountType = "transit"; + this.state.currentBaseMount = name + "/"; + await this.router.changePage("TRANSIT_VIEW"); } catch (e) { const error = e as Error; setErrorText(error.message); diff --git a/src/pages/NewSecretsEngine.ts b/src/pages/NewSecretsEngine.ts index 99a9884..9b73376 100644 --- a/src/pages/NewSecretsEngine.ts +++ b/src/pages/NewSecretsEngine.ts @@ -1,6 +1,5 @@ -import { Page } from "../types/Page"; +import { Page } from "../PageSystem/Page"; import { Tile } from "../elements/Tile"; -import { changePage, setPageContent } from "../pageUtils"; import { makeElement } from "../htmlUtils"; import i18next from "i18next"; @@ -10,7 +9,7 @@ export class NewSecretsEnginePage extends Page { } async render(): Promise { - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", 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({ title: i18next.t("new_secrets_engine_kv_title"), description: i18next.t("new_secrets_engine_kv_description"), - onclick: () => { - void changePage("NEW_KV_ENGINE"); + onclick: async () => { + await this.router.changePage("NEW_KV_ENGINE"); }, }), Tile({ title: i18next.t("new_secrets_engine_totp_title"), description: i18next.t("new_secrets_engine_totp_description"), - onclick: () => { - void changePage("NEW_TOTP_ENGINE"); + onclick: async () => { + await this.router.changePage("NEW_TOTP_ENGINE"); }, }), Tile({ title: i18next.t("new_secrets_engine_transit_title"), description: i18next.t("new_secrets_engine_transit_description"), - onclick: () => { - void changePage("NEW_TRANSIT_ENGINE"); + onclick: async () => { + await this.router.changePage("NEW_TRANSIT_ENGINE"); }, }), ], diff --git a/src/pages/PwGen.ts b/src/pages/PwGen.ts index a59b825..397eadc 100644 --- a/src/pages/PwGen.ts +++ b/src/pages/PwGen.ts @@ -1,9 +1,8 @@ import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox"; import { Margin } from "../elements/Margin"; import { Option } from "../elements/Option"; -import { Page } from "../types/Page"; +import { Page } from "../PageSystem/Page"; import { makeElement } from "../htmlUtils"; -import { setPageContent } from "../pageUtils"; import i18next from "i18next"; const passwordLengthMin = 1; @@ -59,7 +58,7 @@ export class PwGenPage extends Page { passwordForm: HTMLFormElement; async render(): Promise { - setPageContent(""); + await this.router.setPageContent(""); this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault)); this.passwordLengthTitle = makeElement({ @@ -110,7 +109,7 @@ export class PwGenPage extends Page { }) as HTMLFormElement; this.passwordForm.addEventListener("submit", (e) => this.formEvent(e)); - setPageContent(this.passwordForm); + await this.router.setPageContent(this.passwordForm); } getPasswordLengthText(): string { diff --git a/src/pages/SetLanguage.ts b/src/pages/SetLanguage.ts index d2eea59..a0481d3 100644 --- a/src/pages/SetLanguage.ts +++ b/src/pages/SetLanguage.ts @@ -1,8 +1,6 @@ import { Margin } from "../elements/Margin"; -import { Page } from "../types/Page"; -import { changePage, setPageContent } from "../pageUtils"; +import { Page } from "../PageSystem/Page"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; import { reloadNavBar } from "../elements/NavBar"; import i18next from "i18next"; @@ -51,18 +49,18 @@ export class SetLanguagePage extends Page { }), ], }) as HTMLFormElement; - setPageContent(setLanguageForm); - setLanguageForm.addEventListener("submit", async function (e) { + await this.router.setPageContent(setLanguageForm); + setLanguageForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(setLanguageForm); const language = formData.get("language") as string; - pageState.language = language; + this.state.language = language; const t = await i18next.changeLanguage(language); - pageState.pageDirection = t("language_direction"); - reloadNavBar(); - await changePage("HOME"); + this.state.pageDirection = t("language_direction"); + reloadNavBar(this.router); + await this.router.changePage("HOME"); }); } get name(): string { diff --git a/src/pages/SetVaultURL.ts b/src/pages/SetVaultURL.ts index e7d35f2..ff693f9 100644 --- a/src/pages/SetVaultURL.ts +++ b/src/pages/SetVaultURL.ts @@ -1,14 +1,12 @@ -import { Page } from "../types/Page"; -import { changePage, setPageContent } from "../pageUtils"; +import { Page } from "../PageSystem/Page"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; export class SetVaultURLPage extends Page { constructor() { super(); } async render(): Promise { - setPageContent( + await this.router.setPageContent( makeElement({ tag: "form", 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(); const formData = new FormData(document.querySelector("#setVaultURLForm")); - pageState.apiURL = formData.get("vaultURL") as string; - await changePage("HOME"); + this.state.apiURL = formData.get("vaultURL") as string; + await this.router.changePage("HOME"); }); } get name(): string { diff --git a/src/pages/TOTP/NewTOTP.ts b/src/pages/TOTP/NewTOTP.ts index e61f59f..40108f2 100644 --- a/src/pages/TOTP/NewTOTP.ts +++ b/src/pages/TOTP/NewTOTP.ts @@ -1,10 +1,10 @@ import { Margin } from "../../elements/Margin"; 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 { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; function replaceAll(str: string, replace: string, replaceWith: string): string { @@ -21,11 +21,9 @@ export class NewTOTPPage extends Page { super(); } async goBack(): Promise { - await changePage("TOTP"); + await this.router.changePage("TOTP"); } async render(): Promise { - setTitleElement(pageState); - const totpForm = makeElement({ tag: "form", children: [ @@ -84,9 +82,9 @@ export class NewTOTPPage extends Page { ), ], }) as HTMLFormElement; - setPageContent(totpForm); + await this.router.setPageContent(totpForm); - totpForm.addEventListener("submit", async function (e) { + totpForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(totpForm); @@ -99,8 +97,8 @@ export class NewTOTPPage extends Page { }; try { - await addNewTOTP(pageState.currentBaseMount, parms); - await changePage("TOTP"); + await addNewTOTP(this.state.currentBaseMount, parms); + await this.router.changePage("TOTP"); } catch (e: unknown) { const error = e as Error; setErrorText(`API Error: ${error.message}`); @@ -108,8 +106,8 @@ export class NewTOTPPage extends Page { }); } - get titleSuffix(): string { - return i18next.t("totp_new_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("totp_new_suffix")); } get name(): string { diff --git a/src/pages/TOTP/TOTPView.ts b/src/pages/TOTP/TOTPView.ts index 1d78d3b..ae94510 100644 --- a/src/pages/TOTP/TOTPView.ts +++ b/src/pages/TOTP/TOTPView.ts @@ -1,12 +1,12 @@ import { CopyableInputBox } from "../../elements/CopyableInputBox"; import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getTOTPCode } from "../../api/totp/getTOTPCode"; import { getTOTPKeys } from "../../api/totp/getTOTPKeys"; import { makeElement } from "../../htmlUtils"; import { objectToMap } from "../../utils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export interface TOTPListElement extends HTMLElement { @@ -24,9 +24,8 @@ export class TOTPViewPage extends Page { totpListElements: Record; async render(): Promise { - setTitleElement(pageState); const totpList = makeElement({ tag: "div" }); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -35,7 +34,7 @@ export class TOTPViewPage extends Page { text: i18next.t("totp_view_new_btn"), class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], onclick: async () => { - await changePage("NEW_TOTP"); + await this.router.changePage("NEW_TOTP"); }, }), makeElement({ @@ -51,7 +50,7 @@ export class TOTPViewPage extends Page { ); try { - const res = await getTOTPKeys(pageState.currentBaseMount); + const res = await getTOTPKeys(this.state.currentBaseMount); for (const totpKeyName of res) { const totpListElement = this.makeTOTPListElement(totpKeyName); totpList.appendChild(totpListElement); @@ -88,7 +87,7 @@ export class TOTPViewPage extends Page { } async updateTOTPElement(totpKeyName: string, totpListElement: TOTPListElement): Promise { - totpListElement.setCode(await getTOTPCode(pageState.currentBaseMount, totpKeyName)); + totpListElement.setCode(await getTOTPCode(this.state.currentBaseMount, totpKeyName)); } makeTOTPListElement(totpKeyName: string): TOTPListElement { @@ -106,6 +105,10 @@ export class TOTPViewPage extends Page { return gridElement; } + async getPageTitle(): Promise { + return await SecretTitleElement(this.router); + } + get name(): string { return i18next.t("totp_view_title"); } diff --git a/src/pages/Transit/NewTransitKey.ts b/src/pages/Transit/NewTransitKey.ts index 8de7860..55ea8fa 100644 --- a/src/pages/Transit/NewTransitKey.ts +++ b/src/pages/Transit/NewTransitKey.ts @@ -1,10 +1,10 @@ import { Margin } from "../../elements/Margin"; import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { makeElement } from "../../htmlUtils"; import { newTransitKey } from "../../api/transit/newTransitKey"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class NewTransitKeyPage extends Page { @@ -12,8 +12,6 @@ export class NewTransitKeyPage extends Page { super(); } async render(): Promise { - setTitleElement(pageState); - const newTransitKeyForm = makeElement({ tag: "form", children: [ @@ -66,9 +64,9 @@ export class NewTransitKeyPage extends Page { ], }) as HTMLFormElement; - setPageContent(newTransitKeyForm); + await this.router.setPageContent(newTransitKeyForm); - newTransitKeyForm.addEventListener("submit", async function (e) { + newTransitKeyForm.addEventListener("submit", async (e) => { e.preventDefault(); const formData = new FormData(newTransitKeyForm); @@ -76,12 +74,12 @@ export class NewTransitKeyPage extends Page { const type = formData.get("type") as string; try { - await newTransitKey(pageState.currentBaseMount, { + await newTransitKey(this.state.currentBaseMount, { name: name, type: type, }); - pageState.currentSecret = name; - await changePage("TRANSIT_VIEW_SECRET"); + this.state.currentSecret = name; + await this.router.changePage("TRANSIT_VIEW_SECRET"); } catch (e) { const error = e as Error; setErrorText(error.message); @@ -89,8 +87,8 @@ export class NewTransitKeyPage extends Page { }); } - get titleSuffix(): string { - return i18next.t("transit_new_key_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("transit_new_key_suffix")); } get name(): string { diff --git a/src/pages/Transit/TransitDecrypt.ts b/src/pages/Transit/TransitDecrypt.ts index 5349a21..8170c05 100644 --- a/src/pages/Transit/TransitDecrypt.ts +++ b/src/pages/Transit/TransitDecrypt.ts @@ -1,10 +1,10 @@ import { CopyableModal } from "../../elements/CopyableModal"; import { FileUploadInput } from "../../elements/FileUploadInput"; import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { fileToBase64, makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import { transitDecrypt } from "../../api/transit/transitDecrypt"; import i18next from "i18next"; @@ -14,14 +14,13 @@ export class TransitDecryptPage extends Page { } async goBack(): Promise { - await changePage("TRANSIT_VIEW_SECRET"); + await this.router.changePage("TRANSIT_VIEW_SECRET"); } transitDecryptForm: HTMLFormElement; async render(): Promise { - setTitleElement(pageState); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", }), @@ -74,7 +73,7 @@ export class TransitDecryptPage extends Page { }), ], }) as HTMLFormElement; - setPageContent(this.transitDecryptForm); + await this.router.setPageContent(this.transitDecryptForm); this.transitDecryptForm.addEventListener("submit", async (e: Event) => { e.preventDefault(); await this.transitDecryptFormHandler(); @@ -96,7 +95,7 @@ export class TransitDecryptPage extends Page { } try { - const res = await transitDecrypt(pageState.currentBaseMount, pageState.currentSecret, { + const res = await transitDecrypt(this.state.currentBaseMount, this.state.currentSecret, { ciphertext: ciphertext, }); let plaintext = res.plaintext; @@ -115,8 +114,8 @@ export class TransitDecryptPage extends Page { } } - get titleSuffix(): string { - return i18next.t("transit_decrypt_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("transit_decrypt_suffix")); } get name(): string { diff --git a/src/pages/Transit/TransitEncrypt.ts b/src/pages/Transit/TransitEncrypt.ts index d638b9c..201163c 100644 --- a/src/pages/Transit/TransitEncrypt.ts +++ b/src/pages/Transit/TransitEncrypt.ts @@ -1,10 +1,10 @@ import { CopyableModal } from "../../elements/CopyableModal"; import { FileUploadInput } from "../../elements/FileUploadInput"; import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { fileToBase64, makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import { transitEncrypt } from "../../api/transit/transitEncrypt"; import i18next from "i18next"; @@ -14,14 +14,13 @@ export class TransitEncryptPage extends Page { } async goBack(): Promise { - await changePage("TRANSIT_VIEW_SECRET"); + await this.router.changePage("TRANSIT_VIEW_SECRET"); } transitEncryptForm: HTMLFormElement; async render(): Promise { - setTitleElement(pageState); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", }), @@ -74,7 +73,7 @@ export class TransitEncryptPage extends Page { }), ], }) as HTMLFormElement; - setPageContent(this.transitEncryptForm); + await this.router.setPageContent(this.transitEncryptForm); this.transitEncryptForm.addEventListener("submit", async (e: Event) => { e.preventDefault(); @@ -98,7 +97,7 @@ export class TransitEncryptPage extends Page { } try { - const res = await transitEncrypt(pageState.currentBaseMount, pageState.currentSecret, { + const res = await transitEncrypt(this.state.currentBaseMount, this.state.currentSecret, { plaintext: plaintext, }); const modal = CopyableModal( @@ -113,8 +112,8 @@ export class TransitEncryptPage extends Page { } } - get titleSuffix(): string { - return i18next.t("transit_encrypt_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("transit_encrypt_suffix")); } get name(): string { diff --git a/src/pages/Transit/TransitRewrap.ts b/src/pages/Transit/TransitRewrap.ts index 0998a82..bf72e0a 100644 --- a/src/pages/Transit/TransitRewrap.ts +++ b/src/pages/Transit/TransitRewrap.ts @@ -1,12 +1,12 @@ import { CopyableModal } from "../../elements/CopyableModal"; import { Margin } from "../../elements/Margin"; import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getTransitKey } from "../../api/transit/getTransitKey"; import { makeElement } from "../../htmlUtils"; import { objectToMap } from "../../utils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import { transitRewrap } from "../../api/transit/transitRewrap"; import i18next from "i18next"; @@ -18,14 +18,13 @@ export class TransitRewrapPage extends Page { } async goBack(): Promise { - await changePage("TRANSIT_VIEW_SECRET"); + await this.router.changePage("TRANSIT_VIEW_SECRET"); } transitRewrapForm: HTMLFormElement; async render(): Promise { - setTitleElement(pageState); - const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); + const transitKey = await getTransitKey(this.state.currentBaseMount, this.state.currentSecret); const stringVersions = Array.from( objectToMap(transitKey.keys).keys(), @@ -47,7 +46,7 @@ export class TransitRewrapPage extends Page { }; }); - setPageContent(""); + await this.router.setPageContent(""); this.transitRewrapForm = makeElement({ tag: "form", children: [ @@ -82,7 +81,7 @@ export class TransitRewrapPage extends Page { }), ], }) as HTMLFormElement; - setPageContent(this.transitRewrapForm); + await this.router.setPageContent(this.transitRewrapForm); this.transitRewrapForm.addEventListener("submit", async (e: Event) => { e.preventDefault(); @@ -93,7 +92,7 @@ export class TransitRewrapPage extends Page { async transitRewrapFormHandler(): Promise { const formData = new FormData(this.transitRewrapForm); 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, key_version: parseInt(formData.get("version") as string, 10), }); @@ -106,8 +105,8 @@ export class TransitRewrapPage extends Page { } } - get titleSuffix(): string { - return i18next.t("transit_rewrap_suffix"); + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("transit_rewrap_suffix")); } get name(): string { diff --git a/src/pages/Transit/TransitView.ts b/src/pages/Transit/TransitView.ts index 60704be..3990f23 100644 --- a/src/pages/Transit/TransitView.ts +++ b/src/pages/Transit/TransitView.ts @@ -1,9 +1,9 @@ import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; +import { Page } from "../../PageSystem/Page"; +import { SecretTitleElement } from "../../elements/SecretTitleElement"; import { getTransitKeys } from "../../api/transit/getTransitKeys"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; +import { setErrorText } from "../../pageUtils"; import i18next from "i18next"; export class TransitViewPage extends Page { @@ -12,44 +12,42 @@ export class TransitViewPage extends Page { } async goBack(): Promise { - await changePage("HOME"); + await this.router.changePage("HOME"); } async render(): Promise { - pageState.currentSecret = ""; - - setTitleElement(pageState); + this.state.currentSecret = ""; const transitViewContent = makeElement({ tag: "div" }); - setPageContent(transitViewContent); + await this.router.setPageContent(transitViewContent); const newButton = makeElement({ tag: "button", text: "New", class: ["uk-button", "uk-button-primary", "uk-margin-bottom"], - onclick: () => { - void changePage("TRANSIT_NEW_KEY"); + onclick: async () => { + await this.router.changePage("TRANSIT_NEW_KEY"); }, }); transitViewContent.appendChild(newButton); try { - const res = await getTransitKeys(pageState.currentBaseMount); + const res = await getTransitKeys(this.state.currentBaseMount); transitViewContent.appendChild( makeElement({ tag: "ul", class: ["uk-nav", "uk-nav-default"], children: [ - ...res.map(function (secret) { + ...res.map((secret) => { return makeElement({ tag: "li", children: makeElement({ tag: "a", text: secret, - onclick: () => { - pageState.currentSecret = secret; - void changePage("TRANSIT_VIEW_SECRET"); + onclick: async () => { + this.state.currentSecret = secret; + await this.router.changePage("TRANSIT_VIEW_SECRET"); }, }), }); @@ -72,6 +70,10 @@ export class TransitViewPage extends Page { } } + async getPageTitle(): Promise { + return await SecretTitleElement(this.router); + } + get name(): string { return i18next.t("transit_view_title"); } diff --git a/src/pages/Transit/TransitViewSecret.ts b/src/pages/Transit/TransitViewSecret.ts index 5cf7ee2..42b3b0c 100644 --- a/src/pages/Transit/TransitViewSecret.ts +++ b/src/pages/Transit/TransitViewSecret.ts @@ -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 { changePage, setPageContent, setTitleElement } from "../../pageUtils"; import { getTransitKey } from "../../api/transit/getTransitKey"; import { makeElement } from "../../htmlUtils"; -import { pageState } from "../../globalPageState"; import i18next from "i18next"; export class TransitViewSecretPage extends Page { @@ -12,15 +11,13 @@ export class TransitViewSecretPage extends Page { } async goBack(): Promise { - await changePage("TRANSIT_VIEW"); + await this.router.changePage("TRANSIT_VIEW"); } async render(): Promise { - setTitleElement(pageState); + const transitKey = await getTransitKey(this.state.currentBaseMount, this.state.currentSecret); - const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); - - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", 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"), icon: "lock", iconText: i18next.t("transit_view_encrypt_icon_text"), - onclick: () => { - void changePage("TRANSIT_ENCRYPT"); + onclick: async () => { + await this.router.changePage("TRANSIT_ENCRYPT"); }, }), Tile({ @@ -42,8 +39,8 @@ export class TransitViewSecretPage extends Page { description: i18next.t("transit_view_decrypt_description"), icon: "mail", iconText: i18next.t("transit_view_decrypt_icon_text"), - onclick: () => { - void changePage("TRANSIT_DECRYPT"); + onclick: async () => { + await this.router.changePage("TRANSIT_DECRYPT"); }, }), Tile({ @@ -52,8 +49,8 @@ export class TransitViewSecretPage extends Page { description: i18next.t("transit_view_rewrap_description"), icon: "code", iconText: i18next.t("transit_view_rewrap_icon_text"), - onclick: () => { - void changePage("TRANSIT_REWRAP"); + onclick: async () => { + await this.router.changePage("TRANSIT_REWRAP"); }, }), ], @@ -61,6 +58,10 @@ export class TransitViewSecretPage extends Page { ); } + async getPageTitle(): Promise { + return await SecretTitleElement(this.router); + } + get name(): string { return i18next.t("transit_view_secret_title"); } diff --git a/src/pages/Unseal.ts b/src/pages/Unseal.ts index a53e182..3e5b2d0 100644 --- a/src/pages/Unseal.ts +++ b/src/pages/Unseal.ts @@ -1,9 +1,9 @@ import { MarginInline } from "../elements/MarginInline"; -import { Page } from "../types/Page"; +import { Page } from "../PageSystem/Page"; import { QRScanner, QRScannerType } from "../elements/QRScanner"; import { SealStatusType, getSealStatus } from "../api/sys/getSealStatus"; -import { changePage, setErrorText, setPageContent } from "../pageUtils"; import { makeElement } from "../htmlUtils"; +import { setErrorText } from "../pageUtils"; import { submitUnsealKey } from "../api/sys/submitUnsealKey"; import i18next from "i18next"; @@ -68,7 +68,7 @@ export class UnsealPage extends Page { this.unsealInputContent = makeElement({ tag: "div", }); - setPageContent( + await this.router.setPageContent( makeElement({ tag: "div", children: [ @@ -169,7 +169,7 @@ export class UnsealPage extends Page { progressBar.max = keysNeeded; if (!data.sealed) { progressBar.value = keysNeeded; - await changePage("HOME"); + await this.router.changePage("HOME"); } } diff --git a/src/playground.ts b/src/playground.ts index 29ff118..bfbc6ed 100644 --- a/src/playground.ts +++ b/src/playground.ts @@ -1,7 +1,5 @@ -import { PageRouter } from "./PageRouter"; +import { PageRouter } from "./PageSystem/PageRouter"; import { PageState } from "./PageState"; -import { pageRouter } from "./globalPageRouter"; -import { pageState } from "./globalPageState"; import i18next from "i18next"; // Playground is a way to debug and test things. @@ -18,9 +16,9 @@ declare global { } // Please empty this function before committing. -export async function playground(): Promise { +export async function playground(router: PageRouter): Promise { console.log("Welcome to Playground!"); - window.pageState = pageState; + window.pageState = router.state; window.i18next = i18next; - window.router = pageRouter; + window.router = router; } diff --git a/src/types/Page.ts b/src/types/Page.ts deleted file mode 100644 index 79872eb..0000000 --- a/src/types/Page.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { changePage } from "../pageUtils"; - -export class Page { - constructor() { - // Do Nothing - } - async render(): Promise {} - get name(): string { - return "Page"; - } - get titleSuffix(): string { - return ""; - } - async goBack(): Promise { - await changePage("HOME"); - } - async cleanup(): Promise { - // Do Nothing - } -}