mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Auto-close copy notification after 3 seconds + configuration support (#24037)
This commit is contained in:
@@ -32,6 +32,7 @@ export interface IQueryEditorConfiguration {
|
|||||||
readonly inMemoryDataProcessingThreshold: number;
|
readonly inMemoryDataProcessingThreshold: number;
|
||||||
readonly openAfterSave: boolean;
|
readonly openAfterSave: boolean;
|
||||||
readonly showActionBar: boolean;
|
readonly showActionBar: boolean;
|
||||||
|
readonly showCopyCompletedNotification: boolean;
|
||||||
readonly preferProvidersCopyHandler: boolean;
|
readonly preferProvidersCopyHandler: boolean;
|
||||||
readonly promptForLargeRowSelection: boolean;
|
readonly promptForLargeRowSelection: boolean;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ export class DataResourceDataProvider implements IGridDataProvider {
|
|||||||
|
|
||||||
private async copyResultsAsync(selection: Slick.Range[], includeHeaders?: boolean, tableView?: IDisposableDataProvider<Slick.SlickData>): Promise<void> {
|
private async copyResultsAsync(selection: Slick.Range[], includeHeaders?: boolean, tableView?: IDisposableDataProvider<Slick.SlickData>): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await copySelectionToClipboard(this._clipboardService, this._notificationService, this, selection, includeHeaders, tableView);
|
await copySelectionToClipboard(this._clipboardService, this._notificationService, this._configurationService, this, selection, includeHeaders, tableView);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._notificationService.error(localize('copyFailed', "Copy failed with error: {0}", getErrorMessage(error)));
|
this._notificationService.error(localize('copyFailed', "Copy failed with error: {0}", getErrorMessage(error)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,6 +303,11 @@ const queryEditorConfiguration: IConfigurationNode = {
|
|||||||
'description': localize('queryEditor.results.copyRemoveNewLine', "Configuration options for copying multi-line results from the Results View"),
|
'description': localize('queryEditor.results.copyRemoveNewLine', "Configuration options for copying multi-line results from the Results View"),
|
||||||
'default': true
|
'default': true
|
||||||
},
|
},
|
||||||
|
'queryEditor.results.showCopyCompletedNotification': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'description': localize('queryEditor.results.showCopyCompletedNotification', "Whether to show notifications when a results grid copy operation is completed."),
|
||||||
|
'default': true
|
||||||
|
},
|
||||||
'queryEditor.results.skipNewLineAfterTrailingLineBreak': {
|
'queryEditor.results.skipNewLineAfterTrailingLineBreak': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
'description': localize('queryEditor.results.skipNewLineAfterTrailingLineBreak', "Whether to skip adding a line break between rows when copying results if the previous row already has a trailing line break. The default value is false."),
|
'description': localize('queryEditor.results.skipNewLineAfterTrailingLineBreak', "Whether to skip adding a line break between rows when copying results if the previous row already has a trailing line break. The default value is false."),
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { toAction } from 'vs/base/common/actions';
|
|||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
import { GridRange } from 'sql/base/common/gridRange';
|
import { GridRange } from 'sql/base/common/gridRange';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { IQueryEditorConfiguration } from 'sql/platform/query/common/query';
|
||||||
|
|
||||||
export interface IGridDataProvider {
|
export interface IGridDataProvider {
|
||||||
|
|
||||||
@@ -55,9 +57,10 @@ export interface IGridDataProvider {
|
|||||||
serializeResults(format: SaveFormat, selection: Slick.Range[]): Thenable<void>;
|
serializeResults(format: SaveFormat, selection: Slick.Range[]): Thenable<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function executeCopyWithNotification(notificationService: INotificationService, selections: Slick.Range[], copyHandler: (notification: INotificationHandle, rowCount: number) => Promise<void>, cancellationTokenSource?: CancellationTokenSource): Promise<void> {
|
export async function executeCopyWithNotification(notificationService: INotificationService, configurationService: IConfigurationService, selections: Slick.Range[], copyHandler: (notification: INotificationHandle, rowCount: number) => Promise<void>, cancellationTokenSource?: CancellationTokenSource): Promise<void> {
|
||||||
const rowRanges = GridRange.getUniqueRows(GridRange.fromSlickRanges(selections));
|
const rowRanges = GridRange.getUniqueRows(GridRange.fromSlickRanges(selections));
|
||||||
const rowCount = rowRanges.map(range => range.end - range.start + 1).reduce((p, c) => p + c);
|
const rowCount = rowRanges.map(range => range.end - range.start + 1).reduce((p, c) => p + c);
|
||||||
|
const showCopyCompleteNotifications = configurationService.getValue<IQueryEditorConfiguration>('queryEditor').results.showCopyCompletedNotification;
|
||||||
const notificationHandle = notificationService.notify({
|
const notificationHandle = notificationService.notify({
|
||||||
message: nls.localize('gridDataProvider.copying', "Copying..."),
|
message: nls.localize('gridDataProvider.copying', "Copying..."),
|
||||||
severity: Severity.Info,
|
severity: Severity.Info,
|
||||||
@@ -80,15 +83,30 @@ export async function executeCopyWithNotification(notificationService: INotifica
|
|||||||
await copyHandler(notificationHandle, rowCount);
|
await copyHandler(notificationHandle, rowCount);
|
||||||
if (cancellationTokenSource === undefined || !cancellationTokenSource.token.isCancellationRequested) {
|
if (cancellationTokenSource === undefined || !cancellationTokenSource.token.isCancellationRequested) {
|
||||||
notificationHandle.progress.done();
|
notificationHandle.progress.done();
|
||||||
notificationHandle.updateActions({
|
if (showCopyCompleteNotifications) {
|
||||||
primary: [
|
notificationHandle.updateActions({
|
||||||
toAction({
|
primary: [
|
||||||
id: 'closeCopyResultsNotification',
|
toAction({
|
||||||
label: nls.localize('gridDataProvider.closeNotification', "Close"),
|
id: 'closeCopyResultsNotification',
|
||||||
run: () => { notificationHandle.close(); }
|
label: nls.localize('gridDataProvider.closeNotification', 'Close'),
|
||||||
})]
|
run: () => { notificationHandle.close(); }
|
||||||
});
|
}),
|
||||||
notificationHandle.updateMessage(nls.localize('gridDataProvider.copyResultsCompleted', "Selected data has been copied to the clipboard. Row count: {0}.", rowCount));
|
toAction({
|
||||||
|
id: 'disableCopyNotification',
|
||||||
|
label: nls.localize('gridDataProvider.disableCopyNotification', `Don't show again`),
|
||||||
|
run: () => {
|
||||||
|
updateConfigTurnOffCopyNotifications(configurationService);
|
||||||
|
notificationService.info(nls.localize('gridDataProvider.turnOnCopyNotificationsMessage',
|
||||||
|
'Copy completed notifications are now disabled. To re-enable, modify the setting: queryEditor.results.showCopyCompletedNotification'))
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
});
|
||||||
|
notificationHandle.updateMessage(nls.localize('gridDataProvider.copyResultsCompleted', "Selected data has been copied to the clipboard. Row count: {0}.", rowCount));
|
||||||
|
// Auto-close notification after 3 seconds.
|
||||||
|
setTimeout(() => notificationHandle.close(), 3000);
|
||||||
|
} else {
|
||||||
|
notificationHandle.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@@ -97,9 +115,10 @@ export async function executeCopyWithNotification(notificationService: INotifica
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function copySelectionToClipboard(clipboardService: IClipboardService, notificationService: INotificationService, provider: IGridDataProvider, selections: Slick.Range[], includeHeaders?: boolean, tableView?: IDisposableDataProvider<Slick.SlickData>): Promise<void> {
|
export async function copySelectionToClipboard(clipboardService: IClipboardService, notificationService: INotificationService, configurationService: IConfigurationService,
|
||||||
|
provider: IGridDataProvider, selections: Slick.Range[], includeHeaders?: boolean, tableView?: IDisposableDataProvider<Slick.SlickData>): Promise<void> {
|
||||||
const cancellationTokenSource = new CancellationTokenSource()
|
const cancellationTokenSource = new CancellationTokenSource()
|
||||||
await executeCopyWithNotification(notificationService, selections, async (notificationHandle, rowCount) => {
|
await executeCopyWithNotification(notificationService, configurationService, selections, async (notificationHandle, rowCount) => {
|
||||||
const eol = provider.getEolString();
|
const eol = provider.getEolString();
|
||||||
const valueSeparator = '\t';
|
const valueSeparator = '\t';
|
||||||
const shouldRemoveNewLines = provider.shouldRemoveNewLines();
|
const shouldRemoveNewLines = provider.shouldRemoveNewLines();
|
||||||
@@ -214,3 +233,10 @@ function removeNewLines(inputString: string): string {
|
|||||||
let outputString: string = inputString.replace(/(\r\n|\n|\r)/gm, ' ');
|
let outputString: string = inputString.replace(/(\r\n|\n|\r)/gm, ' ');
|
||||||
return outputString;
|
return outputString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables data copy configuration setting.
|
||||||
|
*/
|
||||||
|
function updateConfigTurnOffCopyNotifications(configurationService: IConfigurationService) {
|
||||||
|
configurationService.updateValue('queryEditor.results.showCopyCompletedNotification', false);
|
||||||
|
}
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ export class QueryGridDataProvider implements IGridDataProvider {
|
|||||||
if (preferProvidersCopyHandler && providerSupportCopyResults && (tableView === undefined || !tableView.isDataInMemory)) {
|
if (preferProvidersCopyHandler && providerSupportCopyResults && (tableView === undefined || !tableView.isDataInMemory)) {
|
||||||
await this.handleCopyRequestByProvider(selections, includeHeaders);
|
await this.handleCopyRequestByProvider(selections, includeHeaders);
|
||||||
} else {
|
} else {
|
||||||
await copySelectionToClipboard(this._clipboardService, this._notificationService, this, selections, includeHeaders, tableView);
|
await copySelectionToClipboard(this._clipboardService, this._notificationService, this._configurationService, this, selections, includeHeaders, tableView);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._notificationService.error(nls.localize('copyFailed', "Copy failed with error: {0}", getErrorMessage(error)));
|
this._notificationService.error(nls.localize('copyFailed', "Copy failed with error: {0}", getErrorMessage(error)));
|
||||||
@@ -589,7 +589,7 @@ export class QueryGridDataProvider implements IGridDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleCopyRequestByProvider(selections: Slick.Range[], includeHeaders?: boolean): Promise<void> {
|
private async handleCopyRequestByProvider(selections: Slick.Range[], includeHeaders?: boolean): Promise<void> {
|
||||||
executeCopyWithNotification(this._notificationService, selections, async () => {
|
executeCopyWithNotification(this._notificationService, this._configurationService, selections, async () => {
|
||||||
await this.queryRunner.copyResults(selections, this.batchId, this.resultSetId, this.shouldIncludeHeaders(includeHeaders));
|
await this.queryRunner.copyResults(selections, this.batchId, this.resultSetId, this.shouldIncludeHeaders(includeHeaders));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user