summaryrefslogtreecommitdiff
path: root/packages/auditor-backoffice-ui/src/components/menu/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/auditor-backoffice-ui/src/components/menu/index.tsx')
-rw-r--r--packages/auditor-backoffice-ui/src/components/menu/index.tsx237
1 files changed, 237 insertions, 0 deletions
diff --git a/packages/auditor-backoffice-ui/src/components/menu/index.tsx b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
new file mode 100644
index 000000000..015d3bd05
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
@@ -0,0 +1,237 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { AdminPaths } from "../../AdminRoutes.js";
+import { InstancePaths } from "../../InstanceRoutes.js";
+import { Notification } from "../../utils/types.js";
+import { NavigationBar } from "./NavigationBar.js";
+import { Sidebar } from "./SideBar.js";
+
+function getInstanceTitle(path: string, id: string): string {
+ switch (path) {
+ case InstancePaths.settings:
+ return `${id}: Settings`;
+ case InstancePaths.inventory_list:
+ return `${id}: Inventory`;
+ case InstancePaths.deposit_confirmation_list:
+ return `${id}: Deposit Confirmation`;
+ case InstancePaths.inventory_new:
+ return `${id}: New product`;
+ case InstancePaths.inventory_update:
+ return `${id}: Update product`;
+ case InstancePaths.interface:
+ return `${id}: Interface`;
+ default:
+ return "";
+ }
+}
+
+function getAdminTitle(path: string, instance: string) {
+ if (path === AdminPaths.new_instance) return `New instance`;
+ if (path === AdminPaths.list_instances) return `Instances`;
+ return getInstanceTitle(path, instance);
+}
+
+interface MenuProps {
+ title?: string;
+ path: string;
+ instance: string;
+ admin?: boolean;
+ onLogout?: () => void;
+ onShowSettings: () => void;
+ setInstanceName: (s: string) => void;
+ isPasswordOk: boolean;
+}
+
+function WithTitle({
+ title,
+ children,
+}: {
+ title: string;
+ children: ComponentChildren;
+}): VNode {
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+ return <Fragment>{children}</Fragment>;
+}
+
+export function Menu({
+ onLogout,
+ onShowSettings,
+ title,
+ instance,
+ path,
+ admin,
+ setInstanceName,
+ isPasswordOk
+}: MenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ const titleWithSubtitle = title
+ ? title
+ : !admin
+ ? getInstanceTitle(path, instance)
+ : getAdminTitle(path, instance);
+ const adminInstance = instance === "default";
+ const mimic = admin && !adminInstance;
+ return (
+ <WithTitle title={titleWithSubtitle}>
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={titleWithSubtitle}
+ />
+
+ {onLogout && (
+ <Sidebar
+ onShowSettings={onShowSettings}
+ onLogout={onLogout}
+ admin={admin}
+ mimic={mimic}
+ instance={instance}
+ mobile={mobileOpen}
+ isPasswordOk={isPasswordOk}
+ />
+ )}
+
+ {mimic && (
+ <nav class="level" style={{
+ zIndex: 100,
+ position: "fixed",
+ width: "50%",
+ marginLeft: "20%"
+ }}>
+ <div class="level-item has-text-centered has-background-warning">
+ <p class="is-size-5">
+ You are viewing the instance <b>&quot;{instance}&quot;</b>.{" "}
+ <a
+ href="#/instances"
+ onClick={(e) => {
+ setInstanceName("default");
+ }}
+ >
+ go back
+ </a>
+ </p>
+ </div>
+ </nav>
+ )}
+ </div>
+ </WithTitle>
+ );
+}
+
+interface NotYetReadyAppMenuProps {
+ title: string;
+ onShowSettings: () => void;
+ onLogout?: () => void;
+ isPasswordOk: boolean;
+}
+
+interface NotifProps {
+ notification?: Notification;
+}
+export function NotificationCard({
+ notification: n,
+}: NotifProps): VNode | null {
+ if (!n) return null;
+ return (
+ <div class="notification">
+ <div class="columns is-vcentered">
+ <div class="column is-12">
+ <article
+ class={
+ n.type === "ERROR"
+ ? "message is-danger"
+ : n.type === "WARN"
+ ? "message is-warning"
+ : "message is-info"
+ }
+ >
+ <div class="message-header">
+ <p>{n.message}</p>
+ </div>
+ {n.description && (
+ <div class="message-body">
+ <div>{n.description}</div>
+ {n.details && <pre>{n.details}</pre>}
+ </div>
+ )}
+ </article>
+ </div>
+ </div>
+ </div>
+ );
+}
+
+interface NotConnectedAppMenuProps {
+ title: string;
+}
+export function NotConnectedAppMenu({
+ title,
+}: NotConnectedAppMenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+
+ return (
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={title}
+ />
+ </div>
+ );
+}
+
+export function NotYetReadyAppMenu({
+ onLogout,
+ onShowSettings,
+ title,
+ isPasswordOk
+}: NotYetReadyAppMenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+
+ return (
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={title}
+ />
+ {onLogout && (
+ <Sidebar onShowSettings={onShowSettings} onLogout={onLogout} instance="" mobile={mobileOpen} isPasswordOk={isPasswordOk} />
+ )}
+ </div>
+ );
+}