From b3e87772ec11913b8ac478315329dee4378fc833 Mon Sep 17 00:00:00 2001 From: Rodolfo Date: Tue, 9 Dec 2025 22:02:14 -0500 Subject: [PATCH] gui fixes --- web/maplefile-frontend/index.html | 4 +- .../src/components/Layout/Layout.jsx | 20 +- .../src/components/Layout/TopNavbar.jsx | 21 +- .../src/pages/User/Me/ExportData.jsx | 374 +++--------------- 4 files changed, 81 insertions(+), 338 deletions(-) diff --git a/web/maplefile-frontend/index.html b/web/maplefile-frontend/index.html index 6d621fc..cc650a4 100644 --- a/web/maplefile-frontend/index.html +++ b/web/maplefile-frontend/index.html @@ -7,9 +7,9 @@ - + + - diff --git a/web/maplefile-frontend/src/components/Layout/Layout.jsx b/web/maplefile-frontend/src/components/Layout/Layout.jsx index 0f1b9c6..f4d07c0 100644 --- a/web/maplefile-frontend/src/components/Layout/Layout.jsx +++ b/web/maplefile-frontend/src/components/Layout/Layout.jsx @@ -1,7 +1,7 @@ // File Path: web/frontend/src/components/Layout/Layout.jsx // Fixed Layout Component - Mobile Menu Now Works Properly -import React, { useState, useEffect, useCallback } from "react"; +import React, { useState, useEffect, useCallback, useRef } from "react"; import TopNavbar from "./TopNavbar"; import Sidebar from "./Sidebar"; import { useInactivityTimeout } from "../../hooks/useInactivityTimeout"; @@ -292,7 +292,16 @@ function Layout({ children }) { return () => window.removeEventListener("resize", handleResize); }, [isMobile]); // Include isMobile but use functional state updates to avoid loops + // Track last toggle time to prevent double-clicks + const lastToggleRef = useRef(0); + const handleMenuToggle = useCallback(() => { + const now = Date.now(); + // Prevent double-clicks only (100ms window) + if (now - lastToggleRef.current < 100) { + return; + } + lastToggleRef.current = now; setIsSidebarOpen(current => !current); }, []); @@ -300,8 +309,17 @@ function Layout({ children }) { setIsSidebarOpen(false); }, []); + // Track last collapse toggle time to prevent double-clicks + const lastCollapseToggleRef = useRef(0); + // Handle collapse toggle for desktop view const handleCollapseToggle = useCallback(() => { + const now = Date.now(); + // Prevent double-clicks only (100ms window) + if (now - lastCollapseToggleRef.current < 100) { + return; + } + lastCollapseToggleRef.current = now; setSidebarCollapsed(current => { const newCollapsedState = !current; localStorage.setItem("sidebarCollapsed", newCollapsedState.toString()); diff --git a/web/maplefile-frontend/src/components/Layout/TopNavbar.jsx b/web/maplefile-frontend/src/components/Layout/TopNavbar.jsx index 0f04a5c..8782c30 100644 --- a/web/maplefile-frontend/src/components/Layout/TopNavbar.jsx +++ b/web/maplefile-frontend/src/components/Layout/TopNavbar.jsx @@ -11,6 +11,7 @@ import { UserCircleIcon, ArrowRightOnRectangleIcon, ChevronDownIcon, + LockClosedIcon, } from "@heroicons/react/24/outline"; import { Modal, Button, useUIXTheme } from "../UIX"; @@ -248,12 +249,20 @@ function TopNavbar({ ${isMobile ? "justify-center" : "justify-start ml-4"} `} > - MapleFile Logo + + {/* Lock icon with theme-aware background */} +
+
+ {/* MapleFile text - hidden on mobile */} + + MapleFile + + {/* Spacer for mobile to balance the layout */} diff --git a/web/maplefile-frontend/src/pages/User/Me/ExportData.jsx b/web/maplefile-frontend/src/pages/User/Me/ExportData.jsx index d581ad4..f43dfde 100644 --- a/web/maplefile-frontend/src/pages/User/Me/ExportData.jsx +++ b/web/maplefile-frontend/src/pages/User/Me/ExportData.jsx @@ -6,13 +6,10 @@ import Layout from "../../../components/Layout/Layout"; import { DetailLiteView, Button, useUIXTheme } from "../../../components/UIX"; import { ArrowDownTrayIcon, - InformationCircleIcon, ComputerDesktopIcon, - ShieldCheckIcon, - DocumentTextIcon, - CodeBracketIcon, HomeIcon, UserIcon, + ArrowTopRightOnSquareIcon, } from "@heroicons/react/24/outline"; // Constant empty object to prevent re-renders (reused across renders) @@ -21,34 +18,6 @@ const EMPTY_ENTITY_DATA = {}; const ExportData = () => { const { getThemeClasses } = useUIXTheme(); - // Theme-aware section styles - const sectionStyles = useMemo(() => ({ - success: { - container: getThemeClasses("export-section-success-bg"), - border: getThemeClasses("export-section-success-border"), - icon: getThemeClasses("export-section-success-icon"), - title: getThemeClasses("export-section-success-title"), - text: getThemeClasses("export-section-success-text"), - muted: getThemeClasses("export-section-success-muted"), - }, - info: { - container: getThemeClasses("export-section-info-bg"), - border: getThemeClasses("export-section-info-border"), - icon: getThemeClasses("export-section-info-icon"), - title: getThemeClasses("export-section-info-title"), - text: getThemeClasses("export-section-info-text"), - }, - warning: { - container: getThemeClasses("export-section-warning-bg"), - border: getThemeClasses("export-section-warning-border"), - icon: getThemeClasses("export-section-warning-icon"), - title: getThemeClasses("export-section-warning-title"), - text: getThemeClasses("export-section-warning-text"), - muted: getThemeClasses("export-section-warning-muted"), - code: getThemeClasses("export-section-warning-code"), - }, - }), [getThemeClasses]); - // Breadcrumb configuration const breadcrumbItems = useMemo( () => [ @@ -74,7 +43,7 @@ const ExportData = () => { const headerConfig = useMemo( () => ({ title: "Export Your Data", - subtitle: "Download a complete copy of your account data in accordance with GDPR Article 20 (Right to Data Portability)", + subtitle: "Download a complete copy of your account data (GDPR Article 20)", icon: ArrowDownTrayIcon, }), [], @@ -83,306 +52,53 @@ const ExportData = () => { // Content sections const contentSections = useMemo(() => { return ( -
- {/* Quick Export Option - GDPR Compliance */} -
-
-
-
- - {/* Information Notice */} -
-
-
-
- - {/* E2EE Explanation */} -
-
-
-
- - {/* Desktop Application Installation */} -
-
-
-
- - {/* What Gets Exported */} -
-
-
-
- - {/* GDPR Information */} -
-

- GDPR Article 20 - Right to Data Portability -

-

- You have the right to receive the personal data concerning you, which you have provided to us, in a structured, commonly used and machine-readable format. You also have the right to transmit those data to another controller. -

-

- The MapleFile Desktop Application ensures compliance with this right by providing your complete data archive in standard formats (JSON metadata, original file formats). -

-
- - {/* Security Notice */} -
-
-
-
- - {/* Support Section */} -
-

- Need Help? -

-

- If you encounter any issues installing or using the MapleFile Desktop Application, please: -

-
    -
  • - - Check the README.md file in the repository for detailed documentation -
  • -
  • - - Open an issue on the Codeberg repository for technical support -
  • -
  • - - Review the application's help documentation and user guide -
  • -
-
- - {/* Action Button */} -
- - - + + +
+ + + {/* GDPR Information */} +
+

+ GDPR Article 20 - Right to Data Portability +

+

+ You have the right to receive your personal data in a structured, commonly used, and machine-readable format. The MapleFile Desktop Application provides your complete data archive in standard formats. +

+
); - }, [getThemeClasses, sectionStyles]); + }, [getThemeClasses]); // Field sections for DetailLiteView const fieldSections = useMemo(() => {