Add double click action support for query history (#20204)

* Add double click action support for query history

* localize descriptions
This commit is contained in:
Charles Gagnon
2022-07-29 13:14:26 -07:00
committed by GitHub
parent 395bc3f149
commit 866fa76a65
5 changed files with 97 additions and 19 deletions

View File

@@ -39,6 +39,19 @@
"type": "boolean",
"default": true,
"description": "%queryHistory.captureEnabledDesc%"
},
"queryHistory.doubleClickAction": {
"type": "string",
"description": "%queryHistory.doubleClickAction%",
"default": "open",
"enum": [
"open",
"run"
],
"enumDescriptions": [
"%queryHistory.doubleClickAction.open%",
"%queryHistory.doubleClickAction.run%"
]
}
}
}

View File

@@ -2,6 +2,9 @@
"queryHistory.displayName": "Query History",
"queryHistory.description": "View and run previously executed queries",
"queryHistory.captureEnabledDesc": "Whether Query History capture is enabled. If false queries executed will not be captured.",
"queryHistory.doubleClickAction": "The action taken when a history item is double clicked",
"queryHistory.doubleClickAction.open": "Open a new disconnected editor with the query from the selected history item",
"queryHistory.doubleClickAction.run": "Open a new connected editor with the query and connection from the selected history item and automatically run the query",
"queryHistory.open": "Open Query",
"queryHistory.run": "Run Query",
"queryHistory.delete": "Delete",

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const QUERY_HISTORY_CONFIG_SECTION = 'queryHistory';
export const CAPTURE_ENABLED_CONFIG_SECTION = 'captureEnabled';
export const DOUBLE_CLICK_ACTION_CONFIG_SECTION = 'doubleClickAction';
export const ITEM_SELECTED_COMMAND_ID = 'queryHistory.itemSelected';

View File

@@ -5,37 +5,89 @@
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { DOUBLE_CLICK_ACTION_CONFIG_SECTION, ITEM_SELECTED_COMMAND_ID, QUERY_HISTORY_CONFIG_SECTION } from './constants';
import { QueryHistoryItem } from './queryHistoryItem';
import { QueryHistoryProvider } from './queryHistoryProvider';
let lastSelectedItem: { item: QueryHistoryItem | undefined, time: number | undefined } = {
item: undefined,
time: undefined
};
/**
* The time in ms between clicks to count as a double click on our tree view items
*/
const DOUBLE_CLICK_TIMEOUT_MS = 500;
export async function activate(context: vscode.ExtensionContext): Promise<void> {
const provider = new QueryHistoryProvider();
context.subscriptions.push(provider);
context.subscriptions.push(vscode.window.registerTreeDataProvider('queryHistory', provider));
const treeDataProvider = new QueryHistoryProvider();
context.subscriptions.push(treeDataProvider);
const treeView = vscode.window.createTreeView('queryHistory', {
treeDataProvider,
canSelectMany: false
});
context.subscriptions.push(treeView);
// This is an internal-only command so not adding to package.json
context.subscriptions.push(vscode.commands.registerCommand(ITEM_SELECTED_COMMAND_ID, async (selectedItem: QueryHistoryItem) => {
// VS Code doesn't provide a native way to detect a double-click so we track it ourselves by keeping track of the last item clicked and
// when it was clicked to compare, then if a click happens on the same element quickly enough we trigger the configured action
const clickTime = new Date().getTime();
if (lastSelectedItem.item === selectedItem && lastSelectedItem.time && (clickTime - lastSelectedItem.time) < DOUBLE_CLICK_TIMEOUT_MS) {
const doubleClickAction = vscode.workspace.getConfiguration(QUERY_HISTORY_CONFIG_SECTION).get<string>(DOUBLE_CLICK_ACTION_CONFIG_SECTION);
switch (doubleClickAction) {
case 'run':
await runQuery(selectedItem);
break;
case 'open':
default:
await openQuery(selectedItem);
break;
}
// Clear out the last selected item so we don't run the command again on a 3rd click
lastSelectedItem = {
item: undefined,
time: undefined
};
} else {
// Update the last selected item since we didn't run a command
lastSelectedItem = {
item: selectedItem,
time: clickTime
};
}
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.open', async (item: QueryHistoryItem) => {
return azdata.queryeditor.openQueryDocument(
{
content: item.queryText
}, item.connectionProfile?.providerId);
return openQuery(item);
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.run', async (item: QueryHistoryItem) => {
const doc = await azdata.queryeditor.openQueryDocument(
{
content: item.queryText
}, item.connectionProfile?.providerId);
await azdata.queryeditor.connect(doc.uri, item.connectionProfile?.connectionId || '');
azdata.queryeditor.runQuery(doc.uri);
return runQuery(item);
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.delete', (item: QueryHistoryItem) => {
provider.deleteItem(item);
treeDataProvider.deleteItem(item);
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.clear', () => {
provider.clearAll();
treeDataProvider.clearAll();
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.disableCapture', async () => {
return provider.setCaptureEnabled(false);
return treeDataProvider.setCaptureEnabled(false);
}));
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.enableCapture', async () => {
return provider.setCaptureEnabled(true);
return treeDataProvider.setCaptureEnabled(true);
}));
}
async function openQuery(item: QueryHistoryItem): Promise<void> {
await azdata.queryeditor.openQueryDocument(
{
content: item.queryText
}, item.connectionProfile?.providerId);
}
async function runQuery(item: QueryHistoryItem): Promise<void> {
const doc = await azdata.queryeditor.openQueryDocument(
{
content: item.queryText
}, item.connectionProfile?.providerId);
await azdata.queryeditor.connect(doc.uri, item.connectionProfile?.connectionId || '');
azdata.queryeditor.runQuery(doc.uri);
}

View File

@@ -8,9 +8,8 @@ import * as azdata from 'azdata';
import { EOL } from 'os';
import { QueryHistoryItem } from './queryHistoryItem';
import { removeNewLines } from './utils';
import { CAPTURE_ENABLED_CONFIG_SECTION, ITEM_SELECTED_COMMAND_ID, QUERY_HISTORY_CONFIG_SECTION } from './constants';
const QUERY_HISTORY_CONFIG_SECTION = 'queryHistory';
const CAPTURE_ENABLED_CONFIG_SECTION = 'captureEnabled';
const DEFAULT_CAPTURE_ENABLED = true;
const successIcon = new vscode.ThemeIcon('check', new vscode.ThemeColor('testing.iconPassed'));
const failedIcon = new vscode.ThemeIcon('error', new vscode.ThemeColor('testing.iconFailed'));
@@ -70,6 +69,7 @@ export class QueryHistoryProvider implements vscode.TreeDataProvider<QueryHistor
treeItem.iconPath = item.isSuccess ? successIcon : failedIcon;
treeItem.tooltip = item.queryText;
treeItem.description = item.connectionProfile ? `${item.connectionProfile.serverName}|${item.connectionProfile.databaseName} ${item.timestamp.toLocaleString()}` : item.timestamp.toLocaleString();
treeItem.command = { title: '', command: ITEM_SELECTED_COMMAND_ID, arguments: [item] };
return treeItem;
}