mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add double click action support for query history (#20204)
* Add double click action support for query history * localize descriptions
This commit is contained in:
@@ -39,6 +39,19 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true,
|
"default": true,
|
||||||
"description": "%queryHistory.captureEnabledDesc%"
|
"description": "%queryHistory.captureEnabledDesc%"
|
||||||
|
},
|
||||||
|
"queryHistory.doubleClickAction": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "%queryHistory.doubleClickAction%",
|
||||||
|
"default": "open",
|
||||||
|
"enum": [
|
||||||
|
"open",
|
||||||
|
"run"
|
||||||
|
],
|
||||||
|
"enumDescriptions": [
|
||||||
|
"%queryHistory.doubleClickAction.open%",
|
||||||
|
"%queryHistory.doubleClickAction.run%"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
"queryHistory.displayName": "Query History",
|
"queryHistory.displayName": "Query History",
|
||||||
"queryHistory.description": "View and run previously executed queries",
|
"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.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.open": "Open Query",
|
||||||
"queryHistory.run": "Run Query",
|
"queryHistory.run": "Run Query",
|
||||||
"queryHistory.delete": "Delete",
|
"queryHistory.delete": "Delete",
|
||||||
|
|||||||
10
extensions/query-history/src/constants.ts
Normal file
10
extensions/query-history/src/constants.ts
Normal 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';
|
||||||
@@ -5,37 +5,89 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
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 { QueryHistoryItem } from './queryHistoryItem';
|
||||||
import { QueryHistoryProvider } from './queryHistoryProvider';
|
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> {
|
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||||
const provider = new QueryHistoryProvider();
|
const treeDataProvider = new QueryHistoryProvider();
|
||||||
context.subscriptions.push(provider);
|
context.subscriptions.push(treeDataProvider);
|
||||||
context.subscriptions.push(vscode.window.registerTreeDataProvider('queryHistory', provider));
|
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) => {
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.open', async (item: QueryHistoryItem) => {
|
||||||
return azdata.queryeditor.openQueryDocument(
|
return openQuery(item);
|
||||||
|
}));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.run', async (item: QueryHistoryItem) => {
|
||||||
|
return runQuery(item);
|
||||||
|
}));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.delete', (item: QueryHistoryItem) => {
|
||||||
|
treeDataProvider.deleteItem(item);
|
||||||
|
}));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.clear', () => {
|
||||||
|
treeDataProvider.clearAll();
|
||||||
|
}));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.disableCapture', async () => {
|
||||||
|
return treeDataProvider.setCaptureEnabled(false);
|
||||||
|
}));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.enableCapture', async () => {
|
||||||
|
return treeDataProvider.setCaptureEnabled(true);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openQuery(item: QueryHistoryItem): Promise<void> {
|
||||||
|
await azdata.queryeditor.openQueryDocument(
|
||||||
{
|
{
|
||||||
content: item.queryText
|
content: item.queryText
|
||||||
}, item.connectionProfile?.providerId);
|
}, item.connectionProfile?.providerId);
|
||||||
}));
|
}
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.run', async (item: QueryHistoryItem) => {
|
|
||||||
|
async function runQuery(item: QueryHistoryItem): Promise<void> {
|
||||||
const doc = await azdata.queryeditor.openQueryDocument(
|
const doc = await azdata.queryeditor.openQueryDocument(
|
||||||
{
|
{
|
||||||
content: item.queryText
|
content: item.queryText
|
||||||
}, item.connectionProfile?.providerId);
|
}, item.connectionProfile?.providerId);
|
||||||
await azdata.queryeditor.connect(doc.uri, item.connectionProfile?.connectionId || '');
|
await azdata.queryeditor.connect(doc.uri, item.connectionProfile?.connectionId || '');
|
||||||
azdata.queryeditor.runQuery(doc.uri);
|
azdata.queryeditor.runQuery(doc.uri);
|
||||||
}));
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.delete', (item: QueryHistoryItem) => {
|
|
||||||
provider.deleteItem(item);
|
|
||||||
}));
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.clear', () => {
|
|
||||||
provider.clearAll();
|
|
||||||
}));
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.disableCapture', async () => {
|
|
||||||
return provider.setCaptureEnabled(false);
|
|
||||||
}));
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.enableCapture', async () => {
|
|
||||||
return provider.setCaptureEnabled(true);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ import * as azdata from 'azdata';
|
|||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
import { QueryHistoryItem } from './queryHistoryItem';
|
import { QueryHistoryItem } from './queryHistoryItem';
|
||||||
import { removeNewLines } from './utils';
|
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 DEFAULT_CAPTURE_ENABLED = true;
|
||||||
const successIcon = new vscode.ThemeIcon('check', new vscode.ThemeColor('testing.iconPassed'));
|
const successIcon = new vscode.ThemeIcon('check', new vscode.ThemeColor('testing.iconPassed'));
|
||||||
const failedIcon = new vscode.ThemeIcon('error', new vscode.ThemeColor('testing.iconFailed'));
|
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.iconPath = item.isSuccess ? successIcon : failedIcon;
|
||||||
treeItem.tooltip = item.queryText;
|
treeItem.tooltip = item.queryText;
|
||||||
treeItem.description = item.connectionProfile ? `${item.connectionProfile.serverName}|${item.connectionProfile.databaseName} ${item.timestamp.toLocaleString()}` : item.timestamp.toLocaleString();
|
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;
|
return treeItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user