From 4b71ba4965d75bf24f64bc18bea10ba01f05e893 Mon Sep 17 00:00:00 2001 From: Sachin Chaurasiya Date: Tue, 17 May 2022 11:16:19 +0530 Subject: [PATCH] Fix #4718 UI: Link in the @mention of user refreshes the whole page (#4992) --- .../RichTextEditorPreviewer.tsx | 10 ++++++++++ .../ui/src/constants/feed.constants.ts | 2 +- .../main/resources/ui/src/utils/FeedUtils.tsx | 17 +++++++++-------- .../main/resources/ui/src/utils/StringsUtils.ts | 9 +++++++++ 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/rich-text-editor/RichTextEditorPreviewer.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/rich-text-editor/RichTextEditorPreviewer.tsx index 854d84247ae..13ed40b3ea8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/rich-text-editor/RichTextEditorPreviewer.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/rich-text-editor/RichTextEditorPreviewer.tsx @@ -15,8 +15,10 @@ import classNames from 'classnames'; import React, { useEffect, useState } from 'react'; // Markdown Parser and plugin imports import MarkdownParser from 'react-markdown'; +import { Link } from 'react-router-dom'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; +import { isExternalUrl } from '../../../utils/StringsUtils'; import { BlurLayout } from './BlurLayout'; import { PreviewerProp } from './RichTextEditor.interface'; @@ -96,6 +98,14 @@ const RichTextEditorPreviewer = ({ ); }, + a: ({ children, ...props }) => { + const href = props.href; + if (isExternalUrl(href)) { + return {children}; + } else { + return {children}; + } + }, }} rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}> diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/feed.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/feed.constants.ts index 9940f353517..878de33c60a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/feed.constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/feed.constants.ts @@ -22,7 +22,7 @@ export const entityLinkRegEx = /<#E::([^<>]+?)::([^<>]+?)>/g; export const entityRegex = /<#E::([^<>]+?)::([^<>]+?)\|(\[(.+?)?\]\((.+?)?\))>/; export const entityUrlMap = { - team: 'teams', + team: 'teams-and-users', user: 'users', }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx index 7417814500a..07df5fc50ba 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx @@ -41,6 +41,7 @@ import { } from '../constants/feed.constants'; import { getEntityPlaceHolder } from './CommonUtils'; import { ENTITY_LINK_SEPARATOR } from './EntityUtils'; +import { getEncodedFqn } from './StringsUtils'; import { getRelativeDateByTimeStamp } from './TimeUtils'; export const getEntityType = (entityLink: string) => { @@ -158,9 +159,9 @@ export async function suggestions(searchTerm: string, mentionChar: string) { `@${hit._source.name ?? hit._source.display_name}`, hit._source.deleted ), - link: `${document.location.protocol}//${document.location.host}/${ - entityUrlMap[entityType as keyof typeof entityUrlMap] - }/${hit._source.name}`, + link: `/${entityUrlMap[entityType as keyof typeof entityUrlMap]}/${ + hit._source.name + }`, }; }); } else { @@ -176,9 +177,9 @@ export async function suggestions(searchTerm: string, mentionChar: string) { `@${hit._source.name ?? hit._source.display_name}`, hit._source.deleted ), - link: `${document.location.protocol}//${document.location.host}/${ - entityUrlMap[entityType as keyof typeof entityUrlMap] - }/${hit._source.name}`, + link: `/${entityUrlMap[entityType as keyof typeof entityUrlMap]}/${ + hit._source.name + }`, }; }); } @@ -196,7 +197,7 @@ export async function suggestions(searchTerm: string, mentionChar: string) { return { id: hit._id, value: `#${entityType}/${hit._source.name}`, - link: `${document.location.protocol}//${document.location.host}/${entityType}/${hit._source.fqdn}`, + link: `/${entityType}/${getEncodedFqn(hit._source.fqdn)}`, }; }); } else { @@ -209,7 +210,7 @@ export async function suggestions(searchTerm: string, mentionChar: string) { return { id: hit._id, value: `#${entityType}/${hit._source.name}`, - link: `${document.location.protocol}//${document.location.host}/${entityType}/${hit._source.fqdn}`, + link: `/${entityType}/${getEncodedFqn(hit._source.fqdn)}`, }; }); } diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/StringsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/StringsUtils.ts index b8640ed5889..1b30a2bcb36 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/StringsUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/StringsUtils.ts @@ -131,3 +131,12 @@ export const getErrorText = ( export const getEncodedFqn = (fqn: string) => { return encodeURIComponent(fqn); }; + +/** + * + * @param url - Url to be check + * @returns - True if url is external otherwise false + */ +export const isExternalUrl = (url = '') => { + return /^https?:\/\//.test(url); +};