diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/automations/[automationId]/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/automations/[automationId]/header.tsx index e21d7d3aeb..c14b879ba6 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/automations/[automationId]/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/automations/[automationId]/header.tsx @@ -72,7 +72,7 @@ export const ProjectAutomationDetailsHeader = observer((props: TProps) => { .then(() => { captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.ENABLE, - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ title: t("automations.toasts.enable.success.title"), @@ -85,7 +85,7 @@ export const ProjectAutomationDetailsHeader = observer((props: TProps) => { captureError({ eventName: AUTOMATION_TRACKER_EVENTS.ENABLE, error: err?.message || "Enable failed", - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ title: t("automations.toasts.enable.error.title"), @@ -101,7 +101,7 @@ export const ProjectAutomationDetailsHeader = observer((props: TProps) => { .then(() => { captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.DISABLE, - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ title: t("automations.toasts.disable.success.title"), @@ -114,7 +114,7 @@ export const ProjectAutomationDetailsHeader = observer((props: TProps) => { captureError({ eventName: AUTOMATION_TRACKER_EVENTS.DISABLE, error: err?.message || "Disable failed", - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ title: t("automations.toasts.disable.error.title"), diff --git a/apps/web/core/components/editor/lite-text/editor.tsx b/apps/web/core/components/editor/lite-text/editor.tsx index 6dd6663c2b..43c264a77c 100644 --- a/apps/web/core/components/editor/lite-text/editor.tsx +++ b/apps/web/core/components/editor/lite-text/editor.tsx @@ -15,7 +15,7 @@ import { useMember } from "@/hooks/store/use-member"; import { useUserProfile } from "@/hooks/store/use-user-profile"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; -// plane web services +// plane web service import { WorkspaceService } from "@/plane-web/services"; import { LiteToolbar } from "./lite-toolbar"; const workspaceService = new WorkspaceService(); diff --git a/apps/web/ee/components/automations/details/sidebar/trigger/root.tsx b/apps/web/ee/components/automations/details/sidebar/trigger/root.tsx index 5cf8a39a20..28b2240f3a 100644 --- a/apps/web/ee/components/automations/details/sidebar/trigger/root.tsx +++ b/apps/web/ee/components/automations/details/sidebar/trigger/root.tsx @@ -3,7 +3,12 @@ import isEqual from "lodash/isEqual"; import { observer } from "mobx-react"; import { ChevronDown, Zap } from "lucide-react"; // plane imports -import { AUTOMATION_TRIGGER_SELECT_OPTIONS, DEFAULT_AUTOMATION_CONDITION_FILTER_EXPRESSION, AUTOMATION_TRACKER_ELEMENTS, AUTOMATION_TRACKER_EVENTS } from "@plane/constants"; +import { + AUTOMATION_TRIGGER_SELECT_OPTIONS, + DEFAULT_AUTOMATION_CONDITION_FILTER_EXPRESSION, + AUTOMATION_TRACKER_ELEMENTS, + AUTOMATION_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // helpers import { @@ -82,13 +87,13 @@ export const AutomationDetailsSidebarTriggerRoot: React.FC = observer((pr }); captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.TRIGGER_CREATED, - payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName } + payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName }, }); } catch (error) { console.error("Failed to create trigger:", error); captureError({ eventName: AUTOMATION_TRACKER_EVENTS.TRIGGER_CREATED, - payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName } + payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName }, }); } return; @@ -102,13 +107,13 @@ export const AutomationDetailsSidebarTriggerRoot: React.FC = observer((pr }); captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.TRIGGER_UPDATED, - payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName } + payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName }, }); } catch (error) { console.error("Failed to update trigger handler:", error); captureError({ eventName: AUTOMATION_TRACKER_EVENTS.TRIGGER_UPDATED, - payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName } + payload: { id: automationId, handler_name: selectedTriggerNodeHandlerName }, }); } } diff --git a/apps/web/ee/components/automations/modals/create-update-modal.tsx b/apps/web/ee/components/automations/modals/create-update-modal.tsx index a7901bc733..4d2320f3dc 100644 --- a/apps/web/ee/components/automations/modals/create-update-modal.tsx +++ b/apps/web/ee/components/automations/modals/create-update-modal.tsx @@ -63,7 +63,7 @@ export const CreateUpdateAutomationModal: React.FC = observer((props) => const res = await createAutomation(workspaceSlug, projectId, payload); captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.CREATE, - payload: { id: res?.id } + payload: { id: res?.id }, }); if (res?.redirectionLink) { router.push(res?.redirectionLink); @@ -72,7 +72,7 @@ export const CreateUpdateAutomationModal: React.FC = observer((props) => captureError({ eventName: AUTOMATION_TRACKER_EVENTS.CREATE, error: error?.error || error?.message, - payload: { workspace_slug: workspaceSlug, project_id: projectId } + payload: { workspace_slug: workspaceSlug, project_id: projectId }, }); setToast({ type: TOAST_TYPE.ERROR, @@ -89,13 +89,13 @@ export const CreateUpdateAutomationModal: React.FC = observer((props) => await automation?.update(payload); captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.UPDATE, - payload: { id: data.id } + payload: { id: data.id }, }); } catch (error: any) { captureError({ eventName: AUTOMATION_TRACKER_EVENTS.UPDATE, error: error?.error || error?.message, - payload: { id: data.id } + payload: { id: data.id }, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/apps/web/ee/components/automations/modals/delete-modal.tsx b/apps/web/ee/components/automations/modals/delete-modal.tsx index 53d61c58c1..e8e64346a9 100644 --- a/apps/web/ee/components/automations/modals/delete-modal.tsx +++ b/apps/web/ee/components/automations/modals/delete-modal.tsx @@ -41,7 +41,7 @@ export const DeleteAutomationModal: React.FC = observer((props) => { await handleDelete(); captureSuccess({ eventName: AUTOMATION_TRACKER_EVENTS.DELETE, - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -55,7 +55,7 @@ export const DeleteAutomationModal: React.FC = observer((props) => { captureError({ eventName: AUTOMATION_TRACKER_EVENTS.DELETE, error: error?.message || "Delete failed", - payload: { id: automationId } + payload: { id: automationId }, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/apps/web/styles/globals.css b/apps/web/styles/globals.css index 049160ddaa..e25d37fb81 100644 --- a/apps/web/styles/globals.css +++ b/apps/web/styles/globals.css @@ -1293,7 +1293,8 @@ input[type="color"].custom-color-picker { } @keyframes grow-shrink-vertically { - 0%, 100% { + 0%, + 100% { transform: scaleY(0.5); } 50% { @@ -1301,7 +1302,6 @@ input[type="color"].custom-color-picker { } } - .animate-vertical-scale { transform-origin: center; /* ensures it grows from both ends */ animation: grow-shrink-vertically 0.8s ease-in-out infinite; @@ -1373,41 +1373,33 @@ input[type="color"].custom-color-picker { } } - - - .shimmer { display: inline-block; background-color: rgb(var(--color-text-100)); - background-image: linear-gradient( - to left, - transparent 0%, - rgb(var(--color-text-400)) 50%, - transparent 100% - ); + background-image: linear-gradient(to left, transparent 0%, rgb(var(--color-text-400)) 50%, transparent 100%); background-position: -4rem top; background-repeat: no-repeat; - background-clip: text; /* non-prefixed fallback */ - -webkit-background-clip: text; /* required for Safari/WebKit */ + background-clip: text; /* non-prefixed fallback */ + -webkit-background-clip: text; /* required for Safari/WebKit */ -webkit-text-fill-color: transparent; -webkit-animation: shimmer-ltr 2.2s linear infinite; animation: shimmer-ltr 2.2s linear infinite; -webkit-background-size: 60% 100%; - background-size: 60% 100%; /* unprefixed too */ + background-size: 60% 100%; /* unprefixed too */ } @keyframes shimmer-ltr { - 0% { - background-position: -4rem top; /*50px*/ - } + 0% { + background-position: -4rem top; /*50px*/ + } - 70% { - background-position: 200% top; /*200px*/ - } + 70% { + background-position: 200% top; /*200px*/ + } - 100% { - background-position: 200% top; /*200px*/ - } -} \ No newline at end of file + 100% { + background-position: 200% top; /*200px*/ + } +} diff --git a/packages/editor/src/core/components/editors/rich-text/editor.tsx b/packages/editor/src/core/components/editors/rich-text/editor.tsx index f110c789b2..40a2b0c0be 100644 --- a/packages/editor/src/core/components/editors/rich-text/editor.tsx +++ b/packages/editor/src/core/components/editors/rich-text/editor.tsx @@ -1,7 +1,7 @@ import { forwardRef, useCallback } from "react"; // components import { EditorWrapper } from "@/components/editors"; -import { EditorBubbleMenu } from "@/components/menus"; +import { BlockMenu, EditorBubbleMenu } from "@/components/menus"; // extensions import { SideMenuExtension } from "@/extensions"; // plane editor imports @@ -40,7 +40,12 @@ const RichTextEditor: React.FC = (props) => { return ( - {(editor) => <>{editor && bubbleMenuEnabled && }} + {(editor) => ( + <> + {editor && bubbleMenuEnabled && } + + + )} ); }; diff --git a/packages/editor/src/core/components/menus/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx index fcded03d9e..b53167dd8b 100644 --- a/packages/editor/src/core/components/menus/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -91,6 +91,15 @@ export const BlockMenu = (props: Props) => { // Set the virtual reference as the reference element refs.setReference(virtualReferenceRef.current); + // Ensure the targeted block is selected + const rect = dragHandle.getBoundingClientRect(); + const coords = { left: rect.left + rect.width / 2, top: rect.top + rect.height / 2 }; + const posAtCoords = editor.view.posAtCoords(coords); + if (posAtCoords) { + const $pos = editor.state.doc.resolve(posAtCoords.pos); + const nodePos = $pos.before($pos.depth); + editor.chain().setNodeSelection(nodePos).run(); + } // Show the menu setIsOpen(true); return; @@ -101,7 +110,7 @@ export const BlockMenu = (props: Props) => { setIsOpen(false); } }, - [refs] + [editor, refs] ); const editorState = useEditorState({ @@ -296,6 +305,11 @@ export const BlockMenu = (props: Props) => { setIsOpen(false); e.preventDefault(); e.stopPropagation(); + + // Execute the delete action + editor.chain().deleteSelection().focus().run(); + + setIsOpen(false); }, }, { @@ -363,7 +377,6 @@ export const BlockMenu = (props: Props) => { if (!isOpen) { return null; } - return (
{ }} style={{ ...floatingStyles, + zIndex: 99, animationFillMode: "forwards", transitionTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)", // Expo ease out }}