mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
limit the data size for chart rendering (#14949)
* limit the rows feed to charts * add telemetry and option to hide * fix typo * updates * comments * notebook fix
This commit is contained in:
@@ -73,6 +73,7 @@ export enum TelemetryAction {
|
|||||||
RunQuery = 'RunQuery',
|
RunQuery = 'RunQuery',
|
||||||
RunQueryStatement = 'RunQueryStatement',
|
RunQueryStatement = 'RunQueryStatement',
|
||||||
RunQueryString = 'RunQueryString',
|
RunQueryString = 'RunQueryString',
|
||||||
|
ShowChart = 'ShowChart',
|
||||||
StopAgentJob = 'StopAgentJob',
|
StopAgentJob = 'StopAgentJob',
|
||||||
WizardPagesNavigation = 'WizardPagesNavigation'
|
WizardPagesNavigation = 'WizardPagesNavigation'
|
||||||
}
|
}
|
||||||
@@ -82,3 +83,7 @@ export enum NbTelemetryAction {
|
|||||||
RunAll = 'RunNotebook'
|
RunAll = 'RunNotebook'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TelemetryPropertyName {
|
||||||
|
ChartMaxRowCountExceeded = 'chartMaxRowCountExceeded'
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,33 +2,34 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import 'vs/css!./media/chartView';
|
import 'vs/css!./media/chartView';
|
||||||
|
|
||||||
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
|
||||||
import { Insight } from './insight';
|
|
||||||
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
|
|
||||||
import { ICellValue, VisualizationOptions } from 'sql/workbench/services/query/common/query';
|
|
||||||
import { ChartOptions, IChartOption, ControlType } from './chartOptions';
|
|
||||||
import { Extensions, IInsightRegistry, IInsightData } from 'sql/platform/dashboard/browser/insightRegistry';
|
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
|
||||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
|
||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
|
||||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
|
||||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
|
||||||
import { attachSelectBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
||||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
|
||||||
import { CreateInsightAction, CopyAction, SaveImageAction, IChartActionContext, ConfigureChartAction } from 'sql/workbench/contrib/charts/browser/actions';
|
|
||||||
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
|
|
||||||
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||||
import { IInsightOptions, ChartType, InsightType } from 'sql/workbench/contrib/charts/common/interfaces';
|
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||||
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
|
import { ITaskbarContent, Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
|
import { Extensions, IInsightData, IInsightRegistry } from 'sql/platform/dashboard/browser/insightRegistry';
|
||||||
import { ChartState } from 'sql/workbench/common/editor/query/chartState';
|
import { ChartState } from 'sql/workbench/common/editor/query/chartState';
|
||||||
|
import { ConfigureChartAction, CopyAction, CreateInsightAction, IChartActionContext, SaveImageAction } from 'sql/workbench/contrib/charts/browser/actions';
|
||||||
|
import { getChartMaxRowCount } from 'sql/workbench/contrib/charts/browser/utils';
|
||||||
|
import { ChartType, IInsightOptions, InsightType } from 'sql/workbench/contrib/charts/common/interfaces';
|
||||||
|
import { ICellValue, VisualizationOptions } from 'sql/workbench/services/query/common/query';
|
||||||
|
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||||
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
|
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
import { attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
||||||
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { ChartOptions, ControlType, IChartOption } from './chartOptions';
|
||||||
|
import { Insight } from './insight';
|
||||||
|
|
||||||
|
|
||||||
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
||||||
|
|
||||||
@@ -89,7 +90,8 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
@IContextViewService private _contextViewService: IContextViewService,
|
@IContextViewService private _contextViewService: IContextViewService,
|
||||||
@IThemeService private _themeService: IThemeService,
|
@IThemeService private _themeService: IThemeService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@INotificationService private readonly _notificationService: INotificationService
|
@INotificationService private readonly _notificationService: INotificationService,
|
||||||
|
@IConfigurationService private readonly _configurationService: IConfigurationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.taskbarContainer = DOM.$('div.taskbar-container');
|
this.taskbarContainer = DOM.$('div.taskbar-container');
|
||||||
@@ -195,7 +197,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
public chart(dataId: { batchId: number, resultId: number }) {
|
public chart(dataId: { batchId: number, resultId: number }) {
|
||||||
this.state.dataId = dataId;
|
this.state.dataId = dataId;
|
||||||
this._currentData = dataId;
|
this._currentData = dataId;
|
||||||
this.shouldGraph();
|
this.fetchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(dimension: DOM.Dimension): void {
|
layout(dimension: DOM.Dimension): void {
|
||||||
@@ -209,7 +211,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
|
|
||||||
public set queryRunner(runner: QueryRunner) {
|
public set queryRunner(runner: QueryRunner) {
|
||||||
this._queryRunner = runner;
|
this._queryRunner = runner;
|
||||||
this.shouldGraph();
|
this.fetchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public setData(rows: ICellValue[][], columns: string[]): void {
|
public setData(rows: ICellValue[][], columns: string[]): void {
|
||||||
@@ -228,7 +230,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private shouldGraph() {
|
private fetchData(): void {
|
||||||
// Check if we have the necessary information
|
// Check if we have the necessary information
|
||||||
if (this._currentData && this._queryRunner) {
|
if (this._currentData && this._queryRunner) {
|
||||||
// check if we are being asked to graph something that is available
|
// check if we are being asked to graph something that is available
|
||||||
@@ -236,7 +238,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
if (batch) {
|
if (batch) {
|
||||||
let summary = batch.resultSetSummaries[this._currentData.resultId];
|
let summary = batch.resultSetSummaries[this._currentData.resultId];
|
||||||
if (summary) {
|
if (summary) {
|
||||||
this._queryRunner.getQueryRows(0, summary.rowCount, this._currentData.batchId, this._currentData.resultId).then(d => {
|
this._queryRunner.getQueryRows(0, Math.min(getChartMaxRowCount(this._configurationService), summary.rowCount), this._currentData.batchId, this._currentData.resultId).then(d => {
|
||||||
let rows = d.rows;
|
let rows = d.rows;
|
||||||
let columns = summary.columnInfo.map(c => c.columnName);
|
let columns = summary.columnInfo.map(c => c.columnName);
|
||||||
this.setData(rows, columns);
|
this.setData(rows, columns);
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Extensions, IConfigurationRegistry, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
|
||||||
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
|
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
|
||||||
|
|
||||||
|
const chartsConfiguration: IConfigurationNode = {
|
||||||
|
id: 'builtinCharts',
|
||||||
|
type: 'object',
|
||||||
|
title: nls.localize('builtinChartsConfigurationTitle', "Built-in Charts"),
|
||||||
|
properties: {
|
||||||
|
'builtinCharts.maxRowCount': {
|
||||||
|
type: 'number',
|
||||||
|
default: 300,
|
||||||
|
description: nls.localize('builtinCharts.maxRowCountDescription', "The maximum number of rows for charts to display. Warning: increasing this may impact performance.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
configurationRegistry.registerConfiguration(chartsConfiguration);
|
||||||
@@ -46,3 +46,7 @@ export interface IInsightCtor {
|
|||||||
new <Services extends BrandedService[]>(container: HTMLElement, options: IInsightOptions, ...services: Services): IInsight;
|
new <Services extends BrandedService[]>(container: HTMLElement, options: IInsightOptions, ...services: Services): IInsight;
|
||||||
readonly types: Array<InsightType | ChartType>;
|
readonly types: Array<InsightType | ChartType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IChartsConfiguration {
|
||||||
|
readonly maxRowCount: number;
|
||||||
|
}
|
||||||
|
|||||||
35
src/sql/workbench/contrib/charts/browser/utils.ts
Normal file
35
src/sql/workbench/contrib/charts/browser/utils.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IChartsConfiguration } from 'sql/workbench/contrib/charts/browser/interfaces';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||||
|
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the max allowed row count for chart rendering.
|
||||||
|
*/
|
||||||
|
export function getChartMaxRowCount(configurationService: IConfigurationService): number {
|
||||||
|
return configurationService.getValue<IChartsConfiguration>('builtinCharts').maxRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a toast notification about the max row count for chart has exceeded.
|
||||||
|
*/
|
||||||
|
export function notifyMaxRowCountExceeded(storageService: IStorageService, notificationService: INotificationService, configurationService: IConfigurationService): void {
|
||||||
|
const storageKey = 'charts/ignoreMaxRowCountExceededNotification';
|
||||||
|
if (!storageService.getBoolean(storageKey, StorageScope.GLOBAL, false)) {
|
||||||
|
notificationService.prompt(Severity.Info,
|
||||||
|
nls.localize('charts.maxAllowedRowsExceeded', "Maximum row count for built-in charts has been exceeded, only the first {0} rows are used. To configure the value, you can open user settings and search for: 'builtinCharts.maxRowCount'.", getChartMaxRowCount(configurationService)),
|
||||||
|
[{
|
||||||
|
label: nls.localize('charts.neverShowAgain', "Don't Show Again"),
|
||||||
|
isSecondary: true,
|
||||||
|
run: () => {
|
||||||
|
storageService.store(storageKey, true, StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService
|
|||||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||||
|
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||||
|
|
||||||
suite('Chart View', () => {
|
suite('Chart View', () => {
|
||||||
test('initializes without error', () => {
|
test('initializes without error', () => {
|
||||||
@@ -40,6 +41,7 @@ function createChartView(isQueryEditorChart: boolean): ChartView {
|
|||||||
const themeService = new TestThemeService();
|
const themeService = new TestThemeService();
|
||||||
const instantiationService = new TestInstantiationService();
|
const instantiationService = new TestInstantiationService();
|
||||||
const notificationService = new TestNotificationService();
|
const notificationService = new TestNotificationService();
|
||||||
|
const configurationService = new TestConfigurationService();
|
||||||
instantiationService.stub(IThemeService, themeService);
|
instantiationService.stub(IThemeService, themeService);
|
||||||
return new ChartView(isQueryEditorChart, contextViewService, themeService, instantiationService, notificationService);
|
return new ChartView(isQueryEditorChart, contextViewService, themeService, instantiationService, notificationService, configurationService);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ import { assign } from 'vs/base/common/objects';
|
|||||||
import { QueryResultId } from 'sql/workbench/services/notebook/browser/models/cell';
|
import { QueryResultId } from 'sql/workbench/services/notebook/browser/models/cell';
|
||||||
import { equals } from 'vs/base/common/arrays';
|
import { equals } from 'vs/base/common/arrays';
|
||||||
import { IDisposableDataProvider } from 'sql/base/common/dataProvider';
|
import { IDisposableDataProvider } from 'sql/base/common/dataProvider';
|
||||||
|
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
|
import { getChartMaxRowCount, notifyMaxRowCountExceeded } from 'sql/workbench/contrib/charts/browser/utils';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: GridOutputComponent.SELECTOR,
|
selector: GridOutputComponent.SELECTOR,
|
||||||
template: `<div #output class="notebook-cellTable"></div>`
|
template: `<div #output class="notebook-cellTable"></div>`
|
||||||
@@ -284,8 +289,9 @@ class DataResourceTable extends GridTableBase<any> {
|
|||||||
|
|
||||||
public updateChartData(rowCount: number, columnCount: number, gridDataProvider: IGridDataProvider): void {
|
public updateChartData(rowCount: number, columnCount: number, gridDataProvider: IGridDataProvider): void {
|
||||||
if (this.chartDisplayed) {
|
if (this.chartDisplayed) {
|
||||||
gridDataProvider.getRowData(0, rowCount).then(result => {
|
const actualRowCount = Math.min(getChartMaxRowCount(this.configurationService), rowCount);
|
||||||
let range = new Slick.Range(0, 0, rowCount - 1, columnCount - 1);
|
gridDataProvider.getRowData(0, actualRowCount).then(result => {
|
||||||
|
let range = new Slick.Range(0, 0, actualRowCount - 1, columnCount - 1);
|
||||||
let columns = gridDataProvider.getColumnHeaders(range);
|
let columns = gridDataProvider.getColumnHeaders(range);
|
||||||
this._chart.setData(result.rows, columns);
|
this._chart.setData(result.rows, columns);
|
||||||
});
|
});
|
||||||
@@ -535,7 +541,11 @@ export class NotebookChartAction extends ToggleableAction {
|
|||||||
public static SHOWTABLE_LABEL = localize('notebook.showTable', "Show table");
|
public static SHOWTABLE_LABEL = localize('notebook.showTable', "Show table");
|
||||||
public static SHOWTABLE_ICON = 'table';
|
public static SHOWTABLE_ICON = 'table';
|
||||||
|
|
||||||
constructor(private resourceTable: DataResourceTable) {
|
constructor(private resourceTable: DataResourceTable,
|
||||||
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
|
@IStorageService private readonly storageService: IStorageService,
|
||||||
|
@INotificationService private readonly notificationService: INotificationService,
|
||||||
|
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService) {
|
||||||
super(NotebookChartAction.ID, {
|
super(NotebookChartAction.ID, {
|
||||||
toggleOnLabel: NotebookChartAction.SHOWTABLE_LABEL,
|
toggleOnLabel: NotebookChartAction.SHOWTABLE_LABEL,
|
||||||
toggleOnClass: NotebookChartAction.SHOWTABLE_ICON,
|
toggleOnClass: NotebookChartAction.SHOWTABLE_ICON,
|
||||||
@@ -549,9 +559,17 @@ export class NotebookChartAction extends ToggleableAction {
|
|||||||
this.resourceTable.toggleChartVisibility();
|
this.resourceTable.toggleChartVisibility();
|
||||||
this.toggle(!this.state.isOn);
|
this.toggle(!this.state.isOn);
|
||||||
if (this.state.isOn) {
|
if (this.state.isOn) {
|
||||||
let rowCount = context.table.getData().getLength();
|
const rowCount = context.table.getData().getLength();
|
||||||
let columnCount = context.table.columns.length;
|
const columnCount = context.table.columns.length;
|
||||||
this.resourceTable.updateChartData(rowCount, columnCount, context.gridDataProvider);
|
const maxRowCount = getChartMaxRowCount(this.configurationService);
|
||||||
|
const maxRowCountExceeded = rowCount > maxRowCount;
|
||||||
|
if (maxRowCountExceeded) {
|
||||||
|
notifyMaxRowCountExceeded(this.storageService, this.notificationService, this.configurationService);
|
||||||
|
}
|
||||||
|
this.adsTelemetryService.createActionEvent(TelemetryKeys.TelemetryView.Notebook, TelemetryKeys.TelemetryAction.ShowChart).withAdditionalProperties(
|
||||||
|
{ [TelemetryKeys.TelemetryPropertyName.ChartMaxRowCountExceeded]: maxRowCountExceeded }
|
||||||
|
).send();
|
||||||
|
this.resourceTable.updateChartData(Math.min(rowCount, maxRowCount), columnCount, context.gridDataProvider);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ let sqlTocItems: ITOCEntry<string>[] = [{
|
|||||||
id: 'data/profiler',
|
id: 'data/profiler',
|
||||||
label: localize('profiler', "Profiler"),
|
label: localize('profiler', "Profiler"),
|
||||||
settings: ['profiler.*']
|
settings: ['profiler.*']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'data/builtinCharts',
|
||||||
|
label: localize('builtinCharts', "Built-in Charts"),
|
||||||
|
settings: ['builtinCharts.*']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import { getErrorMessage } from 'vs/base/common/errors';
|
|||||||
import { SaveFormat } from 'sql/workbench/services/query/common/resultSerializer';
|
import { SaveFormat } from 'sql/workbench/services/query/common/resultSerializer';
|
||||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||||
import { IEncodingSupport } from 'vs/workbench/common/editor';
|
import { IEncodingSupport } from 'vs/workbench/common/editor';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
|
import { getChartMaxRowCount, notifyMaxRowCountExceeded } from 'sql/workbench/contrib/charts/browser/utils';
|
||||||
|
|
||||||
export interface IGridActionContext {
|
export interface IGridActionContext {
|
||||||
gridDataProvider: IGridDataProvider;
|
gridDataProvider: IGridDataProvider;
|
||||||
@@ -167,7 +170,11 @@ export class ChartDataAction extends Action {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IEditorService private editorService: IEditorService,
|
@IEditorService private editorService: IEditorService,
|
||||||
@IExtensionRecommendationsService private readonly extensionTipsService: IExtensionRecommendationsService
|
@IExtensionRecommendationsService private readonly extensionTipsService: IExtensionRecommendationsService,
|
||||||
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
|
@IStorageService private readonly storageService: IStorageService,
|
||||||
|
@INotificationService private readonly notificationService: INotificationService,
|
||||||
|
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService
|
||||||
) {
|
) {
|
||||||
super(ChartDataAction.ID, ChartDataAction.LABEL, ChartDataAction.ICON);
|
super(ChartDataAction.ID, ChartDataAction.LABEL, ChartDataAction.ICON);
|
||||||
}
|
}
|
||||||
@@ -175,7 +182,15 @@ export class ChartDataAction extends Action {
|
|||||||
public run(context: IGridActionContext): Promise<boolean> {
|
public run(context: IGridActionContext): Promise<boolean> {
|
||||||
// show the visualizer extension recommendation notification
|
// show the visualizer extension recommendation notification
|
||||||
this.extensionTipsService.promptRecommendedExtensionsByScenario(Constants.visualizerExtensions);
|
this.extensionTipsService.promptRecommendedExtensionsByScenario(Constants.visualizerExtensions);
|
||||||
|
const maxRowCount = getChartMaxRowCount(this.configurationService);
|
||||||
|
const rowCount = context.table.getData().getLength();
|
||||||
|
const maxRowCountExceeded = rowCount > maxRowCount;
|
||||||
|
if (maxRowCountExceeded) {
|
||||||
|
notifyMaxRowCountExceeded(this.storageService, this.notificationService, this.configurationService);
|
||||||
|
}
|
||||||
|
this.adsTelemetryService.createActionEvent(TelemetryKeys.TelemetryView.ResultsPanel, TelemetryKeys.TelemetryAction.ShowChart).withAdditionalProperties(
|
||||||
|
{ [TelemetryKeys.TelemetryPropertyName.ChartMaxRowCountExceeded]: maxRowCountExceeded }
|
||||||
|
).send();
|
||||||
const activeEditor = this.editorService.activeEditorPane as QueryEditor;
|
const activeEditor = this.editorService.activeEditorPane as QueryEditor;
|
||||||
activeEditor.chart({ batchId: context.batchId, resultId: context.resultId });
|
activeEditor.chart({ batchId: context.batchId, resultId: context.resultId });
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
|||||||
@IInstantiationService protected readonly instantiationService: IInstantiationService,
|
@IInstantiationService protected readonly instantiationService: IInstantiationService,
|
||||||
@IEditorService private readonly editorService: IEditorService,
|
@IEditorService private readonly editorService: IEditorService,
|
||||||
@IUntitledTextEditorService private readonly untitledEditorService: IUntitledTextEditorService,
|
@IUntitledTextEditorService private readonly untitledEditorService: IUntitledTextEditorService,
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
@IConfigurationService protected readonly configurationService: IConfigurationService,
|
||||||
@IQueryModelService private readonly queryModelService: IQueryModelService,
|
@IQueryModelService private readonly queryModelService: IQueryModelService,
|
||||||
@IThemeService private readonly themeService: IThemeService
|
@IThemeService private readonly themeService: IThemeService
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -512,4 +512,7 @@ import 'sql/workbench/contrib/extensions/browser/extensions.contribution';
|
|||||||
// Azure
|
// Azure
|
||||||
import 'sql/workbench/contrib/azure/browser/azure.contribution';
|
import 'sql/workbench/contrib/azure/browser/azure.contribution';
|
||||||
|
|
||||||
|
// Charts
|
||||||
|
import 'sql/workbench/contrib/charts/browser/charts.contribution';
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user