diff --git a/src/frontend/src/ui/MainMenu.tsx b/src/frontend/src/ui/MainMenu.tsx index 771912f..b1d41d4 100644 --- a/src/frontend/src/ui/MainMenu.tsx +++ b/src/frontend/src/ui/MainMenu.tsx @@ -137,35 +137,6 @@ export const MainMenuConfig: React.FC = ({ setShowAccountModal(true); }; - const handleGridToggle = () => { - if (!excalidrawAPI) return; - const appState = excalidrawAPI.getAppState(); - appState.gridModeEnabled = !appState.gridModeEnabled; - appState.gridSize = 20; - appState.gridStep = 5; - excalidrawAPI.updateScene({ - appState: appState - }); - }; - - const handleZenModeToggle = () => { - if (!excalidrawAPI) return; - const appState = excalidrawAPI.getAppState(); - appState.zenModeEnabled = !appState.zenModeEnabled; - excalidrawAPI.updateScene({ - appState: appState - }); - }; - - const handleViewModeToggle = () => { - if (!excalidrawAPI) return; - const appState = excalidrawAPI.getAppState(); - appState.viewModeEnabled = !appState.viewModeEnabled; - excalidrawAPI.updateScene({ - appState: appState - }); - }; - const handleLogout = async () => { capture('logout_clicked'); @@ -302,30 +273,6 @@ export const MainMenuConfig: React.FC = ({ Action Button - - - - - } - onClick={handleGridToggle} - > - Toggle grid - - } - onClick={handleViewModeToggle} - > - View mode - - } - onClick={handleZenModeToggle} - > - Zen mode - - - diff --git a/src/frontend/src/ui/SettingsDialog.scss b/src/frontend/src/ui/SettingsDialog.scss index aff6ccb..53968ff 100644 --- a/src/frontend/src/ui/SettingsDialog.scss +++ b/src/frontend/src/ui/SettingsDialog.scss @@ -42,7 +42,6 @@ } &__setting { - margin-bottom: 1rem; padding: 0.5rem; border-radius: 4px; background-color: var(--dialog-bg-color); @@ -59,4 +58,78 @@ margin: 1rem 0; } + &__restore-button { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + background-color: var(--button-bg-color, #cc6d24); + border: 1px solid var(--button-border-color, #ddd); + border-radius: 4px; + color: var(--text-primary-color); + cursor: pointer; + font-size: 0.9rem; + transition: background-color 0.2s ease; + + &:hover { + background-color: var(--button-hover-bg-color, #a4571b); + } + } + + &__confirmation { + padding: 1rem; + border-radius: 4px; + background-color: var(--dialog-bg-color); + border: 1px solid var(--warning-color, #f0ad4e); + } + + &__warning { + color: var(--warning-color, #f0ad4e); + font-weight: bold; + margin: 1rem 0; + } + + &__actions { + display: flex; + gap: 8px; + margin-top: 1rem; + } + + &__button { + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + font-size: 0.9rem; + border: none; + transition: background-color 0.2s ease; + + &--restore { + background-color: var(--danger-color, #d9534f); + color: white; + + &:hover { + background-color: var(--danger-hover-color, #c9302c); + } + + &:disabled { + background-color: var(--disabled-color, #cccccc); + cursor: not-allowed; + } + } + + &--cancel { + background-color: var(--button-bg-color, #cc6d24); + border: 1px solid var(--button-border-color, #ddd); + color: var(--text-primary-color); + + &:hover { + background-color: var(--button-hover-bg-color, #a4571b); + } + + &:disabled { + background-color: var(--disabled-color, #cccccc); + cursor: not-allowed; + } + } + } } diff --git a/src/frontend/src/ui/SettingsDialog.tsx b/src/frontend/src/ui/SettingsDialog.tsx index fe86076..6ab7540 100644 --- a/src/frontend/src/ui/SettingsDialog.tsx +++ b/src/frontend/src/ui/SettingsDialog.tsx @@ -2,6 +2,9 @@ import React, { useState, useCallback, useEffect } from "react"; import { Dialog } from "@atyrode/excalidraw"; import { Range } from "./Range"; import { UserSettings, DEFAULT_SETTINGS } from "../types/settings"; +import { RefreshCw } from "lucide-react"; +import { normalizeCanvasData } from "../utils/canvasUtils"; +import { capture } from "../utils/posthog"; import "./SettingsDialog.scss"; interface SettingsDialogProps { @@ -15,6 +18,8 @@ const SettingsDialog: React.FC = ({ }) => { const [modalIsShown, setModalIsShown] = useState(true); const [settings, setSettings] = useState(DEFAULT_SETTINGS); + const [showRestoreConfirmation, setShowRestoreConfirmation] = useState(false); + const [isRestoring, setIsRestoring] = useState(false); // Get current settings from excalidrawAPI when component mounts useEffect(() => { @@ -35,6 +40,43 @@ const SettingsDialog: React.FC = ({ } }, [onClose]); + const handleRestoreTutorialCanvas = async () => { + if (!excalidrawAPI) return; + + try { + setIsRestoring(true); + capture('restore_tutorial_canvas_clicked'); + + // Fetch the default canvas data from the backend + const response = await fetch('/api/canvas/default', { + method: 'GET', + credentials: 'include' + }); + + if (!response.ok) { + throw new Error(`Failed to fetch default canvas: ${response.statusText}`); + } + + const defaultCanvasData = await response.json(); + + // Normalize the canvas data before updating the scene + const normalizedData = normalizeCanvasData(defaultCanvasData); + + // Update the canvas with the normalized default data + excalidrawAPI.updateScene(normalizedData); + + console.log("Canvas reset to default successfully"); + + // Close the dialog after successful restore + handleClose(); + } catch (error) { + console.error("Failed to reset canvas:", error); + } finally { + setIsRestoring(false); + setShowRestoreConfirmation(false); + } + }; + /** * Updates a specific setting and syncs it with the excalidraw app state * @param key The setting key to update @@ -92,6 +134,42 @@ const SettingsDialog: React.FC = ({ + +
+

Canvas Management

+ {showRestoreConfirmation ? ( +
+

Are you sure you want to restore the tutorial canvas?

+

This will replace your current canvas and cannot be undone!

+
+ + +
+
+ ) : ( +
+ +
+ )} +
);