gui fixes
This commit is contained in:
parent
3bf89fe2fa
commit
b3e87772ec
4 changed files with 81 additions and 338 deletions
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
<!-- Security Headers (Defense in Depth - Backend should also set HTTP headers) -->
|
<!-- Security Headers (Defense in Depth - Backend should also set HTTP headers) -->
|
||||||
<!-- Note: connect-src includes localhost:8000 (API), localhost:8334 (MinIO/S3 dev), and production S3 endpoints -->
|
<!-- Note: connect-src includes localhost:8000 (API), localhost:8334 (MinIO/S3 dev), and production S3 endpoints -->
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://localhost:8000 http://localhost:8334 https://*.digitaloceanspaces.com https://*.amazonaws.com ws://localhost:*; frame-ancestors 'none'; base-uri 'self'; form-action 'self';">
|
<!-- Note: frame-ancestors and X-Frame-Options must be set via HTTP headers, not meta tags -->
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://localhost:8000 http://localhost:8334 https://*.digitaloceanspaces.com https://*.amazonaws.com ws://localhost:*; base-uri 'self'; form-action 'self';">
|
||||||
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
||||||
<meta http-equiv="X-Frame-Options" content="DENY">
|
|
||||||
<meta name="referrer" content="strict-origin-when-cross-origin">
|
<meta name="referrer" content="strict-origin-when-cross-origin">
|
||||||
<meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()">
|
<meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// File Path: web/frontend/src/components/Layout/Layout.jsx
|
// File Path: web/frontend/src/components/Layout/Layout.jsx
|
||||||
// Fixed Layout Component - Mobile Menu Now Works Properly
|
// 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 TopNavbar from "./TopNavbar";
|
||||||
import Sidebar from "./Sidebar";
|
import Sidebar from "./Sidebar";
|
||||||
import { useInactivityTimeout } from "../../hooks/useInactivityTimeout";
|
import { useInactivityTimeout } from "../../hooks/useInactivityTimeout";
|
||||||
|
|
@ -292,7 +292,16 @@ function Layout({ children }) {
|
||||||
return () => window.removeEventListener("resize", handleResize);
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
}, [isMobile]); // Include isMobile but use functional state updates to avoid loops
|
}, [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 handleMenuToggle = useCallback(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
// Prevent double-clicks only (100ms window)
|
||||||
|
if (now - lastToggleRef.current < 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastToggleRef.current = now;
|
||||||
setIsSidebarOpen(current => !current);
|
setIsSidebarOpen(current => !current);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
@ -300,8 +309,17 @@ function Layout({ children }) {
|
||||||
setIsSidebarOpen(false);
|
setIsSidebarOpen(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Track last collapse toggle time to prevent double-clicks
|
||||||
|
const lastCollapseToggleRef = useRef(0);
|
||||||
|
|
||||||
// Handle collapse toggle for desktop view
|
// Handle collapse toggle for desktop view
|
||||||
const handleCollapseToggle = useCallback(() => {
|
const handleCollapseToggle = useCallback(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
// Prevent double-clicks only (100ms window)
|
||||||
|
if (now - lastCollapseToggleRef.current < 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastCollapseToggleRef.current = now;
|
||||||
setSidebarCollapsed(current => {
|
setSidebarCollapsed(current => {
|
||||||
const newCollapsedState = !current;
|
const newCollapsedState = !current;
|
||||||
localStorage.setItem("sidebarCollapsed", newCollapsedState.toString());
|
localStorage.setItem("sidebarCollapsed", newCollapsedState.toString());
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
UserCircleIcon,
|
UserCircleIcon,
|
||||||
ArrowRightOnRectangleIcon,
|
ArrowRightOnRectangleIcon,
|
||||||
ChevronDownIcon,
|
ChevronDownIcon,
|
||||||
|
LockClosedIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { Modal, Button, useUIXTheme } from "../UIX";
|
import { Modal, Button, useUIXTheme } from "../UIX";
|
||||||
|
|
||||||
|
|
@ -248,12 +249,20 @@ function TopNavbar({
|
||||||
${isMobile ? "justify-center" : "justify-start ml-4"}
|
${isMobile ? "justify-center" : "justify-start ml-4"}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<img
|
<Link
|
||||||
src="/img/compressed-logo.png"
|
to="/dashboard"
|
||||||
alt="MapleFile Logo"
|
className="flex items-center gap-2 hover:opacity-90 transition-opacity"
|
||||||
className="h-8 w-auto sm:h-9 md:h-10"
|
aria-label="Go to Dashboard"
|
||||||
draggable="false"
|
>
|
||||||
/>
|
{/* Lock icon with theme-aware background */}
|
||||||
|
<div className={`${getThemeClasses("bg-gradient-secondary")} p-1.5 sm:p-2 rounded-lg`}>
|
||||||
|
<LockClosedIcon className="h-5 w-5 sm:h-6 sm:w-6 text-white" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
{/* MapleFile text - hidden on mobile */}
|
||||||
|
<span className="hidden sm:inline text-white font-semibold text-base md:text-lg tracking-tight">
|
||||||
|
MapleFile
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Spacer for mobile to balance the layout */}
|
{/* Spacer for mobile to balance the layout */}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,10 @@ import Layout from "../../../components/Layout/Layout";
|
||||||
import { DetailLiteView, Button, useUIXTheme } from "../../../components/UIX";
|
import { DetailLiteView, Button, useUIXTheme } from "../../../components/UIX";
|
||||||
import {
|
import {
|
||||||
ArrowDownTrayIcon,
|
ArrowDownTrayIcon,
|
||||||
InformationCircleIcon,
|
|
||||||
ComputerDesktopIcon,
|
ComputerDesktopIcon,
|
||||||
ShieldCheckIcon,
|
|
||||||
DocumentTextIcon,
|
|
||||||
CodeBracketIcon,
|
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
UserIcon,
|
UserIcon,
|
||||||
|
ArrowTopRightOnSquareIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
// Constant empty object to prevent re-renders (reused across renders)
|
// Constant empty object to prevent re-renders (reused across renders)
|
||||||
|
|
@ -21,34 +18,6 @@ const EMPTY_ENTITY_DATA = {};
|
||||||
const ExportData = () => {
|
const ExportData = () => {
|
||||||
const { getThemeClasses } = useUIXTheme();
|
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
|
// Breadcrumb configuration
|
||||||
const breadcrumbItems = useMemo(
|
const breadcrumbItems = useMemo(
|
||||||
() => [
|
() => [
|
||||||
|
|
@ -74,7 +43,7 @@ const ExportData = () => {
|
||||||
const headerConfig = useMemo(
|
const headerConfig = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
title: "Export Your Data",
|
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,
|
icon: ArrowDownTrayIcon,
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
|
|
@ -83,306 +52,53 @@ const ExportData = () => {
|
||||||
// Content sections
|
// Content sections
|
||||||
const contentSections = useMemo(() => {
|
const contentSections = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6" role="main" aria-label="Export data options">
|
<div className="space-y-6" role="main" aria-label="Export data information">
|
||||||
{/* Quick Export Option - GDPR Compliance */}
|
{/* Desktop App Required Notice */}
|
||||||
<section
|
<section
|
||||||
aria-labelledby="quick-export-heading"
|
aria-labelledby="desktop-required-heading"
|
||||||
className={`${sectionStyles.success.container} border-2 ${sectionStyles.success.border} rounded-xl p-6`}
|
className={`${getThemeClasses("bg-accent-light")} border-2 ${getThemeClasses("border-accent")} rounded-xl p-6`}
|
||||||
>
|
>
|
||||||
<div className="flex items-start">
|
<div className="flex items-start">
|
||||||
<ArrowDownTrayIcon className={`h-6 w-6 ${sectionStyles.success.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
<ComputerDesktopIcon className={`h-8 w-8 ${getThemeClasses("text-accent")} mr-4 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 id="quick-export-heading" className={`text-lg font-semibold ${sectionStyles.success.title} mb-2`}>
|
<h3 id="desktop-required-heading" className={`text-xl font-semibold ${getThemeClasses("text-primary")} mb-3`}>
|
||||||
Quick Export (Web Browser)
|
Desktop App Required
|
||||||
</h3>
|
</h3>
|
||||||
<p className={`${sectionStyles.success.text} mb-3`}>
|
<p className={`${getThemeClasses("text-secondary")} mb-4 text-base`}>
|
||||||
In compliance with GDPR Article 20, you can export your data directly from your web browser. This option is suitable for accounts with moderate amounts of data.
|
Data export is only available through the <strong>MapleFile Desktop Application</strong>. Due to end-to-end encryption, your files can only be decrypted and exported using the native app.
|
||||||
</p>
|
</p>
|
||||||
<p className={`${sectionStyles.success.text} mb-4`}>
|
<a
|
||||||
<strong>What gets exported:</strong> Profile information, collection metadata, and file lists (metadata only - actual file downloads require desktop app due to E2EE).
|
href="https://maplefile.com"
|
||||||
</p>
|
target="_blank"
|
||||||
<div className="flex space-x-3">
|
rel="noopener noreferrer"
|
||||||
<Button
|
aria-label="Download MapleFile Desktop App (opens in new tab)"
|
||||||
variant="primary"
|
|
||||||
icon={ArrowDownTrayIcon}
|
|
||||||
onClick={() => alert('This feature will be implemented by the backend team. It should generate a JSON export of user profile, collections, and file metadata.')}
|
|
||||||
>
|
|
||||||
Export Metadata (JSON)
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<p className={`text-xs ${sectionStyles.success.muted} mt-3`}>
|
|
||||||
<strong>Timeline:</strong> Your export will be available for download within 24 hours. Large exports may take up to 72 hours. You'll receive an email when ready.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Information Notice */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="desktop-info-heading"
|
|
||||||
className={`${sectionStyles.info.container} border-2 ${sectionStyles.info.border} rounded-xl p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex items-start">
|
|
||||||
<InformationCircleIcon className={`h-6 w-6 ${sectionStyles.info.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
|
||||||
<div className="flex-1">
|
|
||||||
<h3 id="desktop-info-heading" className={`text-lg font-semibold ${sectionStyles.info.title} mb-2`}>
|
|
||||||
Desktop Application for Complete Export
|
|
||||||
</h3>
|
|
||||||
<p className={`${sectionStyles.info.text} mb-3`}>
|
|
||||||
For exporting <strong>complete data including decrypted files</strong>, we recommend using the <strong>MapleFile Desktop Application</strong>. Due to end-to-end encryption, only the desktop app can decrypt and export your actual file contents.
|
|
||||||
</p>
|
|
||||||
<p className={sectionStyles.info.text}>
|
|
||||||
The desktop application efficiently manages the decryption and download of your complete data archive with all files in their original format.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* E2EE Explanation */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="e2ee-heading"
|
|
||||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex items-start mb-4">
|
|
||||||
<ShieldCheckIcon className={`h-6 w-6 ${getThemeClasses("icon-success")} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
|
||||||
<div>
|
|
||||||
<h3 id="e2ee-heading" className={`text-lg font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
|
||||||
Why End-to-End Encryption Matters
|
|
||||||
</h3>
|
|
||||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
|
||||||
Your files are encrypted on your device before they're uploaded to our servers. This means:
|
|
||||||
</p>
|
|
||||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Encryption benefits">
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Only you can decrypt and read your files</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>MapleFile servers cannot access your file contents</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Your privacy is protected even if servers are compromised</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Decryption requires your local encryption keys</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Desktop Application Installation */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="install-heading"
|
|
||||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex items-start mb-4">
|
|
||||||
<ComputerDesktopIcon className={`h-6 w-6 mr-3 flex-shrink-0 mt-0.5 ${getThemeClasses("link-primary")}`} aria-hidden="true" />
|
|
||||||
<div className="flex-1">
|
|
||||||
<h3 id="install-heading" className={`text-lg font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
|
||||||
Install MapleFile Desktop Application
|
|
||||||
</h3>
|
|
||||||
<p className={`${getThemeClasses("text-secondary")} mb-4`}>
|
|
||||||
The MapleFile Desktop Application is a native application that can export your data with full decryption support and an intuitive user interface.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Repository Link */}
|
|
||||||
<div className={`${getThemeClasses("bg-muted")} border ${getThemeClasses("border-secondary")} rounded-lg p-4 mb-4`}>
|
|
||||||
<div className="flex items-start">
|
|
||||||
<CodeBracketIcon className={`h-5 w-5 ${getThemeClasses("text-muted")} mr-3 mt-0.5`} aria-hidden="true" />
|
|
||||||
<div className="flex-1">
|
|
||||||
<p className={`text-sm font-medium mb-2 ${getThemeClasses("text-primary")}`}>
|
|
||||||
Source Code & Installation Instructions
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
href="https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={`${getThemeClasses("link-primary")} hover:underline text-sm font-mono break-all`}
|
|
||||||
>
|
|
||||||
https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Installation Steps */}
|
|
||||||
<div className="space-y-3">
|
|
||||||
<h4 className={`font-medium ${getThemeClasses("text-primary")}`}>Installation Steps:</h4>
|
|
||||||
<ol className={`space-y-3 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Installation steps">
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">1.</span>
|
|
||||||
<span>Visit the repository link above</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">2.</span>
|
|
||||||
<span>Follow the installation instructions in the README.md file</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">3.</span>
|
|
||||||
<span>Install the desktop application for your operating system (Windows, macOS, or Linux)</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">4.</span>
|
|
||||||
<span>Log in to your MapleFile account using the desktop application</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">5.</span>
|
|
||||||
<span>Use the export feature to download and decrypt your data</span>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* What Gets Exported */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="exported-data-heading"
|
|
||||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex items-start">
|
|
||||||
<DocumentTextIcon className={`h-6 w-6 ${getThemeClasses("text-muted")} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
|
||||||
<div className="flex-1">
|
|
||||||
<h3 id="exported-data-heading" className={`text-lg font-semibold mb-3 ${getThemeClasses("text-primary")}`}>
|
|
||||||
What Data Will Be Exported
|
|
||||||
</h3>
|
|
||||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
|
||||||
The desktop application will export a complete archive of your MapleFile account, including:
|
|
||||||
</p>
|
|
||||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Exported data types">
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span><strong>Profile Information:</strong> Your account details, settings, and preferences</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span><strong>Collections (Folders):</strong> All your collection metadata and structure</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span><strong>Files:</strong> All uploaded files, fully decrypted and in their original format</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span><strong>File Metadata:</strong> Creation dates, modification dates, file sizes, and descriptions</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span><strong>Sharing Information:</strong> Details about collections shared with you or by you</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p className={`${getThemeClasses("text-muted")} text-sm mt-4`}>
|
|
||||||
The export will be provided as a ZIP archive with a structured folder hierarchy matching your collections.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* GDPR Information */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="gdpr-heading"
|
|
||||||
className={`${getThemeClasses("bg-muted")} border ${getThemeClasses("border-secondary")} rounded-xl p-6`}
|
|
||||||
>
|
|
||||||
<h3 id="gdpr-heading" className={`text-sm font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
|
||||||
GDPR Article 20 - Right to Data Portability
|
|
||||||
</h3>
|
|
||||||
<p className={`text-sm ${getThemeClasses("text-secondary")} mb-2`}>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
<p className={`text-sm ${getThemeClasses("text-muted")}`}>
|
|
||||||
The MapleFile Desktop Application ensures compliance with this right by providing your complete data archive in standard formats (JSON metadata, original file formats).
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Security Notice */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="security-heading"
|
|
||||||
className={`${sectionStyles.warning.container} border-2 ${sectionStyles.warning.border} rounded-xl p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex items-start">
|
|
||||||
<ShieldCheckIcon className={`h-6 w-6 ${sectionStyles.warning.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
|
||||||
<div className="flex-1">
|
|
||||||
<h3 id="security-heading" className={`text-lg font-semibold ${sectionStyles.warning.title} mb-2`}>
|
|
||||||
Security: Verify Your Download
|
|
||||||
</h3>
|
|
||||||
<p className={`${sectionStyles.warning.text} mb-3`}>
|
|
||||||
For your security, always verify the authenticity of downloaded software:
|
|
||||||
</p>
|
|
||||||
<ul className={`space-y-2 ${sectionStyles.warning.text}`} role="list" aria-label="Security verification steps">
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Only download from the official Codeberg repository linked above</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Verify the repository URL matches: <code className={`${sectionStyles.warning.code} px-1 rounded`}>codeberg.org/mapleopentech</code></span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Check that your browser shows a secure HTTPS connection (padlock icon)</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
|
||||||
<span>Review the release notes and commit history before installation</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p className={`text-sm ${sectionStyles.warning.muted} mt-3`}>
|
|
||||||
<strong>Warning:</strong> Never download MapleFile software from unofficial sources or third-party websites.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Support Section */}
|
|
||||||
<section
|
|
||||||
aria-labelledby="support-heading"
|
|
||||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
|
||||||
>
|
|
||||||
<h3 id="support-heading" className={`text-lg font-semibold mb-3 ${getThemeClasses("text-primary")}`}>
|
|
||||||
Need Help?
|
|
||||||
</h3>
|
|
||||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
|
||||||
If you encounter any issues installing or using the MapleFile Desktop Application, please:
|
|
||||||
</p>
|
|
||||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Support options">
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span>Check the README.md file in the repository for detailed documentation</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span>Open an issue on the Codeberg repository for technical support</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start">
|
|
||||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
|
||||||
<span>Review the application's help documentation and user guide</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Action Button */}
|
|
||||||
<div className="flex justify-center py-6">
|
|
||||||
<a
|
|
||||||
href="https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
aria-label="Go to MapleFile Desktop Application Repository (opens in new tab)"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
icon={CodeBracketIcon}
|
|
||||||
>
|
>
|
||||||
Go to MapleFile Desktop Application Repository
|
<Button
|
||||||
</Button>
|
variant="primary"
|
||||||
</a>
|
icon={ArrowTopRightOnSquareIcon}
|
||||||
|
>
|
||||||
|
Download at maplefile.com
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* GDPR Information */}
|
||||||
|
<section
|
||||||
|
aria-labelledby="gdpr-heading"
|
||||||
|
className={`${getThemeClasses("bg-muted")} border ${getThemeClasses("border-secondary")} rounded-xl p-6`}
|
||||||
|
>
|
||||||
|
<h3 id="gdpr-heading" className={`text-sm font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
||||||
|
GDPR Article 20 - Right to Data Portability
|
||||||
|
</h3>
|
||||||
|
<p className={`text-sm ${getThemeClasses("text-secondary")}`}>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}, [getThemeClasses, sectionStyles]);
|
}, [getThemeClasses]);
|
||||||
|
|
||||||
// Field sections for DetailLiteView
|
// Field sections for DetailLiteView
|
||||||
const fieldSections = useMemo(() => {
|
const fieldSections = useMemo(() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue