-
Notifications
You must be signed in to change notification settings - Fork 383
Add support for configuring link target behavior in Rich Text Editor #10430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
9bdc163
21e300d
6f1d3da
ded6f04
4ebf145
03ed2ee
cb4abb1
30fbb42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -54,6 +54,11 @@ import { createPortal } from "react-dom"; | |||||||
| import { useTranslation } from "react-i18next"; | ||||||||
| import { getSelectedNode } from "../utils/get-selected-node"; | ||||||||
| import "./link-plugin.scss"; | ||||||||
| import FormControlLabel from "@oxygen-ui/react/FormControlLabel/FormControlLabel"; | ||||||||
| import Checkbox from "@oxygen-ui/react/Checkbox"; | ||||||||
| import Hint from "../../../resources/elements/hint"; | ||||||||
| import Box from "@oxygen-ui/react/Box/Box"; | ||||||||
| import Tooltip from "@oxygen-ui/react/Tooltip"; | ||||||||
|
|
||||||||
| const LowPriority: CommandListenerPriority = 1; | ||||||||
| const HighPriority: CommandListenerPriority = 3; | ||||||||
|
|
@@ -162,7 +167,7 @@ const LinkEditor = (): ReactElement => { | |||||||
| const [ isEditMode, setEditMode ] = useState(false); | ||||||||
| const [ lastSelection, setLastSelection ] = useState<BaseSelection | null>(null); | ||||||||
| const [ selectedUrlType, setSelectedUrlType ] = useState<string>("CUSTOM"); | ||||||||
|
|
||||||||
| const [ linkTarget, setLinkTarget ] = useState<"_blank" | "_self">("_blank"); | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seems |
||||||||
| const { t } = useTranslation(); | ||||||||
|
|
||||||||
| /** | ||||||||
|
|
@@ -178,14 +183,18 @@ const LinkEditor = (): ReactElement => { | |||||||
|
|
||||||||
| if ($isLinkNode(parent)) { | ||||||||
| const url: string = parent.getURL(); | ||||||||
| const target:string = parent.getTarget() || "_blank"; | ||||||||
|
|
||||||||
| setLinkUrl(getPlaceholderUrl(url)); | ||||||||
| setSelectedUrlType(determineUrlType(url)); | ||||||||
| setLinkTarget(target as "_blank" | "_self"); | ||||||||
| } else if ($isLinkNode(node)) { | ||||||||
| const url: string = node.getURL(); | ||||||||
| const target:string = node.getTarget() || "_blank"; | ||||||||
|
|
||||||||
| setLinkUrl(getPlaceholderUrl(url)); | ||||||||
| setSelectedUrlType(determineUrlType(url)); | ||||||||
| setLinkTarget(target as "_blank" | "_self"); | ||||||||
| } else { | ||||||||
| setLinkUrl(""); | ||||||||
| setSelectedUrlType("CUSTOM"); | ||||||||
|
|
@@ -367,20 +376,24 @@ const LinkEditor = (): ReactElement => { | |||||||
| if (url) { | ||||||||
| // First use the default command to handle the link creation/update. | ||||||||
| editor.dispatchCommand(TOGGLE_LINK_COMMAND, url); | ||||||||
|
|
||||||||
| // Then update the link attributes to include safe properties. | ||||||||
| const selection: BaseSelection = $getSelection(); | ||||||||
| const selection: BaseSelection | null = $getSelection(); | ||||||||
|
|
||||||||
| if ($isRangeSelection(selection)) { | ||||||||
| const node: TextNode | ElementNode = getSelectedNode(selection); | ||||||||
| const linkNode: ElementNode = $isLinkNode(node) ? node : node.getParent(); | ||||||||
|
|
||||||||
| if ($isLinkNode(linkNode)) { | ||||||||
| // Update the link node with safe attributes. | ||||||||
| linkNode.setTarget("_blank"); | ||||||||
| linkNode.setRel("noopener noreferrer"); | ||||||||
| linkNode.setTarget(linkTarget); | ||||||||
| if(linkTarget === "_blank") { | ||||||||
| linkNode.setRel("noopener noreferrer"); | ||||||||
| } else { | ||||||||
| linkNode.setRel(""); | ||||||||
| } | ||||||||
|
Comment on lines
+394
to
+396
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this else block necessary?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Mahima-Sanketh-Git shall we address this as well? I believe this else block is necessary because @coderabbitai please validate.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The problematic scenario:
So The 🧠 Learnings used |
||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| } else { | ||||||||
| // If no URL, remove the link (same as TOGGLE_LINK_COMMAND with null). | ||||||||
| editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); | ||||||||
|
|
@@ -391,7 +404,7 @@ const LinkEditor = (): ReactElement => { | |||||||
| HighPriority | ||||||||
| ) | ||||||||
| ); | ||||||||
| }, [ editor, updateLinkEditor, isEditMode ]); | ||||||||
| }, [ editor, updateLinkEditor, isEditMode, linkTarget ]); | ||||||||
|
|
||||||||
| /** | ||||||||
| * Updates the link editor position. | ||||||||
|
|
@@ -465,13 +478,66 @@ const LinkEditor = (): ReactElement => { | |||||||
| } | ||||||||
| } } | ||||||||
| /> | ||||||||
| {/* Link Target Checkbox - With Description */} | ||||||||
| <Box sx={ { alignItems:"center", display: "flex", flexDirection: "row", gap: 0 | ||||||||
| } }> | ||||||||
|
Mahima-Sanketh-Git marked this conversation as resolved.
Outdated
|
||||||||
| <FormControlLabel | ||||||||
| control={ | ||||||||
| <Checkbox | ||||||||
| checked={ linkTarget === "_blank" } | ||||||||
| onChange={ (event: React.ChangeEvent<HTMLInputElement>) => { | ||||||||
| const newTarget:"_blank" | "_self" = | ||||||||
| event.target.checked ? "_blank" : "_self"; | ||||||||
|
|
||||||||
| setLinkTarget(newTarget); | ||||||||
|
|
||||||||
| if (lastSelection !== null) { | ||||||||
| const currentUrl:any = getCurrentUrl(); | ||||||||
|
|
||||||||
| if (currentUrl !== "") { | ||||||||
| editor.update(() => { | ||||||||
| const selection:BaseSelection | null = $getSelection(); | ||||||||
|
|
||||||||
| if ($isRangeSelection(selection)) { | ||||||||
| const node:TextNode | ElementNode = | ||||||||
| getSelectedNode(selection); | ||||||||
| const linkNode:any = $isLinkNode(node) | ||||||||
| ? node | ||||||||
|
Mahima-Sanketh-Git marked this conversation as resolved.
Outdated
|
||||||||
| : node.getParent(); | ||||||||
|
|
||||||||
| if ($isLinkNode(linkNode)) { | ||||||||
| linkNode.setTarget(newTarget); | ||||||||
| linkNode.setRel(newTarget === "_blank" | ||||||||
| ? "noopener noreferrer" : ""); | ||||||||
| } | ||||||||
| } | ||||||||
| }); | ||||||||
| } | ||||||||
| } | ||||||||
| } } | ||||||||
| data-componentid="link-target-checkbox" | ||||||||
| /> | ||||||||
| } | ||||||||
| label={t("flows:core.elements.richText.linkEditor.linkTargetLabel")} | ||||||||
| /> | ||||||||
| <Tooltip title={linkTarget === "_blank" | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| ? t("flows:core.elements.richText.linkEditor.newTabHint") | ||||||||
| : t("flows:core.elements.richText.linkEditor.sameTabHint") | ||||||||
| } > | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| <span><Hint></Hint></span> | ||||||||
| </Tooltip> | ||||||||
|
|
||||||||
| </Box> | ||||||||
| <Button | ||||||||
| size="small" | ||||||||
| variant="outlined" | ||||||||
| className="link-input-save-button" | ||||||||
| onClick={ (event: ReactMouseEvent<HTMLButtonElement>) => { | ||||||||
| event.preventDefault(); | ||||||||
| if (lastSelection !== null) { | ||||||||
| editor.update(()=>{ | ||||||||
| lastSelection?.clone?.(); | ||||||||
| }); | ||||||||
| const currentUrl: string = getCurrentUrl(); | ||||||||
|
|
||||||||
| if (currentUrl !== "") { | ||||||||
|
|
||||||||
Uh oh!
There was an error while loading. Please reload this page.