Files
azuredatastudio/src/sql/workbench/contrib/query/browser/statusBarItems.ts

256 lines
8.5 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQueryModelService } from 'sql/workbench/services/query/common/queryModel';
import { IntervalTimer } from 'vs/base/common/async';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { localize } from 'vs/nls';
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
import { parseNumAsTimeString } from 'sql/platform/connection/common/utils';
import { Event } from 'vs/base/common/event';
import { QueryEditorInput } from 'sql/workbench/common/editor/query/queryEditorInput';
import { IStatusbarService, IStatusbarEntryAccessor, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar';
export class TimeElapsedStatusBarContributions extends Disposable implements IWorkbenchContribution {
private static readonly ID = 'status.query.timeElapsed';
private statusItem: IStatusbarEntryAccessor;
private intervalTimer = new IntervalTimer();
private disposable = this._register(new DisposableStore());
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IEditorService private readonly editorService: IEditorService,
@IQueryModelService private readonly queryModelService: IQueryModelService
) {
super();
this.statusItem = this._register(
this.statusbarService.addEntry({
text: '',
ariaLabel: ''
},
TimeElapsedStatusBarContributions.ID,
localize('status.query.timeElapsed', "Time Elapsed"),
StatusbarAlignment.RIGHT, 100)
);
this._register(editorService.onDidActiveEditorChange(this.update, this));
this.update();
}
private hide() {
this.statusbarService.updateEntryVisibility(TimeElapsedStatusBarContributions.ID, false);
}
private show() {
this.statusbarService.updateEntryVisibility(TimeElapsedStatusBarContributions.ID, true);
}
private update() {
this.intervalTimer.cancel();
this.disposable.clear();
this.hide();
const activeInput = this.editorService.activeEditor;
if (activeInput && activeInput instanceof QueryEditorInput && activeInput.uri) {
const uri = activeInput.uri;
const runner = this.queryModelService.getQueryRunner(uri);
if (runner) {
if (runner.hasCompleted || runner.isExecuting) {
this._displayValue(runner);
}
this.disposable.add(runner.onQueryStart(e => {
this._displayValue(runner);
}));
this.disposable.add(runner.onQueryEnd(e => {
this._displayValue(runner);
}));
} else {
this.disposable.add(this.queryModelService.onRunQueryStart(e => {
if (e === uri) {
this._displayValue(this.queryModelService.getQueryRunner(uri));
}
}));
this.disposable.add(this.queryModelService.onRunQueryComplete(e => {
if (e === uri) {
this._displayValue(this.queryModelService.getQueryRunner(uri));
}
}));
}
}
}
private _displayValue(runner: QueryRunner) {
this.intervalTimer.cancel();
if (runner.isExecuting) {
this.intervalTimer.cancelAndSet(() => {
const value = runner.queryStartTime ? Date.now() - runner.queryStartTime.getTime() : 0;
const timeString = parseNumAsTimeString(value, false);
this.statusItem.update({
text: timeString,
ariaLabel: timeString
});
}, 1000);
const value = runner.queryStartTime ? Date.now() - runner.queryStartTime.getTime() : 0;
const timeString = parseNumAsTimeString(value, false);
this.statusItem.update({
text: timeString,
ariaLabel: timeString
});
} else {
const value = runner.queryStartTime && runner.queryEndTime
? runner.queryEndTime.getTime() - runner.queryStartTime.getTime() : 0;
const timeString = parseNumAsTimeString(value, false);
this.statusItem.update({
text: timeString,
ariaLabel: timeString
});
}
this.show();
}
}
export class RowCountStatusBarContributions extends Disposable implements IWorkbenchContribution {
private static readonly ID = 'status.query.rowCount';
private statusItem: IStatusbarEntryAccessor;
private disposable = this._register(new DisposableStore());
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IEditorService private readonly editorService: IEditorService,
@IQueryModelService private readonly queryModelService: IQueryModelService
) {
super();
this.statusItem = this._register(
this.statusbarService.addEntry({
text: '',
ariaLabel: ''
},
RowCountStatusBarContributions.ID,
localize('status.query.rowCount', "Row Count"),
StatusbarAlignment.RIGHT, 100)
);
this._register(editorService.onDidActiveEditorChange(this.update, this));
this.update();
}
private hide() {
this.statusbarService.updateEntryVisibility(RowCountStatusBarContributions.ID, false);
}
private show() {
this.statusbarService.updateEntryVisibility(RowCountStatusBarContributions.ID, true);
}
private update() {
this.disposable.clear();
this.hide();
const activeInput = this.editorService.activeEditor;
if (activeInput && activeInput instanceof QueryEditorInput && activeInput.uri) {
const uri = activeInput.uri;
const runner = this.queryModelService.getQueryRunner(uri);
if (runner) {
if (runner.hasCompleted || runner.isExecuting) {
this._displayValue(runner);
}
this.disposable.add(runner.onQueryStart(e => {
this._displayValue(runner);
}));
this.disposable.add(runner.onResultSetUpdate(e => {
this._displayValue(runner);
}));
this.disposable.add(runner.onQueryEnd(e => {
this._displayValue(runner);
}));
} else {
this.disposable.add(this.queryModelService.onRunQueryStart(e => {
if (e === uri) {
this._displayValue(this.queryModelService.getQueryRunner(uri));
}
}));
this.disposable.add(this.queryModelService.onRunQueryUpdate(e => {
if (e === uri) {
this._displayValue(this.queryModelService.getQueryRunner(uri));
}
}));
this.disposable.add(this.queryModelService.onRunQueryComplete(e => {
if (e === uri) {
this._displayValue(this.queryModelService.getQueryRunner(uri));
}
}));
}
}
}
private _displayValue(runner: QueryRunner) {
const rowCount = runner.batchSets.reduce((p, c) => {
return p + c.resultSetSummaries.reduce((rp, rc) => {
return rp + rc.rowCount;
}, 0);
}, 0);
const text = localize('rowCount', "{0} rows", rowCount.toLocaleString());
this.statusItem.update({ text, ariaLabel: text });
this.show();
}
}
export class QueryStatusStatusBarContributions extends Disposable implements IWorkbenchContribution {
private static readonly ID = 'status.query.status';
private visisbleUri: string | undefined;
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IEditorService private readonly editorService: IEditorService,
@IQueryModelService private readonly queryModelService: IQueryModelService
) {
super();
this._register(
this.statusbarService.addEntry({
text: localize('query.status.executing', "Executing query..."),
ariaLabel: localize('query.status.executing', "Executing query...")
},
QueryStatusStatusBarContributions.ID,
localize('status.query.status', "Execution Status"),
StatusbarAlignment.RIGHT, 100)
);
this._register(Event.filter(this.queryModelService.onRunQueryStart, uri => uri === this.visisbleUri)(this.update, this));
this._register(Event.filter(this.queryModelService.onRunQueryComplete, uri => uri === this.visisbleUri)(this.update, this));
this._register(this.editorService.onDidActiveEditorChange(this.update, this));
this.update();
}
private update() {
this.hide();
this.visisbleUri = undefined;
const activeInput = this.editorService.activeEditor;
if (activeInput && activeInput instanceof QueryEditorInput && activeInput.uri) {
this.visisbleUri = activeInput.uri;
const runner = this.queryModelService.getQueryRunner(this.visisbleUri);
if (runner && runner.isExecuting) {
this.show();
}
}
}
private hide() {
this.statusbarService.updateEntryVisibility(QueryStatusStatusBarContributions.ID, false);
}
private show() {
this.statusbarService.updateEntryVisibility(QueryStatusStatusBarContributions.ID, true);
}
}