whoami7 - Manager
:
/
home
/
dataiclx
/
vielorbe.com
/
wp-content
/
plugins
/
suremails
/
src
/
screens
/
logs
/
Upload File:
files >> //home/dataiclx/vielorbe.com/wp-content/plugins/suremails/src/screens/logs/drawer-log-body.js
import { useState, memo, useEffect, useMemo } from '@wordpress/element'; import { Badge, Select } from '@bsf/force-ui'; import { __, sprintf } from '@wordpress/i18n'; import { formatDate, parseHeaders, getStatusLabel, getStatusVariant, ShadowDOM, stringToHtml, containsHtmlTag, convertUTCConnection, get_connection_message, } from '@utils/utils'; import CollapsibleSection from '@components/collapsible-section'; import ContentGuardChecks from './content-guard-checks'; import { AttachmentList } from '@components/attachments/attachments'; import Title from '@components/title/title'; const DrawerLogBody = ( { log } ) => { const [ selectedRetry, setSelectedRetry ] = useState( null ); const [ groupedResponses, setGroupedResponses ] = useState( {} ); const attachments = Array.isArray( log.attachments ) ? log.attachments : []; // Parse serialized JSON or comma-separated values in email fields const parseEmailField = ( field ) => { if ( ! field ) { return []; } try { // Check if serialized JSON and parse return typeof field === 'string' && field.startsWith( '[' ) ? JSON.parse( field ) : field.split( ',' ).map( ( email ) => email.trim() ); } catch { return field.split( ',' ).map( ( email ) => email.trim() ); } }; // Function to extract charset from Content-Type const extractCharset = ( contentType ) => { if ( ! contentType ) { return ''; } const match = contentType.match( /charset=([\w-]+)/i ); return match ? match[ 1 ] : ''; }; // Use the utility function to parse headers const headers = log.headers ? parseHeaders( log.headers ) : {}; // Initialize headerFields with default empty arrays or values const headerFields = { From: headers.From ? headers.From[ 0 ] : '', 'Reply-To': headers[ 'Reply-To' ] || [], CC: headers.Cc || [], BCC: headers.Bcc || [], 'Content-Type': headers[ 'Content-Type' ] ? headers[ 'Content-Type' ][ 0 ] : '', Charset: extractCharset( headers[ 'Content-Type' ] ? headers[ 'Content-Type' ][ 0 ] : '' ), 'X-Mailer': headers[ 'X-Mailer' ] ? headers[ 'X-Mailer' ][ 0 ] : '', }; useEffect( () => { const response = log.response || []; const grouped = response.reduce( ( acc, res ) => { const retryNumber = Number( res.retry ); if ( ! acc[ retryNumber ] ) { acc[ retryNumber ] = []; } acc[ retryNumber ].push( res ); return acc; }, {} ); setGroupedResponses( grouped ); }, [ log.response ] ); const sortedRetryKeys = useMemo( () => { return Object.keys( groupedResponses ) .map( Number ) .sort( ( a, b ) => a - b ); }, [ groupedResponses ] ); const retries = useMemo( () => { return sortedRetryKeys.map( ( retry ) => ( { label: `Response ${ retry + 1 }`, value: retry, } ) ); }, [ sortedRetryKeys ] ); const getRetryLabel = ( value ) => { const retry = retries.find( ( r ) => r.value === value ); return retry ? retry.label : ''; }; useEffect( () => { if ( retries.length > 0 ) { const isValidRetry = retries.some( ( retry ) => retry.value === selectedRetry ); if ( ! isValidRetry ) { setSelectedRetry( retries[ retries.length - 1 ].value ); } } else { setSelectedRetry( null ); } }, [ retries, selectedRetry ] ); const handleRetryChange = ( selectedValue ) => { setSelectedRetry( selectedValue ); }; const createAndAttachEmailBody = ( content ) => ( node ) => { if ( ! node || ! content ) { return; } const emailBodyShadow = new ShadowDOM( node ); if ( emailBodyShadow.hasChildNodes() ) { return; } // Wrapper for adding 8px padding to the email body const wrapper = document.createElement( 'div' ); wrapper.style.padding = containsHtmlTag( content ) ? '0' : '0.5rem'; // Escape HTML tags and convert plain text to HTML wrapper.innerHTML = stringToHtml( content ); // Append the wrapper to the email body shadow emailBodyShadow.appendChild( wrapper ); }; return ( <div className="rounded-lg bg-background-secondary"> { /* Email Information Section */ } <CollapsibleSection alwaysOpen> <CollapsibleSection.Content> <div className="space-y-2"> <div className="flex items-center justify-between"> <p> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Sent by:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { log.email_from } </strong> </p> <div className="flex items-center space-x-2"> <Badge className="py-0.5" label={ log.connection } variant="blue" disableHover /> <Badge className="py-0.5" label={ getStatusLabel( log.status, log?.response ) } variant={ getStatusVariant( log.status, log?.response ) } disableHover /> </div> </div> { /* Second Row: Sent to and Date */ } <div className="flex items-center justify-between"> <p> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Sent to:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { parseEmailField( log.email_to ).join( ', ' ) } </strong> </p> <p className="text-sm font-normal text-text-secondary"> { formatDate( log.updated_at, { day: true, month: true, year: true, hour: true, minute: true, hour12: true, } ) } </p> </div> { /* Third Row: Subject */ } <p> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Subject:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { log.subject } </strong> </p> <div className="flex items-start justify-start gap-1"> <p> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Resent:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { log.meta?.resend } </strong> </p> <p> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Retries:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { log.meta?.retry } </strong> </p> </div> </div> </CollapsibleSection.Content> </CollapsibleSection> { /* Email Body Section */ } <CollapsibleSection defaultOpen> <CollapsibleSection.Trigger> <Title tag="h4" title={ __( 'Email Body', 'suremails' ) } /> </CollapsibleSection.Trigger> <CollapsibleSection.Content className="bg-background-secondary rounded overflow-hidden"> <div ref={ createAndAttachEmailBody( log.body ) }> { log.body ? false : __( 'No email body available.', 'suremails' ) } </div> </CollapsibleSection.Content> </CollapsibleSection> { /* Content guard checks */ } <ContentGuardChecks log={ log } /> { /* Server Response Section */ } <CollapsibleSection defaultOpen> <CollapsibleSection.Trigger> <Title tag="h4" title={ __( 'Server Response', 'suremails' ) } /> </CollapsibleSection.Trigger> <CollapsibleSection.Content> <div className="flex flex-col gap-2 mt-2"> { ' ' } <Select value={ getRetryLabel( selectedRetry ) } onChange={ ( value ) => handleRetryChange( value ) } className="w-full" by={ selectedRetry } > <Select.Button /> <Select.Options> { retries.map( ( retry ) => ( <Select.Option key={ retry.value } value={ retry.value } > { retry.label } </Select.Option> ) ) } </Select.Options> </Select> <div className="flex items-start justify-between gap-2 mt-2 rounded-md bg-background-primary"> <div className="flex-1"> { groupedResponses[ selectedRetry ]?.length > 0 ? ( <div className="flex flex-col gap-2"> { ' ' } { groupedResponses[ selectedRetry ].map( ( res, index ) => ( <div key={ index } className="py-2 px-2 gap-3 rounded border bg-background-secondary" > { /* Message and Connection inline */ } <div className="flex flex-col gap-1"> { ' ' } <p className="font-medium text-sm text-text-primary"> { __( 'Message:', 'suremails' ) }{ ' ' } <span className="font-normal text-sm text-text-secondary"> { res.Message } </span> </p> <p className="font-medium text-sm text-text-primary"> { __( 'Connection:', 'suremails' ) }{ ' ' } <span className="font-normal text-text-secondary"> { res.timestamp ? get_connection_message( res.Connection, res.timestamp ) : convertUTCConnection( res.Connection ) } </span> </p> </div> </div> ) ) } </div> ) : ( <p className="text-sm text-text-secondary"> { __( 'No server response available.', 'suremails' ) } </p> ) } </div> </div> </div> </CollapsibleSection.Content> </CollapsibleSection> { /* Email Headers Section */ } <CollapsibleSection defaultOpen> <CollapsibleSection.Trigger> <Title tag="h4" title={ __( 'Email Headers', 'suremails' ) } /> </CollapsibleSection.Trigger> <CollapsibleSection.Content> <div className="mt-2 space-y-2"> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'From:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields.From && headerFields.From.length > 0 ? ( <span>{ headerFields.From }</span> ) : ( '' ) } </strong> </div> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Reply-To:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields[ 'Reply-To' ] && headerFields[ 'Reply-To' ].length > 0 ? ( <span> { headerFields[ 'Reply-To' ].join( ', ' ) } </span> ) : ( '' ) } </strong> </div> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'CC:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields.CC && headerFields.CC.length > 0 ? ( <span> { headerFields.CC.join( ', ' ) } </span> ) : ( '' ) } </strong> </div> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'BCC:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields.BCC && headerFields.BCC.length > 0 ? ( <span> { headerFields.BCC.join( ', ' ) } </span> ) : ( '' ) } </strong> </div> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'Content-Type:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields[ 'Content-Type' ] || '' } </strong> </div> <div> <strong className="text-sm font-normal text-text-tertiary"> { __( 'X-Mailer:', 'suremails' ) } </strong>{ ' ' } <strong className="text-sm font-normal text-text-primary"> { headerFields[ 'X-Mailer' ] || '' } </strong> </div> </div> </CollapsibleSection.Content> </CollapsibleSection> { /* Email Attachments Section */ } <CollapsibleSection defaultOpen={ attachments.length > 0 }> <CollapsibleSection.Trigger> <Title tag="h4" title={ sprintf( /* translators: %d: Number of attachments. */ __( 'Attachments (%d)', 'suremails' ), attachments.length ) } /> </CollapsibleSection.Trigger> <CollapsibleSection.Content> <AttachmentList attachments={ attachments } /> </CollapsibleSection.Content> </CollapsibleSection> </div> ); }; export default memo( DrawerLogBody );
Copyright ©2021 || Defacer Indonesia