Merge pull request #1765 from github/koesie10/selected-copy
Use selected repositories for copying repo lists
This commit is contained in:
@@ -123,7 +123,7 @@ import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
|
||||
import { VariantAnalysisResultsManager } from './remote-queries/variant-analysis-results-manager';
|
||||
import { initializeDbModule } from './databases/db-module';
|
||||
import { ExtensionApp } from './common/vscode/vscode-app';
|
||||
import { RepositoriesFilterSortState } from './pure/variant-analysis-filter-sort';
|
||||
import { RepositoriesFilterSortStateWithIds } from './pure/variant-analysis-filter-sort';
|
||||
|
||||
/**
|
||||
* extension.ts
|
||||
@@ -963,7 +963,7 @@ async function activateWithInstalledDistribution(
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortState) => {
|
||||
commandRunner('codeQL.copyVariantAnalysisRepoList', async (variantAnalysisId: number, filterSort?: RepositoriesFilterSortStateWithIds) => {
|
||||
await variantAnalysisManager.copyRepoListToClipboard(variantAnalysisId, filterSort);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
VariantAnalysisScannedRepositoryResult,
|
||||
VariantAnalysisScannedRepositoryState,
|
||||
} from '../remote-queries/shared/variant-analysis';
|
||||
import { RepositoriesFilterSortState } from './variant-analysis-filter-sort';
|
||||
import { RepositoriesFilterSortStateWithIds } from './variant-analysis-filter-sort';
|
||||
|
||||
/**
|
||||
* This module contains types and code that are shared between
|
||||
@@ -475,7 +475,7 @@ export interface OpenQueryTextMessage {
|
||||
|
||||
export interface CopyRepositoryListMessage {
|
||||
t: 'copyRepositoryList';
|
||||
filterSort?: RepositoriesFilterSortState;
|
||||
filterSort?: RepositoriesFilterSortStateWithIds;
|
||||
}
|
||||
|
||||
export interface ExportResultsMessage {
|
||||
|
||||
@@ -13,6 +13,10 @@ export type RepositoriesFilterSortState = {
|
||||
sortKey: SortKey;
|
||||
}
|
||||
|
||||
export type RepositoriesFilterSortStateWithIds = RepositoriesFilterSortState & {
|
||||
repositoryIds?: number[];
|
||||
}
|
||||
|
||||
export const defaultFilterSortState: RepositoriesFilterSortState = {
|
||||
searchValue: '',
|
||||
sortKey: SortKey.Name,
|
||||
@@ -52,7 +56,7 @@ export function compareRepository(filterSortState: RepositoriesFilterSortState |
|
||||
}
|
||||
|
||||
type SortableResult = {
|
||||
repository: SortableRepository;
|
||||
repository: SortableRepository & Pick<Repository, 'id'>;
|
||||
resultCount?: number;
|
||||
}
|
||||
|
||||
@@ -72,11 +76,7 @@ export function compareWithResults(filterSortState: RepositoriesFilterSortState
|
||||
};
|
||||
}
|
||||
|
||||
// These define the behavior for undefined input values
|
||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[], filterSortState: RepositoriesFilterSortState | undefined): T[];
|
||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined;
|
||||
|
||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined {
|
||||
export function filterAndSortRepositoriesWithResultsByName<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortState | undefined): T[] | undefined {
|
||||
if (!repositories) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -85,3 +85,17 @@ export function filterAndSortRepositoriesWithResults<T extends SortableResult>(r
|
||||
.filter(repo => matchesFilter(repo.repository, filterSortState))
|
||||
.sort(compareWithResults(filterSortState));
|
||||
}
|
||||
|
||||
export function filterAndSortRepositoriesWithResults<T extends SortableResult>(repositories: T[] | undefined, filterSortState: RepositoriesFilterSortStateWithIds | undefined): T[] | undefined {
|
||||
if (!repositories) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (filterSortState?.repositoryIds && filterSortState.repositoryIds.length > 0) {
|
||||
return repositories
|
||||
.filter(repo => filterSortState.repositoryIds?.includes(repo.repository.id))
|
||||
.sort(compareWithResults(filterSortState));
|
||||
}
|
||||
|
||||
return filterAndSortRepositoriesWithResultsByName(repositories, filterSortState);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import { CodeQLCliServer } from '../cli';
|
||||
import {
|
||||
defaultFilterSortState,
|
||||
filterAndSortRepositoriesWithResults,
|
||||
RepositoriesFilterSortState,
|
||||
RepositoriesFilterSortStateWithIds,
|
||||
} from '../pure/variant-analysis-filter-sort';
|
||||
|
||||
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
|
||||
@@ -371,7 +371,7 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
await cancelVariantAnalysis(credentials, variantAnalysis);
|
||||
}
|
||||
|
||||
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortState = defaultFilterSortState) {
|
||||
public async copyRepoListToClipboard(variantAnalysisId: number, filterSort: RepositoriesFilterSortStateWithIds = defaultFilterSortState) {
|
||||
const variantAnalysis = this.variantAnalyses.get(variantAnalysisId);
|
||||
if (!variantAnalysis) {
|
||||
throw new Error(`No variant analysis with id: ${variantAnalysisId}`);
|
||||
|
||||
@@ -97,9 +97,12 @@ export function VariantAnalysis({
|
||||
const copyRepositoryList = useCallback(() => {
|
||||
vscode.postMessage({
|
||||
t: 'copyRepositoryList',
|
||||
filterSort: filterSortState,
|
||||
filterSort: {
|
||||
...filterSortState,
|
||||
repositoryIds: selectedRepositoryIds,
|
||||
},
|
||||
});
|
||||
}, [filterSortState]);
|
||||
}, [filterSortState, selectedRepositoryIds]);
|
||||
|
||||
if (variantAnalysis?.actionsWorkflowRunId === undefined) {
|
||||
return <VariantAnalysisLoading />;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
VariantAnalysisScannedRepositoryState
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
filterAndSortRepositoriesWithResults,
|
||||
filterAndSortRepositoriesWithResultsByName,
|
||||
RepositoriesFilterSortState,
|
||||
} from '../../pure/variant-analysis-filter-sort';
|
||||
|
||||
@@ -55,7 +55,7 @@ export const VariantAnalysisAnalyzedRepos = ({
|
||||
}, [repositoryResults]);
|
||||
|
||||
const repositories = useMemo(() => {
|
||||
return filterAndSortRepositoriesWithResults(variantAnalysis.scannedRepos, filterSortState);
|
||||
return filterAndSortRepositoriesWithResultsByName(variantAnalysis.scannedRepos, filterSortState);
|
||||
}, [filterSortState, variantAnalysis.scannedRepos]);
|
||||
|
||||
const onSelectedChange = useCallback((repositoryId: number, selected: boolean) => {
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { compareRepository, compareWithResults, defaultFilterSortState, matchesFilter, SortKey } from '../../../pure/variant-analysis-filter-sort';
|
||||
import {
|
||||
compareRepository,
|
||||
compareWithResults,
|
||||
defaultFilterSortState,
|
||||
filterAndSortRepositoriesWithResults,
|
||||
filterAndSortRepositoriesWithResultsByName,
|
||||
matchesFilter,
|
||||
SortKey,
|
||||
} from '../../../pure/variant-analysis-filter-sort';
|
||||
|
||||
// TODO: Move this file to the "pure" tests once it has been switched to Jest
|
||||
describe(matchesFilter.name, () => {
|
||||
@@ -170,11 +178,13 @@ describe(compareWithResults.name, () => {
|
||||
|
||||
const left = {
|
||||
repository: {
|
||||
id: 10,
|
||||
fullName: 'github/galaxy',
|
||||
},
|
||||
};
|
||||
const right = {
|
||||
repository: {
|
||||
id: 12,
|
||||
fullName: 'github/world',
|
||||
},
|
||||
};
|
||||
@@ -192,12 +202,14 @@ describe(compareWithResults.name, () => {
|
||||
|
||||
const left = {
|
||||
repository: {
|
||||
id: 11,
|
||||
fullName: 'github/galaxy',
|
||||
stargazersCount: 1,
|
||||
},
|
||||
};
|
||||
const right = {
|
||||
repository: {
|
||||
id: 12,
|
||||
fullName: 'github/world',
|
||||
stargazersCount: 10,
|
||||
},
|
||||
@@ -216,12 +228,14 @@ describe(compareWithResults.name, () => {
|
||||
|
||||
const left = {
|
||||
repository: {
|
||||
id: 11,
|
||||
fullName: 'github/galaxy',
|
||||
updatedAt: '2020-01-01T00:00:00Z',
|
||||
},
|
||||
};
|
||||
const right = {
|
||||
repository: {
|
||||
id: 12,
|
||||
fullName: 'github/world',
|
||||
updatedAt: '2021-01-01T00:00:00Z',
|
||||
},
|
||||
@@ -240,12 +254,14 @@ describe(compareWithResults.name, () => {
|
||||
|
||||
const left = {
|
||||
repository: {
|
||||
id: 11,
|
||||
fullName: 'github/galaxy',
|
||||
},
|
||||
resultCount: 10,
|
||||
};
|
||||
const right = {
|
||||
repository: {
|
||||
id: 12,
|
||||
fullName: 'github/world',
|
||||
},
|
||||
resultCount: 100,
|
||||
@@ -278,3 +294,136 @@ describe(compareWithResults.name, () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(filterAndSortRepositoriesWithResultsByName.name, () => {
|
||||
const repositories = [
|
||||
{
|
||||
repository: {
|
||||
id: 10,
|
||||
fullName: 'github/galaxy',
|
||||
},
|
||||
resultCount: 10,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 11,
|
||||
fullName: 'github/world',
|
||||
},
|
||||
resultCount: undefined,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 13,
|
||||
fullName: 'github/planet',
|
||||
},
|
||||
resultCount: 500,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 783532,
|
||||
fullName: 'github/stars',
|
||||
},
|
||||
resultCount: 8000,
|
||||
}
|
||||
];
|
||||
|
||||
describe('when sort key is given without filter', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResultsByName(repositories, {
|
||||
...defaultFilterSortState,
|
||||
sortKey: SortKey.ResultsCount,
|
||||
})).toEqual([repositories[3], repositories[2], repositories[0], repositories[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sort key and search filter are given', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResultsByName(repositories, {
|
||||
...defaultFilterSortState,
|
||||
sortKey: SortKey.ResultsCount,
|
||||
searchValue: 'la',
|
||||
})).toEqual([repositories[2], repositories[0]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(filterAndSortRepositoriesWithResults.name, () => {
|
||||
const repositories = [
|
||||
{
|
||||
repository: {
|
||||
id: 10,
|
||||
fullName: 'github/galaxy',
|
||||
},
|
||||
resultCount: 10,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 11,
|
||||
fullName: 'github/world',
|
||||
},
|
||||
resultCount: undefined,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 13,
|
||||
fullName: 'github/planet',
|
||||
},
|
||||
resultCount: 500,
|
||||
},
|
||||
{
|
||||
repository: {
|
||||
id: 783532,
|
||||
fullName: 'github/stars',
|
||||
},
|
||||
resultCount: 8000,
|
||||
}
|
||||
];
|
||||
|
||||
describe('when sort key is given without filter', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||
...defaultFilterSortState,
|
||||
sortKey: SortKey.ResultsCount,
|
||||
})).toEqual([repositories[3], repositories[2], repositories[0], repositories[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sort key and search filter are given', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||
...defaultFilterSortState,
|
||||
sortKey: SortKey.ResultsCount,
|
||||
searchValue: 'la',
|
||||
})).toEqual([repositories[2], repositories[0]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sort key, search filter, and repository ids are given', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||
...defaultFilterSortState,
|
||||
sortKey: SortKey.ResultsCount,
|
||||
searchValue: 'la',
|
||||
repositoryIds: [repositories[1].repository.id, repositories[3].repository.id],
|
||||
})).toEqual([repositories[3], repositories[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when repository ids are given', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||
...defaultFilterSortState,
|
||||
repositoryIds: [repositories[0].repository.id, repositories[3].repository.id],
|
||||
})).toEqual([repositories[0], repositories[3]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when empty repository ids are given', () => {
|
||||
it('returns the correct results', () => {
|
||||
expect(filterAndSortRepositoriesWithResults(repositories, {
|
||||
...defaultFilterSortState,
|
||||
repositoryIds: [],
|
||||
})).toEqual([repositories[0], repositories[2], repositories[3], repositories[1]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user