From 38f69d44a18f95670e9554fae221bb9de5325040 Mon Sep 17 00:00:00 2001 From: Or Geva Date: Tue, 16 May 2023 17:13:13 +0300 Subject: [PATCH] Add message passing from the webview to the IDE --- src/App.tsx | 23 ++---- src/api/eventManager.ts | 35 ++++++++ src/api/ideEvent.ts | 12 +++ src/api/webviewEvent.ts | 18 ++++ src/components/Page/Dependency/Dependency.tsx | 2 +- .../Page/Dependency/Navigator/Navigator.tsx | 2 +- .../Dependency/Navigator/PageHolder.test.tsx | 2 +- .../Page/Dependency/Navigator/PageHolder.tsx | 2 +- .../Page/Dependency/Navigator/Tab.test.tsx | 2 +- src/components/Page/Eos/Eos.tsx | 4 +- src/components/Page/IaC/IaC.tsx | 4 +- src/components/Page/Secrets/Secrets.tsx | 4 +- .../UI/List/AnalysisStepsListElement.tsx | 20 ++++- .../UI/Summary/CveVulnerability.tsx | 2 +- src/components/UI/Summary/Severity.tsx | 2 +- src/model/EosPage.ts | 14 ---- src/model/analysisStep.ts | 6 +- src/model/dependencyPage.ts | 26 ------ src/model/iacPage.ts | 19 ----- src/model/index.ts | 13 --- src/model/pageType.ts | 8 -- src/model/secretsPage.ts | 19 ----- src/model/webviewPages.ts | 82 +++++++++++++++++++ src/setupTests.ts | 3 +- src/store/eventContext.tsx | 4 + src/types/index.ts | 17 ++-- 26 files changed, 207 insertions(+), 138 deletions(-) create mode 100644 src/api/eventManager.ts create mode 100644 src/api/ideEvent.ts create mode 100644 src/api/webviewEvent.ts delete mode 100644 src/model/EosPage.ts delete mode 100644 src/model/dependencyPage.ts delete mode 100644 src/model/iacPage.ts delete mode 100644 src/model/index.ts delete mode 100644 src/model/pageType.ts delete mode 100644 src/model/secretsPage.ts create mode 100644 src/model/webviewPages.ts create mode 100644 src/store/eventContext.tsx diff --git a/src/App.tsx b/src/App.tsx index 52da8e28..5c6ccb9d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,28 +1,21 @@ import css from './App.module.css' import Dependency from './components/Page/Dependency/Dependency' -import { IDependencyPage } from './model/dependencyPage' -import { PageType } from './model/pageType' -import { useState } from 'react' +import { useState, useMemo } from 'react' import Eos from './components/Page/Eos/Eos' -import { IEosPage } from './model/EosPage' -import { IIaCPage } from './model/iacPage' import IaC from './components/Page/IaC/IaC' -import { ISecretsPage } from './model/secretsPage' import Secrets from './components/Page/Secrets/Secrets' +import { WebviewPage, PageType } from './model/webviewPages' +import { EventManager } from './api/eventManager' +import { eventManagerContext } from './store/eventContext' /** * The main page on which the Webview will be drawn based on the incoming request page type. */ function App(): JSX.Element { - const [data, setDependencyData] = useState( - {} as IDependencyPage | IEosPage | IIaCPage | ISecretsPage - ) + const [data, setDependencyData] = useState({} as WebviewPage) + const eventManager = useMemo(() => new EventManager(setDependencyData), []) let page - window.addEventListener('message', event => { - setDependencyData(event.data.data) - }) - switch (data.pageType) { case PageType.Dependency: page = @@ -42,7 +35,9 @@ function App(): JSX.Element { return (
-
{page}
+ +
{page}
+
) } diff --git a/src/api/eventManager.ts b/src/api/eventManager.ts new file mode 100644 index 00000000..6ef7c929 --- /dev/null +++ b/src/api/eventManager.ts @@ -0,0 +1,35 @@ +import { IAnalysisStep } from '../model/analysisStep' +import { WebviewPage } from '../model/webviewPages' +import { IdeEvent, IdeEventType, JumpToCodeEvent } from './ideEvent' +import { WebviewEvent, webviewEventType } from './webviewEvent' + +export class EventManager { + private sendFunc = new Function('request', 'console.log(request)') + + constructor(private setPageState: React.Dispatch>) { + this.setEventReceiver() + } + + private sendEvent = (req: IdeEvent): void => { + this.sendFunc(req) + } + + private setEventReceiver(): void { + window.addEventListener('message', event => { + const eventData: WebviewEvent = event.data + + switch (eventData.type) { + case webviewEventType.SetEmitter: + this.sendFunc = new Function(eventData.emitterFunc)() + break + case webviewEventType.ShowPage: + this.setPageState(eventData.pageData) + break + } + }) + } + + public jumpToCode(data: IAnalysisStep): void { + this.sendEvent({ type: IdeEventType.JUMP_TO_CODE, data: data } as JumpToCodeEvent) + } +} diff --git a/src/api/ideEvent.ts b/src/api/ideEvent.ts new file mode 100644 index 00000000..a3e12a2b --- /dev/null +++ b/src/api/ideEvent.ts @@ -0,0 +1,12 @@ +import { IAnalysisStep } from '../model/analysisStep' + +export interface JumpToCodeEvent { + type: IdeEventType.JUMP_TO_CODE + data: IAnalysisStep +} + +export enum IdeEventType { + JUMP_TO_CODE = 'SHOW_CODE' +} + +export type IdeEvent = JumpToCodeEvent diff --git a/src/api/webviewEvent.ts b/src/api/webviewEvent.ts new file mode 100644 index 00000000..b9fa5234 --- /dev/null +++ b/src/api/webviewEvent.ts @@ -0,0 +1,18 @@ +import { WebviewPage } from '../model/webviewPages' + +export interface ShowPageEvent { + type: webviewEventType.ShowPage + pageData: WebviewPage +} + +export interface SetEmitterEvent { + type: webviewEventType.SetEmitter + emitterFunc: string +} + +export enum webviewEventType { + SetEmitter = 'SET_EMITTER', + ShowPage = 'SHOW_DATA' +} + +export type WebviewEvent = ShowPageEvent | SetEmitterEvent diff --git a/src/components/Page/Dependency/Dependency.tsx b/src/components/Page/Dependency/Dependency.tsx index fb1ac5f7..b6c0d615 100644 --- a/src/components/Page/Dependency/Dependency.tsx +++ b/src/components/Page/Dependency/Dependency.tsx @@ -3,8 +3,8 @@ import Summary from '../../UI/Summary/Summary' import Edited from '../../UI/Edited/Edited' import Header from '../../UI/Header/Header' import Navigator from './Navigator/Navigator' -import { IDependencyPage } from '../../../model/dependencyPage' import CveVulnerability from '../../UI/Summary/CveVulnerability' +import { IDependencyPage } from '../../../model/webviewPages' export interface Props { data: IDependencyPage diff --git a/src/components/Page/Dependency/Navigator/Navigator.tsx b/src/components/Page/Dependency/Navigator/Navigator.tsx index b6cc2986..2904d4d4 100644 --- a/src/components/Page/Dependency/Navigator/Navigator.tsx +++ b/src/components/Page/Dependency/Navigator/Navigator.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' -import { IDependencyPage } from '../../../../model/dependencyPage' import { IExtendedInformation } from '../../../../model/extendedInformation' import { IReference } from '../../../../model/reference' import { ActiveTab, ITab } from '../../../../model/tab' import PageHolder from './PageHolder' import Tab from './Tab' +import { IDependencyPage } from '../../../../model/webviewPages' export interface Props { data: IDependencyPage diff --git a/src/components/Page/Dependency/Navigator/PageHolder.test.tsx b/src/components/Page/Dependency/Navigator/PageHolder.test.tsx index da9b530f..ec0416e8 100644 --- a/src/components/Page/Dependency/Navigator/PageHolder.test.tsx +++ b/src/components/Page/Dependency/Navigator/PageHolder.test.tsx @@ -1,8 +1,8 @@ import { render, screen } from '@testing-library/react' -import { IDependencyPage } from '../../../../model/dependencyPage' import { ActiveTab } from '../../../../model/tab' import withMarkup, { getFakeDependencyPage } from '../../../../setupTests' import PageHolder from './PageHolder' +import { IDependencyPage } from '../../../../model/webviewPages' describe('PageHolder component', () => { describe('Research page', () => { test('Renders short description', () => { diff --git a/src/components/Page/Dependency/Navigator/PageHolder.tsx b/src/components/Page/Dependency/Navigator/PageHolder.tsx index 98b9f61a..528b18f8 100644 --- a/src/components/Page/Dependency/Navigator/PageHolder.tsx +++ b/src/components/Page/Dependency/Navigator/PageHolder.tsx @@ -2,13 +2,13 @@ import ContextualAnalysis from './page/ContextualAnalysis' import Reference from './page/Reference' import Research from './page/Research' import css from './Page.module.css' -import { IDependencyPage } from '../../../../model/dependencyPage' import ImpactGraph from './page/ImpactGraph' import PublicSources from './page/PublicSources' import { useState, useEffect } from 'react' import { ActiveTab } from '../../../../model/tab' import { TreeNode } from '../../../../model/treeNode' import { toTreeNode } from '../../../../utils/utils' +import { IDependencyPage } from '../../../../model/webviewPages' interface Props { activeTab: ActiveTab diff --git a/src/components/Page/Dependency/Navigator/Tab.test.tsx b/src/components/Page/Dependency/Navigator/Tab.test.tsx index edc4c1d6..6a498426 100644 --- a/src/components/Page/Dependency/Navigator/Tab.test.tsx +++ b/src/components/Page/Dependency/Navigator/Tab.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from '@testing-library/react' -import { ActiveTab } from '../../../../model' import Tab from './Tab' +import { ActiveTab } from '../../../../model/tab' describe('Tab component', () => { test('Renders three tabs', () => { const FirstTab = 'First-Tab' diff --git a/src/components/Page/Eos/Eos.tsx b/src/components/Page/Eos/Eos.tsx index 43aac5e9..0d85a8c5 100644 --- a/src/components/Page/Eos/Eos.tsx +++ b/src/components/Page/Eos/Eos.tsx @@ -1,13 +1,13 @@ import css from './Eos.module.css' import Summary from '../../UI/Summary/Summary' import Header from '../../UI/Header/Header' -import { IEosPage } from '../../../model/EosPage' import { ISeverity } from '../../../model/severity' import Vulnerability from '../../UI/Summary/Vulnerability' import VulnerabilityLine from '../../UI/Summary/VulnerabilityLine' import Research from './Research' import ContextualAnalysis from './ContextualAnalysis' import Severity from '../../UI/Summary/Severity' +import { IEosPage } from '../../../model/webviewPages' export interface Props { data: IEosPage @@ -24,7 +24,7 @@ export default function Eos(props: Props): JSX.Element { - +
- + {props.data.abbreviation && } diff --git a/src/components/Page/Secrets/Secrets.tsx b/src/components/Page/Secrets/Secrets.tsx index 22de8e95..50259b89 100644 --- a/src/components/Page/Secrets/Secrets.tsx +++ b/src/components/Page/Secrets/Secrets.tsx @@ -5,7 +5,7 @@ import Severity from '../../UI/Summary/Severity' import Vulnerability from '../../UI/Summary/Vulnerability' import Abbreviation from '../../UI/Summary/Abbreviation' import Findings from '../../UI/Findings/Findings' -import { ISecretsPage } from '../../../model/secretsPage' +import { ISecretsPage } from '../../../model/webviewPages' import { Collapse } from '../../UI/Collapse/Collapse' export interface Props { @@ -17,7 +17,7 @@ function Secrets(props: Props): JSX.Element {
- + {props.data.abbreviation && } diff --git a/src/components/UI/List/AnalysisStepsListElement.tsx b/src/components/UI/List/AnalysisStepsListElement.tsx index 2af769b5..85624a99 100644 --- a/src/components/UI/List/AnalysisStepsListElement.tsx +++ b/src/components/UI/List/AnalysisStepsListElement.tsx @@ -1,21 +1,35 @@ import { IAnalysisStep } from '../../../model/analysisStep' import css from './AnalysisStepsListElement.module.css' import CodeBlock from '../CodeBlock/CodeBlock' - +import { useContext } from 'react' +import { eventManagerContext } from '../../../store/eventContext' interface Props { items: IAnalysisStep[] } export default function AnalysisStepsListElement(props: Props): JSX.Element { + const ctx = useContext(eventManagerContext) + + const onClick = (event: React.MouseEvent, item: IAnalysisStep): void => { + event.preventDefault() + ctx.jumpToCode(item) + } + return ( <> {props.items.map((item, i) => ( -