Skip to content

Commit c2ca72a

Browse files
authored
Clicking "View query" on Issue categories opens settings.json (#6874)
Fixes #6855
1 parent a099cd0 commit c2ca72a

4 files changed

Lines changed: 129 additions & 154 deletions

File tree

src/commands.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { IComment } from './common/comment';
1313
import { commands } from './common/executeCommands';
1414
import Logger from './common/logger';
1515
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE } from './common/settingKeys';
16+
import { editQuery } from './common/settingsUtils';
1617
import { ITelemetry } from './common/telemetry';
1718
import { asTempStorageURI, fromPRUri, fromReviewUri, Schemes, toPRUri } from './common/uri';
1819
import { formatError } from './common/utils';
@@ -1151,7 +1152,10 @@ ${contents}
11511152
"pr.editQuery" : {}
11521153
*/
11531154
telemetry.sendTelemetryEvent('pr.editQuery');
1154-
return query.editQuery();
1155+
if (query.label === undefined) {
1156+
return;
1157+
}
1158+
return editQuery(PR_SETTINGS_NAMESPACE, query.label);
11551159
}),
11561160
);
11571161

src/common/settingsUtils.ts

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
'use strict';
77
import * as vscode from 'vscode';
8-
import { PR_SETTINGS_NAMESPACE, USE_REVIEW_MODE } from './settingKeys';
8+
import { PR_SETTINGS_NAMESPACE, QUERIES, USE_REVIEW_MODE } from './settingKeys';
99

1010
export function getReviewMode(): { merged: boolean, closed: boolean } {
1111
const desktopDefaults = { merged: false, closed: false };
@@ -30,4 +30,125 @@ export function initBasedOnSettingChange(namespace: string, key: string, isEnabl
3030
}
3131
});
3232
disposables.push(eventDisposable);
33+
}
34+
35+
interface QueryInspect {
36+
key: string;
37+
defaultValue?: { label: string; query: string }[];
38+
globalValue?: { label: string; query: string }[];
39+
workspaceValue?: { label: string; query: string }[];
40+
workspaceFolderValue?: { label: string; query: string }[];
41+
defaultLanguageValue?: { label: string; query: string }[];
42+
globalLanguageValue?: { label: string; query: string }[];
43+
workspaceLanguageValue?: { label: string; query: string }[];
44+
workspaceFolderLanguageValue?: { label: string; query: string }[];
45+
languageIds?: string[]
46+
}
47+
48+
export function editQuery(namespace: string, queryName: string) {
49+
const config = vscode.workspace.getConfiguration(namespace);
50+
const inspect = config.inspect<{ label: string; query: string }[]>(QUERIES);
51+
const queryValue = config.get<{ label: string; query: string }[]>(QUERIES)?.find((query) => query.label === queryName)?.query;
52+
53+
const inputBox = vscode.window.createQuickPick();
54+
inputBox.title = vscode.l10n.t('Edit Query "{0}"', queryName ?? '');
55+
inputBox.value = queryValue ?? '';
56+
inputBox.items = [{ iconPath: new vscode.ThemeIcon('pencil'), label: vscode.l10n.t('Save edits'), alwaysShow: true }, { iconPath: new vscode.ThemeIcon('add'), label: vscode.l10n.t('Add new query'), alwaysShow: true }, { iconPath: new vscode.ThemeIcon('settings'), label: vscode.l10n.t('Edit in settings.json'), alwaysShow: true }];
57+
inputBox.activeItems = [];
58+
inputBox.selectedItems = [];
59+
inputBox.onDidAccept(async () => {
60+
inputBox.busy = true;
61+
if (inputBox.selectedItems[0] === inputBox.items[0]) {
62+
const newQuery = inputBox.value;
63+
if (newQuery !== queryValue) {
64+
let newValue: { label: string; query: string }[];
65+
let target: vscode.ConfigurationTarget;
66+
if (inspect?.workspaceFolderValue) {
67+
target = vscode.ConfigurationTarget.WorkspaceFolder;
68+
newValue = inspect.workspaceFolderValue;
69+
} else if (inspect?.workspaceValue) {
70+
target = vscode.ConfigurationTarget.Workspace;
71+
newValue = inspect.workspaceValue;
72+
} else {
73+
target = vscode.ConfigurationTarget.Global;
74+
newValue = config.get<{ label: string; query: string }[]>(QUERIES) ?? [];
75+
}
76+
newValue.find((query) => query.label === queryName)!.query = newQuery;
77+
await config.update(QUERIES, newValue, target);
78+
}
79+
} else if (inputBox.selectedItems[0] === inputBox.items[1]) {
80+
addNewQuery(config, inspect, inputBox.value);
81+
} else if (inputBox.selectedItems[0] === inputBox.items[2]) {
82+
openSettingsAtQuery(config, inspect, queryName);
83+
}
84+
inputBox.dispose();
85+
});
86+
inputBox.onDidHide(() => inputBox.dispose());
87+
inputBox.show();
88+
}
89+
90+
function addNewQuery(config: vscode.WorkspaceConfiguration, inspect: QueryInspect | undefined, startingValue: string) {
91+
const inputBox = vscode.window.createInputBox();
92+
inputBox.title = vscode.l10n.t('Enter the title of the new query');
93+
inputBox.placeholder = vscode.l10n.t('Title');
94+
inputBox.step = 1;
95+
inputBox.totalSteps = 2;
96+
inputBox.show();
97+
let title: string | undefined;
98+
inputBox.onDidAccept(async () => {
99+
inputBox.validationMessage = '';
100+
if (inputBox.step === 1) {
101+
if (!inputBox.value) {
102+
inputBox.validationMessage = vscode.l10n.t('Title is required');
103+
return;
104+
}
105+
106+
title = inputBox.value;
107+
inputBox.value = startingValue;
108+
inputBox.title = vscode.l10n.t('Enter the GitHub search query');
109+
inputBox.step++;
110+
} else {
111+
if (!inputBox.value) {
112+
inputBox.validationMessage = vscode.l10n.t('Query is required');
113+
return;
114+
}
115+
inputBox.busy = true;
116+
if (inputBox.value && title) {
117+
if (inspect?.workspaceValue) {
118+
inspect.workspaceValue.push({ label: title, query: inputBox.value });
119+
await config.update(QUERIES, inspect.workspaceValue, vscode.ConfigurationTarget.Workspace);
120+
} else {
121+
const value = config.get<{ label: string; query: string }[]>(QUERIES);
122+
value?.push({ label: title, query: inputBox.value });
123+
await config.update(QUERIES, value, vscode.ConfigurationTarget.Global);
124+
}
125+
}
126+
inputBox.dispose();
127+
}
128+
});
129+
inputBox.onDidHide(() => inputBox.dispose());
130+
}
131+
132+
async function openSettingsAtQuery(config: vscode.WorkspaceConfiguration, inspect: QueryInspect | undefined, queryName: string) {
133+
let command: string;
134+
if (inspect?.workspaceValue) {
135+
command = 'workbench.action.openWorkspaceSettingsFile';
136+
} else {
137+
const value = config.get<{ label: string; query: string }[]>(QUERIES);
138+
if (inspect?.defaultValue && JSON.stringify(inspect?.defaultValue) === JSON.stringify(value)) {
139+
await config.update(QUERIES, inspect.defaultValue, vscode.ConfigurationTarget.Global);
140+
}
141+
command = 'workbench.action.openSettingsJson';
142+
}
143+
await vscode.commands.executeCommand(command);
144+
const editor = vscode.window.activeTextEditor;
145+
if (editor) {
146+
const text = editor.document.getText();
147+
const search = text.search(queryName);
148+
if (search >= 0) {
149+
const position = editor.document.positionAt(search);
150+
editor.revealRange(new vscode.Range(position, position));
151+
editor.selection = new vscode.Selection(position, position);
152+
}
153+
}
33154
}

src/issues/issueFeatureRegistrar.ts

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import {
1616
ENABLED,
1717
ISSUE_COMPLETIONS,
1818
ISSUES_SETTINGS_NAMESPACE,
19-
QUERIES,
2019
USER_COMPLETIONS,
2120
} from '../common/settingKeys';
21+
import { editQuery } from '../common/settingsUtils';
2222
import { ITelemetry } from '../common/telemetry';
2323
import { fromRepoUri, RepoUriParams, Schemes, toNewIssueUri } from '../common/uri';
2424
import { EXTENSION_ID } from '../constants';
@@ -434,7 +434,7 @@ export class IssueFeatureRegistrar extends Disposable {
434434
"issue.editQuery" : {}
435435
*/
436436
this.telemetry.sendTelemetryEvent('issue.editQuery');
437-
return this.editQuery(query);
437+
return editQuery(ISSUES_SETTINGS_NAMESPACE, query.queryLabel);
438438
},
439439
this,
440440
),
@@ -736,32 +736,6 @@ export class IssueFeatureRegistrar extends Disposable {
736736
}
737737
}
738738

739-
async editQuery(query: QueryNode) {
740-
const config = vscode.workspace.getConfiguration(ISSUES_SETTINGS_NAMESPACE, null);
741-
const inspect = config.inspect<{ label: string; query: string }[]>(QUERIES);
742-
let command: string;
743-
if (inspect?.workspaceValue) {
744-
command = 'workbench.action.openWorkspaceSettingsFile';
745-
} else {
746-
const value = config.get<{ label: string; query: string }[]>(QUERIES);
747-
if (inspect?.defaultValue && JSON.stringify(inspect?.defaultValue) === JSON.stringify(value)) {
748-
config.update(QUERIES, inspect.defaultValue, vscode.ConfigurationTarget.Global);
749-
}
750-
command = 'workbench.action.openSettingsJson';
751-
}
752-
await vscode.commands.executeCommand(command);
753-
const editor = vscode.window.activeTextEditor;
754-
if (editor) {
755-
const text = editor.document.getText();
756-
const search = text.search(query.queryLabel);
757-
if (search >= 0) {
758-
const position = editor.document.positionAt(search);
759-
editor.revealRange(new vscode.Range(position, position));
760-
editor.selection = new vscode.Selection(position, position);
761-
}
762-
}
763-
}
764-
765739
getCurrent() {
766740
// This is used by the "api" command issues.getCurrent
767741
const currentIssues = this._stateManager.currentIssues();

src/view/treeNodes/categoryNode.ts

Lines changed: 0 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import * as vscode from 'vscode';
77
import { AuthenticationError } from '../../common/authentication';
8-
import { PR_SETTINGS_NAMESPACE, QUERIES } from '../../common/settingKeys';
98
import { ITelemetry } from '../../common/telemetry';
109
import { formatError } from '../../common/utils';
1110
import { FolderRepositoryManager, ItemsResponseResult } from '../../github/folderRepositoryManager';
@@ -27,19 +26,6 @@ export enum PRCategoryActionType {
2726
ConfigureRemotes,
2827
}
2928

30-
interface QueryInspect {
31-
key: string;
32-
defaultValue?: { label: string; query: string }[];
33-
globalValue?: { label: string; query: string }[];
34-
workspaceValue?: { label: string; query: string }[];
35-
workspaceFolderValue?: { label: string; query: string }[];
36-
defaultLanguageValue?: { label: string; query: string }[];
37-
globalLanguageValue?: { label: string; query: string }[];
38-
workspaceLanguageValue?: { label: string; query: string }[];
39-
workspaceFolderLanguageValue?: { label: string; query: string }[];
40-
languageIds?: string[]
41-
}
42-
4329
export class PRCategoryActionNode extends TreeNode implements vscode.TreeItem {
4430
public collapsibleState: vscode.TreeItemCollapsibleState;
4531
public iconPath?: { light: string | vscode.Uri; dark: string | vscode.Uri };
@@ -167,81 +153,6 @@ export class CategoryTreeNode extends TreeNode implements vscode.TreeItem {
167153
}
168154
}
169155

170-
private async addNewQuery(config: vscode.WorkspaceConfiguration, inspect: QueryInspect | undefined, startingValue: string) {
171-
const inputBox = vscode.window.createInputBox();
172-
inputBox.title = vscode.l10n.t('Enter the title of the new query');
173-
inputBox.placeholder = vscode.l10n.t('Title');
174-
inputBox.step = 1;
175-
inputBox.totalSteps = 2;
176-
inputBox.show();
177-
let title: string | undefined;
178-
inputBox.onDidAccept(async () => {
179-
inputBox.validationMessage = '';
180-
if (inputBox.step === 1) {
181-
if (!inputBox.value) {
182-
inputBox.validationMessage = vscode.l10n.t('Title is required');
183-
return;
184-
}
185-
186-
title = inputBox.value;
187-
inputBox.value = startingValue;
188-
inputBox.title = vscode.l10n.t('Enter the GitHub search query');
189-
inputBox.step++;
190-
} else {
191-
if (!inputBox.value) {
192-
inputBox.validationMessage = vscode.l10n.t('Query is required');
193-
return;
194-
}
195-
inputBox.busy = true;
196-
if (inputBox.value && title) {
197-
if (inspect?.workspaceValue) {
198-
inspect.workspaceValue.push({ label: title, query: inputBox.value });
199-
await config.update(QUERIES, inspect.workspaceValue, vscode.ConfigurationTarget.Workspace);
200-
} else {
201-
const value = config.get<{ label: string; query: string }[]>(QUERIES);
202-
value?.push({ label: title, query: inputBox.value });
203-
await config.update(QUERIES, value, vscode.ConfigurationTarget.Global);
204-
}
205-
}
206-
inputBox.dispose();
207-
}
208-
});
209-
inputBox.onDidHide(() => inputBox.dispose());
210-
}
211-
212-
private updateQuery(queries: { label: string; query: string }[], queryToUpdate: { label: string; query: string }) {
213-
for (const query of queries) {
214-
if (query.label === queryToUpdate.label) {
215-
query.query = queryToUpdate.query;
216-
return;
217-
}
218-
}
219-
}
220-
221-
private async openSettings(config: vscode.WorkspaceConfiguration, inspect: QueryInspect | undefined) {
222-
let command: string;
223-
if (inspect?.workspaceValue) {
224-
command = 'workbench.action.openWorkspaceSettingsFile';
225-
} else {
226-
const value = config.get<{ label: string; query: string }[]>(QUERIES);
227-
if (inspect?.defaultValue && JSON.stringify(inspect?.defaultValue) === JSON.stringify(value)) {
228-
await config.update(QUERIES, inspect.defaultValue, vscode.ConfigurationTarget.Global);
229-
}
230-
command = 'workbench.action.openSettingsJson';
231-
}
232-
await vscode.commands.executeCommand(command);
233-
const editor = vscode.window.activeTextEditor;
234-
if (editor) {
235-
const text = editor.document.getText();
236-
const search = text.search(this.label!);
237-
if (search >= 0) {
238-
const position = editor.document.positionAt(search);
239-
editor.revealRange(new vscode.Range(position, position));
240-
editor.selection = new vscode.Selection(position, position);
241-
}
242-
}
243-
}
244-
245156
public async expandPullRequest(pullRequest: PullRequestModel, retry: boolean = true): Promise<boolean> {
246157
if (!this.children && retry) {
247158
await this.getChildren();
@@ -265,41 +176,6 @@ export class CategoryTreeNode extends TreeNode implements vscode.TreeItem {
265176
return false;
266177
}
267178

268-
async editQuery() {
269-
const config = vscode.workspace.getConfiguration(PR_SETTINGS_NAMESPACE);
270-
const inspect = config.inspect<{ label: string; query: string }[]>(QUERIES);
271-
272-
const inputBox = vscode.window.createQuickPick();
273-
inputBox.title = vscode.l10n.t('Edit Pull Request Query "{0}"', this.label ?? '');
274-
inputBox.value = this._categoryQuery ?? '';
275-
inputBox.items = [{ iconPath: new vscode.ThemeIcon('pencil'), label: vscode.l10n.t('Save edits'), alwaysShow: true }, { iconPath: new vscode.ThemeIcon('add'), label: vscode.l10n.t('Add new query'), alwaysShow: true }, { iconPath: new vscode.ThemeIcon('settings'), label: vscode.l10n.t('Edit in settings.json'), alwaysShow: true }];
276-
inputBox.activeItems = [];
277-
inputBox.selectedItems = [];
278-
inputBox.onDidAccept(async () => {
279-
inputBox.busy = true;
280-
if (inputBox.selectedItems[0] === inputBox.items[0]) {
281-
const newQuery = inputBox.value;
282-
if (newQuery !== this._categoryQuery && this.label) {
283-
if (inspect?.workspaceValue) {
284-
this.updateQuery(inspect.workspaceValue, { label: this.label, query: newQuery });
285-
await config.update(QUERIES, inspect.workspaceValue, vscode.ConfigurationTarget.Workspace);
286-
} else {
287-
const value = config.get<{ label: string; query: string }[]>(QUERIES) ?? inspect!.defaultValue!;
288-
this.updateQuery(value, { label: this.label, query: newQuery });
289-
await config.update(QUERIES, value, vscode.ConfigurationTarget.Global);
290-
}
291-
}
292-
} else if (inputBox.selectedItems[0] === inputBox.items[1]) {
293-
this.addNewQuery(config, inspect, inputBox.value);
294-
} else if (inputBox.selectedItems[0] === inputBox.items[2]) {
295-
this.openSettings(config, inspect);
296-
}
297-
inputBox.dispose();
298-
});
299-
inputBox.onDidHide(() => inputBox.dispose());
300-
inputBox.show();
301-
}
302-
303179
override async getChildren(): Promise<TreeNode[]> {
304180
await super.getChildren();
305181
const isFirstLoad = !this._firstLoad;

0 commit comments

Comments
 (0)