Add public mode
This commit is contained in:
parent
56370ec936
commit
f16eeb6e45
@ -0,0 +1,34 @@
|
|||||||
|
import React, { PropsWithChildren } from "react";
|
||||||
|
|
||||||
|
const localStorageKey = "public-mode";
|
||||||
|
|
||||||
|
interface PublicModeContext {
|
||||||
|
enabled: boolean;
|
||||||
|
setEnabled: (enabled: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PublicModeContextK = React.createContext<PublicModeContext | null>(null);
|
||||||
|
|
||||||
|
export function PublicModeProvider(p: PropsWithChildren): React.ReactElement {
|
||||||
|
const [enabled, setEnabled] = React.useState(
|
||||||
|
localStorage.getItem(localStorageKey) !== "false"
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PublicModeContextK
|
||||||
|
value={{
|
||||||
|
enabled: enabled,
|
||||||
|
setEnabled(enabled) {
|
||||||
|
localStorage.setItem(localStorageKey, enabled ? "true" : "false");
|
||||||
|
setEnabled(enabled);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{p.children}
|
||||||
|
</PublicModeContextK>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePublicMode(): PublicModeContext {
|
||||||
|
return React.use(PublicModeContextK)!;
|
||||||
|
}
|
@ -15,6 +15,7 @@ import { LoadingMessageProvider } from "./hooks/context_providers/LoadingMessage
|
|||||||
import { SnackbarProvider } from "./hooks/context_providers/SnackbarProvider.tsx";
|
import { SnackbarProvider } from "./hooks/context_providers/SnackbarProvider.tsx";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { AsyncWidget } from "./widgets/AsyncWidget.tsx";
|
import { AsyncWidget } from "./widgets/AsyncWidget.tsx";
|
||||||
|
import { PublicModeProvider } from "./hooks/context_providers/PublicModeProvider.tsx";
|
||||||
|
|
||||||
createRoot(document.getElementById("root")!).render(
|
createRoot(document.getElementById("root")!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
@ -24,12 +25,16 @@ createRoot(document.getElementById("root")!).render(
|
|||||||
<ConfirmDialogProvider>
|
<ConfirmDialogProvider>
|
||||||
<SnackbarProvider>
|
<SnackbarProvider>
|
||||||
<LoadingMessageProvider>
|
<LoadingMessageProvider>
|
||||||
|
<PublicModeProvider>
|
||||||
<AsyncWidget
|
<AsyncWidget
|
||||||
loadKey={1}
|
loadKey={1}
|
||||||
load={async () => { await ServerApi.LoadConfig(); }}
|
load={async () => {
|
||||||
|
await ServerApi.LoadConfig();
|
||||||
|
}}
|
||||||
errMsg="Failed to load static server configuration!"
|
errMsg="Failed to load static server configuration!"
|
||||||
build={() => <App />}
|
build={() => <App />}
|
||||||
/>
|
/>
|
||||||
|
</PublicModeProvider>
|
||||||
</LoadingMessageProvider>
|
</LoadingMessageProvider>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
</ConfirmDialogProvider>
|
</ConfirmDialogProvider>
|
||||||
|
@ -13,8 +13,10 @@ import { fmtDateFromTime, time } from "../utils/DateUtils";
|
|||||||
import { AmountWidget } from "../widgets/AmountWidget";
|
import { AmountWidget } from "../widgets/AmountWidget";
|
||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
|
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
|
||||||
|
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
|
||||||
|
|
||||||
export function HomeRoute(): React.ReactElement {
|
export function HomeRoute(): React.ReactElement {
|
||||||
|
const publicMode = usePublicMode().enabled;
|
||||||
const account = useAccounts();
|
const account = useAccounts();
|
||||||
|
|
||||||
const loadKey = React.useRef(1);
|
const loadKey = React.useRef(1);
|
||||||
@ -62,6 +64,20 @@ export function HomeRoute(): React.ReactElement {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
{publicMode ? (
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
|
flex: 1,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Dasbhoard is hidden when public mode is enabled.
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
<AsyncWidget
|
<AsyncWidget
|
||||||
ready={global !== undefined}
|
ready={global !== undefined}
|
||||||
loadKey={loadKey.current}
|
loadKey={loadKey.current}
|
||||||
@ -69,6 +85,7 @@ export function HomeRoute(): React.ReactElement {
|
|||||||
errMsg="Failed to load statistics!"
|
errMsg="Failed to load statistics!"
|
||||||
build={() => <StatsDashboard global={global!} lastYear={lastYear!} />}
|
build={() => <StatsDashboard global={global!} lastYear={lastYear!} />}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</MoneyMgrWebRouteContainer>
|
</MoneyMgrWebRouteContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import Paper from "@mui/material/Paper";
|
|||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import { Link, Outlet } from "react-router-dom";
|
import { Link, Outlet } from "react-router-dom";
|
||||||
import loginSplashImage from "./mufid-majnun-LVcjYwuHQlg-unsplash.jpg";
|
import loginSplashImage from "./mufid-majnun-LVcjYwuHQlg-unsplash.jpg";
|
||||||
|
import { PublicModeButton } from "./PublicModeButtonWidget";
|
||||||
|
import { DarkThemeButton } from "./DarkThemeButtonWidget";
|
||||||
|
|
||||||
function Copyright(props: any): React.ReactElement {
|
function Copyright(props: any): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
@ -86,7 +88,19 @@ export function BaseLoginPage() {
|
|||||||
{/* inner page */}
|
{/* inner page */}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|
||||||
<Copyright sx={{ mt: 5 }} style={{ margin: " 40px 0px" }} />
|
<Copyright sx={{ mt: 5 }} style={{ margin: "40px 0px" }} />
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "50px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PublicModeButton />
|
||||||
|
<DarkThemeButton />
|
||||||
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -7,9 +7,11 @@ export function DarkThemeButton(): React.ReactElement {
|
|||||||
const darkTheme = useDarkTheme();
|
const darkTheme = useDarkTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip title="Activer / désactiver le mode sombre">
|
<Tooltip title="Enable / Disable dark theme">
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => { darkTheme.setEnabled(!darkTheme.enabled); }}
|
onClick={() => {
|
||||||
|
darkTheme.setEnabled(!darkTheme.enabled);
|
||||||
|
}}
|
||||||
style={{ color: "inherit" }}
|
style={{ color: "inherit" }}
|
||||||
>
|
>
|
||||||
{!darkTheme.enabled ? <DarkModeIcon /> : <Brightness7Icon />}
|
{!darkTheme.enabled ? <DarkModeIcon /> : <Brightness7Icon />}
|
@ -14,8 +14,10 @@ import { useAccounts } from "../hooks/AccountsListProvider";
|
|||||||
import { AccountWidget } from "./AccountWidget";
|
import { AccountWidget } from "./AccountWidget";
|
||||||
import { RouterLink } from "./RouterLink";
|
import { RouterLink } from "./RouterLink";
|
||||||
import { AmountWidget } from "./AmountWidget";
|
import { AmountWidget } from "./AmountWidget";
|
||||||
|
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
|
||||||
|
|
||||||
export function MoneyNavList(): React.ReactElement {
|
export function MoneyNavList(): React.ReactElement {
|
||||||
|
const publicMode = usePublicMode();
|
||||||
const accounts = useAccounts();
|
const accounts = useAccounts();
|
||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
@ -62,7 +64,9 @@ export function MoneyNavList(): React.ReactElement {
|
|||||||
<NavLink
|
<NavLink
|
||||||
key={a.id}
|
key={a.id}
|
||||||
label={a.name}
|
label={a.name}
|
||||||
secondaryLabel={<AmountWidget amount={a.balance} />}
|
secondaryLabel={
|
||||||
|
publicMode.enabled ? <></> : <AmountWidget amount={a.balance} />
|
||||||
|
}
|
||||||
uri={`/account/${a.id}`}
|
uri={`/account/${a.id}`}
|
||||||
icon={<AccountWidget account={a} />}
|
icon={<AccountWidget account={a} />}
|
||||||
/>
|
/>
|
||||||
|
@ -9,8 +9,9 @@ import Toolbar from "@mui/material/Toolbar";
|
|||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useAuthInfo } from "./BaseAuthenticatedPage";
|
import { useAuthInfo } from "./BaseAuthenticatedPage";
|
||||||
import { DarkThemeButton } from "./DarkThemeButton";
|
import { DarkThemeButton } from "./DarkThemeButtonWidget";
|
||||||
import { RouterLink } from "./RouterLink";
|
import { RouterLink } from "./RouterLink";
|
||||||
|
import { PublicModeButton } from "./PublicModeButtonWidget";
|
||||||
|
|
||||||
export function MoneyWebAppBar(p: {
|
export function MoneyWebAppBar(p: {
|
||||||
onSignOut: () => void;
|
onSignOut: () => void;
|
||||||
@ -41,6 +42,7 @@ export function MoneyWebAppBar(p: {
|
|||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<PublicModeButton />
|
||||||
<DarkThemeButton />
|
<DarkThemeButton />
|
||||||
|
|
||||||
<Button size="large" color="inherit">
|
<Button size="large" color="inherit">
|
||||||
|
21
moneymgr_web/src/widgets/PublicModeButtonWidget.tsx
Normal file
21
moneymgr_web/src/widgets/PublicModeButtonWidget.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import PublicIcon from "@mui/icons-material/Public";
|
||||||
|
import PublicOffIcon from "@mui/icons-material/PublicOff";
|
||||||
|
import { IconButton, Tooltip } from "@mui/material";
|
||||||
|
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
|
||||||
|
|
||||||
|
export function PublicModeButton(): React.ReactElement {
|
||||||
|
const publicMode = usePublicMode();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={`${publicMode.enabled ? "Disable" : "Enable"} public mode`}>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
publicMode.setEnabled(!publicMode.enabled);
|
||||||
|
}}
|
||||||
|
style={{ color: "inherit" }}
|
||||||
|
>
|
||||||
|
{!publicMode.enabled ? <PublicOffIcon /> : <PublicIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user