Merge remote-tracking branch 'origin/main' into koesie10/variant-analysis-results-manager

This commit is contained in:
Koen Vlaswinkel
2022-10-07 11:36:17 +02:00
11 changed files with 489 additions and 209 deletions

View File

@@ -33,5 +33,6 @@ export const parameters = {
};
(window as any).acquireVsCodeApi = () => ({
postMessage: action('post-vscode-message')
postMessage: action('post-vscode-message'),
setState: action('set-vscode-state'),
});

View File

@@ -11,7 +11,7 @@
"dependencies": {
"@octokit/plugin-retry": "^3.0.9",
"@octokit/rest": "^19.0.4",
"@primer/octicons-react": "^16.3.0",
"@primer/octicons-react": "^17.6.0",
"@primer/react": "^35.0.0",
"@vscode/codicons": "^0.0.31",
"@vscode/webview-ui-toolkit": "^1.0.1",
@@ -5537,9 +5537,9 @@
"integrity": "sha512-Ej2OUc3ZIFaR7WwIUqESO1DTzmpb7wc8xbTVRT9s52jZQDjN7g5iljoK3ocYZm+BIAcKn3MvcwB42hEk4Ga4xQ=="
},
"node_modules/@primer/octicons-react": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-16.3.0.tgz",
"integrity": "sha512-nxB6L5IYeR2hPY6q7DAyQGW42MO0kA4PqMBNysN4WaZAHjiKgtTDr9rI+759PqGK7BTTuT43HTuu2cMsg7pH0Q==",
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-17.6.0.tgz",
"integrity": "sha512-jn1fWag3eU6BvOltMS2MqLPNh39D45cpegsTO2Qhb8SlJoUsj/ZO1qbJgYd9ibvZo8evDyXx3syh4kDbxJQFsg==",
"engines": {
"node": ">=8"
},
@@ -44167,9 +44167,9 @@
"integrity": "sha512-Ej2OUc3ZIFaR7WwIUqESO1DTzmpb7wc8xbTVRT9s52jZQDjN7g5iljoK3ocYZm+BIAcKn3MvcwB42hEk4Ga4xQ=="
},
"@primer/octicons-react": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-16.3.0.tgz",
"integrity": "sha512-nxB6L5IYeR2hPY6q7DAyQGW42MO0kA4PqMBNysN4WaZAHjiKgtTDr9rI+759PqGK7BTTuT43HTuu2cMsg7pH0Q=="
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-17.6.0.tgz",
"integrity": "sha512-jn1fWag3eU6BvOltMS2MqLPNh39D45cpegsTO2Qhb8SlJoUsj/ZO1qbJgYd9ibvZo8evDyXx3syh4kDbxJQFsg=="
},
"@primer/primitives": {
"version": "7.1.1",

View File

@@ -63,6 +63,7 @@
"onCommand:codeQL.quickQuery",
"onCommand:codeQL.restartQueryServer",
"onWebviewPanel:resultsView",
"onWebviewPanel:codeQL.variantAnalysis",
"onFileSystem:codeql-zip-archive"
],
"main": "./out/extension",
@@ -1207,7 +1208,7 @@
"dependencies": {
"@octokit/plugin-retry": "^3.0.9",
"@octokit/rest": "^19.0.4",
"@primer/octicons-react": "^16.3.0",
"@primer/octicons-react": "^17.6.0",
"@primer/react": "^35.0.0",
"@vscode/codicons": "^0.0.31",
"@vscode/webview-ui-toolkit": "^1.0.1",

View File

@@ -33,6 +33,11 @@ export abstract class AbstractWebview<ToMessage extends WebviewMessage, FromMess
super();
}
public async restoreView(panel: WebviewPanel): Promise<void> {
this.panel = panel;
this.setupPanel(panel);
}
protected get isShowingPanel() {
return !!this.panel;
}
@@ -59,37 +64,43 @@ export abstract class AbstractWebview<ToMessage extends WebviewMessage, FromMess
],
}
);
this.push(
this.panel.onDidDispose(
() => {
this.panel = undefined;
this.panelLoaded = false;
this.onPanelDispose();
},
null,
ctx.subscriptions
)
);
this.panel.webview.html = getHtmlForWebview(
ctx,
this.panel.webview,
config.view,
{
allowInlineStyles: true,
}
);
this.push(
this.panel.webview.onDidReceiveMessage(
async (e) => this.onMessage(e),
undefined,
ctx.subscriptions
)
);
this.setupPanel(this.panel);
}
return this.panel;
}
protected setupPanel(panel: WebviewPanel): void {
const config = this.getPanelConfig();
this.push(
panel.onDidDispose(
() => {
this.panel = undefined;
this.panelLoaded = false;
this.onPanelDispose();
},
null,
this.ctx.subscriptions
)
);
panel.webview.html = getHtmlForWebview(
this.ctx,
panel.webview,
config.view,
{
allowInlineStyles: true,
}
);
this.push(
panel.webview.onDidReceiveMessage(
async (e) => this.onMessage(e),
undefined,
this.ctx.subscriptions
)
);
}
protected abstract getPanelConfig(): WebviewPanelConfig;
protected abstract onPanelDispose(): void;

View File

@@ -104,6 +104,8 @@ import { LogScannerService } from './log-insights/log-scanner-service';
import { createInitialQueryInfo } from './run-queries-shared';
import { LegacyQueryRunner } from './legacy-query-server/legacyRunner';
import { QueryRunner } from './queryRunner';
import { VariantAnalysisView } from './remote-queries/variant-analysis-view';
import { VariantAnalysisViewSerializer } from './remote-queries/variant-analysis-view-serializer';
import { VariantAnalysis } from './remote-queries/shared/variant-analysis';
import {
VariantAnalysis as VariantAnalysisApiResponse,
@@ -176,6 +178,7 @@ export interface CodeQLExtensionInterface {
readonly distributionManager: DistributionManager;
readonly databaseManager: DatabaseManager;
readonly databaseUI: DatabaseUI;
readonly variantAnalysisManager: VariantAnalysisManager;
readonly dispose: () => void;
}
@@ -386,7 +389,10 @@ export async function activate(ctx: ExtensionContext): Promise<CodeQLExtensionIn
allowAutoUpdating: true
})));
return await installOrUpdateThenTryActivate({
const variantAnalysisViewSerializer = new VariantAnalysisViewSerializer(ctx);
Window.registerWebviewPanelSerializer(VariantAnalysisView.viewType, variantAnalysisViewSerializer);
const codeQlExtension = await installOrUpdateThenTryActivate({
isUserInitiated: !!ctx.globalState.get(shouldUpdateOnNextActivationKey),
shouldDisplayMessageWhenNoUpdates: false,
@@ -394,6 +400,10 @@ export async function activate(ctx: ExtensionContext): Promise<CodeQLExtensionIn
// otherwise, ask user to accept the update
allowAutoUpdating: !!ctx.globalState.get(shouldUpdateOnNextActivationKey)
});
variantAnalysisViewSerializer.onExtensionLoaded(codeQlExtension.variantAnalysisManager);
return codeQlExtension;
}
async function activateWithInstalledDistribution(
@@ -939,7 +949,10 @@ async function activateWithInstalledDistribution(
ctx.subscriptions.push(
commandRunner('codeQL.mockVariantAnalysisView', async () => {
await variantAnalysisManager.showView(1);
// Generate a random variant analysis ID for testing
const variantAnalysisId: number = Math.floor(Math.random() * 1000000);
await variantAnalysisManager.showView(variantAnalysisId);
})
);
@@ -1164,6 +1177,7 @@ async function activateWithInstalledDistribution(
distributionManager,
databaseManager: dbm,
databaseUI,
variantAnalysisManager,
dispose: () => {
ctx.subscriptions.forEach(d => d.dispose());
}

View File

@@ -440,6 +440,15 @@ export interface SetVariantAnalysisMessage {
variantAnalysis: VariantAnalysis;
}
export type StopVariantAnalysisMessage = {
t: 'stopVariantAnalysis';
variantAnalysisId: number;
}
export type VariantAnalysisState = {
variantAnalysisId: number;
}
export interface SetRepoResultsMessage {
t: 'setRepoResults';
repoResults: VariantAnalysisScannedRepositoryResult[];
@@ -456,4 +465,5 @@ export type ToVariantAnalysisMessage =
| SetRepoStatesMessage;
export type FromVariantAnalysisMessage =
| ViewLoadedMsg;
| ViewLoadedMsg
| StopVariantAnalysisMessage;

View File

@@ -0,0 +1,48 @@
import { ExtensionContext, WebviewPanel, WebviewPanelSerializer } from 'vscode';
import { VariantAnalysisView } from './variant-analysis-view';
import { VariantAnalysisState } from '../pure/interface-types';
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
export class VariantAnalysisViewSerializer implements WebviewPanelSerializer {
private resolvePromises: ((value: VariantAnalysisViewManager<VariantAnalysisView>) => void)[] = [];
private manager?: VariantAnalysisViewManager<VariantAnalysisView>;
public constructor(
private readonly ctx: ExtensionContext,
) { }
onExtensionLoaded(manager: VariantAnalysisViewManager<VariantAnalysisView>): void {
this.manager = manager;
this.resolvePromises.forEach((resolve) => resolve(manager));
this.resolvePromises = [];
}
async deserializeWebviewPanel(webviewPanel: WebviewPanel, state: unknown): Promise<void> {
if (!state || typeof state !== 'object') {
return;
}
if (!('variantAnalysisId' in state)) {
return;
}
const variantAnalysisState: VariantAnalysisState = state as VariantAnalysisState;
const manager = await this.waitForExtensionFullyLoaded();
const view = new VariantAnalysisView(this.ctx, variantAnalysisState.variantAnalysisId, manager);
await view.restoreView(webviewPanel);
}
private waitForExtensionFullyLoaded(): Promise<VariantAnalysisViewManager<VariantAnalysisView>> {
if (this.manager) {
return Promise.resolve(this.manager);
}
return new Promise<VariantAnalysisViewManager<VariantAnalysisView>>((resolve) => {
this.resolvePromises.push(resolve);
});
}
}

View File

@@ -1,12 +1,20 @@
import { ExtensionContext, ViewColumn } from 'vscode';
import { AbstractWebview, WebviewPanelConfig } from '../abstract-webview';
import { WebviewMessage } from '../interface-utils';
import { logger } from '../logging';
import { VariantAnalysisViewInterface, VariantAnalysisViewManager } from './variant-analysis-view-manager';
import { VariantAnalysis, VariantAnalysisScannedRepositoryState } from './shared/variant-analysis';
import { FromVariantAnalysisMessage, ToVariantAnalysisMessage } from '../pure/interface-types';
import { assertNever } from '../pure/helpers-pure';
import {
VariantAnalysis,
VariantAnalysisQueryLanguage,
VariantAnalysisRepoStatus,
VariantAnalysisScannedRepositoryState,
VariantAnalysisStatus
} from './shared/variant-analysis';
import { VariantAnalysisViewInterface, VariantAnalysisViewManager } from './variant-analysis-view-manager';
export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessage, FromVariantAnalysisMessage> implements VariantAnalysisViewInterface {
public static readonly viewType = 'codeQL.variantAnalysis';
public constructor(
ctx: ExtensionContext,
public readonly variantAnalysisId: number,
@@ -19,6 +27,8 @@ export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessag
public async openView() {
this.getPanel().reveal(undefined, true);
await this.waitForPanelLoaded();
}
public async updateView(variantAnalysis: VariantAnalysis): Promise<void> {
@@ -45,11 +55,11 @@ export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessag
protected getPanelConfig(): WebviewPanelConfig {
return {
viewId: 'variantAnalysisView',
viewId: VariantAnalysisView.viewType,
title: `CodeQL Query Results for ${this.variantAnalysisId}`,
viewColumn: ViewColumn.Active,
preserveFocus: true,
view: 'variant-analysis'
view: 'variant-analysis',
};
}
@@ -57,7 +67,173 @@ export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessag
this.manager.unregisterView(this);
}
protected async onMessage(msg: WebviewMessage): Promise<void> {
void logger.log('Received message on variant analysis view: ' + msg.t);
protected async onMessage(msg: FromVariantAnalysisMessage): Promise<void> {
switch (msg.t) {
case 'viewLoaded':
this.onWebViewLoaded();
void logger.log('Variant analysis view loaded');
await this.postMessage({
t: 'setVariantAnalysis',
variantAnalysis: this.getVariantAnalysis(),
});
break;
case 'stopVariantAnalysis':
void logger.log(`Stop variant analysis: ${msg.variantAnalysisId}`);
break;
default:
assertNever(msg);
}
}
private getVariantAnalysis(): VariantAnalysis {
return {
id: this.variantAnalysisId,
controllerRepoId: 1,
actionsWorkflowRunId: 789263,
query: {
name: 'Example query',
filePath: 'example.ql',
language: VariantAnalysisQueryLanguage.Javascript,
},
databases: {},
status: VariantAnalysisStatus.InProgress,
scannedRepos: [
{
repository: {
id: 1,
fullName: 'octodemo/hello-world-1',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 2,
fullName: 'octodemo/hello-world-2',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 3,
fullName: 'octodemo/hello-world-3',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 4,
fullName: 'octodemo/hello-world-4',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 5,
fullName: 'octodemo/hello-world-5',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 6,
fullName: 'octodemo/hello-world-6',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 7,
fullName: 'octodemo/hello-world-7',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 8,
fullName: 'octodemo/hello-world-8',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 9,
fullName: 'octodemo/hello-world-9',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 10,
fullName: 'octodemo/hello-world-10',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
],
skippedRepos: {
notFoundRepos: {
repositoryCount: 2,
repositories: [
{
fullName: 'octodemo/hello-globe'
},
{
fullName: 'octodemo/hello-planet'
}
]
},
noCodeqlDbRepos: {
repositoryCount: 4,
repositories: [
{
id: 100,
fullName: 'octodemo/no-db-1'
},
{
id: 101,
fullName: 'octodemo/no-db-2'
},
{
id: 102,
fullName: 'octodemo/no-db-3'
},
{
id: 103,
fullName: 'octodemo/no-db-4'
}
]
},
overLimitRepos: {
repositoryCount: 1,
repositories: [
{
id: 201,
fullName: 'octodemo/over-limit-1'
}
]
},
accessMismatchRepos: {
repositoryCount: 1,
repositories: [
{
id: 205,
fullName: 'octodemo/private'
}
]
}
},
};
}
}

View File

@@ -3,14 +3,171 @@ import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { VariantAnalysis as VariantAnalysisComponent } from '../../view/variant-analysis/VariantAnalysis';
import {
VariantAnalysis as VariantAnalysisDomainModel,
VariantAnalysisQueryLanguage, VariantAnalysisRepoStatus, VariantAnalysisStatus
} from '../../remote-queries/shared/variant-analysis';
export default {
title: 'Variant Analysis/Variant Analysis',
component: VariantAnalysisComponent,
} as ComponentMeta<typeof VariantAnalysisComponent>;
const Template: ComponentStory<typeof VariantAnalysisComponent> = () => (
<VariantAnalysisComponent />
const Template: ComponentStory<typeof VariantAnalysisComponent> = (args) => (
<VariantAnalysisComponent {...args} />
);
export const VariantAnalysis = Template.bind({});
const variantAnalysis: VariantAnalysisDomainModel = {
id: 1,
controllerRepoId: 1,
actionsWorkflowRunId: 789263,
query: {
name: 'Example query',
filePath: 'example.ql',
language: VariantAnalysisQueryLanguage.Javascript,
},
databases: {},
status: VariantAnalysisStatus.InProgress,
scannedRepos: [
{
repository: {
id: 1,
fullName: 'octodemo/hello-world-1',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 2,
fullName: 'octodemo/hello-world-2',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 3,
fullName: 'octodemo/hello-world-3',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 4,
fullName: 'octodemo/hello-world-4',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 5,
fullName: 'octodemo/hello-world-5',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 6,
fullName: 'octodemo/hello-world-6',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 7,
fullName: 'octodemo/hello-world-7',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 8,
fullName: 'octodemo/hello-world-8',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 9,
fullName: 'octodemo/hello-world-9',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 10,
fullName: 'octodemo/hello-world-10',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
],
skippedRepos: {
notFoundRepos: {
repositoryCount: 2,
repositories: [
{
fullName: 'octodemo/hello-globe'
},
{
fullName: 'octodemo/hello-planet'
}
]
},
noCodeqlDbRepos: {
repositoryCount: 4,
repositories: [
{
id: 100,
fullName: 'octodemo/no-db-1'
},
{
id: 101,
fullName: 'octodemo/no-db-2'
},
{
id: 102,
fullName: 'octodemo/no-db-3'
},
{
id: 103,
fullName: 'octodemo/no-db-4'
}
]
},
overLimitRepos: {
repositoryCount: 1,
repositories: [
{
id: 201,
fullName: 'octodemo/over-limit-1'
}
]
},
accessMismatchRepos: {
repositoryCount: 1,
repositories: [
{
id: 205,
fullName: 'octodemo/private'
}
]
}
},
};
export const Loading = Template.bind({});
Loading.args = {};
export const FullExample = Template.bind({});
FullExample.args = {
variantAnalysis: variantAnalysis,
};

View File

@@ -1,167 +1,16 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import { ToVariantAnalysisMessage } from '../../pure/interface-types';
import {
VariantAnalysis as VariantAnalysisDomainModel,
VariantAnalysisQueryLanguage,
VariantAnalysisRepoStatus, VariantAnalysisScannedRepositoryResult, VariantAnalysisScannedRepositoryState,
VariantAnalysisStatus
VariantAnalysisScannedRepositoryResult,
VariantAnalysisScannedRepositoryState,
} from '../../remote-queries/shared/variant-analysis';
import { VariantAnalysisHeader } from './VariantAnalysisHeader';
import { VariantAnalysisOutcomePanels } from './VariantAnalysisOutcomePanels';
import { VariantAnalysisLoading } from './VariantAnalysisLoading';
const variantAnalysis: VariantAnalysisDomainModel = {
id: 1,
controllerRepoId: 1,
actionsWorkflowRunId: 789263,
query: {
name: 'Example query',
filePath: 'example.ql',
language: VariantAnalysisQueryLanguage.Javascript,
},
databases: {},
status: VariantAnalysisStatus.InProgress,
scannedRepos: [
{
repository: {
id: 1,
fullName: 'octodemo/hello-world-1',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Succeeded,
},
{
repository: {
id: 2,
fullName: 'octodemo/hello-world-2',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Canceled,
},
{
repository: {
id: 3,
fullName: 'octodemo/hello-world-3',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.TimedOut,
},
{
repository: {
id: 4,
fullName: 'octodemo/hello-world-4',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Failed,
},
{
repository: {
id: 5,
fullName: 'octodemo/hello-world-5',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.InProgress,
},
{
repository: {
id: 6,
fullName: 'octodemo/hello-world-6',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.InProgress,
},
{
repository: {
id: 7,
fullName: 'octodemo/hello-world-7',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 8,
fullName: 'octodemo/hello-world-8',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 9,
fullName: 'octodemo/hello-world-9',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
{
repository: {
id: 10,
fullName: 'octodemo/hello-world-10',
private: false,
},
analysisStatus: VariantAnalysisRepoStatus.Pending,
},
],
skippedRepos: {
notFoundRepos: {
repositoryCount: 9999,
repositories: [
{
fullName: 'octodemo/hello-globe'
},
{
fullName: 'octodemo/hello-planet'
}
]
},
noCodeqlDbRepos: {
repositoryCount: 4,
repositories: [
{
id: 100,
fullName: 'octodemo/no-db-1',
private: false,
},
{
id: 101,
fullName: 'octodemo/no-db-2',
private: true,
},
{
id: 102,
fullName: 'octodemo/no-db-3',
private: true,
},
{
id: 103,
fullName: 'octodemo/no-db-4',
private: false,
}
]
},
overLimitRepos: {
repositoryCount: 1,
repositories: [
{
id: 201,
fullName: 'octodemo/over-limit-1'
}
]
},
accessMismatchRepos: {
repositoryCount: 1,
repositories: [
{
id: 205,
fullName: 'octodemo/private'
}
]
}
},
};
import { ToVariantAnalysisMessage } from '../../pure/interface-types';
import { vscode } from '../vscode-api';
const repositoryResults: VariantAnalysisScannedRepositoryResult[] = [
{
@@ -207,11 +56,11 @@ type Props = {
}
export function VariantAnalysis({
variantAnalysis: initialVariantAnalysis = variantAnalysis,
variantAnalysis: initialVariantAnalysis,
repoStates: initialRepoStates = [],
repoResults: initialRepoResults = repositoryResults,
}: Props): JSX.Element {
const [variantAnalysis, setVariantAnalysis] = useState<VariantAnalysisDomainModel>(initialVariantAnalysis);
const [variantAnalysis, setVariantAnalysis] = useState<VariantAnalysisDomainModel | undefined>();
const [repoStates, setRepoStates] = useState<VariantAnalysisScannedRepositoryState[]>(initialRepoStates);
const [repoResults, setRepoResults] = useState<VariantAnalysisScannedRepositoryResult[]>(initialRepoResults);
@@ -221,6 +70,9 @@ export function VariantAnalysis({
const msg: ToVariantAnalysisMessage = evt.data;
if (msg.t === 'setVariantAnalysis') {
setVariantAnalysis(msg.variantAnalysis);
vscode.setState({
variantAnalysisId: msg.variantAnalysis.id,
});
} else if (msg.t === 'setRepoResults') {
setRepoResults(oldRepoResults => {
const newRepoIds = msg.repoResults.map(r => r.repositoryId);
@@ -240,7 +92,7 @@ export function VariantAnalysis({
});
});
if (variantAnalysis.actionsWorkflowRunId === undefined) {
if (variantAnalysis?.actionsWorkflowRunId === undefined) {
return <VariantAnalysisLoading />;
}

View File

@@ -1,10 +1,20 @@
import { FromCompareViewMessage, FromRemoteQueriesMessage, FromResultsViewMsg } from '../pure/interface-types';
import {
FromCompareViewMessage,
FromRemoteQueriesMessage,
FromResultsViewMsg,
FromVariantAnalysisMessage, VariantAnalysisState
} from '../pure/interface-types';
export interface VsCodeApi {
/**
* Post message back to vscode extension.
*/
postMessage(msg: FromResultsViewMsg | FromCompareViewMessage | FromRemoteQueriesMessage): void;
postMessage(msg: FromResultsViewMsg | FromCompareViewMessage | FromRemoteQueriesMessage | FromVariantAnalysisMessage): void;
/**
* Set state of the webview.
*/
setState(state: VariantAnalysisState): void;
}
declare const acquireVsCodeApi: () => VsCodeApi;