You've already forked wizgit-vscode-extension
feat: Add export functionality for issues and pull requests
- Implemented exportIssues and exportPullRequests functions to export data in markdown, CSV, and JSON formats. - Created helper functions for generating markdown and CSV formats for issues and pull requests. - Added showExportDialog for user interaction to select export options. - Implemented saveToFile function to handle file saving. feat: Implement favorites and recent repositories management - Added functionality to add, remove, and check favorites for repositories. - Implemented recent repositories tracking with a limit on the number of recent entries. - Created a quick pick interface to show favorites and recent repositories. feat: Introduce notifications management - Implemented functions to fetch, mark as read, and manage notifications. - Created a NotificationProvider class to display notifications in a tree view. - Added functionality to show notifications in a modal with quick actions. feat: Implement search functionality for repositories, issues, and pull requests - Added searchRepositories, searchIssues, and searchPullRequests functions with filtering options. - Implemented getLabels and getCollaborators functions for additional filtering capabilities. - Created a showFilterQuickPick function for user interaction to select filters. feat: Enhance status bar with shortcuts and dynamic updates - Added default keyboard shortcuts for various commands. - Implemented createStatusBarItem and updateStatusBar functions to manage status bar display. - Created a showStatusMenu function for quick actions related to the extension.
This commit is contained in:
265
src/features/search.ts
Normal file
265
src/features/search.ts
Normal file
@@ -0,0 +1,265 @@
|
||||
import * as vscode from 'vscode';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export interface SearchOptions {
|
||||
query: string;
|
||||
state?: 'open' | 'closed';
|
||||
labels?: string[];
|
||||
assignee?: string;
|
||||
sort?: 'created' | 'updated' | 'popularity';
|
||||
order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export interface FilterOptions {
|
||||
state?: 'open' | 'closed';
|
||||
labels?: string[];
|
||||
assignee?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search repositories across WizGIT
|
||||
*/
|
||||
export async function searchRepositories(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
query: string,
|
||||
page: number = 1,
|
||||
limit: number = 30
|
||||
): Promise<any> {
|
||||
try {
|
||||
const url = new URL(`${apiEndpoint}/repos/search`);
|
||||
url.searchParams.append('q', query);
|
||||
url.searchParams.append('page', page.toString());
|
||||
url.searchParams.append('limit', limit.toString());
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Search failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Repository search error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search issues in a repository with filters
|
||||
*/
|
||||
export async function searchIssues(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
options: SearchOptions & { page?: number; limit?: number }
|
||||
): Promise<any> {
|
||||
try {
|
||||
const url = new URL(`${apiEndpoint}/repos/${owner}/${repo}/issues`);
|
||||
|
||||
url.searchParams.append('page', (options.page || 1).toString());
|
||||
url.searchParams.append('limit', (options.limit || 30).toString());
|
||||
|
||||
if (options.query) {
|
||||
url.searchParams.append('q', options.query);
|
||||
}
|
||||
if (options.state) {
|
||||
url.searchParams.append('state', options.state);
|
||||
}
|
||||
if (options.sort) {
|
||||
url.searchParams.append('sort', options.sort);
|
||||
}
|
||||
if (options.order) {
|
||||
url.searchParams.append('order', options.order);
|
||||
}
|
||||
if (options.labels && options.labels.length > 0) {
|
||||
url.searchParams.append('labels', options.labels.join(','));
|
||||
}
|
||||
if (options.assignee) {
|
||||
url.searchParams.append('assignee', options.assignee);
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Search failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Issue search error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search pull requests with filters
|
||||
*/
|
||||
export async function searchPullRequests(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
options: SearchOptions & { page?: number; limit?: number }
|
||||
): Promise<any> {
|
||||
try {
|
||||
const url = new URL(`${apiEndpoint}/repos/${owner}/${repo}/pulls`);
|
||||
|
||||
url.searchParams.append('page', (options.page || 1).toString());
|
||||
url.searchParams.append('limit', (options.limit || 30).toString());
|
||||
|
||||
if (options.query) {
|
||||
url.searchParams.append('q', options.query);
|
||||
}
|
||||
if (options.state) {
|
||||
url.searchParams.append('state', options.state);
|
||||
}
|
||||
if (options.sort) {
|
||||
url.searchParams.append('sort', options.sort);
|
||||
}
|
||||
if (options.order) {
|
||||
url.searchParams.append('order', options.order);
|
||||
}
|
||||
if (options.assignee) {
|
||||
url.searchParams.append('assignee', options.assignee);
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Search failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('PR search error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available labels for filtering
|
||||
*/
|
||||
export async function getLabels(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
owner: string,
|
||||
repo: string
|
||||
): Promise<any[]> {
|
||||
try {
|
||||
const response = await fetch(`${apiEndpoint}/repos/${owner}/${repo}/labels`, {
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch labels: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return (await response.json()) as any[];
|
||||
} catch (error) {
|
||||
console.error('Get labels error:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get collaborators for assignee filtering
|
||||
*/
|
||||
export async function getCollaborators(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
owner: string,
|
||||
repo: string
|
||||
): Promise<any[]> {
|
||||
try {
|
||||
const response = await fetch(`${apiEndpoint}/repos/${owner}/${repo}/collaborators`, {
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch collaborators: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return (await response.json()) as any[];
|
||||
} catch (error) {
|
||||
console.error('Get collaborators error:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a quick filter picker for issues/PRs
|
||||
*/
|
||||
export async function showFilterQuickPick(
|
||||
apiEndpoint: string,
|
||||
token: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
type: 'issues' | 'pulls'
|
||||
): Promise<FilterOptions | null> {
|
||||
const filterOptions: FilterOptions = {};
|
||||
|
||||
// State filter
|
||||
const stateSelection = await vscode.window.showQuickPick(
|
||||
['All', 'Open', 'Closed'],
|
||||
{ placeHolder: 'Filter by state (optional)' }
|
||||
);
|
||||
|
||||
if (stateSelection && stateSelection !== 'All') {
|
||||
filterOptions.state = stateSelection === 'Open' ? 'open' : 'closed';
|
||||
}
|
||||
|
||||
// Assignee filter
|
||||
const collaborators = await getCollaborators(apiEndpoint, token, owner, repo);
|
||||
if (collaborators.length > 0) {
|
||||
const assigneeItems = ['No filter', ...collaborators.map(c => c.login)];
|
||||
const assigneeSelection = await vscode.window.showQuickPick(
|
||||
assigneeItems,
|
||||
{ placeHolder: 'Filter by assignee (optional)' }
|
||||
);
|
||||
|
||||
if (assigneeSelection && assigneeSelection !== 'No filter') {
|
||||
filterOptions.assignee = assigneeSelection;
|
||||
}
|
||||
}
|
||||
|
||||
// Labels filter (only for issues)
|
||||
if (type === 'issues') {
|
||||
const labels = await getLabels(apiEndpoint, token, owner, repo);
|
||||
if (labels.length > 0) {
|
||||
const labelItems = labels.map(l => l.name);
|
||||
const labelSelection = await vscode.window.showQuickPick(
|
||||
labelItems,
|
||||
{ placeHolder: 'Filter by label (optional)', canPickMany: true }
|
||||
);
|
||||
|
||||
if (labelSelection && labelSelection.length > 0) {
|
||||
filterOptions.labels = labelSelection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(filterOptions).length > 0 ? filterOptions : null;
|
||||
}
|
||||
Reference in New Issue
Block a user