From 1c0ae993a06ae2df4dd20f2bd29d1c4b6d238209 Mon Sep 17 00:00:00 2001 From: czhen <56986964+shczhen@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:43:05 +0800 Subject: [PATCH] fix: editor context menu and popup --- .../src/components/Popup/EditorPopup.tsx | 69 +++++++++++++++---- .../src/components/ui/Sonner.tsx | 16 +++++ .../designer_frontend/src/main.tsx | 2 +- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/core/src/ten_manager/designer_frontend/src/components/Popup/EditorPopup.tsx b/core/src/ten_manager/designer_frontend/src/components/Popup/EditorPopup.tsx index 85c28e3716..db064434bc 100644 --- a/core/src/ten_manager/designer_frontend/src/components/Popup/EditorPopup.tsx +++ b/core/src/ten_manager/designer_frontend/src/components/Popup/EditorPopup.tsx @@ -6,10 +6,12 @@ // import React, { useEffect, useState, useContext } from "react"; import Editor from "@monaco-editor/react"; +import { toast } from "sonner"; import Popup from "@/components/Popup/Popup"; import { getFileContent, saveFileContent } from "@/api/api"; import { ThemeProviderContext } from "@/components/theme-context"; +import { Button } from "@/components/ui/Button"; const DEFAULT_WIDTH = 800; const DEFAULT_HEIGHT = 400; @@ -46,14 +48,18 @@ const ConfirmDialog: React.FC = ({ onClose={onCancel} preventFocusSteal={true} resizable={false} - initialWidth={400} - initialHeight={200} + initialWidth={288} + initialHeight={180} > -
-

{message}

-
- - +
+

{message}

+
+ +
@@ -74,6 +80,7 @@ const EditorPopup: React.FC = ({ data, onClose }) => { setFileContent(respData.content); } catch (error) { console.error("Failed to fetch file content:", error); + toast.error("Failed to fetch file content"); } }; @@ -83,11 +90,13 @@ const EditorPopup: React.FC = ({ data, onClose }) => { const saveFile = async (content: string) => { try { await saveFileContent(data.url, content); - console.log("File saved successfully"); + toast.success("File saved successfully"); // We can add UI prompts, such as displaying a success notification. - } catch (error) { + } catch (error: unknown) { console.error("Failed to save file content:", error); - // We can add UI prompts, such as popping up an error notification. + toast.error("Failed to save file content", { + description: error instanceof Error ? error.message : "Unknown error", + }); } }; @@ -127,8 +136,44 @@ const EditorPopup: React.FC = ({ data, onClose }) => { }} onChange={(value) => setFileContent(value || "")} onMount={(editor) => { - editor.focus(); // Set the keyboard focus to the editor. - + // --- set context menu actions --- + // reference: https://github.com/microsoft/monaco-editor/issues/1280#issuecomment-2420136963 + const keepIds = [ + "editor.action.clipboardCopyAction", + "editor.action.clipboardCutAction", + "editor.action.clipboardPasteAction", + "editor.action.formatDocument", + "vs.editor.ICodeEditor:1:save-file", + "vs.actions.separator", + ]; + const contextmenu = editor.getContribution( + "editor.contrib.contextmenu" + ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const realMethod = (contextmenu as any)._getMenuActions; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (contextmenu as any)._getMenuActions = function (...args: any[]) { + const items = realMethod.apply(contextmenu, args); + const filteredItems = items.filter(function (item: { + id: string; + }) { + return keepIds.includes(item.id); + }); + // Remove separator if it's the last item + if ( + filteredItems.length > 0 && + filteredItems[filteredItems.length - 1].id === + "vs.actions.separator" + ) { + filteredItems.pop(); + } + return filteredItems; + }; + + // --- set keyboard focus to the editor --- + editor.focus(); + + // --- add save-file action --- editor.addAction({ id: "save-file", label: "Save", diff --git a/core/src/ten_manager/designer_frontend/src/components/ui/Sonner.tsx b/core/src/ten_manager/designer_frontend/src/components/ui/Sonner.tsx index 8274ab111f..10e908244d 100644 --- a/core/src/ten_manager/designer_frontend/src/components/ui/Sonner.tsx +++ b/core/src/ten_manager/designer_frontend/src/components/ui/Sonner.tsx @@ -1,6 +1,13 @@ /* eslint-disable max-len */ import { useTheme } from "next-themes"; import { Toaster as Sonner } from "sonner"; +import { + TriangleAlertIcon, + CircleCheckIcon, + InfoIcon, + LoaderCircleIcon, + CircleXIcon, +} from "lucide-react"; type ToasterProps = React.ComponentProps; @@ -22,6 +29,15 @@ const Toaster = ({ ...props }: ToasterProps) => { "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", }, }} + icons={{ + success: , + info: , + warning: , + error: , + loading: ( + + ), + }} {...props} /> ); diff --git a/core/src/ten_manager/designer_frontend/src/main.tsx b/core/src/ten_manager/designer_frontend/src/main.tsx index 10e20bd685..74f6747215 100644 --- a/core/src/ten_manager/designer_frontend/src/main.tsx +++ b/core/src/ten_manager/designer_frontend/src/main.tsx @@ -16,6 +16,6 @@ import "@/index.css"; createRoot(document.getElementById("root")!).render( - + );