mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add charting functionality to SQL notebooks. (#9306)
This commit is contained in:
@@ -28,6 +28,7 @@ import { ChartState } from 'sql/workbench/common/editor/query/chartState';
|
|||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { find } from 'vs/base/common/arrays';
|
import { find } from 'vs/base/common/arrays';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import { DbCellValue } from 'azdata';
|
||||||
|
|
||||||
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
||||||
|
|
||||||
@@ -198,6 +199,22 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
this.shouldGraph();
|
this.shouldGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setData(rows: DbCellValue[][], columns: string[]): void {
|
||||||
|
if (!rows) {
|
||||||
|
this._data = { columns: [], rows: [] };
|
||||||
|
this._notificationService.error(nls.localize('charting.failedToGetRows', "Failed to get rows for the dataset to chart."));
|
||||||
|
} else {
|
||||||
|
this._data = {
|
||||||
|
columns: columns,
|
||||||
|
rows: rows.map(r => r.map(c => c.displayValue))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.insight) {
|
||||||
|
this.insight.data = this._data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private shouldGraph() {
|
private shouldGraph() {
|
||||||
// Check if we have the necessary information
|
// Check if we have the necessary information
|
||||||
if (this._currentData && this._queryRunner) {
|
if (this._currentData && this._queryRunner) {
|
||||||
@@ -207,18 +224,9 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
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, summary.rowCount, this._currentData.batchId, this._currentData.resultId).then(d => {
|
||||||
if (!d.resultSubset.rows) { // be defensive against this
|
let rows = d.resultSubset.rows;
|
||||||
this._data = { columns: [], rows: [] };
|
let columns = summary.columnInfo.map(c => c.columnName);
|
||||||
this._notificationService.error(nls.localize('charting.failedToGetRows', "Failed to get rows for the dataset to chart."));
|
this.setData(rows, columns);
|
||||||
} else {
|
|
||||||
this._data = {
|
|
||||||
columns: summary.columnInfo.map(c => c.columnName),
|
|
||||||
rows: d.resultSubset.rows.map(r => r.map(c => c.displayValue))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (this.insight) {
|
|
||||||
this.insight.data = this._data;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionbar-container {
|
.actionbar-container {
|
||||||
@@ -25,6 +26,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.options-container {
|
.options-container {
|
||||||
width: 250px;
|
min-width: 250px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,16 +247,6 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
|
|||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Styling for all links in notebooks
|
|
||||||
const linkForeground = theme.getColor(textLinkForeground);
|
|
||||||
if (linkForeground) {
|
|
||||||
collector.addRule(`
|
|
||||||
.notebookEditor .scrollable a {
|
|
||||||
color: ${linkForeground};
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Styling for tables in notebooks
|
// Styling for tables in notebooks
|
||||||
const borderColor = theme.getColor(SIDE_BAR_BACKGROUND);
|
const borderColor = theme.getColor(SIDE_BAR_BACKGROUND);
|
||||||
if (borderColor) {
|
if (borderColor) {
|
||||||
@@ -269,6 +259,7 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
|
|||||||
|
|
||||||
// Styling for markdown cells & links in notebooks.
|
// Styling for markdown cells & links in notebooks.
|
||||||
// This matches the values used by default in all web views
|
// This matches the values used by default in all web views
|
||||||
|
const linkForeground = theme.getColor(textLinkForeground);
|
||||||
if (linkForeground) {
|
if (linkForeground) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
.notebookEditor a:link {
|
.notebookEditor a:link {
|
||||||
|
|||||||
@@ -28,16 +28,19 @@ import { GridTableState } from 'sql/workbench/common/editor/query/gridPanelState
|
|||||||
import { GridTableBase } from 'sql/workbench/contrib/query/browser/gridPanel';
|
import { GridTableBase } from 'sql/workbench/contrib/query/browser/gridPanel';
|
||||||
import { getErrorMessage } from 'vs/base/common/errors';
|
import { getErrorMessage } from 'vs/base/common/errors';
|
||||||
import { ISerializationService, SerializeDataParams } from 'sql/platform/serialization/common/serializationService';
|
import { ISerializationService, SerializeDataParams } from 'sql/platform/serialization/common/serializationService';
|
||||||
import { SaveResultAction } from 'sql/workbench/contrib/query/browser/actions';
|
import { SaveResultAction, IGridActionContext } from 'sql/workbench/contrib/query/browser/actions';
|
||||||
import { ResultSerializer, SaveResultsResponse, SaveFormat } from 'sql/workbench/services/query/common/resultSerializer';
|
import { ResultSerializer, SaveResultsResponse, SaveFormat } from 'sql/workbench/services/query/common/resultSerializer';
|
||||||
import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { values } from 'vs/base/common/collections';
|
import { values } from 'vs/base/common/collections';
|
||||||
import { assign } from 'vs/base/common/objects';
|
import { assign } from 'vs/base/common/objects';
|
||||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||||
|
import { ChartView } from 'sql/workbench/contrib/charts/browser/chartView';
|
||||||
|
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||||
|
import { ToggleableAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: GridOutputComponent.SELECTOR,
|
selector: GridOutputComponent.SELECTOR,
|
||||||
template: `<div #output class="notebook-cellTable" (mouseover)="hover=true" (mouseleave)="hover=false"></div>`
|
template: `<div #output class="notebook-cellTable"></div>`
|
||||||
})
|
})
|
||||||
export class GridOutputComponent extends AngularDisposable implements IMimeComponent, OnInit {
|
export class GridOutputComponent extends AngularDisposable implements IMimeComponent, OnInit {
|
||||||
public static readonly SELECTOR: string = 'grid-output';
|
public static readonly SELECTOR: string = 'grid-output';
|
||||||
@@ -48,7 +51,7 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
|
|||||||
private _cellModel: ICellModel;
|
private _cellModel: ICellModel;
|
||||||
private _bundleOptions: MimeModel.IOptions;
|
private _bundleOptions: MimeModel.IOptions;
|
||||||
private _table: DataResourceTable;
|
private _table: DataResourceTable;
|
||||||
private _hover: boolean;
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
||||||
@Inject(IThemeService) private readonly themeService: IThemeService
|
@Inject(IThemeService) private readonly themeService: IThemeService
|
||||||
@@ -76,14 +79,6 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input() set hover(value: boolean) {
|
|
||||||
// only reaction on hover changes
|
|
||||||
if (this._hover !== value) {
|
|
||||||
this.toggleActionbar(value);
|
|
||||||
this._hover = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.renderGrid();
|
this.renderGrid();
|
||||||
}
|
}
|
||||||
@@ -100,8 +95,7 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
|
|||||||
outputElement.appendChild(this._table.element);
|
outputElement.appendChild(this._table.element);
|
||||||
this._register(attachTableStyler(this._table, this.themeService));
|
this._register(attachTableStyler(this._table, this.themeService));
|
||||||
this.layout();
|
this.layout();
|
||||||
// By default, do not show the actions
|
|
||||||
this.toggleActionbar(false);
|
|
||||||
this._table.onAdd();
|
this._table.onAdd();
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
}
|
}
|
||||||
@@ -113,36 +107,26 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
|
|||||||
this._table.layout(maxSize, undefined, ActionsOrientation.HORIZONTAL);
|
this._table.layout(maxSize, undefined, ActionsOrientation.HORIZONTAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleActionbar(visible: boolean) {
|
|
||||||
let outputElement = <HTMLElement>this.output.nativeElement;
|
|
||||||
let actionsContainers: HTMLElement[] = Array.prototype.slice.call(outputElement.getElementsByClassName('actions-container'));
|
|
||||||
if (actionsContainers && actionsContainers.length) {
|
|
||||||
if (visible) {
|
|
||||||
actionsContainers.forEach(container => container.style.visibility = 'visible');
|
|
||||||
} else {
|
|
||||||
actionsContainers.forEach(container => container.style.visibility = 'hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataResourceTable extends GridTableBase<any> {
|
class DataResourceTable extends GridTableBase<any> {
|
||||||
|
|
||||||
private _gridDataProvider: IGridDataProvider;
|
private _gridDataProvider: IGridDataProvider;
|
||||||
|
private _chart: ChartView;
|
||||||
|
private _chartContainer: HTMLElement;
|
||||||
|
|
||||||
constructor(source: IDataResource,
|
constructor(source: IDataResource,
|
||||||
documentUri: string,
|
public readonly documentUri: string,
|
||||||
state: GridTableState,
|
state: GridTableState,
|
||||||
@IContextMenuService contextMenuService: IContextMenuService,
|
@IContextMenuService contextMenuService: IContextMenuService,
|
||||||
@IInstantiationService instantiationService: IInstantiationService,
|
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||||
@IEditorService editorService: IEditorService,
|
@IEditorService editorService: IEditorService,
|
||||||
@IUntitledTextEditorService untitledEditorService: IUntitledTextEditorService,
|
@IUntitledTextEditorService untitledEditorService: IUntitledTextEditorService,
|
||||||
@IConfigurationService configurationService: IConfigurationService,
|
@IConfigurationService configurationService: IConfigurationService
|
||||||
@ISerializationService private _serializationService: ISerializationService
|
|
||||||
) {
|
) {
|
||||||
super(state, createResultSet(source), contextMenuService, instantiationService, editorService, untitledEditorService, configurationService);
|
super(state, createResultSet(source), contextMenuService, instantiationService, editorService, untitledEditorService, configurationService);
|
||||||
this._gridDataProvider = this.instantiationService.createInstance(DataResourceDataProvider, source, this.resultSet, documentUri);
|
this._gridDataProvider = this.instantiationService.createInstance(DataResourceDataProvider, source, this.resultSet, this.documentUri);
|
||||||
|
this._chart = this.instantiationService.createInstance(ChartView);
|
||||||
}
|
}
|
||||||
|
|
||||||
get gridDataProvider(): IGridDataProvider {
|
get gridDataProvider(): IGridDataProvider {
|
||||||
@@ -154,14 +138,12 @@ class DataResourceTable extends GridTableBase<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getContextActions(): IAction[] {
|
protected getContextActions(): IAction[] {
|
||||||
if (!this._serializationService.hasProvider()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV),
|
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV),
|
||||||
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL),
|
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL),
|
||||||
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON),
|
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON),
|
||||||
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML),
|
this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML),
|
||||||
|
this.instantiationService.createInstance(NotebookChartAction, this)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +152,33 @@ class DataResourceTable extends GridTableBase<any> {
|
|||||||
// When we add this back in, we should update this calculation
|
// When we add this back in, we should update this calculation
|
||||||
return Math.max(this.maxSize, /* ACTIONBAR_HEIGHT + BOTTOM_PADDING */ 0);
|
return Math.max(this.maxSize, /* ACTIONBAR_HEIGHT + BOTTOM_PADDING */ 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public layout(size?: number, orientation?: Orientation, actionsOrientation?: ActionsOrientation): void {
|
||||||
|
super.layout(size, orientation, actionsOrientation);
|
||||||
|
|
||||||
|
if (!this._chartContainer) {
|
||||||
|
this._chartContainer = document.createElement('div');
|
||||||
|
this._chartContainer.style.display = 'none';
|
||||||
|
this._chartContainer.style.width = '100%';
|
||||||
|
|
||||||
|
this.element.appendChild(this._chartContainer);
|
||||||
|
this._chart.render(this._chartContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleChartVisibility(): void {
|
||||||
|
if (this.tableContainer.style.display !== 'none') {
|
||||||
|
this.tableContainer.style.display = 'none';
|
||||||
|
this._chartContainer.style.display = 'inline-block';
|
||||||
|
} else {
|
||||||
|
this.tableContainer.style.display = 'inline-block';
|
||||||
|
this._chartContainer.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get chart(): ChartView {
|
||||||
|
return this._chart;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataResourceDataProvider implements IGridDataProvider {
|
class DataResourceDataProvider implements IGridDataProvider {
|
||||||
@@ -252,7 +261,6 @@ class DataResourceDataProvider implements IGridDataProvider {
|
|||||||
return this._serializationService.hasProvider();
|
return this._serializationService.hasProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
serializeResults(format: SaveFormat, selection: Slick.Range[]): Thenable<void> {
|
serializeResults(format: SaveFormat, selection: Slick.Range[]): Thenable<void> {
|
||||||
let serializer = this._instantiationService.createInstance(ResultSerializer);
|
let serializer = this._instantiationService.createInstance(ResultSerializer);
|
||||||
return serializer.handleSerialization(this.documentUri, format, (filePath) => this.doSerialize(serializer, filePath, format, selection));
|
return serializer.handleSerialization(this.documentUri, format, (filePath) => this.doSerialize(serializer, filePath, format, selection));
|
||||||
@@ -375,3 +383,37 @@ class SimpleDbColumn implements azdata.IDbColumn {
|
|||||||
udtAssemblyQualifiedName: string;
|
udtAssemblyQualifiedName: string;
|
||||||
dataTypeName: string;
|
dataTypeName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NotebookChartAction extends ToggleableAction {
|
||||||
|
public static ID = 'notebook.showChart';
|
||||||
|
public static SHOWCHART_LABEL = localize('notebook.showChart', "Show chart");
|
||||||
|
public static SHOWCHART_ICON = 'viewChart';
|
||||||
|
|
||||||
|
public static HIDECHART_LABEL = localize('notebook.hideChart', "Hide chart");
|
||||||
|
public static HIDECHART_ICON = 'close';
|
||||||
|
|
||||||
|
constructor(private resourceTable: DataResourceTable) {
|
||||||
|
super(NotebookChartAction.ID, {
|
||||||
|
toggleOnLabel: NotebookChartAction.HIDECHART_LABEL,
|
||||||
|
toggleOnClass: NotebookChartAction.HIDECHART_ICON,
|
||||||
|
toggleOffLabel: NotebookChartAction.SHOWCHART_LABEL,
|
||||||
|
toggleOffClass: NotebookChartAction.SHOWCHART_ICON,
|
||||||
|
isOn: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(context: IGridActionContext): Promise<boolean> {
|
||||||
|
this.resourceTable.toggleChartVisibility();
|
||||||
|
this.toggle(!this.state.isOn);
|
||||||
|
if (this.state.isOn) {
|
||||||
|
let rowCount = context.table.getData().getLength();
|
||||||
|
let range = new Slick.Range(0, 0, rowCount - 1, context.table.columns.length - 1);
|
||||||
|
let columns = context.gridDataProvider.getColumnHeaders(range);
|
||||||
|
|
||||||
|
context.gridDataProvider.getRowData(0, rowCount).then(result => {
|
||||||
|
this.resourceTable.chart.setData(result.resultSubset.rows, columns);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export class SaveResultAction extends Action {
|
|||||||
public async run(context: IGridActionContext): Promise<boolean> {
|
public async run(context: IGridActionContext): Promise<boolean> {
|
||||||
if (!context.gridDataProvider.canSerialize) {
|
if (!context.gridDataProvider.canSerialize) {
|
||||||
this.notificationService.warn(localize('saveToFileNotSupported', "Save to file is not supported by the backing data source"));
|
this.notificationService.warn(localize('saveToFileNotSupported', "Save to file is not supported by the backing data source"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await context.gridDataProvider.serializeResults(this.format, mapForNumberColumn(context.selection));
|
await context.gridDataProvider.serializeResults(this.format, mapForNumberColumn(context.selection));
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
|||||||
|
|
||||||
public id = generateUuid();
|
public id = generateUuid();
|
||||||
readonly element: HTMLElement = this.container;
|
readonly element: HTMLElement = this.container;
|
||||||
|
protected tableContainer: HTMLElement;
|
||||||
|
|
||||||
private _state: GridTableState;
|
private _state: GridTableState;
|
||||||
|
|
||||||
@@ -366,7 +367,6 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
this.container.style.width = '100%';
|
this.container.style.width = '100%';
|
||||||
this.container.style.height = '100%';
|
this.container.style.height = '100%';
|
||||||
this.container.className = 'grid-panel';
|
|
||||||
|
|
||||||
this.columns = this.resultSet.columnInfo.map((c, i) => {
|
this.columns = this.resultSet.columnInfo.map((c, i) => {
|
||||||
let isLinked = c.isXml || c.isJson;
|
let isLinked = c.isXml || c.isJson;
|
||||||
@@ -435,11 +435,12 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
|||||||
this.container.appendChild(actionBarContainer);
|
this.container.appendChild(actionBarContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tableContainer = document.createElement('div');
|
this.tableContainer = document.createElement('div');
|
||||||
tableContainer.style.display = 'inline-block';
|
this.tableContainer.className = 'grid-panel';
|
||||||
tableContainer.style.width = `calc(100% - ${ACTIONBAR_WIDTH}px)`;
|
this.tableContainer.style.display = 'inline-block';
|
||||||
|
this.tableContainer.style.width = `calc(100% - ${ACTIONBAR_WIDTH}px)`;
|
||||||
|
|
||||||
this.container.appendChild(tableContainer);
|
this.container.appendChild(this.tableContainer);
|
||||||
|
|
||||||
let collection = new VirtualizedCollection(
|
let collection = new VirtualizedCollection(
|
||||||
50,
|
50,
|
||||||
@@ -463,7 +464,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
|||||||
defaultColumnWidth: 120
|
defaultColumnWidth: 120
|
||||||
};
|
};
|
||||||
this.dataProvider = new AsyncDataProvider(collection);
|
this.dataProvider = new AsyncDataProvider(collection);
|
||||||
this.table = this._register(new Table(tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions));
|
this.table = this._register(new Table(this.tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions));
|
||||||
this.table.setTableTitle(localize('resultsGrid', "Results grid"));
|
this.table.setTableTitle(localize('resultsGrid', "Results grid"));
|
||||||
this.table.setSelectionModel(this.selectionModel);
|
this.table.setSelectionModel(this.selectionModel);
|
||||||
this.table.registerPlugin(new MouseWheelSupport());
|
this.table.registerPlugin(new MouseWheelSupport());
|
||||||
|
|||||||
Reference in New Issue
Block a user