mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-27 09:35:37 -05:00
move code from parts to contrib (#8319)
This commit is contained in:
27
src/sql/workbench/contrib/query/common/constants.ts
Normal file
27
src/sql/workbench/contrib/query/common/constants.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const copyIncludeHeaders = 'copyIncludeHeaders';
|
||||
export const configSaveAsCsv = 'saveAsCsv';
|
||||
export const configSaveAsXml = 'saveAsXml';
|
||||
export const configCopyRemoveNewLine = 'copyRemoveNewLine';
|
||||
export const configShowBatchTime = 'showBatchTime';
|
||||
export const querySection = 'query';
|
||||
export const shortcutStart = 'shortcut';
|
||||
|
||||
export const tabColorModeOff = 'off';
|
||||
export const tabColorModeBorder = 'border';
|
||||
export const tabColorModeFill = 'fill';
|
||||
|
||||
export const defaultChartType = 'defaultChartType';
|
||||
export const chartTypeBar = 'bar';
|
||||
export const chartTypeDoughnut = 'doughnut';
|
||||
export const chartTypeHorizontalBar = 'horizontalBar';
|
||||
export const chartTypeLine = 'line';
|
||||
export const chartTypePie = 'pie';
|
||||
export const chartTypeScatter = 'scatter';
|
||||
export const chartTypeTimeSeries = 'timeSeries';
|
||||
export const allChartTypes = [chartTypeBar, chartTypeDoughnut, chartTypeHorizontalBar, chartTypeLine,
|
||||
chartTypePie, chartTypeScatter, chartTypeTimeSeries];
|
||||
64
src/sql/workbench/contrib/query/common/gridPanelState.ts
Normal file
64
src/sql/workbench/contrib/query/common/gridPanelState.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class GridPanelState {
|
||||
public tableStates: GridTableState[] = [];
|
||||
public scrollPosition: number;
|
||||
|
||||
dispose() {
|
||||
dispose(this.tableStates);
|
||||
}
|
||||
}
|
||||
|
||||
export class GridTableState extends Disposable {
|
||||
|
||||
private _maximized: boolean;
|
||||
|
||||
private _onMaximizedChange = this._register(new Emitter<boolean>());
|
||||
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
|
||||
|
||||
private _onCanBeMaximizedChange = this._register(new Emitter<boolean>());
|
||||
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
|
||||
|
||||
private _canBeMaximized: boolean;
|
||||
|
||||
/* The top row of the current scroll */
|
||||
public scrollPositionY = 0;
|
||||
public scrollPositionX = 0;
|
||||
public columnSizes?: number[] = undefined;
|
||||
public selection: Slick.Range[];
|
||||
public activeCell: Slick.Cell;
|
||||
|
||||
constructor(public readonly resultId: number, public readonly batchId: number) {
|
||||
super();
|
||||
}
|
||||
|
||||
public get canBeMaximized(): boolean {
|
||||
return this._canBeMaximized;
|
||||
}
|
||||
|
||||
public set canBeMaximized(val: boolean) {
|
||||
if (val === this._canBeMaximized) {
|
||||
return;
|
||||
}
|
||||
this._canBeMaximized = val;
|
||||
this._onCanBeMaximizedChange.fire(val);
|
||||
}
|
||||
|
||||
public get maximized(): boolean {
|
||||
return this._maximized;
|
||||
}
|
||||
|
||||
public set maximized(val: boolean) {
|
||||
if (val === this._maximized) {
|
||||
return;
|
||||
}
|
||||
this._maximized = val;
|
||||
this._onMaximizedChange.fire(val);
|
||||
}
|
||||
}
|
||||
39
src/sql/workbench/contrib/query/common/localizedConstants.ts
Normal file
39
src/sql/workbench/contrib/query/common/localizedConstants.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
// localizable strings
|
||||
|
||||
export const runQueryBatchStartMessage = localize('runQueryBatchStartMessage', "Started executing query at ");
|
||||
export const runQueryBatchStartLine = localize('runQueryBatchStartLine', "Line {0}");
|
||||
|
||||
export const msgCancelQueryFailed = localize('msgCancelQueryFailed', "Canceling the query failed: {0}");
|
||||
|
||||
export const msgSaveStarted = localize('msgSaveStarted', "Started saving results to ");
|
||||
export const msgSaveFailed = localize('msgSaveFailed', "Failed to save results. ");
|
||||
export const msgSaveSucceeded = localize('msgSaveSucceeded', "Successfully saved results to ");
|
||||
|
||||
export const msgStatusRunQueryInProgress = localize('msgStatusRunQueryInProgress', "Executing query...");
|
||||
|
||||
// /** Results Pane Labels */
|
||||
export const maximizeLabel = localize('maximizeLabel', "Maximize");
|
||||
export const restoreLabel = localize('resultsPane.restoreLabel', "Restore");
|
||||
export const saveCSVLabel = localize('saveCSVLabel', "Save as CSV");
|
||||
export const saveJSONLabel = localize('saveJSONLabel', "Save as JSON");
|
||||
export const saveExcelLabel = localize('saveExcelLabel', "Save as Excel");
|
||||
export const saveXMLLabel = localize('saveXMLLabel', "Save as XML");
|
||||
export const viewChartLabel = localize('viewChartLabel', "View as Chart");
|
||||
export const viewVisualizerLabel = localize('viewVisualizerLabel', "Visualize");
|
||||
|
||||
export const resultPaneLabel = localize('resultPaneLabel', "Results");
|
||||
export const executeQueryLabel = localize('executeQueryLabel', "Executing query ");
|
||||
|
||||
/** Messages Pane Labels */
|
||||
export const messagePaneLabel = localize('messagePaneLabel', "Messages");
|
||||
export const elapsedTimeLabel = localize('elapsedTimeLabel', "Total execution time: {0}");
|
||||
|
||||
/** Warning message for save icons */
|
||||
export const msgCannotSaveMultipleSelections = localize('msgCannotSaveMultipleSelections', "Save results command cannot be used with multiple selections.");
|
||||
12
src/sql/workbench/contrib/query/common/messagePanelState.ts
Normal file
12
src/sql/workbench/contrib/query/common/messagePanelState.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class MessagePanelState {
|
||||
public scrollPosition: number;
|
||||
|
||||
dispose() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 class QueryModelViewState {
|
||||
public componentId: string;
|
||||
public dispose() {
|
||||
}
|
||||
}
|
||||
19
src/sql/workbench/contrib/query/common/queryContext.ts
Normal file
19
src/sql/workbench/contrib/query/common/queryContext.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
/**
|
||||
* Context Keys to use with keybindings for the results grid and messages used in query and edit data views
|
||||
*/
|
||||
export const queryEditorVisibleId = 'queryEditorVisible';
|
||||
export const resultsVisibleId = 'resultsVisible';
|
||||
export const resultsGridFocussedId = 'resultsGridFocussed';
|
||||
export const resultsMessagesFocussedId = 'resultsMessagesFocussed';
|
||||
|
||||
export const QueryEditorVisibleContext = new RawContextKey<boolean>(queryEditorVisibleId, false);
|
||||
export const ResultsVisibleContext = new RawContextKey<boolean>(resultsVisibleId, false);
|
||||
export const ResultsGridFocussedContext = new RawContextKey<boolean>(resultsGridFocussedId, false);
|
||||
export const ResultsMessagesFocussedContext = new RawContextKey<boolean>(resultsMessagesFocussedId, false);
|
||||
366
src/sql/workbench/contrib/query/common/queryInput.ts
Normal file
366
src/sql/workbench/contrib/query/common/queryInput.ts
Normal file
@@ -0,0 +1,366 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||
import { EditorInput, ConfirmResult, EncodingMode, IEncodingSupport } from 'vs/workbench/common/editor';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
import { IConnectionManagementService, IConnectableInput, INewConnectionParams, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
|
||||
import { QueryResultsInput } from 'sql/workbench/contrib/query/common/queryResultsInput';
|
||||
import { IQueryModelService } from 'sql/platform/query/common/queryModel';
|
||||
|
||||
import { ISelectionData, ExecutionPlanOptions } from 'azdata';
|
||||
import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel';
|
||||
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
|
||||
const MAX_SIZE = 13;
|
||||
|
||||
type PublicPart<T> = { [K in keyof T]: T[K] };
|
||||
|
||||
function trimTitle(title: string): string {
|
||||
const length = title.length;
|
||||
const diff = length - MAX_SIZE;
|
||||
|
||||
if (diff <= 0) {
|
||||
return title;
|
||||
} else {
|
||||
const start = (length / 2) - (diff / 2);
|
||||
return title.slice(0, start) + '...' + title.slice(start + diff, length);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IQueryEditorStateChange {
|
||||
connectedChange?: boolean;
|
||||
resultsVisibleChange?: boolean;
|
||||
executingChange?: boolean;
|
||||
connectingChange?: boolean;
|
||||
sqlCmdModeChanged?: boolean;
|
||||
}
|
||||
|
||||
export class QueryEditorState extends Disposable {
|
||||
private _connected = false;
|
||||
private _isSqlCmdMode = false;
|
||||
private _resultsVisible = false;
|
||||
private _executing = false;
|
||||
private _connecting = false;
|
||||
|
||||
private _onChange = this._register(new Emitter<IQueryEditorStateChange>());
|
||||
public onChange = this._onChange.event;
|
||||
|
||||
public set connected(val: boolean) {
|
||||
if (val !== this._connected) {
|
||||
this._connected = val;
|
||||
this._onChange.fire({ connectedChange: true });
|
||||
}
|
||||
}
|
||||
|
||||
public get connected(): boolean {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
public set connecting(val: boolean) {
|
||||
if (val !== this._connecting) {
|
||||
this._connecting = val;
|
||||
this._onChange.fire({ connectingChange: true });
|
||||
}
|
||||
}
|
||||
|
||||
public get connecting(): boolean {
|
||||
return this._connecting;
|
||||
}
|
||||
|
||||
public set resultsVisible(val: boolean) {
|
||||
if (val !== this._resultsVisible) {
|
||||
this._resultsVisible = val;
|
||||
this._onChange.fire({ resultsVisibleChange: true });
|
||||
}
|
||||
}
|
||||
|
||||
public get resultsVisible(): boolean {
|
||||
return this._resultsVisible;
|
||||
}
|
||||
|
||||
public set executing(val: boolean) {
|
||||
if (val !== this._executing) {
|
||||
this._executing = val;
|
||||
this._onChange.fire({ executingChange: true });
|
||||
}
|
||||
}
|
||||
|
||||
public get executing(): boolean {
|
||||
return this._executing;
|
||||
}
|
||||
|
||||
public set isSqlCmdMode(val: boolean) {
|
||||
if (val !== this._isSqlCmdMode) {
|
||||
this._isSqlCmdMode = val;
|
||||
this._onChange.fire({ sqlCmdModeChanged: true });
|
||||
}
|
||||
}
|
||||
|
||||
public get isSqlCmdMode(): boolean {
|
||||
return this._isSqlCmdMode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Input for the QueryEditor. This input is simply a wrapper around a QueryResultsInput for the QueryResultsEditor
|
||||
* and a UntitledEditorInput for the SQL File Editor.
|
||||
*/
|
||||
export class QueryInput extends EditorInput implements IEncodingSupport, IConnectableInput, PublicPart<UntitledEditorInput>, IDisposable {
|
||||
|
||||
public static ID: string = 'workbench.editorinputs.queryInput';
|
||||
public static SCHEMA: string = 'sql';
|
||||
|
||||
private _state = this._register(new QueryEditorState());
|
||||
public get state(): QueryEditorState { return this._state; }
|
||||
|
||||
private _updateSelection: Emitter<ISelectionData>;
|
||||
|
||||
constructor(
|
||||
private _description: string,
|
||||
private _sql: UntitledEditorInput,
|
||||
private _results: QueryResultsInput,
|
||||
private _connectionProviderName: string,
|
||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||
@IQueryModelService private _queryModelService: IQueryModelService,
|
||||
@IConfigurationService private _configurationService: IConfigurationService,
|
||||
@IFileService private _fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
this._updateSelection = new Emitter<ISelectionData>();
|
||||
|
||||
this._register(this._sql);
|
||||
this._register(this._results);
|
||||
|
||||
// re-emit sql editor events through this editor if it exists
|
||||
if (this._sql) {
|
||||
this._register(this._sql.onDidChangeDirty(() => this._onDidChangeDirty.fire()));
|
||||
}
|
||||
|
||||
// Attach to event callbacks
|
||||
if (this._queryModelService) {
|
||||
// Register callbacks for the Actions
|
||||
this._register(
|
||||
this._queryModelService.onRunQueryStart(uri => {
|
||||
if (this.uri === uri) {
|
||||
this.onRunQuery();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this._register(
|
||||
this._queryModelService.onRunQueryComplete(uri => {
|
||||
if (this.uri === uri) {
|
||||
this.onQueryComplete();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (this._connectionManagementService) {
|
||||
this._register(this._connectionManagementService.onDisconnect(result => {
|
||||
if (result.connectionUri === this.uri) {
|
||||
this.onDisconnect();
|
||||
}
|
||||
}));
|
||||
if (this.uri) {
|
||||
if (this._connectionProviderName) {
|
||||
this._connectionManagementService.doChangeLanguageFlavor(this.uri, 'sql', this._connectionProviderName);
|
||||
} else {
|
||||
this._connectionManagementService.ensureDefaultLanguageFlavor(this.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._configurationService) {
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('sql.showConnectionInfoInTitle')) {
|
||||
this._onDidChangeLabel.fire();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this.onDisconnect();
|
||||
this.onQueryComplete();
|
||||
}
|
||||
|
||||
// Getters for private properties
|
||||
public get uri(): string { return this.getResource().toString(true); }
|
||||
public get sql(): UntitledEditorInput { return this._sql; }
|
||||
public get results(): QueryResultsInput { return this._results; }
|
||||
public updateSelection(selection: ISelectionData): void { this._updateSelection.fire(selection); }
|
||||
public getTypeId(): string { return QueryInput.ID; }
|
||||
// Description is shown beside the tab name in the combobox of open editors
|
||||
public getDescription(): string { return this._description; }
|
||||
public supportsSplitEditor(): boolean { return false; }
|
||||
public getMode(): string { return QueryInput.SCHEMA; }
|
||||
public revert(): Promise<boolean> { return this._sql.revert(); }
|
||||
public setMode(mode: string) {
|
||||
this._sql.setMode(mode);
|
||||
}
|
||||
|
||||
public matches(otherInput: any): boolean {
|
||||
if (otherInput instanceof QueryInput) {
|
||||
return this._sql.matches(otherInput.sql);
|
||||
}
|
||||
|
||||
return this._sql.matches(otherInput);
|
||||
}
|
||||
|
||||
// Forwarding resource functions to the inline sql file editor
|
||||
public get onDidModelChangeContent(): Event<void> { return this._sql.onDidModelChangeContent; }
|
||||
public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; }
|
||||
public resolve(): Promise<UntitledEditorModel & IResolvedTextEditorModel> { return this._sql.resolve(); }
|
||||
public save(): Promise<boolean> { return this._sql.save(); }
|
||||
public isDirty(): boolean { return this._sql.isDirty(); }
|
||||
public confirmSave(): Promise<ConfirmResult> { return this._sql.confirmSave(); }
|
||||
public getResource(): URI { return this._sql.getResource(); }
|
||||
public getEncoding(): string { return this._sql.getEncoding(); }
|
||||
public suggestFileName(): string { return this._sql.suggestFileName(); }
|
||||
hasBackup(): boolean {
|
||||
if (this.sql) {
|
||||
return this.sql.hasBackup();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public matchInputInstanceType(inputType: any): boolean {
|
||||
return (this._sql instanceof inputType);
|
||||
}
|
||||
|
||||
public inputFileExists(): Promise<boolean> {
|
||||
return this._fileService.exists(this.getResource());
|
||||
}
|
||||
|
||||
public getName(longForm?: boolean): string {
|
||||
if (this._configurationService.getValue('sql.showConnectionInfoInTitle')) {
|
||||
let profile = this._connectionManagementService.getConnectionProfile(this.uri);
|
||||
let title = '';
|
||||
if (this._description && this._description !== '') {
|
||||
title = this._description + ' ';
|
||||
}
|
||||
if (profile) {
|
||||
if (profile.userName) {
|
||||
title += `${profile.serverName}.${profile.databaseName} (${profile.userName})`;
|
||||
} else {
|
||||
title += `${profile.serverName}.${profile.databaseName} (${profile.authenticationType})`;
|
||||
}
|
||||
} else {
|
||||
title += localize('disconnected', "disconnected");
|
||||
}
|
||||
return this._sql.getName() + (longForm ? (' - ' + title) : ` - ${trimTitle(title)}`);
|
||||
} else {
|
||||
return this._sql.getName();
|
||||
}
|
||||
}
|
||||
|
||||
// Called to get the tooltip of the tab
|
||||
public getTitle() {
|
||||
return this.getName(true);
|
||||
}
|
||||
|
||||
public get hasAssociatedFilePath(): boolean { return this._sql.hasAssociatedFilePath; }
|
||||
|
||||
public setEncoding(encoding: string, mode: EncodingMode /* ignored, we only have Encode */): void {
|
||||
this._sql.setEncoding(encoding, mode);
|
||||
}
|
||||
|
||||
// State update funtions
|
||||
public runQuery(selection?: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
|
||||
this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions);
|
||||
this.state.executing = true;
|
||||
}
|
||||
|
||||
public runQueryStatement(selection?: ISelectionData): void {
|
||||
this._queryModelService.runQueryStatement(this.uri, selection, this);
|
||||
this.state.executing = true;
|
||||
}
|
||||
|
||||
public runQueryString(text: string): void {
|
||||
this._queryModelService.runQueryString(this.uri, text, this);
|
||||
this.state.executing = true;
|
||||
}
|
||||
|
||||
public onConnectStart(): void {
|
||||
this.state.connecting = true;
|
||||
this.state.connected = false;
|
||||
}
|
||||
|
||||
public onConnectReject(): void {
|
||||
this.state.connecting = false;
|
||||
this.state.connected = false;
|
||||
}
|
||||
|
||||
public onConnectCanceled(): void {
|
||||
// If we're currently connecting and then cancel, set connected state to false
|
||||
// Otherwise, keep connected state as it was
|
||||
if (this.state.connecting) {
|
||||
this.state.connected = false;
|
||||
}
|
||||
this.state.connecting = false;
|
||||
}
|
||||
|
||||
public onConnectSuccess(params?: INewConnectionParams): void {
|
||||
this.state.connected = true;
|
||||
this.state.connecting = false;
|
||||
|
||||
let isRunningQuery = this._queryModelService.isRunningQuery(this.uri);
|
||||
if (!isRunningQuery && params && params.runQueryOnCompletion) {
|
||||
let selection: ISelectionData | undefined = params ? params.querySelection : undefined;
|
||||
if (params.runQueryOnCompletion === RunQueryOnConnectionMode.executeCurrentQuery) {
|
||||
this.runQueryStatement(selection);
|
||||
} else if (params.runQueryOnCompletion === RunQueryOnConnectionMode.executeQuery) {
|
||||
this.runQuery(selection);
|
||||
} else if (params.runQueryOnCompletion === RunQueryOnConnectionMode.estimatedQueryPlan) {
|
||||
this.runQuery(selection, { displayEstimatedQueryPlan: true });
|
||||
} else if (params.runQueryOnCompletion === RunQueryOnConnectionMode.actualQueryPlan) {
|
||||
this.runQuery(selection, { displayActualQueryPlan: true });
|
||||
}
|
||||
}
|
||||
this._onDidChangeLabel.fire();
|
||||
}
|
||||
|
||||
public onDisconnect(): void {
|
||||
this.state.connected = false;
|
||||
this._onDidChangeLabel.fire();
|
||||
}
|
||||
|
||||
public onRunQuery(): void {
|
||||
this.state.executing = true;
|
||||
this.state.resultsVisible = true;
|
||||
}
|
||||
|
||||
public onQueryComplete(): void {
|
||||
this.state.executing = false;
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._queryModelService.disposeQuery(this.uri);
|
||||
this._connectionManagementService.disconnectEditor(this, true);
|
||||
|
||||
this._sql.close();
|
||||
this._results.close();
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color that should be displayed
|
||||
*/
|
||||
public get tabColor(): string {
|
||||
return this._connectionManagementService.getTabColorForUri(this.uri);
|
||||
}
|
||||
|
||||
public get isSharedSession(): boolean {
|
||||
return !!(this.uri && startsWith(this.uri, 'vsls:'));
|
||||
}
|
||||
}
|
||||
98
src/sql/workbench/contrib/query/common/queryResultsInput.ts
Normal file
98
src/sql/workbench/contrib/query/common/queryResultsInput.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { EditorInput } from 'vs/workbench/common/editor';
|
||||
|
||||
import { TopOperationsState } from 'sql/workbench/contrib/queryPlan/common/topOperationsState';
|
||||
import { ChartState } from 'sql/workbench/contrib/charts/common/interfaces';
|
||||
import { QueryPlanState } from 'sql/workbench/contrib/queryPlan/common/queryPlanState';
|
||||
import { MessagePanelState } from 'sql/workbench/contrib/query/common/messagePanelState';
|
||||
import { GridPanelState } from 'sql/workbench/contrib/query/common/gridPanelState';
|
||||
import { QueryModelViewState } from 'sql/workbench/contrib/query/common/modelViewTab/modelViewState';
|
||||
|
||||
export class ResultsViewState {
|
||||
public readonly gridPanelState: GridPanelState = new GridPanelState();
|
||||
public readonly messagePanelState: MessagePanelState = new MessagePanelState();
|
||||
public readonly chartState: ChartState = new ChartState();
|
||||
public readonly queryPlanState: QueryPlanState = new QueryPlanState();
|
||||
public readonly topOperationsState = new TopOperationsState();
|
||||
public readonly dynamicModelViewTabsState: Map<string, QueryModelViewState> = new Map<string, QueryModelViewState>();
|
||||
|
||||
public activeTab: string;
|
||||
public readonly visibleTabs: Set<string> = new Set<string>();
|
||||
|
||||
dispose() {
|
||||
this.gridPanelState.dispose();
|
||||
this.messagePanelState.dispose();
|
||||
this.chartState.dispose();
|
||||
this.queryPlanState.dispose();
|
||||
this.dynamicModelViewTabsState.forEach((state: QueryModelViewState, identifier: string) => {
|
||||
state.dispose();
|
||||
});
|
||||
this.dynamicModelViewTabsState.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Input for the QueryResultsEditor. This input helps with logic for the viewing and editing of
|
||||
* data in the results grid.
|
||||
*/
|
||||
export class QueryResultsInput extends EditorInput {
|
||||
|
||||
private _state?= new ResultsViewState();
|
||||
|
||||
public get state(): ResultsViewState | undefined {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
constructor(private _uri: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.state!.dispose();
|
||||
this._state = undefined;
|
||||
super.close();
|
||||
}
|
||||
|
||||
getTypeId(): string {
|
||||
return QueryResultsInput.ID;
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return localize('extensionsInputName', "Extension");
|
||||
}
|
||||
|
||||
matches(other: any): boolean {
|
||||
if (other instanceof QueryResultsInput) {
|
||||
return (other._uri === this._uri);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
resolve(refresh?: boolean): Promise<any> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
supportsSplitEditor(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
//// Properties
|
||||
|
||||
static get ID() {
|
||||
return 'workbench.query.queryResultsInput';
|
||||
}
|
||||
|
||||
get uri(): string {
|
||||
return this._uri;
|
||||
}
|
||||
}
|
||||
379
src/sql/workbench/contrib/query/common/resultSerializer.ts
Normal file
379
src/sql/workbench/contrib/query/common/resultSerializer.ts
Normal file
@@ -0,0 +1,379 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as ConnectionConstants from 'sql/platform/connection/common/constants';
|
||||
import * as LocalizedConstants from 'sql/workbench/contrib/query/common/localizedConstants';
|
||||
import { SaveResultsRequestParams } from 'azdata';
|
||||
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
|
||||
import { ISaveRequest, SaveFormat } from 'sql/workbench/contrib/grid/common/interfaces';
|
||||
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { getBaseLabel } from 'vs/base/common/labels';
|
||||
import { ShowFileInFolderAction, OpenFileInFolderAction } from 'sql/workbench/common/workspaceActions';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { getRootPath, resolveCurrentDirectory, resolveFilePath } from 'sql/platform/common/pathUtilities';
|
||||
import { IOutputService, IOutputChannelRegistry, IOutputChannel, Extensions as OutputExtensions } from 'vs/workbench/contrib/output/common/output';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFileDialogService, FileFilter } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
let prevSavePath: string;
|
||||
|
||||
|
||||
export interface SaveResultsResponse {
|
||||
succeeded: boolean;
|
||||
messages?: string;
|
||||
}
|
||||
|
||||
interface ICsvConfig {
|
||||
includeHeaders: boolean;
|
||||
delimiter: string;
|
||||
lineSeperator: string;
|
||||
textIdentifier: string;
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
interface IXmlConfig {
|
||||
formatted: boolean;
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles save results request from the context menu of slickGrid
|
||||
*/
|
||||
export class ResultSerializer {
|
||||
public static tempFileCount: number = 1;
|
||||
|
||||
constructor(
|
||||
@IOutputService private _outputService: IOutputService,
|
||||
@IQueryManagementService private _queryManagementService: IQueryManagementService,
|
||||
@IConfigurationService private _configurationService: IConfigurationService,
|
||||
@IEditorService private _editorService: IEditorService,
|
||||
@IWorkspaceContextService private _contextService: IWorkspaceContextService,
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Handle save request by getting filename from user and sending request to service
|
||||
*/
|
||||
public saveResults(uri: string, saveRequest: ISaveRequest): Promise<void> {
|
||||
const self = this;
|
||||
return this.promptForFilepath(saveRequest.format, uri).then(filePath => {
|
||||
if (filePath) {
|
||||
if (!path.isAbsolute(filePath)) {
|
||||
filePath = resolveFilePath(uri, filePath, this.rootPath)!;
|
||||
}
|
||||
let saveResultsParams = this.getParameters(uri, filePath, saveRequest.batchIndex, saveRequest.resultSetNumber, saveRequest.format, saveRequest.selection ? saveRequest.selection[0] : undefined);
|
||||
let sendRequest = () => this.sendSaveRequestToService(saveResultsParams);
|
||||
return self.doSave(filePath, saveRequest.format, sendRequest);
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
private async sendSaveRequestToService(saveResultsParams: SaveResultsRequestParams): Promise<SaveResultsResponse> {
|
||||
let result = await this._queryManagementService.saveResults(saveResultsParams);
|
||||
return {
|
||||
succeeded: !result.messages,
|
||||
messages: result.messages
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle save request by getting filename from user and sending request to service
|
||||
*/
|
||||
public handleSerialization(uri: string, format: SaveFormat, sendRequest: ((filePath: string) => Promise<SaveResultsResponse | undefined>)): Thenable<void> {
|
||||
const self = this;
|
||||
return this.promptForFilepath(format, uri).then(filePath => {
|
||||
if (filePath) {
|
||||
if (!path.isAbsolute(filePath)) {
|
||||
filePath = resolveFilePath(uri, filePath, this.rootPath)!;
|
||||
}
|
||||
return self.doSave(filePath, format, () => sendRequest(filePath!));
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
private ensureOutputChannelExists(): void {
|
||||
Registry.as<IOutputChannelRegistry>(OutputExtensions.OutputChannels)
|
||||
.registerChannel({
|
||||
id: ConnectionConstants.outputChannelName,
|
||||
label: ConnectionConstants.outputChannelName,
|
||||
log: true
|
||||
});
|
||||
}
|
||||
|
||||
private get outputChannel(): IOutputChannel {
|
||||
this.ensureOutputChannelExists();
|
||||
return this._outputService.getChannel(ConnectionConstants.outputChannelName)!;
|
||||
}
|
||||
|
||||
private get rootPath(): string | undefined {
|
||||
return getRootPath(this._contextService);
|
||||
}
|
||||
|
||||
private logToOutputChannel(message: string): void {
|
||||
this.outputChannel.append(message);
|
||||
}
|
||||
|
||||
|
||||
private promptForFilepath(format: SaveFormat, resourceUri: string): Promise<string | undefined> {
|
||||
let filepathPlaceHolder = prevSavePath ? path.dirname(prevSavePath) : resolveCurrentDirectory(resourceUri, this.rootPath);
|
||||
if (filepathPlaceHolder) {
|
||||
filepathPlaceHolder = path.join(filepathPlaceHolder, this.getResultsDefaultFilename(format));
|
||||
}
|
||||
|
||||
return this.fileDialogService.showSaveDialog({
|
||||
title: nls.localize('resultsSerializer.saveAsFileTitle', "Choose Results File"),
|
||||
defaultUri: filepathPlaceHolder ? URI.file(filepathPlaceHolder) : undefined,
|
||||
filters: this.getResultsFileExtension(format)
|
||||
}).then(filePath => {
|
||||
if (filePath) {
|
||||
prevSavePath = filePath.fsPath;
|
||||
return filePath.fsPath;
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private getResultsDefaultFilename(format: SaveFormat): string {
|
||||
let fileName = 'Results';
|
||||
switch (format) {
|
||||
case SaveFormat.CSV:
|
||||
fileName = fileName + '.csv';
|
||||
break;
|
||||
case SaveFormat.JSON:
|
||||
fileName = fileName + '.json';
|
||||
break;
|
||||
case SaveFormat.EXCEL:
|
||||
fileName = fileName + '.xlsx';
|
||||
break;
|
||||
case SaveFormat.XML:
|
||||
fileName = fileName + '.xml';
|
||||
break;
|
||||
default:
|
||||
fileName = fileName + '.txt';
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
private getResultsFileExtension(format: SaveFormat): FileFilter[] {
|
||||
let fileFilters = new Array<FileFilter>();
|
||||
let fileFilter: { extensions: string[]; name: string } = Object.create(null);
|
||||
|
||||
switch (format) {
|
||||
case SaveFormat.CSV:
|
||||
fileFilter.name = nls.localize('resultsSerializer.saveAsFileExtensionCSVTitle', "CSV (Comma delimited)");
|
||||
fileFilter.extensions = ['csv'];
|
||||
break;
|
||||
case SaveFormat.JSON:
|
||||
fileFilter.name = nls.localize('resultsSerializer.saveAsFileExtensionJSONTitle', "JSON");
|
||||
fileFilter.extensions = ['json'];
|
||||
break;
|
||||
case SaveFormat.EXCEL:
|
||||
fileFilter.name = nls.localize('resultsSerializer.saveAsFileExtensionExcelTitle', "Excel Workbook");
|
||||
fileFilter.extensions = ['xlsx'];
|
||||
break;
|
||||
case SaveFormat.XML:
|
||||
fileFilter.name = nls.localize('resultsSerializer.saveAsFileExtensionXMLTitle', "XML");
|
||||
fileFilter.extensions = ['xml'];
|
||||
break;
|
||||
default:
|
||||
fileFilter.name = nls.localize('resultsSerializer.saveAsFileExtensionTXTTitle', "Plain Text");
|
||||
fileFilter.extensions = ['txt'];
|
||||
}
|
||||
|
||||
fileFilters.push(fileFilter);
|
||||
return fileFilters;
|
||||
}
|
||||
|
||||
public getBasicSaveParameters(format: string): SaveResultsRequestParams {
|
||||
let saveResultsParams: SaveResultsRequestParams;
|
||||
|
||||
if (format === SaveFormat.CSV) {
|
||||
saveResultsParams = this.getConfigForCsv();
|
||||
} else if (format === SaveFormat.JSON) {
|
||||
saveResultsParams = this.getConfigForJson();
|
||||
} else if (format === SaveFormat.EXCEL) {
|
||||
saveResultsParams = this.getConfigForExcel();
|
||||
} else if (format === SaveFormat.XML) {
|
||||
saveResultsParams = this.getConfigForXml();
|
||||
}
|
||||
return saveResultsParams!; // this could be unsafe
|
||||
}
|
||||
|
||||
|
||||
private getConfigForCsv(): SaveResultsRequestParams {
|
||||
let saveResultsParams = <SaveResultsRequestParams>{ resultFormat: SaveFormat.CSV as string };
|
||||
|
||||
// get save results config from vscode config
|
||||
let saveConfig = this._configurationService.getValue<ICsvConfig>('sql.saveAsCsv');
|
||||
// if user entered config, set options
|
||||
if (saveConfig) {
|
||||
if (saveConfig.includeHeaders !== undefined) {
|
||||
saveResultsParams.includeHeaders = saveConfig.includeHeaders;
|
||||
}
|
||||
if (saveConfig.delimiter !== undefined) {
|
||||
saveResultsParams.delimiter = saveConfig.delimiter;
|
||||
}
|
||||
if (saveConfig.lineSeperator !== undefined) {
|
||||
saveResultsParams.lineSeperator = saveConfig.lineSeperator;
|
||||
}
|
||||
if (saveConfig.textIdentifier !== undefined) {
|
||||
saveResultsParams.textIdentifier = saveConfig.textIdentifier;
|
||||
}
|
||||
if (saveConfig.encoding !== undefined) {
|
||||
saveResultsParams.encoding = saveConfig.encoding;
|
||||
}
|
||||
}
|
||||
|
||||
return saveResultsParams;
|
||||
}
|
||||
|
||||
private getConfigForJson(): SaveResultsRequestParams {
|
||||
// JSON does not currently have special conditions
|
||||
let saveResultsParams = <SaveResultsRequestParams>{ resultFormat: SaveFormat.JSON as string };
|
||||
return saveResultsParams;
|
||||
}
|
||||
|
||||
private getConfigForExcel(): SaveResultsRequestParams {
|
||||
// get save results config from vscode config
|
||||
// Note: we are currently using the configSaveAsCsv setting since it has the option mssql.saveAsCsv.includeHeaders
|
||||
// and we want to have just 1 setting that lists this.
|
||||
let config = this.getConfigForCsv();
|
||||
config.resultFormat = SaveFormat.EXCEL;
|
||||
config.delimiter = undefined;
|
||||
config.lineSeperator = undefined;
|
||||
config.textIdentifier = undefined;
|
||||
config.encoding = undefined;
|
||||
return config;
|
||||
}
|
||||
|
||||
private getConfigForXml(): SaveResultsRequestParams {
|
||||
let saveResultsParams = <SaveResultsRequestParams>{ resultFormat: SaveFormat.XML as string };
|
||||
|
||||
// get save results config from vscode config
|
||||
let saveConfig = this._configurationService.getValue<IXmlConfig>('sql.saveAsXml');
|
||||
// if user entered config, set options
|
||||
if (saveConfig) {
|
||||
if (saveConfig.formatted !== undefined) {
|
||||
saveResultsParams.formatted = saveConfig.formatted;
|
||||
}
|
||||
if (saveConfig.encoding !== undefined) {
|
||||
saveResultsParams.encoding = saveConfig.encoding;
|
||||
}
|
||||
}
|
||||
|
||||
return saveResultsParams;
|
||||
}
|
||||
|
||||
|
||||
private getParameters(uri: string, filePath: string, batchIndex: number, resultSetNo: number, format: string, selection?: Slick.Range): SaveResultsRequestParams {
|
||||
let saveResultsParams = this.getBasicSaveParameters(format);
|
||||
saveResultsParams.filePath = filePath;
|
||||
saveResultsParams.ownerUri = uri;
|
||||
saveResultsParams.resultSetIndex = resultSetNo;
|
||||
saveResultsParams.batchIndex = batchIndex;
|
||||
if (this.isSelected(selection)) {
|
||||
saveResultsParams.rowStartIndex = selection.fromRow;
|
||||
saveResultsParams.rowEndIndex = selection.toRow;
|
||||
saveResultsParams.columnStartIndex = selection.fromCell;
|
||||
saveResultsParams.columnEndIndex = selection.toCell;
|
||||
}
|
||||
return saveResultsParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a range of cells were selected.
|
||||
*/
|
||||
private isSelected(selection?: Slick.Range): selection is Slick.Range {
|
||||
return !!(selection && !((selection.fromCell === selection.toCell) && (selection.fromRow === selection.toRow)));
|
||||
}
|
||||
|
||||
|
||||
private promptFileSavedNotification(savedFilePath: string) {
|
||||
let label = getBaseLabel(path.dirname(savedFilePath));
|
||||
|
||||
this._notificationService.prompt(
|
||||
Severity.Info,
|
||||
LocalizedConstants.msgSaveSucceeded + savedFilePath,
|
||||
[{
|
||||
label: nls.localize('openLocation', "Open file location"),
|
||||
run: () => {
|
||||
let action = this._instantiationService.createInstance(ShowFileInFolderAction, savedFilePath, label || path.sep);
|
||||
action.run();
|
||||
action.dispose();
|
||||
}
|
||||
}, {
|
||||
label: nls.localize('openFile', "Open file"),
|
||||
run: () => {
|
||||
let action = this._instantiationService.createInstance(OpenFileInFolderAction, savedFilePath, label || path.sep);
|
||||
action.run();
|
||||
action.dispose();
|
||||
}
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request to sql tools service to save a result set
|
||||
*/
|
||||
private async doSave(filePath: string, format: string, sendRequest: () => Promise<SaveResultsResponse | undefined>): Promise<void> {
|
||||
|
||||
this.logToOutputChannel(LocalizedConstants.msgSaveStarted + filePath);
|
||||
|
||||
// send message to the sqlserverclient for converting results to the requested format and saving to filepath
|
||||
try {
|
||||
let result = await sendRequest();
|
||||
if (!result || result.messages) {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: LocalizedConstants.msgSaveFailed + (result ? result.messages : '')
|
||||
});
|
||||
this.logToOutputChannel(LocalizedConstants.msgSaveFailed + (result ? result.messages : ''));
|
||||
} else {
|
||||
this.promptFileSavedNotification(filePath);
|
||||
this.logToOutputChannel(LocalizedConstants.msgSaveSucceeded + filePath);
|
||||
this.openSavedFile(filePath, format);
|
||||
}
|
||||
// TODO telemetry for save results
|
||||
// Telemetry.sendTelemetryEvent('SavedResults', { 'type': format });
|
||||
|
||||
} catch (error) {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: LocalizedConstants.msgSaveFailed + error
|
||||
});
|
||||
this.logToOutputChannel(LocalizedConstants.msgSaveFailed + error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the saved file in a new vscode editor pane
|
||||
*/
|
||||
private openSavedFile(filePath: string, format: string): void {
|
||||
if (format !== SaveFormat.EXCEL) {
|
||||
let uri = URI.file(filePath);
|
||||
this._editorService.openEditor({ resource: uri }).then((result) => {
|
||||
|
||||
}, (error: any) => {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: error
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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';
|
||||
import * as editorOptions from 'vs/editor/common/config/editorOptions';
|
||||
import EDITOR_FONT_DEFAULTS = editorOptions.EDITOR_FONT_DEFAULTS;
|
||||
|
||||
export const RESULTS_GRID_DEFAULTS = {
|
||||
cellPadding: [5, 8, 4],
|
||||
rowHeight: 24
|
||||
};
|
||||
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(Extensions.Configuration);
|
||||
|
||||
const resultsGridConfiguration: IConfigurationNode = {
|
||||
id: 'resultsGrid',
|
||||
type: 'object',
|
||||
title: nls.localize('resultsGridConfigurationTitle', "Results Grid and Messages"),
|
||||
overridable: true,
|
||||
properties: {
|
||||
'resultsGrid.fontFamily': {
|
||||
type: 'string',
|
||||
default: EDITOR_FONT_DEFAULTS.fontFamily,
|
||||
description: nls.localize('fontFamily', "Controls the font family.")
|
||||
},
|
||||
'resultsGrid.fontWeight': {
|
||||
type: 'string',
|
||||
enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
||||
default: EDITOR_FONT_DEFAULTS.fontWeight,
|
||||
description: nls.localize('fontWeight', "Controls the font weight.")
|
||||
},
|
||||
'resultsGrid.fontSize': {
|
||||
type: 'number',
|
||||
default: EDITOR_FONT_DEFAULTS.fontSize,
|
||||
description: nls.localize('fontSize', "Controls the font size in pixels.")
|
||||
},
|
||||
'resultsGrid.letterSpacing': {
|
||||
type: 'number',
|
||||
default: EDITOR_FONT_DEFAULTS.letterSpacing,
|
||||
description: nls.localize('letterSpacing', "Controls the letter spacing in pixels.")
|
||||
},
|
||||
'resultsGrid.rowHeight': {
|
||||
type: 'number',
|
||||
default: RESULTS_GRID_DEFAULTS.rowHeight,
|
||||
description: nls.localize('rowHeight', "Controls the row height in pixels")
|
||||
},
|
||||
'resultsGrid.cellPadding': {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
],
|
||||
default: RESULTS_GRID_DEFAULTS.cellPadding,
|
||||
description: nls.localize('cellPadding', "Controls the cell padding in pixels")
|
||||
},
|
||||
'resultsGrid.autoSizeColumns': {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: nls.localize('autoSizeColumns', "Auto size the columns width on inital results. Could have performance problems with large number of columns or large cells")
|
||||
},
|
||||
'resultsGrid.maxColumnWidth': {
|
||||
type: 'number',
|
||||
default: 212,
|
||||
description: nls.localize('maxColumnWidth', "The maximum width in pixels for auto-sized columns")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configurationRegistry.registerConfiguration(resultsGridConfiguration);
|
||||
Reference in New Issue
Block a user