courrier preview

This commit is contained in:
alma 2025-05-01 11:20:15 +02:00
parent c4958d7e4c
commit 7f87e4f00a
2 changed files with 82 additions and 112 deletions

View File

@ -74,6 +74,9 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
// Add any custom toolbar handlers here
}
},
clipboard: {
matchVisual: false // Disable clipboard matching for better HTML handling
},
// Don't initialize better-table yet - we'll do it after content is loaded
'better-table': false,
},
@ -93,68 +96,54 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
direction
});
// Make sure content is properly sanitized before injecting it
const cleanContent = sanitizeHtml(processedContent || initialContent);
// Simplify complex email content to something Quill can handle better
const sanitizedContent = sanitizeHtml(processedContent || initialContent);
// First, directly set the content
if (editorRef.current) {
editorRef.current.innerHTML = cleanContent;
// Use direct innerHTML setting for the initial content
quillRef.current.root.innerHTML = sanitizedContent;
// Set the direction for the content
quillRef.current.format('direction', direction);
if (direction === 'rtl') {
quillRef.current.format('align', 'right');
}
// Then let Quill parse and format it correctly
setTimeout(() => {
// Only proceed if editor ref is still available
if (!editorRef.current) return;
// Set cursor at the beginning
quillRef.current.setSelection(0, 0);
// Ensure the cursor and scroll position is at the top of the editor
if (editorRef.current) {
editorRef.current.scrollTop = 0;
// Get the content from the editor element
const content = editorRef.current.innerHTML;
// Find and scroll parent containers that might have scroll
const scrollable = [
editorRef.current.closest('.ql-container'),
editorRef.current.closest('.rich-email-editor-container'),
editorRef.current.closest('.overflow-y-auto'),
document.querySelector('.overflow-y-auto')
];
// Clear the editor
quillRef.current.setText('');
// Insert clean content
quillRef.current.clipboard.dangerouslyPasteHTML(0, content);
// Set the direction for the content
quillRef.current.format('direction', direction);
if (direction === 'rtl') {
quillRef.current.format('align', 'right');
}
// Set cursor at the beginning (before the quoted content)
quillRef.current.setSelection(0, 0);
// Ensure the cursor and scroll position is at the top of the editor
if (editorRef.current) {
editorRef.current.scrollTop = 0;
// Find and scroll parent containers that might have scroll
const scrollable = [
editorRef.current.closest('.ql-container'),
editorRef.current.closest('.rich-email-editor-container'),
editorRef.current.closest('.overflow-y-auto'),
document.querySelector('.overflow-y-auto')
];
scrollable.forEach(el => {
if (el instanceof HTMLElement) {
el.scrollTop = 0;
}
});
}
}, 100);
scrollable.forEach(el => {
if (el instanceof HTMLElement) {
el.scrollTop = 0;
}
});
}
} catch (err) {
console.error('Error setting initial content:', err);
// Fallback: just set text
quillRef.current.setText('');
// Try simplest approach
// Extract text as a last resort
try {
quillRef.current.clipboard.dangerouslyPasteHTML(initialContent);
// Create a temporary div to extract text from HTML
const tempDiv = document.createElement('div');
tempDiv.innerHTML = initialContent;
const textContent = tempDiv.textContent || tempDiv.innerText || '';
quillRef.current.setText(textContent);
} catch (e) {
console.error('Fallback failed too:', e);
// Last resort: strip all HTML
quillRef.current.setText(initialContent.replace(/<[^>]*>/g, ''));
quillRef.current.setText('');
}
}
}
@ -187,24 +176,22 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
};
}, []);
// Update content from props if changed externally
// Update content from props if changed externally - using a simpler approach
useEffect(() => {
if (quillRef.current && isReady) {
if (quillRef.current && isReady && initialContent) {
const currentContent = quillRef.current.root.innerHTML;
// Only update if content changed to avoid editor position reset
if (initialContent !== currentContent) {
try {
// Preserve cursor position if possible
const selection = quillRef.current.getSelection();
// Process content to ensure correct direction
const { direction, html: processedContent } = processContentWithDirection(initialContent);
// First clear the content
quillRef.current.root.innerHTML = '';
// Sanitize the HTML
const sanitizedContent = sanitizeHtml(processedContent || initialContent);
// Then insert the new content at position 0
quillRef.current.clipboard.dangerouslyPasteHTML(0, sanitizeHtml(processedContent || initialContent));
// SIMPLIFIED: Set content directly to the root element rather than using clipboard
quillRef.current.root.innerHTML = sanitizedContent;
// Set the direction for the content
quillRef.current.format('direction', direction);
@ -215,14 +202,20 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
// Force update
quillRef.current.update();
// Restore selection if possible
if (selection) {
setTimeout(() => quillRef.current.setSelection(selection), 10);
}
// Set selection to beginning
quillRef.current.setSelection(0, 0);
} catch (err) {
console.error('Error updating content:', err);
// Fallback update method
quillRef.current.clipboard.dangerouslyPasteHTML(sanitizeHtml(initialContent));
// Safer fallback that avoids clipboard API
try {
// Extract basic text if everything else fails
const tempDiv = document.createElement('div');
tempDiv.innerHTML = initialContent;
const textContent = tempDiv.textContent || tempDiv.innerText || '';
quillRef.current.setText(textContent);
} catch (e) {
console.error('All fallbacks failed:', e);
}
}
}
}
@ -399,36 +392,13 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
font-size: 13px !important;
}
/* Status styles for email displays */
:global(.ql-editor td[class*="status"]),
:global(.ql-editor td[class*="Status"]) {
background-color: #f8f9fa !important;
font-weight: 500 !important;
}
/* Amount styles */
:global(.ql-editor td[class*="amount"]),
:global(.ql-editor td[class*="Amount"]),
:global(.ql-editor td[class*="price"]),
:global(.ql-editor td[class*="Price"]) {
text-align: right !important;
font-family: monospace !important;
}
/* Header row styles */
:global(.ql-editor tr:first-child td),
:global(.ql-editor th) {
background-color: #f8f9fa !important;
font-weight: 600 !important;
}
/* Improve table cells with specific content */
:global(.ql-editor td:has(div[class*="number"])),
:global(.ql-editor td:has(div[class*="Number"])),
:global(.ql-editor td:has(div[class*="invoice"])),
:global(.ql-editor td:has(div[class*="Invoice"])) {
font-family: monospace !important;
letter-spacing: 0.5px !important;
/* Email quote styling */
:global(.email-original-content) {
margin-top: 20px !important;
padding-top: 10px !important;
border-top: 1px solid #ddd !important;
color: #555 !important;
font-size: 13px !important;
}
/* Fix quoted paragraphs */

View File

@ -279,14 +279,15 @@ export function formatReplyEmail(originalEmail: EmailMessage | LegacyEmailMessag
// Extract content using centralized utility
const { text: originalTextContent, html: originalHtmlContent } = extractEmailContent(originalEmail);
// Create content with appropriate quote formatting
// Create a simpler HTML structure that's easier for Quill to handle
const replyBody = `
<br/>
<br/>
<blockquote style="border-left: 2px solid #ddd; padding-left: 10px; margin: 10px 0; color: #505050;">
<p>On ${dateStr}, ${fromStr} wrote:</p>
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
</blockquote>
<div class="email-original-content">
<div>On ${dateStr}, ${fromStr} wrote:</div>
<blockquote style="margin: 10px 0; padding-left: 10px; border-left: 2px solid #ddd; color: #505050;">
${originalTextContent.replace(/\n/g, '<br>')}
</blockquote>
</div>
`;
// Process the content with proper direction
@ -334,20 +335,19 @@ export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMe
// Extract content using centralized utility
const { text: originalTextContent, html: originalHtmlContent } = extractEmailContent(originalEmail);
// Create forwarded content with header information
// Create a simpler forwarded content structure for better Quill compatibility
const forwardBody = `
<br/>
<br/>
<div class="email-forwarded-content">
<p>---------- Forwarded message ---------</p>
<p><strong>From:</strong> ${fromStr}</p>
<p><strong>Date:</strong> ${dateStr}</p>
<p><strong>Subject:</strong> ${subject || ''}</p>
<p><strong>To:</strong> ${toStr}</p>
${ccStr ? `<p><strong>Cc:</strong> ${ccStr}</p>` : ''}
<div style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 15px;">
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
</div>
<div class="email-original-content">
<div>---------- Forwarded message ---------</div>
<div><strong>From:</strong> ${fromStr}</div>
<div><strong>Date:</strong> ${dateStr}</div>
<div><strong>Subject:</strong> ${subject || ''}</div>
<div><strong>To:</strong> ${toStr}</div>
${ccStr ? `<div><strong>Cc:</strong> ${ccStr}</div>` : ''}
<blockquote style="margin-top: 10px; padding-left: 10px; border-left: 2px solid #ddd; color: #505050;">
${originalTextContent.replace(/\n/g, '<br>')}
</blockquote>
</div>
`;