refactor(task-drawer): update tab behavior and enhance link handling in description editor

- Changed tab component property from 'destroyInactiveTabPane' to 'destroyOnHidden' for improved tab management.
- Added CSS styles for links in the description editor to enhance visibility based on theme mode.
- Implemented link click handling to open links in a new tab while preventing default editor behavior, improving user experience.
This commit is contained in:
chamikaJ
2025-07-08 16:02:12 +05:30
parent 8fb33e311d
commit 66e01119d2
2 changed files with 41 additions and 4 deletions

View File

@@ -27,6 +27,18 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
const wrapperRef = useRef<HTMLDivElement>(null); const wrapperRef = useRef<HTMLDivElement>(null);
const themeMode = useAppSelector(state => state.themeReducer.mode); const themeMode = useAppSelector(state => state.themeReducer.mode);
// CSS styles for description content links
const descriptionStyles = `
.description-content a {
color: ${themeMode === 'dark' ? '#4dabf7' : '#1890ff'} !important;
text-decoration: underline !important;
cursor: pointer !important;
}
.description-content a:hover {
color: ${themeMode === 'dark' ? '#74c0fc' : '#40a9ff'} !important;
}
`;
// Load TinyMCE script only when editor is opened // Load TinyMCE script only when editor is opened
const loadTinyMCE = async () => { const loadTinyMCE = async () => {
if (isTinyMCELoaded) return; if (isTinyMCELoaded) return;
@@ -35,7 +47,7 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
try { try {
// Load TinyMCE script dynamically // Load TinyMCE script dynamically
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
if (window.tinymce) { if ((window as any).tinymce) {
resolve(); resolve();
return; return;
} }
@@ -75,7 +87,7 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
const isClickedInsideWrapper = wrapper && wrapper.contains(target); const isClickedInsideWrapper = wrapper && wrapper.contains(target);
const isClickedInsideEditor = document.querySelector('.tox-tinymce')?.contains(target); const isClickedInsideEditor = document.querySelector('.tox-tinymce')?.contains(target);
const isClickedInsideToolbarPopup = document const isClickedInsideToolbarPopup = document
.querySelector('.tox-menu, .tox-pop, .tox-collection') .querySelector('.tox-menu, .tox-pop, .tox-collection, .tox-dialog, .tox-dialog-wrap, .tox-silver-sink')
?.contains(target); ?.contains(target);
if ( if (
@@ -119,6 +131,28 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
await loadTinyMCE(); await loadTinyMCE();
}; };
const handleContentClick = (event: React.MouseEvent) => {
const target = event.target as HTMLElement;
// Check if clicked element is a link
if (target.tagName === 'A' || target.closest('a')) {
event.preventDefault(); // Prevent default link behavior
event.stopPropagation(); // Prevent opening the editor
const link = target.tagName === 'A' ? target : target.closest('a');
if (link) {
const href = (link as HTMLAnchorElement).href;
if (href) {
// Open link in new tab/window for security
window.open(href, '_blank', 'noopener,noreferrer');
}
}
return;
}
// If not a link, open the editor
handleOpenEditor();
};
const darkModeStyles = const darkModeStyles =
themeMode === 'dark' themeMode === 'dark'
? ` ? `
@@ -134,6 +168,8 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
return ( return (
<div ref={wrapperRef}> <div ref={wrapperRef}>
{/* Inject CSS styles for links */}
<style>{descriptionStyles}</style>
{isEditorOpen ? ( {isEditorOpen ? (
<div <div
style={{ style={{
@@ -219,7 +255,7 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
</div> </div>
) : ( ) : (
<div <div
onClick={handleOpenEditor} onClick={handleContentClick}
onMouseEnter={() => setIsHovered(true)} onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)} onMouseLeave={() => setIsHovered(false)}
style={{ style={{
@@ -244,6 +280,7 @@ const DescriptionEditor = ({ description, taskId, parentTaskId }: DescriptionEdi
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(content), __html: DOMPurify.sanitize(content),
}} }}
className="description-content"
/> />
) : ( ) : (
<div <div

View File

@@ -222,7 +222,7 @@ const TaskDrawer = () => {
<Tabs <Tabs
type="card" type="card"
items={tabItems} items={tabItems}
destroyInactiveTabPane destroyOnHidden
onChange={handleTabChange} onChange={handleTabChange}
activeKey={activeTab} activeKey={activeTab}
/> />