From 714a753aed1b96b2e0ea8c4c6bbb4b998ee88ce8 Mon Sep 17 00:00:00 2001 From: ogp-weeloong <135598754+ogp-weeloong@users.noreply.github.com> Date: Tue, 9 Jun 2026 06:58:23 +0000 Subject: [PATCH] [EMAIL-PREVIEW-4] PLU-386: Enable email previews in appropriate previous result data (#1655) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Problem We want pipe owners to be able to preview their email across a variety of email clients (Outlook, Yahoo etc). # High-level Approach See #1652 for more details. # This PR Updates the "View" button in "Previous Result" section to support email previews for postman's previous result email: 1. Adds `email` to TDataOutMetadatumType 2. Make the "Previous Result" table use the email preview modal to render the "View" button when the type is `email`. 3. Sets postman email's dataout metadatum type to `email`, so that it launches the email modal when "View" is clicked. ### Beedio # [Screen Recording 2026-06-02 at 10.36.28 PM.mov (uploaded via Graphite) ](https://app.graphite.com/user-attachments/video/637f57ce-3e6d-4d54-a190-55f85d40458d.mov) # Tests - [ ] Check that I can preview the previous result's email using the new email preview modal - [ ] [Regression test] Check that other types of previous result previews (e.g. tiles previews) still use their appropriate modal - [ ] [Regression test] Check that emails from published pipes have variables substituted correctly --- .../get-data-out-metadata.ts | 2 +- .../components/EmailPreviewModal/index.tsx | 4 ++- .../RichTextEditor/PreviewButton.tsx | 2 +- .../VariablesList/VariableItemWithModal.tsx | 36 +++++++++++++++++-- .../src/components/VariablesList/index.tsx | 15 ++++++-- packages/frontend/src/helpers/variables.ts | 1 + packages/types/index.d.ts | 1 + 7 files changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/apps/postman/actions/send-transactional-email/get-data-out-metadata.ts b/packages/backend/src/apps/postman/actions/send-transactional-email/get-data-out-metadata.ts index 27b4ff4aa..7d71dd0d0 100644 --- a/packages/backend/src/apps/postman/actions/send-transactional-email/get-data-out-metadata.ts +++ b/packages/backend/src/apps/postman/actions/send-transactional-email/get-data-out-metadata.ts @@ -16,7 +16,7 @@ async function getDataOutMetadata( body: { label: 'Body', order: 2, - type: 'html', + type: 'email', displayedValue: 'Preview body', }, recipient: { diff --git a/packages/frontend/src/components/EmailPreviewModal/index.tsx b/packages/frontend/src/components/EmailPreviewModal/index.tsx index 45753dffd..b5848c5ea 100644 --- a/packages/frontend/src/components/EmailPreviewModal/index.tsx +++ b/packages/frontend/src/components/EmailPreviewModal/index.tsx @@ -133,12 +133,14 @@ interface EmailPreviewModalProps { isOpen: boolean onClose: () => void html: string + title: string } export default function EmailPreviewModal({ isOpen, onClose, html, + title, }: EmailPreviewModalProps) { const [selectedClientId, setSelectedClientId] = useState( 'outlook-windows-legacy', @@ -161,7 +163,7 @@ export default function EmailPreviewModal({ - Preview your email + {title} diff --git a/packages/frontend/src/components/RichTextEditor/PreviewButton.tsx b/packages/frontend/src/components/RichTextEditor/PreviewButton.tsx index 74c3d4d05..75e195d6d 100644 --- a/packages/frontend/src/components/RichTextEditor/PreviewButton.tsx +++ b/packages/frontend/src/components/RichTextEditor/PreviewButton.tsx @@ -38,7 +38,7 @@ function usePreviewer(previewType: TFieldPreviewType | undefined) { (props: PreviewerProps): ReactNode => { switch (previewType) { case 'email': - return + return } return null }, diff --git a/packages/frontend/src/components/VariablesList/VariableItemWithModal.tsx b/packages/frontend/src/components/VariablesList/VariableItemWithModal.tsx index bb05b5b9c..cbb81dbb5 100644 --- a/packages/frontend/src/components/VariablesList/VariableItemWithModal.tsx +++ b/packages/frontend/src/components/VariablesList/VariableItemWithModal.tsx @@ -1,4 +1,4 @@ -import { useContext } from 'react' +import { lazy, Suspense, useCallback, useContext, useTransition } from 'react' import { useDisclosure } from '@chakra-ui/react' import { EditorContext } from '@/contexts/Editor' @@ -9,6 +9,8 @@ import HtmlVariableModal from './HtmlVariableModal' import TableVariableModal from './TableVariableModal' import { VariableItem } from '.' +const LazyEmailPreviewModal = lazy(() => import('../EmailPreviewModal')) + interface VariableItemWithModalProps { variable: Variable onClick?: (variable: Variable) => void @@ -35,7 +37,16 @@ export default function VariableItemWithModal( const canOpenModal = // we do not want to show a table preview if there are no rows (variable.type === 'table' && variable.displayedValue !== '0 rows') || - variable.type === 'html' + variable.type === 'html' || + variable.type === 'email' + + const preloadModal = useCallback(() => { + if (variable.type === 'email') { + import('../EmailPreviewModal') + } + }, [variable.type]) + + const [isPending, startTransition] = useTransition() const handleClick = () => { if (!onClick) { @@ -87,6 +98,19 @@ export default function VariableItemWithModal( onClose={onModalClose} /> ) + case 'email': + return ( + + {isModalOpen && ( + + )} + + ) } } @@ -97,8 +121,14 @@ export default function VariableItemWithModal( startTransition(() => onModalOpen()) + : undefined + } withViewButton={canOpenModal} + onViewButtonPreload={preloadModal} + isViewButtonLoading={isPending} /> {renderModal()} diff --git a/packages/frontend/src/components/VariablesList/index.tsx b/packages/frontend/src/components/VariablesList/index.tsx index 067f4c08c..1f18a8bba 100644 --- a/packages/frontend/src/components/VariablesList/index.tsx +++ b/packages/frontend/src/components/VariablesList/index.tsx @@ -22,7 +22,7 @@ import { POPOVER_MOTION_PROPS } from '@/theme/constants' import VariableItemWithModal from './VariableItemWithModal' -const VARIABLES_WITH_MODALS = ['table', 'html'] +const VARIABLES_WITH_MODALS = ['table', 'html', 'email'] const VARIABLE_ITEM_HEIGHT = 77 const SUGGESTION_VARIABLE_ITEM_HEIGHT = 61 @@ -92,11 +92,15 @@ export function VariableItem({ onClick, isLast, withViewButton, + onViewButtonPreload, + isViewButtonLoading, }: { variable: Variable onClick?: (variable: Variable) => void isLast?: boolean withViewButton?: boolean + onViewButtonPreload?: () => void + isViewButtonLoading?: boolean }): JSX.Element { const shouldShowBottomBorder = !withViewButton && (onClick || isLast) @@ -172,7 +176,14 @@ export function VariableItem({ {onClick && withViewButton && ( - )} diff --git a/packages/frontend/src/helpers/variables.ts b/packages/frontend/src/helpers/variables.ts index e14546047..0edf2575f 100644 --- a/packages/frontend/src/helpers/variables.ts +++ b/packages/frontend/src/helpers/variables.ts @@ -19,6 +19,7 @@ export const VISIBLE_VARIABLE_TYPES: TDataOutMetadatumType[] = [ 'approval', 'ai_response', 'html', + 'email', ] export interface StepWithVariables { diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index 91f9b2047..92ca87657 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -63,6 +63,7 @@ export type TDataOutMetadatumType = | 'approval' | 'ai_response' | 'html' + | 'email' /** * This should only be defined on _leaf_ nodes (i.e. **primitive array