Skip to content

Commit 92bbf3a

Browse files
authored
Merge pull request #1534 from github/koesie10/variant-analysis-header-domain-model
Use domain model for VariantAnalysisHeader
2 parents 5c478e9 + f269887 commit 92bbf3a

8 files changed

Lines changed: 279 additions & 65 deletions

File tree

extensions/ql-vscode/src/remote-queries/shared/variant-analysis.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export enum VariantAnalysisStatus {
3434
InProgress = 'inProgress',
3535
Succeeded = 'succeeded',
3636
Failed = 'failed',
37+
Canceled = 'canceled',
3738
}
3839

3940
export enum VariantAnalysisFailureReason {
@@ -95,3 +96,41 @@ export interface VariantAnalysisSubmission {
9596
repositoryOwners?: string[],
9697
}
9798
}
99+
100+
/**
101+
* @param repo
102+
* @returns whether the repo scan is in a completed state, i.e. it cannot normally change state anymore
103+
*/
104+
export function hasRepoScanCompleted(repo: VariantAnalysisScannedRepository): boolean {
105+
return [
106+
// All states that indicates the repository has been scanned and cannot
107+
// change status anymore.
108+
VariantAnalysisRepoStatus.Succeeded, VariantAnalysisRepoStatus.Failed,
109+
VariantAnalysisRepoStatus.Canceled, VariantAnalysisRepoStatus.TimedOut,
110+
].includes(repo.analysisStatus);
111+
}
112+
113+
/**
114+
* @param repos
115+
* @returns the total number of results. Will be `undefined` when there are no repos with results.
116+
*/
117+
export function getTotalResultCount(repos: VariantAnalysisScannedRepository[] | undefined): number | undefined {
118+
const reposWithResultCounts = repos?.filter(repo => repo.resultCount !== undefined);
119+
if (reposWithResultCounts === undefined || reposWithResultCounts.length === 0) {
120+
return undefined;
121+
}
122+
123+
return reposWithResultCounts.reduce((acc, repo) => acc + (repo.resultCount ?? 0), 0);
124+
}
125+
126+
/**
127+
* @param skippedRepos
128+
* @returns the total number of skipped repositories.
129+
*/
130+
export function getSkippedRepoCount(skippedRepos: VariantAnalysisSkippedRepositories | undefined): number {
131+
if (!skippedRepos) {
132+
return 0;
133+
}
134+
135+
return Object.values(skippedRepos).reduce((acc, group) => acc + group.repositoryCount, 0);
136+
}

extensions/ql-vscode/src/stories/variant-analysis/VariantAnalysisHeader.stories.tsx

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import React from 'react';
22

3-
import { ComponentStory, ComponentMeta } from '@storybook/react';
3+
import { ComponentMeta, ComponentStory } from '@storybook/react';
44

55
import { VariantAnalysisContainer } from '../../view/variant-analysis/VariantAnalysisContainer';
66
import { VariantAnalysisHeader } from '../../view/variant-analysis/VariantAnalysisHeader';
7-
import { VariantAnalysisStatus } from '../../remote-queries/shared/variant-analysis';
7+
import {
8+
VariantAnalysis,
9+
VariantAnalysisQueryLanguage,
10+
VariantAnalysisRepoStatus,
11+
VariantAnalysisScannedRepository,
12+
VariantAnalysisStatus
13+
} from '../../remote-queries/shared/variant-analysis';
814

915
export default {
1016
title: 'Variant Analysis/Variant Analysis Header',
@@ -60,30 +66,75 @@ const Template: ComponentStory<typeof VariantAnalysisHeader> = (args) => (
6066
<VariantAnalysisHeader {...args} />
6167
);
6268

69+
const buildVariantAnalysis = (data: Partial<VariantAnalysis>) => ({
70+
id: 1,
71+
controllerRepoId: 1,
72+
query: {
73+
name: 'Query name',
74+
filePath: 'example.ql',
75+
language: VariantAnalysisQueryLanguage.Javascript,
76+
},
77+
databases: {},
78+
status: VariantAnalysisStatus.InProgress,
79+
...data,
80+
});
81+
82+
const buildScannedRepo = (id: number, data?: Partial<VariantAnalysisScannedRepository>): VariantAnalysisScannedRepository => ({
83+
repository: {
84+
id: id,
85+
fullName: `octodemo/hello-world-${id}`,
86+
private: false,
87+
},
88+
analysisStatus: VariantAnalysisRepoStatus.Pending,
89+
...data,
90+
});
91+
6392
export const InProgress = Template.bind({});
6493
InProgress.args = {
65-
queryName: 'Query name',
66-
queryFileName: 'example.ql',
67-
variantAnalysisStatus: VariantAnalysisStatus.InProgress,
68-
totalRepositoryCount: 10,
69-
completedRepositoryCount: 2,
70-
resultCount: 99_999,
94+
variantAnalysis: buildVariantAnalysis({
95+
scannedRepos: [
96+
buildScannedRepo(1, {
97+
analysisStatus: VariantAnalysisRepoStatus.Succeeded,
98+
resultCount: 99_999,
99+
}),
100+
buildScannedRepo(2, {
101+
analysisStatus: VariantAnalysisRepoStatus.Failed,
102+
}),
103+
buildScannedRepo(3, {
104+
analysisStatus: VariantAnalysisRepoStatus.Succeeded,
105+
resultCount: 0,
106+
}),
107+
buildScannedRepo(4),
108+
buildScannedRepo(5),
109+
buildScannedRepo(6),
110+
buildScannedRepo(7),
111+
buildScannedRepo(8),
112+
buildScannedRepo(9),
113+
buildScannedRepo(10),
114+
]
115+
}),
71116
};
72117

73118
export const Succeeded = Template.bind({});
74119
Succeeded.args = {
75120
...InProgress.args,
76-
variantAnalysisStatus: VariantAnalysisStatus.Succeeded,
77-
totalRepositoryCount: 1000,
78-
completedRepositoryCount: 1000,
121+
variantAnalysis: buildVariantAnalysis({
122+
status: VariantAnalysisStatus.Succeeded,
123+
scannedRepos: Array.from({ length: 1000 }, (_, i) => buildScannedRepo(i + 1, {
124+
analysisStatus: VariantAnalysisRepoStatus.Succeeded,
125+
resultCount: 100,
126+
}))
127+
}),
79128
duration: 720_000,
80129
completedAt: new Date(1661263446000),
81130
};
82131

83132
export const Failed = Template.bind({});
84133
Failed.args = {
85134
...InProgress.args,
86-
variantAnalysisStatus: VariantAnalysisStatus.Failed,
135+
variantAnalysis: buildVariantAnalysis({
136+
status: VariantAnalysisStatus.Failed,
137+
}),
87138
duration: 10_000,
88139
completedAt: new Date(1661263446000),
89140
};

extensions/ql-vscode/src/stories/variant-analysis/VariantAnalysisStats.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Started.args = {
4646
export const StartedWithWarnings = Template.bind({});
4747
StartedWithWarnings.args = {
4848
...Starting.args,
49-
queryResult: 'warning',
49+
hasWarnings: true,
5050
};
5151

5252
export const Succeeded = Template.bind({});
@@ -64,7 +64,7 @@ SucceededWithWarnings.args = {
6464
...Succeeded.args,
6565
totalRepositoryCount: 10,
6666
completedRepositoryCount: 2,
67-
queryResult: 'warning',
67+
hasWarnings: true,
6868
};
6969

7070
export const Failed = Template.bind({});
@@ -78,5 +78,5 @@ Failed.args = {
7878
export const Stopped = Template.bind({});
7979
Stopped.args = {
8080
...SucceededWithWarnings.args,
81-
queryResult: 'stopped',
81+
variantAnalysisStatus: VariantAnalysisStatus.Canceled,
8282
};

extensions/ql-vscode/src/view/variant-analysis/VariantAnalysis.tsx

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,113 @@
11
import * as React from 'react';
2-
import { VariantAnalysisStatus } from '../../remote-queries/shared/variant-analysis';
2+
3+
import {
4+
VariantAnalysis as VariantAnalysisDomainModel,
5+
VariantAnalysisQueryLanguage,
6+
VariantAnalysisRepoStatus,
7+
VariantAnalysisStatus
8+
} from '../../remote-queries/shared/variant-analysis';
39
import { VariantAnalysisContainer } from './VariantAnalysisContainer';
410
import { VariantAnalysisHeader } from './VariantAnalysisHeader';
511

12+
const variantAnalysis: VariantAnalysisDomainModel = {
13+
id: 1,
14+
controllerRepoId: 1,
15+
query: {
16+
name: 'Example query',
17+
filePath: 'example.ql',
18+
language: VariantAnalysisQueryLanguage.Javascript,
19+
},
20+
databases: {},
21+
status: VariantAnalysisStatus.InProgress,
22+
scannedRepos: [
23+
{
24+
repository: {
25+
id: 1,
26+
fullName: 'octodemo/hello-world-1',
27+
private: false,
28+
},
29+
analysisStatus: VariantAnalysisRepoStatus.Pending,
30+
},
31+
{
32+
repository: {
33+
id: 2,
34+
fullName: 'octodemo/hello-world-2',
35+
private: false,
36+
},
37+
analysisStatus: VariantAnalysisRepoStatus.Pending,
38+
},
39+
{
40+
repository: {
41+
id: 3,
42+
fullName: 'octodemo/hello-world-3',
43+
private: false,
44+
},
45+
analysisStatus: VariantAnalysisRepoStatus.Pending,
46+
},
47+
{
48+
repository: {
49+
id: 4,
50+
fullName: 'octodemo/hello-world-4',
51+
private: false,
52+
},
53+
analysisStatus: VariantAnalysisRepoStatus.Pending,
54+
},
55+
{
56+
repository: {
57+
id: 5,
58+
fullName: 'octodemo/hello-world-5',
59+
private: false,
60+
},
61+
analysisStatus: VariantAnalysisRepoStatus.Pending,
62+
},
63+
{
64+
repository: {
65+
id: 6,
66+
fullName: 'octodemo/hello-world-6',
67+
private: false,
68+
},
69+
analysisStatus: VariantAnalysisRepoStatus.Pending,
70+
},
71+
{
72+
repository: {
73+
id: 7,
74+
fullName: 'octodemo/hello-world-7',
75+
private: false,
76+
},
77+
analysisStatus: VariantAnalysisRepoStatus.Pending,
78+
},
79+
{
80+
repository: {
81+
id: 8,
82+
fullName: 'octodemo/hello-world-8',
83+
private: false,
84+
},
85+
analysisStatus: VariantAnalysisRepoStatus.Pending,
86+
},
87+
{
88+
repository: {
89+
id: 9,
90+
fullName: 'octodemo/hello-world-9',
91+
private: false,
92+
},
93+
analysisStatus: VariantAnalysisRepoStatus.Pending,
94+
},
95+
{
96+
repository: {
97+
id: 10,
98+
fullName: 'octodemo/hello-world-10',
99+
private: false,
100+
},
101+
analysisStatus: VariantAnalysisRepoStatus.Pending,
102+
},
103+
]
104+
};
105+
6106
export function VariantAnalysis(): JSX.Element {
7107
return (
8108
<VariantAnalysisContainer>
9109
<VariantAnalysisHeader
10-
queryName="Example query"
11-
queryFileName="example.ql"
12-
totalRepositoryCount={10}
13-
variantAnalysisStatus={VariantAnalysisStatus.InProgress}
110+
variantAnalysis={variantAnalysis}
14111
onOpenQueryFileClick={() => console.log('Open query')}
15112
onViewQueryTextClick={() => console.log('View query')}
16113
onStopQueryClick={() => console.log('Stop query')}

extensions/ql-vscode/src/view/variant-analysis/VariantAnalysisHeader.tsx

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import * as React from 'react';
2+
import { useMemo } from 'react';
23
import styled from 'styled-components';
3-
import { VariantAnalysisStatus } from '../../remote-queries/shared/variant-analysis';
4+
import {
5+
getSkippedRepoCount, getTotalResultCount,
6+
hasRepoScanCompleted,
7+
VariantAnalysis,
8+
} from '../../remote-queries/shared/variant-analysis';
49
import { QueryDetails } from './QueryDetails';
510
import { VariantAnalysisActions } from './VariantAnalysisActions';
611
import { VariantAnalysisStats } from './VariantAnalysisStats';
712

813
export type VariantAnalysisHeaderProps = {
9-
queryName: string;
10-
queryFileName: string;
11-
variantAnalysisStatus: VariantAnalysisStatus;
14+
variantAnalysis: VariantAnalysis;
1215

13-
totalRepositoryCount: number;
14-
completedRepositoryCount?: number | undefined;
15-
16-
queryResult?: 'warning' | 'stopped';
17-
18-
resultCount?: number | undefined;
1916
duration?: number | undefined;
2017
completedAt?: Date | undefined;
2118

@@ -42,44 +39,51 @@ const Row = styled.div`
4239
`;
4340

4441
export const VariantAnalysisHeader = ({
45-
queryName,
46-
queryFileName,
47-
totalRepositoryCount,
48-
completedRepositoryCount,
49-
queryResult,
50-
resultCount,
42+
variantAnalysis,
5143
duration,
5244
completedAt,
53-
variantAnalysisStatus,
5445
onOpenQueryFileClick,
5546
onViewQueryTextClick,
5647
onStopQueryClick,
5748
onCopyRepositoryListClick,
5849
onExportResultsClick,
5950
onViewLogsClick,
6051
}: VariantAnalysisHeaderProps) => {
52+
const totalScannedRepositoryCount = useMemo(() => {
53+
return variantAnalysis.scannedRepos?.length ?? 0;
54+
}, [variantAnalysis.scannedRepos]);
55+
const completedRepositoryCount = useMemo(() => {
56+
return variantAnalysis.scannedRepos?.filter(repo => hasRepoScanCompleted(repo))?.length ?? 0;
57+
}, [variantAnalysis.scannedRepos]);
58+
const resultCount = useMemo(() => {
59+
return getTotalResultCount(variantAnalysis.scannedRepos);
60+
}, [variantAnalysis.scannedRepos]);
61+
const hasSkippedRepos = useMemo(() => {
62+
return getSkippedRepoCount(variantAnalysis.skippedRepos) > 0;
63+
}, [variantAnalysis.skippedRepos]);
64+
6165
return (
6266
<Container>
6367
<Row>
6468
<QueryDetails
65-
queryName={queryName}
66-
queryFileName={queryFileName}
69+
queryName={variantAnalysis.query.name}
70+
queryFileName={variantAnalysis.query.filePath}
6771
onOpenQueryFileClick={onOpenQueryFileClick}
6872
onViewQueryTextClick={onViewQueryTextClick}
6973
/>
7074
<VariantAnalysisActions
71-
variantAnalysisStatus={variantAnalysisStatus}
75+
variantAnalysisStatus={variantAnalysis.status}
7276
onStopQueryClick={onStopQueryClick}
7377
onCopyRepositoryListClick={onCopyRepositoryListClick}
7478
onExportResultsClick={onExportResultsClick}
7579
/>
7680
</Row>
7781
<VariantAnalysisStats
78-
variantAnalysisStatus={variantAnalysisStatus}
79-
totalRepositoryCount={totalRepositoryCount}
82+
variantAnalysisStatus={variantAnalysis.status}
83+
totalRepositoryCount={totalScannedRepositoryCount}
8084
completedRepositoryCount={completedRepositoryCount}
81-
queryResult={queryResult}
8285
resultCount={resultCount}
86+
hasWarnings={hasSkippedRepos}
8387
duration={duration}
8488
completedAt={completedAt}
8589
onViewLogsClick={onViewLogsClick}

0 commit comments

Comments
 (0)