From ba69f6dca436713f1459f98645d9f2349dcf0c50 Mon Sep 17 00:00:00 2001 From: Alex TYRODE Date: Mon, 5 May 2025 06:19:49 +0000 Subject: [PATCH] feat: add new pad creation functionality in PadsDialog - Implemented a button for creating new pads, enhancing user interaction within the PadsDialog. - Added state management for the creation process, including loading and error handling. - Integrated analytics tracking for pad creation events to improve user insights. - Updated styling for the new pad button to ensure a consistent UI experience. --- src/frontend/src/ui/PadsDialog.scss | 28 ++++++++++++++++++ src/frontend/src/ui/PadsDialog.tsx | 45 +++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/ui/PadsDialog.scss b/src/frontend/src/ui/PadsDialog.scss index 1fd9dfb..033e0b6 100644 --- a/src/frontend/src/ui/PadsDialog.scss +++ b/src/frontend/src/ui/PadsDialog.scss @@ -21,6 +21,34 @@ font-size: 1.2rem; font-weight: 600; } + + &__new-pad-button { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.4rem 0.8rem; + border-radius: 4px; + border: none; + background-color: #cc6d24; + color: white; + font-size: 0.9rem; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: #b05e1f; + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + + &--creating { + opacity: 0.7; + cursor: wait; + } + } &__content { padding: 1rem; diff --git a/src/frontend/src/ui/PadsDialog.tsx b/src/frontend/src/ui/PadsDialog.tsx index 64a3772..c269afb 100644 --- a/src/frontend/src/ui/PadsDialog.tsx +++ b/src/frontend/src/ui/PadsDialog.tsx @@ -1,8 +1,8 @@ import React, { useState, useCallback } from "react"; import { Dialog } from "@atyrode/excalidraw"; -import { Pencil, Trash2 } from "lucide-react"; +import { Pencil, Trash2, FilePlus2 } from "lucide-react"; import { useAllPads, useRenamePad, useDeletePad, PadData } from "../api/hooks"; -import { loadPadData, getActivePad, setActivePad, saveCurrentPadBeforeSwitching } from "../utils/canvasUtils"; +import { loadPadData, getActivePad, setActivePad, saveCurrentPadBeforeSwitching, createNewPad } from "../utils/canvasUtils"; import { queryClient } from "../api/queryClient"; import { capture } from "../utils/posthog"; import "./PadsDialog.scss"; @@ -21,6 +21,7 @@ const PadsDialog: React.FC = ({ const activePadId = getActivePad(); const [editingPadId, setEditingPadId] = useState(null); const [newPadName, setNewPadName] = useState(""); + const [isCreatingPad, setIsCreatingPad] = useState(false); // Get the renamePad mutation const { mutate: renamePad } = useRenamePad({ @@ -76,6 +77,37 @@ const PadsDialog: React.FC = ({ } }); + const handleCreateNewPad = async () => { + if (isCreatingPad || !excalidrawAPI) return; // Prevent multiple clicks or if API not available + + try { + setIsCreatingPad(true); + + // Create a new pad using the imported function + // Note: createNewPad already updates the query cache internally + const newPad = await createNewPad(excalidrawAPI, activePadId, (data) => { + console.debug("[pad.ws] Canvas saved before creating new pad"); + }); + + // Track pad creation event + capture("pad_created", { + padId: newPad.id, + padName: newPad.display_name + }); + + // Set the new pad as active and load it + setActivePad(newPad.id); + loadPadData(excalidrawAPI, newPad.id, newPad.data); + + // Close the dialog + handleClose(); + } catch (error) { + console.error('[pad.ws] Error creating new pad:', error); + } finally { + setIsCreatingPad(false); + } + }; + const handleClose = useCallback(() => { setModalIsShown(false); if (onClose) { @@ -265,6 +297,15 @@ const PadsDialog: React.FC = ({

Manage Pads

+ } closeOnClickOutside={true}