Skip to content

Commit b95ee89

Browse files
committed
Combine repository row components into a single component
This is a follow-up to clean up the skipped and analyzed repository component duplication. The rows in both tabs are very similar, so this will combine them to use a single component.
1 parent 0a6db47 commit b95ee89

File tree

8 files changed

+107
-183
lines changed

8 files changed

+107
-183
lines changed

extensions/ql-vscode/src/stories/variant-analysis/VariantAnalysisAnalyzedRepoItem.stories.tsx renamed to extensions/ql-vscode/src/stories/variant-analysis/RepoRow.stories.tsx

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@ import React from 'react';
33
import { ComponentMeta, ComponentStory } from '@storybook/react';
44

55
import { VariantAnalysisContainer } from '../../view/variant-analysis/VariantAnalysisContainer';
6-
import { VariantAnalysisAnalyzedRepoItem } from '../../view/variant-analysis/VariantAnalysisAnalyzedRepoItem';
76
import { VariantAnalysisRepoStatus } from '../../remote-queries/shared/variant-analysis';
87
import { AnalysisAlert, AnalysisRawResults } from '../../remote-queries/shared/analysis-result';
98

109
import analysesResults from '../remote-queries/data/analysesResultsMessage.json';
1110
import rawResults from '../remote-queries/data/rawResults.json';
11+
import { RepoRow } from '../../view/variant-analysis/RepoRow';
1212

1313
export default {
14-
title: 'Variant Analysis/Analyzed Repo Item',
15-
component: VariantAnalysisAnalyzedRepoItem,
14+
title: 'Variant Analysis/Repo Row',
15+
component: RepoRow,
1616
decorators: [
1717
(Story) => (
1818
<VariantAnalysisContainer>
1919
<Story />
2020
</VariantAnalysisContainer>
2121
)
2222
],
23-
} as ComponentMeta<typeof VariantAnalysisAnalyzedRepoItem>;
23+
} as ComponentMeta<typeof RepoRow>;
2424

25-
const Template: ComponentStory<typeof VariantAnalysisAnalyzedRepoItem> = (args) => (
26-
<VariantAnalysisAnalyzedRepoItem {...args} />
25+
const Template: ComponentStory<typeof RepoRow> = (args) => (
26+
<RepoRow {...args} />
2727
);
2828

2929
export const Pending = Template.bind({});
@@ -77,3 +77,26 @@ RawResults.args = {
7777
resultCount: 1,
7878
rawResults: rawResults as unknown as AnalysisRawResults,
7979
};
80+
81+
export const SkippedOnlyFullName = Template.bind({});
82+
SkippedOnlyFullName.args = {
83+
repository: {
84+
fullName: 'octodemo/hello-globe',
85+
}
86+
};
87+
88+
export const SkippedPublic = Template.bind({});
89+
SkippedPublic.args = {
90+
repository: {
91+
fullName: 'octodemo/hello-globe',
92+
private: false,
93+
}
94+
};
95+
96+
export const SkippedPrivate = Template.bind({});
97+
SkippedPrivate.args = {
98+
repository: {
99+
fullName: 'octodemo/hello-globe',
100+
private: true,
101+
}
102+
};

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

Lines changed: 0 additions & 45 deletions
This file was deleted.

extensions/ql-vscode/src/view/variant-analysis/VariantAnalysisAnalyzedRepoItem.tsx renamed to extensions/ql-vscode/src/view/variant-analysis/RepoRow.tsx

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as React from 'react';
22
import { useCallback, useState } from 'react';
33
import styled from 'styled-components';
4-
import { VSCodeBadge } from '@vscode/webview-ui-toolkit/react';
4+
import { VSCodeBadge, VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react';
55
import { isCompletedAnalysisRepoStatus, VariantAnalysisRepoStatus } from '../../remote-queries/shared/variant-analysis';
66
import { formatDecimal } from '../../pure/number';
7-
import { Codicon, ErrorIcon, LoadingIcon, SuccessIcon } from '../common';
7+
import { Codicon, ErrorIcon, LoadingIcon, SuccessIcon, WarningIcon } from '../common';
88
import { Repository } from '../../remote-queries/shared/repository';
99
import { AnalysisAlert, AnalysisRawResults } from '../../remote-queries/shared/analysis-result';
1010
import { AnalyzedRepoItemContent } from './AnalyzedRepoItemContent';
@@ -31,20 +31,22 @@ const TitleContainer = styled.button`
3131
}
3232
`;
3333

34-
const Visibility = styled.span`
34+
const VisibilityText = styled.span`
3535
font-size: 0.85em;
3636
color: var(--vscode-descriptionForeground);
3737
`;
3838

39-
export type VariantAnalysisAnalyzedRepoItemProps = {
40-
repository: Repository;
41-
status: VariantAnalysisRepoStatus;
42-
resultCount?: number;
43-
44-
interpretedResults?: AnalysisAlert[];
45-
rawResults?: AnalysisRawResults;
39+
type VisibilityProps = {
40+
isPrivate?: boolean;
4641
}
4742

43+
const Visibility = ({ isPrivate }: VisibilityProps) => {
44+
if (isPrivate === undefined) {
45+
return null;
46+
}
47+
return <VisibilityText>{isPrivate ? 'private' : 'public'}</VisibilityText>;
48+
};
49+
4850
const getErrorLabel = (status: VariantAnalysisRepoStatus.Failed | VariantAnalysisRepoStatus.TimedOut | VariantAnalysisRepoStatus.Canceled): string => {
4951
switch (status) {
5052
case VariantAnalysisRepoStatus.Failed:
@@ -56,35 +58,50 @@ const getErrorLabel = (status: VariantAnalysisRepoStatus.Failed | VariantAnalysi
5658
}
5759
};
5860

59-
export const VariantAnalysisAnalyzedRepoItem = ({
61+
export type RepoRowProps = {
62+
// Only fullName is required
63+
repository: Partial<Repository> & Pick<Repository, 'fullName'>;
64+
status?: VariantAnalysisRepoStatus;
65+
resultCount?: number;
66+
67+
interpretedResults?: AnalysisAlert[];
68+
rawResults?: AnalysisRawResults;
69+
}
70+
71+
export const RepoRow = ({
6072
repository,
6173
status,
6274
resultCount,
6375
interpretedResults,
6476
rawResults,
65-
}: VariantAnalysisAnalyzedRepoItemProps) => {
77+
}: RepoRowProps) => {
6678
const [isExpanded, setExpanded] = useState(false);
6779

6880
const toggleExpanded = useCallback(() => {
6981
setExpanded(oldIsExpanded => !oldIsExpanded);
7082
}, []);
7183

72-
const disabled = !isCompletedAnalysisRepoStatus(status);
84+
const disabled = !status || !isCompletedAnalysisRepoStatus(status);
7385

7486
return (
7587
<div>
7688
<TitleContainer onClick={toggleExpanded} disabled={disabled} aria-expanded={isExpanded}>
77-
{isExpanded ? <ExpandCollapseCodicon name="chevron-down" label="Collapse" /> : <ExpandCollapseCodicon name="chevron-right" label="Expand" />}
89+
<VSCodeCheckbox disabled />
90+
{isExpanded ? <ExpandCollapseCodicon name="chevron-down" label="Collapse" /> :
91+
<ExpandCollapseCodicon name="chevron-right" label="Expand" />}
7892
<VSCodeBadge>{resultCount === undefined ? '-' : formatDecimal(resultCount)}</VSCodeBadge>
7993
<span>{repository.fullName}</span>
80-
<Visibility>{repository.private ? 'private' : 'public'}</Visibility>
94+
<Visibility isPrivate={repository.private} />
8195
<span>
8296
{status === VariantAnalysisRepoStatus.Succeeded && <SuccessIcon />}
83-
{(status === VariantAnalysisRepoStatus.Failed || status === VariantAnalysisRepoStatus.TimedOut || status === VariantAnalysisRepoStatus.Canceled) && <ErrorIcon label={getErrorLabel(status)} />}
97+
{(status === VariantAnalysisRepoStatus.Failed || status === VariantAnalysisRepoStatus.TimedOut || status === VariantAnalysisRepoStatus.Canceled) &&
98+
<ErrorIcon label={getErrorLabel(status)} />}
8499
{status === VariantAnalysisRepoStatus.InProgress && <LoadingIcon label="In progress" />}
100+
{!status && <WarningIcon />}
85101
</span>
86102
</TitleContainer>
87-
{isExpanded && <AnalyzedRepoItemContent status={status} interpretedResults={interpretedResults} rawResults={rawResults} />}
103+
{isExpanded && status &&
104+
<AnalyzedRepoItemContent status={status} interpretedResults={interpretedResults} rawResults={rawResults} />}
88105
</div>
89106
);
90107
};

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import * as React from 'react';
22
import styled from 'styled-components';
33
import { VariantAnalysis, VariantAnalysisScannedRepositoryResult } from '../../remote-queries/shared/variant-analysis';
4-
import { VariantAnalysisAnalyzedRepoItem } from './VariantAnalysisAnalyzedRepoItem';
4+
import { RepoRow } from './RepoRow';
55
import { useMemo } from 'react';
66

77
const Container = styled.div`
88
display: flex;
99
flex-direction: column;
10-
gap: 1em;
10+
gap: 0.5em;
1111
`;
1212

1313
export type VariantAnalysisAnalyzedReposProps = {
@@ -33,7 +33,7 @@ export const VariantAnalysisAnalyzedRepos = ({
3333
const results = repositoryResultsById.get(repository.repository.id);
3434

3535
return (
36-
<VariantAnalysisAnalyzedRepoItem
36+
<RepoRow
3737
key={repository.repository.id}
3838
repository={repository.repository}
3939
status={repository.analysisStatus}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import styled from 'styled-components';
33
import { VariantAnalysisSkippedRepositoryGroup } from '../../remote-queries/shared/variant-analysis';
44
import { Alert } from '../common';
5-
import { VariantAnalysisSkippedRepositoryRow } from './VariantAnalysisSkippedRepositoryRow';
5+
import { RepoRow } from './RepoRow';
66

77
export type VariantAnalysisSkippedRepositoriesTabProps = {
88
alertTitle: string,
@@ -44,7 +44,7 @@ export const VariantAnalysisSkippedRepositoriesTab = ({
4444
<Container>
4545
{getSkipReasonAlert(alertTitle, alertMessage, skippedRepositoryGroup)}
4646
{skippedRepositoryGroup.repositories.map((repo) =>
47-
<VariantAnalysisSkippedRepositoryRow key={`repo/${repo.fullName}`} repository={repo} />
47+
<RepoRow key={`repo/${repo.fullName}`} repository={repo} />
4848
)}
4949
</Container>
5050
);

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

Lines changed: 0 additions & 48 deletions
This file was deleted.

extensions/ql-vscode/src/view/variant-analysis/__tests__/VariantAnalysisAnalyzedRepoItem.spec.tsx renamed to extensions/ql-vscode/src/view/variant-analysis/__tests__/RepoRow.spec.tsx

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import * as React from 'react';
22
import { render as reactRender, screen } from '@testing-library/react';
33
import { VariantAnalysisRepoStatus } from '../../../remote-queries/shared/variant-analysis';
4-
import {
5-
VariantAnalysisAnalyzedRepoItem,
6-
VariantAnalysisAnalyzedRepoItemProps
7-
} from '../VariantAnalysisAnalyzedRepoItem';
84
import userEvent from '@testing-library/user-event';
5+
import { RepoRow, RepoRowProps } from '../RepoRow';
96

10-
describe(VariantAnalysisAnalyzedRepoItem.name, () => {
11-
const render = (props: Partial<VariantAnalysisAnalyzedRepoItemProps> = {}) => {
7+
describe(RepoRow.name, () => {
8+
const render = (props: Partial<RepoRowProps> = {}) => {
129
return reactRender(
13-
<VariantAnalysisAnalyzedRepoItem
10+
<RepoRow
1411
repository={{
1512
id: 1,
1613
fullName: 'octodemo/hello-world-1',
@@ -105,7 +102,17 @@ describe(VariantAnalysisAnalyzedRepoItem.name, () => {
105102
})).toBeEnabled();
106103
});
107104

108-
it('shows the repo as public', () => {
105+
it('shows repository name', async () => {
106+
render({
107+
repository: {
108+
fullName: 'octodemo/hello-world',
109+
}
110+
});
111+
112+
expect(screen.getByText('octodemo/hello-world')).toBeInTheDocument();
113+
});
114+
115+
it('shows visibility when public', () => {
109116
render({
110117
repository: {
111118
id: 1,
@@ -117,7 +124,7 @@ describe(VariantAnalysisAnalyzedRepoItem.name, () => {
117124
expect(screen.getByText('public')).toBeInTheDocument();
118125
});
119126

120-
it('shows the repo as private', () => {
127+
it('shows visibility when private', () => {
121128
render({
122129
repository: {
123130
id: 1,
@@ -129,6 +136,19 @@ describe(VariantAnalysisAnalyzedRepoItem.name, () => {
129136
expect(screen.getByText('private')).toBeInTheDocument();
130137
});
131138

139+
it('does not show visibility when unknown', () => {
140+
render({
141+
repository: {
142+
id: undefined,
143+
fullName: 'octodemo/hello-world-1',
144+
private: undefined,
145+
}
146+
});
147+
148+
expect(screen.queryByText('public')).not.toBeInTheDocument();
149+
expect(screen.queryByText('private')).not.toBeInTheDocument();
150+
});
151+
132152
it('can expand the repo item', async () => {
133153
render({
134154
status: VariantAnalysisRepoStatus.TimedOut,
@@ -143,4 +163,14 @@ describe(VariantAnalysisAnalyzedRepoItem.name, () => {
143163
});
144164
screen.getByText('Error: Timed out');
145165
});
166+
167+
it('does not allow expanding the repo item when status is undefined', async () => {
168+
render({
169+
status: undefined,
170+
});
171+
172+
expect(screen.getByRole('button', {
173+
expanded: false
174+
})).toBeDisabled();
175+
});
146176
});

0 commit comments

Comments
 (0)