Skip to content

Commit

Permalink
Merge 1344
Browse files Browse the repository at this point in the history
Hotfix: Slow link detection
  • Loading branch information
bilalesi authored Jul 20, 2023
2 parents 44d089a + 0958e4b commit 2036c5d
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 70 deletions.
18 changes: 3 additions & 15 deletions src/shared/components/ResourceEditor/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { forwardRef } from 'react';
import codemiror, { EditorConfiguration } from 'codemirror';
import { UnControlled as CodeMirror } from 'react-codemirror2';
import { INDENT_UNIT } from './editorUtils';
import { INDENT_UNIT, highlightUrlOverlay } from './editorUtils';
import { clsx } from 'clsx';
import { Spin } from 'antd';

Expand All @@ -12,25 +12,13 @@ type TCodeEditor = {
fullscreen: boolean;
keyFoldCode(cm: any): void;
handleChange(editor: any, data: any, value: any): void;
onLinksFound(): void;
};
type TEditorConfiguration = EditorConfiguration & {
foldCode: boolean;
};

const CodeEditor = forwardRef<codemiror.Editor | undefined, TCodeEditor>(
(
{
busy,
value,
editable,
fullscreen,
keyFoldCode,
handleChange,
onLinksFound,
},
ref
) => {
({ busy, value, editable, fullscreen, keyFoldCode, handleChange }, ref) => {
return (
<Spin spinning={busy}>
<CodeMirror
Expand Down Expand Up @@ -61,9 +49,9 @@ const CodeEditor = forwardRef<codemiror.Editor | undefined, TCodeEditor>(
)}
onChange={handleChange}
editorDidMount={editor => {
highlightUrlOverlay(editor);
(ref as React.MutableRefObject<codemiror.Editor>).current = editor;
}}
onUpdate={onLinksFound}
/>
</Spin>
);
Expand Down
2 changes: 1 addition & 1 deletion src/shared/components/ResourceEditor/ResourceEditor.less
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
}

.code-mirror-editor {
.fusion-resource-link {
.cm-fusion-resource-link:not(.cm-property) {
color: #0974ca !important;
cursor: pointer !important;
background-color: rgba(#0974ca, 0.12);
Expand Down
2 changes: 0 additions & 2 deletions src/shared/components/ResourceEditor/ResourceEditor.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ document.createRange = () => {
describe('ResourceEditor', () => {
it('check if code editor will be rendered in the screen', async () => {
const editor = React.createRef<codemiror.Editor>();
const onLinksFound = jest.fn();
const { queryByText, container } = render(
<CodeEditor
data-testid="code-mirror-editor"
value={JSON.stringify(resourceResolverApi)}
editable={false}
onLinksFound={onLinksFound}
busy={false}
keyFoldCode={() => {}}
handleChange={() => {}}
Expand Down
42 changes: 40 additions & 2 deletions src/shared/components/ResourceEditor/editorUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NexusClient, Resource } from '@bbp/nexus-sdk';
import { has } from 'lodash';
import isValidUrl, {
isAllowedProtocol,
isExternalLink,
isStorageLink,
isUrlCurieFormat,
Expand Down Expand Up @@ -46,6 +47,8 @@ type TReturnedResolvedData = Omit<

export const LINE_HEIGHT = 15;
export const INDENT_UNIT = 4;
export const CODEMIRROR_HOVER_CLASS = 'CodeMirror-hover-tooltip';
export const CODEMIRROR_LINK_CLASS = 'fusion-resource-link';
const NEAR_BY = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0];
const isDownloadableLink = (resource: Resource) => {
return Boolean(
Expand Down Expand Up @@ -74,6 +77,15 @@ export const getDataExplorerResourceItemArray = (
data._rev,
]) as TDEResource;
};
export const isClickableLine = (url: string) => {
return (
isValidUrl(url) &&
isAllowedProtocol(url) &&
!isUrlCurieFormat(url) &&
!isStorageLink(url)
);
};

export function getTokenAndPosAt(e: MouseEvent, current: CodeMirror.Editor) {
const node = e.target || e.srcElement;
const text =
Expand All @@ -86,9 +98,12 @@ export function getTokenAndPosAt(e: MouseEvent, current: CodeMirror.Editor) {
};
const pos = current.coordsChar(coords);
const token = current.getTokenAt(pos);
if (token && token.string === text) {
const url = token
? token.string.replace(/\\/g, '').replace(/\"/g, '')
: null;
if (token && url === text) {
return {
token,
url,
coords: {
left: editorRect.left,
top: coords.top + LINE_HEIGHT,
Expand All @@ -101,6 +116,29 @@ export function getTokenAndPosAt(e: MouseEvent, current: CodeMirror.Editor) {
coords: { left: editorRect.left, top: e.pageY },
};
}
export const highlightUrlOverlay = (editor: CodeMirror.Editor) => {
editor.addOverlay({
token: (stream: any, tall: any, call: any) => {
const rxWord = '" '; // Define what separates a word
let ch = stream.peek();
let word = '';
// \uE001: end of line
// \uE000: start of line
if (rxWord.includes(ch) || ch === '\uE000' || ch === '\uE001') {
stream.next();
return null;
}

while ((ch = stream.peek()) && !rxWord.includes(ch)) {
word += ch;
stream.next();
}

if (isClickableLine(word)) return CODEMIRROR_LINK_CLASS;
return;
},
});
};
export async function editorLinkResolutionHandler({
nexus,
apiEndpoint,
Expand Down
39 changes: 1 addition & 38 deletions src/shared/components/ResourceEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,12 @@ import 'codemirror/addon/fold/foldcode';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/brace-fold';

import isValidUrl, {
isAllowedProtocal,
isStorageLink,
isUrlCurieFormat,
} from '../../../utils/validUrl';
import CodeEditor from './CodeEditor';
import { RootState } from '../../store/reducers';
import {
useEditorPopover,
useEditorTooltip,
CODEMIRROR_LINK_CLASS,
} from './useEditorTooltip';
import { useEditorPopover, useEditorTooltip } from './useEditorTooltip';
import { DATA_EXPLORER_GRAPH_FLOW_PATH } from '../../store/reducers/data-explorer';
import ResourceResolutionCache from './ResourcesLRUCache';
import './ResourceEditor.less';

const AnchorLinkIcon = require('../../images/AnchorLink.svg');
export interface ResourceEditorProps {
rawData: { [key: string]: any };
onSubmit: (rawData: { [key: string]: any }) => void;
Expand All @@ -53,15 +42,6 @@ export interface ResourceEditorProps {

const switchMarginRight = { marginRight: 5 };

const isClickableLine = (url: string) => {
return (
isValidUrl(url) &&
isAllowedProtocal(url) &&
!isUrlCurieFormat(url) &&
!isStorageLink(url)
);
};

const ResourceEditor: React.FunctionComponent<ResourceEditorProps> = props => {
const {
rawData,
Expand Down Expand Up @@ -96,7 +76,6 @@ const ResourceEditor: React.FunctionComponent<ResourceEditorProps> = props => {
oidc: state.oidc,
config: state.config,
}));
const userAuthenticated = oidc.user && oidc.user.access_token;
const keyFoldCode = (cm: any) => {
cm.foldCode(cm.getCursor());
};
Expand Down Expand Up @@ -131,16 +110,6 @@ const ResourceEditor: React.FunctionComponent<ResourceEditorProps> = props => {
}
onMetadataChange?.(checked);
};
const onLinksFound = () => {
const elements = document.getElementsByClassName('cm-string');
Array.from(elements).forEach((item, index) => {
const itemSpan = item as HTMLSpanElement;
const url = itemSpan.innerText.replace(/^"|"$/g, '');
if (isClickableLine(url)) {
itemSpan.classList.add(CODEMIRROR_LINK_CLASS);
}
});
};

React.useEffect(() => {
setEditing(false);
Expand Down Expand Up @@ -204,11 +173,6 @@ const ResourceEditor: React.FunctionComponent<ResourceEditorProps> = props => {
<div
data-testid="resource-editor"
className={valid ? 'resource-editor' : 'resource-editor _invalid'}
style={
{
'--resource-link-anchor-icon': `url(${AnchorLinkIcon})`,
} as React.CSSProperties
}
>
{showControlPanel && (
<div className="control-panel">
Expand Down Expand Up @@ -298,7 +262,6 @@ const ResourceEditor: React.FunctionComponent<ResourceEditorProps> = props => {
editable={editable}
handleChange={handleChange}
keyFoldCode={keyFoldCode}
onLinksFound={onLinksFound}
fullscreen={fullscreen}
/>
</div>
Expand Down
15 changes: 5 additions & 10 deletions src/shared/components/ResourceEditor/useEditorTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import clsx from 'clsx';
import { useNexusContext } from '@bbp/react-nexus';
import { useSelector } from 'react-redux';
import {
CODEMIRROR_HOVER_CLASS,
TEditorPopoverResolvedData,
editorLinkResolutionHandler,
getTokenAndPosAt,
Expand All @@ -15,8 +16,6 @@ import useResolutionActions from './useResolutionActions';

const downloadImg = require('../../images/DownloadingLoop.svg');

export const CODEMIRROR_HOVER_CLASS = 'CodeMirror-hover-tooltip';
export const CODEMIRROR_LINK_CLASS = 'fusion-resource-link';
type TTooltipCreator = Pick<
TEditorPopoverResolvedData,
'error' | 'resolvedAs' | 'results'
Expand Down Expand Up @@ -226,10 +225,8 @@ function useEditorTooltip({

async function onMouseOver(ev: MouseEvent) {
const node = ev.target as HTMLElement;
if (node) {
const { token } = getTokenAndPosAt(ev, currentEditor);
const content = token?.string || '';
const url = content.replace(/\\/g, '').replace(/\"/g, '');
if (node && !node.classList.contains('cm-property')) {
const { url } = getTokenAndPosAt(ev, currentEditor);
if (url && mayBeResolvableLink(url)) {
node.classList.add('wait-for-tooltip');
removeTooltipsFromDOM();
Expand Down Expand Up @@ -340,10 +337,8 @@ function useEditorPopover({
async function onMouseDown(_: CodeMirror.Editor, ev: MouseEvent) {
removeTooltipsFromDOM();
const node = ev.target as HTMLElement;
if (node) {
const { token } = getTokenAndPosAt(ev, currentEditor);
const content = token?.string || '';
const url = content.replace(/\\/g, '').replace(/\"/g, '');
if (node && !node.classList.contains('cm-property')) {
const { url } = getTokenAndPosAt(ev, currentEditor);
if (url && mayBeResolvableLink(url)) {
editorLinkResolutionHandler({
nexus,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/validUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function isExternalLink(url: string): boolean {
function isStorageLink(url: string): boolean {
return url.startsWith('file:///gpfs');
}
function isAllowedProtocal(url: string): boolean {
function isAllowedProtocol(url: string): boolean {
return url.startsWith('https://') || url.startsWith('http://');
}

Expand All @@ -43,6 +43,6 @@ export {
isUrlCurieFormat,
isExternalLink,
isStorageLink,
isAllowedProtocal,
isAllowedProtocol,
};
export default isValidUrl;

0 comments on commit 2036c5d

Please sign in to comment.