mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Add option for using generic SQL queries to filter EditData rows via a query editor pane. (#1329)
This commit is contained in:
@@ -658,7 +658,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.5",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.7",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
||||||
"vscode-extension-telemetry": "^0.0.15"
|
"vscode-extension-telemetry": "^0.0.15"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.4.0-alpha.30",
|
"version": "1.4.0-alpha.31",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
||||||
|
|||||||
@@ -131,6 +131,14 @@
|
|||||||
background: url("filter_inverse.svg") center center no-repeat !important;
|
background: url("filter_inverse.svg") center center no-repeat !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs .icon.filterLabel {
|
||||||
|
background-image: url("filter.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .icon.filterLabel,
|
||||||
|
.hc-black .icon.filterLabel {
|
||||||
|
background-image: url("filter_inverse.svg");
|
||||||
|
}
|
||||||
|
|
||||||
.vs .icon.warning-badge,
|
.vs .icon.warning-badge,
|
||||||
.vs-dark .icon.warning-badge,
|
.vs-dark .icon.warning-badge,
|
||||||
|
|||||||
@@ -4,19 +4,21 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { EditorInput, EditorModel } from 'vs/workbench/common/editor';
|
import { EditorInput, EditorModel, ConfirmResult, EncodingMode } from 'vs/workbench/common/editor';
|
||||||
import { IConnectionManagementService, IConnectableInput, INewConnectionParams } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectableInput, INewConnectionParams } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import Event, { Emitter } from 'vs/base/common/event';
|
import Event, { Emitter } from 'vs/base/common/event';
|
||||||
import { EditSessionReadyParams } from 'sqlops';
|
import { EditSessionReadyParams, ISelectionData } from 'sqlops';
|
||||||
import URI from 'vs/base/common/uri';
|
import URI from 'vs/base/common/uri';
|
||||||
import nls = require('vs/nls');
|
import nls = require('vs/nls');
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
|
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||||
|
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input for the EditDataEditor. This input is simply a wrapper around a QueryResultsInput for the QueryResultsEditor
|
* Input for the EditDataEditor.
|
||||||
*/
|
*/
|
||||||
export class EditDataInput extends EditorInput implements IConnectableInput {
|
export class EditDataInput extends EditorInput implements IConnectableInput {
|
||||||
public static ID: string = 'workbench.editorinputs.editDataInput';
|
public static ID: string = 'workbench.editorinputs.editDataInput';
|
||||||
@@ -25,15 +27,23 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
private _editorContainer: HTMLElement;
|
private _editorContainer: HTMLElement;
|
||||||
private _updateTaskbar: Emitter<EditDataInput>;
|
private _updateTaskbar: Emitter<EditDataInput>;
|
||||||
private _editorInitializing: Emitter<boolean>;
|
private _editorInitializing: Emitter<boolean>;
|
||||||
private _showTableView: Emitter<EditDataInput>;
|
private _showResultsEditor: Emitter<EditDataInput>;
|
||||||
private _refreshButtonEnabled: boolean;
|
private _refreshButtonEnabled: boolean;
|
||||||
private _stopButtonEnabled: boolean;
|
private _stopButtonEnabled: boolean;
|
||||||
private _setup: boolean;
|
private _setup: boolean;
|
||||||
private _toDispose: IDisposable[];
|
private _toDispose: IDisposable[];
|
||||||
private _rowLimit: number;
|
private _rowLimit: number;
|
||||||
private _objectType: string;
|
private _objectType: string;
|
||||||
|
private _css: HTMLStyleElement;
|
||||||
|
private _useQueryFilter: boolean;
|
||||||
|
|
||||||
constructor(private _uri: URI, private _schemaName, private _tableName,
|
constructor(
|
||||||
|
private _uri: URI,
|
||||||
|
private _schemaName,
|
||||||
|
private _tableName,
|
||||||
|
private _sql: UntitledEditorInput,
|
||||||
|
private _queryString: string,
|
||||||
|
private _results: EditDataResultsInput,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IQueryModelService private _queryModelService: IQueryModelService,
|
@IQueryModelService private _queryModelService: IQueryModelService,
|
||||||
@INotificationService private notificationService: INotificationService
|
@INotificationService private notificationService: INotificationService
|
||||||
@@ -42,12 +52,20 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
this._visible = false;
|
this._visible = false;
|
||||||
this._hasBootstrapped = false;
|
this._hasBootstrapped = false;
|
||||||
this._updateTaskbar = new Emitter<EditDataInput>();
|
this._updateTaskbar = new Emitter<EditDataInput>();
|
||||||
this._showTableView = new Emitter<EditDataInput>();
|
this._showResultsEditor = new Emitter<EditDataInput>();
|
||||||
this._editorInitializing = new Emitter<boolean>();
|
this._editorInitializing = new Emitter<boolean>();
|
||||||
this._setup = false;
|
this._setup = false;
|
||||||
this._stopButtonEnabled = false;
|
this._stopButtonEnabled = false;
|
||||||
this._refreshButtonEnabled = false;
|
this._refreshButtonEnabled = false;
|
||||||
this._toDispose = [];
|
this._toDispose = [];
|
||||||
|
this._useQueryFilter = false;
|
||||||
|
|
||||||
|
// re-emit sql editor events through this editor if it exists
|
||||||
|
if (this._sql) {
|
||||||
|
this._toDispose.push(this._sql.onDidChangeDirty(() => this._onDidChangeDirty.fire()));
|
||||||
|
this._sql.disableSaving();
|
||||||
|
}
|
||||||
|
this.disableSaving();
|
||||||
|
|
||||||
//TODO determine is this is a table or a view
|
//TODO determine is this is a table or a view
|
||||||
this._objectType = 'TABLE';
|
this._objectType = 'TABLE';
|
||||||
@@ -79,27 +97,45 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
public get tableName(): string { return this._tableName; }
|
public get tableName(): string { return this._tableName; }
|
||||||
public get schemaName(): string { return this._schemaName; }
|
public get schemaName(): string { return this._schemaName; }
|
||||||
public get uri(): string { return this._uri.toString(); }
|
public get uri(): string { return this._uri.toString(); }
|
||||||
public get updateTaskbar(): Event<EditDataInput> { return this._updateTaskbar.event; }
|
public get sql(): UntitledEditorInput { return this._sql; }
|
||||||
public get editorInitializing(): Event<boolean> { return this._editorInitializing.event; }
|
public get results(): EditDataResultsInput { return this._results; }
|
||||||
public get showTableView(): Event<EditDataInput> { return this._showTableView.event; }
|
public getResultsInputResource(): string { return this._results.uri; }
|
||||||
|
public get updateTaskbarEvent(): Event<EditDataInput> { return this._updateTaskbar.event; }
|
||||||
|
public get editorInitializingEvent(): Event<boolean> { return this._editorInitializing.event; }
|
||||||
|
public get showResultsEditorEvent(): Event<EditDataInput> { return this._showResultsEditor.event; }
|
||||||
public get stopButtonEnabled(): boolean { return this._stopButtonEnabled; }
|
public get stopButtonEnabled(): boolean { return this._stopButtonEnabled; }
|
||||||
public get refreshButtonEnabled(): boolean { return this._refreshButtonEnabled; }
|
public get refreshButtonEnabled(): boolean { return this._refreshButtonEnabled; }
|
||||||
public get container(): HTMLElement { return this._editorContainer; }
|
public get container(): HTMLElement { return this._editorContainer; }
|
||||||
public get hasBootstrapped(): boolean { return this._hasBootstrapped; }
|
public get hasBootstrapped(): boolean { return this._hasBootstrapped; }
|
||||||
public get visible(): boolean { return this._visible; }
|
|
||||||
public get setup(): boolean { return this._setup; }
|
public get setup(): boolean { return this._setup; }
|
||||||
public get rowLimit(): number { return this._rowLimit; }
|
public get rowLimit(): number { return this._rowLimit; }
|
||||||
public get objectType(): string { return this._objectType; }
|
public get objectType(): string { return this._objectType; }
|
||||||
|
public showResultsEditor(): void { this._showResultsEditor.fire(); }
|
||||||
|
public isDirty(): boolean { return false; }
|
||||||
|
public save(): TPromise<boolean> { return TPromise.as(false); }
|
||||||
|
public confirmSave(): TPromise<ConfirmResult> { return TPromise.wrap(ConfirmResult.DONT_SAVE); }
|
||||||
public getTypeId(): string { return EditDataInput.ID; }
|
public getTypeId(): string { return EditDataInput.ID; }
|
||||||
public setVisibleTrue(): void { this._visible = true; }
|
|
||||||
public setBootstrappedTrue(): void { this._hasBootstrapped = true; }
|
public setBootstrappedTrue(): void { this._hasBootstrapped = true; }
|
||||||
public getResource(): URI { return this._uri; }
|
public getResource(): URI { return this._uri; }
|
||||||
public getName(): string { return this._uri.path; }
|
|
||||||
public supportsSplitEditor(): boolean { return false; }
|
public supportsSplitEditor(): boolean { return false; }
|
||||||
public setupComplete() { this._setup = true; }
|
public setupComplete() { this._setup = true; }
|
||||||
public set container(container: HTMLElement) {
|
public get queryString(): string {
|
||||||
this._disposeContainer();
|
return this._queryString;
|
||||||
this._editorContainer = container;
|
}
|
||||||
|
public set queryString(queryString: string) {
|
||||||
|
this._queryString = queryString;
|
||||||
|
}
|
||||||
|
public get css(): HTMLStyleElement {
|
||||||
|
return this._css;
|
||||||
|
}
|
||||||
|
public set css(css: HTMLStyleElement) {
|
||||||
|
this._css = css;
|
||||||
|
}
|
||||||
|
public get queryPaneEnabled(): boolean {
|
||||||
|
return this._useQueryFilter;
|
||||||
|
}
|
||||||
|
public set queryPaneEnabled(useQueryFilter: boolean) {
|
||||||
|
this._useQueryFilter = useQueryFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State Update Callbacks
|
// State Update Callbacks
|
||||||
@@ -111,13 +147,9 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public initEditEnd(result: EditSessionReadyParams): void {
|
public initEditEnd(result: EditSessionReadyParams): void {
|
||||||
if (result.success) {
|
|
||||||
this._refreshButtonEnabled = true;
|
this._refreshButtonEnabled = true;
|
||||||
this._stopButtonEnabled = false;
|
this._stopButtonEnabled = false;
|
||||||
} else {
|
if (!result.success) {
|
||||||
this._refreshButtonEnabled = false;
|
|
||||||
this._stopButtonEnabled = false;
|
|
||||||
|
|
||||||
this.notificationService.notify({
|
this.notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
message: result.message
|
message: result.message
|
||||||
@@ -142,8 +174,16 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onConnectSuccess(params?: INewConnectionParams): void {
|
public onConnectSuccess(params?: INewConnectionParams): void {
|
||||||
this._queryModelService.initializeEdit(this.uri, this.schemaName, this.tableName, this._objectType, this._rowLimit);
|
let rowLimit: number = undefined;
|
||||||
this._showTableView.fire(this);
|
let queryString: string = undefined;
|
||||||
|
if (this._useQueryFilter) {
|
||||||
|
queryString = this._queryString;
|
||||||
|
} else {
|
||||||
|
rowLimit = this._rowLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._queryModelService.initializeEdit(this.uri, this.schemaName, this.tableName, this._objectType, rowLimit, queryString);
|
||||||
|
this.showResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDisconnect(): void {
|
public onDisconnect(): void {
|
||||||
@@ -157,27 +197,19 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
// Boiler Plate Functions
|
// Boiler Plate Functions
|
||||||
public matches(otherInput: any): boolean {
|
public matches(otherInput: any): boolean {
|
||||||
if (otherInput instanceof EditDataInput) {
|
if (otherInput instanceof EditDataInput) {
|
||||||
return (this.uri === otherInput.uri);
|
return this._sql.matches(otherInput.sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return this._sql.matches(otherInput);
|
||||||
}
|
|
||||||
|
|
||||||
public resolve(refresh?: boolean): TPromise<EditorModel> {
|
|
||||||
return TPromise.as(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
|
this._queryModelService.disposeQuery(this.uri);
|
||||||
|
this._sql.dispose();
|
||||||
|
this._results.dispose();
|
||||||
this._toDispose = dispose(this._toDispose);
|
this._toDispose = dispose(this._toDispose);
|
||||||
this._disposeContainer();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _disposeContainer() {
|
super.dispose();
|
||||||
if (this._editorContainer && this._editorContainer.parentElement) {
|
|
||||||
this._editorContainer.parentElement.removeChild(this._editorContainer);
|
|
||||||
this._editorContainer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
@@ -186,11 +218,22 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
return this._connectionManagementService.disconnectEditor(this, true);
|
return this._connectionManagementService.disconnectEditor(this, true);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
super.close();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get tabColor(): string {
|
public get tabColor(): string {
|
||||||
return this._connectionManagementService.getTabColorForUri(this.uri);
|
return this._connectionManagementService.getTabColorForUri(this.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get onDidModelChangeContent(): Event<void> { return this._sql.onDidModelChangeContent; }
|
||||||
|
public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; }
|
||||||
|
public resolve(refresh?: boolean): TPromise<EditorModel> { return this._sql.resolve(); }
|
||||||
|
public getEncoding(): string { return this._sql.getEncoding(); }
|
||||||
|
public suggestFileName(): string { return this._sql.suggestFileName(); }
|
||||||
|
public getName(): string { return this._sql.getName(); }
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/sql/parts/editData/common/editDataResultsInput.ts
Normal file
105
src/sql/parts/editData/common/editDataResultsInput.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { localize } from 'vs/nls';
|
||||||
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
|
import { EditorInput } from 'vs/workbench/common/editor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input for the EditDataResultsEditor. This input helps with logic for the viewing and editing of
|
||||||
|
* data in the results grid.
|
||||||
|
*/
|
||||||
|
export class EditDataResultsInput extends EditorInput {
|
||||||
|
|
||||||
|
// Tracks if the editor that holds this input should be visible (i.e. true if a query has been run)
|
||||||
|
private _visible: boolean;
|
||||||
|
|
||||||
|
// Tracks if the editor has holds this input has has bootstrapped angular yet
|
||||||
|
private _hasBootstrapped: boolean;
|
||||||
|
|
||||||
|
// Holds the HTML content for the editor when the editor discards this input and loads another
|
||||||
|
private _editorContainer: HTMLElement;
|
||||||
|
public css: HTMLStyleElement;
|
||||||
|
|
||||||
|
constructor(private _uri: string) {
|
||||||
|
super();
|
||||||
|
this._visible = false;
|
||||||
|
this._hasBootstrapped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypeId(): string {
|
||||||
|
return EditDataResultsInput.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
matches(other: any): boolean {
|
||||||
|
if (other instanceof EditDataResultsInput) {
|
||||||
|
return (other._uri === this._uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(refresh?: boolean): TPromise<any> {
|
||||||
|
return TPromise.as(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsSplitEditor(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setBootstrappedTrue(): void {
|
||||||
|
this._hasBootstrapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
this._disposeContainer();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _disposeContainer() {
|
||||||
|
if (!this._editorContainer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parentContainer = this._editorContainer.parentNode;
|
||||||
|
if (parentContainer) {
|
||||||
|
parentContainer.removeChild(this._editorContainer);
|
||||||
|
this._editorContainer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Properties
|
||||||
|
|
||||||
|
static get ID() {
|
||||||
|
return 'workbench.editorinputs.editDataResultsInput';
|
||||||
|
}
|
||||||
|
|
||||||
|
set container(container: HTMLElement) {
|
||||||
|
this._disposeContainer();
|
||||||
|
this._editorContainer = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
get container(): HTMLElement {
|
||||||
|
return this._editorContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasBootstrapped(): boolean {
|
||||||
|
return this._hasBootstrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
get visible(): boolean {
|
||||||
|
return this._visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
set visible(visible: boolean) {
|
||||||
|
this._visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
get uri(): string {
|
||||||
|
return this._uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,13 +6,14 @@
|
|||||||
import 'vs/css!sql/parts/query/editor/media/queryEditor';
|
import 'vs/css!sql/parts/query/editor/media/queryEditor';
|
||||||
|
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
|
import * as strings from 'vs/base/common/strings';
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { Builder, Dimension } from 'vs/base/browser/builder';
|
import { Builder, Dimension, withElementById } from 'vs/base/browser/builder';
|
||||||
|
|
||||||
import { EditorOptions } from 'vs/workbench/common/editor';
|
import { EditorOptions, EditorInput } from 'vs/workbench/common/editor';
|
||||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||||
import { Position } from 'vs/platform/editor/common/editor';
|
import { Position, IEditorControl, IEditor } from 'vs/platform/editor/common/editor';
|
||||||
|
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
@@ -21,6 +22,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { EditDataInput } from 'sql/parts/editData/common/editDataInput';
|
import { EditDataInput } from 'sql/parts/editData/common/editDataInput';
|
||||||
|
|
||||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import * as queryContext from 'sql/parts/query/common/queryContext';
|
||||||
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
|
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
@@ -29,13 +31,22 @@ import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
|||||||
import { IEditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
|
import { IEditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import {
|
import {
|
||||||
RefreshTableAction, StopRefreshTableAction,
|
RefreshTableAction, StopRefreshTableAction, ChangeMaxRowsAction, ChangeMaxRowsActionItem, ShowQueryPaneAction
|
||||||
ChangeMaxRowsAction, ChangeMaxRowsActionItem
|
|
||||||
} from 'sql/parts/editData/execution/editDataActions';
|
} from 'sql/parts/editData/execution/editDataActions';
|
||||||
import { EditDataModule } from 'sql/parts/grid/views/editData/editData.module';
|
import { EditDataModule } from 'sql/parts/grid/views/editData/editData.module';
|
||||||
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { EDITDATA_SELECTOR } from 'sql/parts/grid/views/editData/editData.component';
|
import { EDITDATA_SELECTOR } from 'sql/parts/grid/views/editData/editData.component';
|
||||||
import { EditDataComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
import { EditDataComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
||||||
|
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
|
||||||
|
import { CodeEditor } from 'vs/editor/browser/codeEditor';
|
||||||
|
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { ISelectionData } from 'sqlops';
|
||||||
|
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||||
|
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
|
||||||
|
import { IFlexibleSash, VerticalFlexibleSash, HorizontalFlexibleSash } from 'sql/parts/query/views/flexibleSash';
|
||||||
|
import { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||||
|
import { EditDataResultsEditor } from 'sql/parts/editData/editor/editDataResultsEditor';
|
||||||
|
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor that hosts an action bar and a resultSetInput for an edit data session
|
* Editor that hosts an action bar and a resultSetInput for an edit data session
|
||||||
@@ -44,17 +55,34 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
|
|
||||||
public static ID: string = 'workbench.editor.editDataEditor';
|
public static ID: string = 'workbench.editor.editDataEditor';
|
||||||
|
|
||||||
|
// The height of the tabs above the editor
|
||||||
|
private readonly _tabHeight: number = 35;
|
||||||
|
|
||||||
|
// The minimum width/height of the editors hosted in the QueryEditor
|
||||||
|
private readonly _minEditorSize: number = 220;
|
||||||
|
|
||||||
|
private _sash: IFlexibleSash;
|
||||||
private _dimension: Dimension;
|
private _dimension: Dimension;
|
||||||
private _container: HTMLElement;
|
|
||||||
|
private _resultsEditor: EditDataResultsEditor;
|
||||||
|
private _resultsEditorContainer: HTMLElement;
|
||||||
|
|
||||||
|
private _sqlEditor: TextResourceEditor;
|
||||||
|
private _sqlEditorContainer: HTMLElement;
|
||||||
|
|
||||||
private _taskbar: Taskbar;
|
private _taskbar: Taskbar;
|
||||||
private _taskbarContainer: HTMLElement;
|
private _taskbarContainer: HTMLElement;
|
||||||
private _changeMaxRowsActionItem: ChangeMaxRowsActionItem;
|
private _changeMaxRowsActionItem: ChangeMaxRowsActionItem;
|
||||||
private _stopRefreshTableAction: StopRefreshTableAction;
|
private _stopRefreshTableAction: StopRefreshTableAction;
|
||||||
private _refreshTableAction: RefreshTableAction;
|
private _refreshTableAction: RefreshTableAction;
|
||||||
private _changeMaxRowsAction: ChangeMaxRowsAction;
|
private _changeMaxRowsAction: ChangeMaxRowsAction;
|
||||||
|
private _showQueryPaneAction: ShowQueryPaneAction;
|
||||||
private _spinnerElement: HTMLElement;
|
private _spinnerElement: HTMLElement;
|
||||||
private _initialized: boolean = false;
|
private _initialized: boolean = false;
|
||||||
|
|
||||||
|
private _queryEditorVisible: IContextKey<boolean>;
|
||||||
|
private hideQueryResultsView = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ITelemetryService _telemetryService: ITelemetryService,
|
@ITelemetryService _telemetryService: ITelemetryService,
|
||||||
@IThemeService themeService: IThemeService,
|
@IThemeService themeService: IThemeService,
|
||||||
@@ -62,19 +90,61 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
@IWorkbenchEditorService private _editorService: IWorkbenchEditorService,
|
@IWorkbenchEditorService private _editorService: IWorkbenchEditorService,
|
||||||
@IContextMenuService private _contextMenuService: IContextMenuService,
|
@IContextMenuService private _contextMenuService: IContextMenuService,
|
||||||
@IQueryModelService private _queryModelService: IQueryModelService,
|
@IQueryModelService private _queryModelService: IQueryModelService,
|
||||||
|
@IEditorDescriptorService private _editorDescriptorService: IEditorDescriptorService,
|
||||||
|
@IEditorGroupService private _editorGroupService: IEditorGroupService,
|
||||||
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IBootstrapService private _bootstrapService: IBootstrapService
|
@IBootstrapService private _bootstrapService: IBootstrapService
|
||||||
) {
|
) {
|
||||||
super(EditDataEditor.ID, _telemetryService, themeService);
|
super(EditDataEditor.ID, _telemetryService, themeService);
|
||||||
|
|
||||||
|
if (contextKeyService) {
|
||||||
|
this._queryEditorVisible = queryContext.QueryEditorVisibleContext.bindTo(contextKeyService);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUBLIC METHODS ////////////////////////////////////////////////////////////
|
// PUBLIC METHODS ////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
public get editDataInput(): EditDataInput { return <EditDataInput>this.input; }
|
public get editDataInput(): EditDataInput { return <EditDataInput>this.input; }
|
||||||
public get uri(): string { return this.input ? this.editDataInput.uri.toString() : undefined; }
|
|
||||||
public get tableName(): string { return this.editDataInput.tableName; }
|
public get tableName(): string { return this.editDataInput.tableName; }
|
||||||
|
public get uri(): string { return this.input ? this.editDataInput.uri.toString() : undefined; }
|
||||||
|
public set resultsEditorVisibility(isVisible: boolean) {
|
||||||
|
let input: EditDataInput = <EditDataInput>this.input;
|
||||||
|
input.results.visible = isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the position of the editor.
|
||||||
|
*/
|
||||||
|
public changePosition(position: Position): void {
|
||||||
|
if (this._resultsEditor) {
|
||||||
|
this._resultsEditor.changePosition(position);
|
||||||
|
}
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
this._sqlEditor.changePosition(position);
|
||||||
|
}
|
||||||
|
super.changePosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to indicate to the editor that the input should be cleared and resources associated with the
|
||||||
|
* input should be freed.
|
||||||
|
*/
|
||||||
|
public clearInput(): void {
|
||||||
|
if (this._resultsEditor) {
|
||||||
|
this._resultsEditor.clearInput();
|
||||||
|
}
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
this._sqlEditor.clearInput();
|
||||||
|
}
|
||||||
|
this._disposeEditors();
|
||||||
|
super.clearInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
public close(): void {
|
||||||
|
this.editDataInput.close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to create the editor in the parent builder.
|
* Called to create the editor in the parent builder.
|
||||||
@@ -83,9 +153,82 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
const parentElement = parent.getHTMLElement();
|
const parentElement = parent.getHTMLElement();
|
||||||
DOM.addClass(parentElement, 'side-by-side-editor');
|
DOM.addClass(parentElement, 'side-by-side-editor');
|
||||||
this._createTaskbar(parentElement);
|
this._createTaskbar(parentElement);
|
||||||
this._container = document.createElement('div');
|
}
|
||||||
this._container.style.height = 'calc(100% - 28px)';
|
|
||||||
DOM.append(parentElement, this._container);
|
public dispose(): void {
|
||||||
|
this._disposeEditors();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets focus on this editor. Specifically, it sets the focus on the hosted text editor.
|
||||||
|
*/
|
||||||
|
public focus(): void {
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
this._sqlEditor.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getControl(): IEditorControl {
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
return this._sqlEditor.getControl();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getEditorText(): string {
|
||||||
|
if (this._sqlEditor && this._sqlEditor.getControl()) {
|
||||||
|
let control = this._sqlEditor.getControl();
|
||||||
|
let codeEditor: CodeEditor = <CodeEditor>control;
|
||||||
|
|
||||||
|
if (codeEditor) {
|
||||||
|
let value = codeEditor.getModel().getValue();
|
||||||
|
if (value !== undefined && value.length > 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the spinner element to show that something was happening, hidden by default
|
||||||
|
*/
|
||||||
|
public hideSpinner(): void {
|
||||||
|
this._spinnerElement.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the internal variable keeping track of the editor's size, and re-calculates the sash position.
|
||||||
|
* To be called when the container of this editor changes size.
|
||||||
|
*/
|
||||||
|
public layout(dimension: Dimension): void {
|
||||||
|
this._dimension = dimension;
|
||||||
|
|
||||||
|
if (this._sash) {
|
||||||
|
this._setSashDimension();
|
||||||
|
this._sash.layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._doLayout();
|
||||||
|
this._resizeGridContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this editor and the sub-editors to visible.
|
||||||
|
*/
|
||||||
|
public setEditorVisible(visible: boolean, position: Position): void {
|
||||||
|
if (this._resultsEditor) {
|
||||||
|
this._resultsEditor.setVisible(visible, position);
|
||||||
|
}
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
this._sqlEditor.setVisible(visible, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.setEditorVisible(visible, position);
|
||||||
|
|
||||||
|
// Note: must update after calling super.setEditorVisible so that the accurate count is handled
|
||||||
|
this._updateQueryEditorVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,9 +238,9 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
let oldInput = <EditDataInput>this.input;
|
let oldInput = <EditDataInput>this.input;
|
||||||
if (!newInput.setup) {
|
if (!newInput.setup) {
|
||||||
this._initialized = false;
|
this._initialized = false;
|
||||||
this._register(newInput.updateTaskbar((owner) => this._updateTaskbar(owner)));
|
this._register(newInput.updateTaskbarEvent((owner) => this._updateTaskbar(owner)));
|
||||||
this._register(newInput.editorInitializing((initializing) => this.onEditorInitializingChanged(initializing)));
|
this._register(newInput.editorInitializingEvent((initializing) => this._onEditorInitializingChanged(initializing)));
|
||||||
this._register(newInput.showTableView(() => this._showTableView()));
|
this._register(newInput.showResultsEditorEvent(() => this._showResultsEditor()));
|
||||||
newInput.onRowDropDownSet(this._changeMaxRowsActionItem.defaultRowCount);
|
newInput.onRowDropDownSet(this._changeMaxRowsActionItem.defaultRowCount);
|
||||||
newInput.setupComplete();
|
newInput.setupComplete();
|
||||||
}
|
}
|
||||||
@@ -106,15 +249,6 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
.then(() => this._updateInput(oldInput, newInput, options));
|
.then(() => this._updateInput(oldInput, newInput, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEditorInitializingChanged(initializing: boolean): void {
|
|
||||||
if (initializing) {
|
|
||||||
this.showSpinner();
|
|
||||||
} else {
|
|
||||||
this._initialized = true;
|
|
||||||
this.hideSpinner();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the spinner element that shows something is happening, hidden by default
|
* Show the spinner element that shows something is happening, hidden by default
|
||||||
*/
|
*/
|
||||||
@@ -126,92 +260,74 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public toggleResultsEditorVisibility(): void {
|
||||||
* Hide the spinner element to show that something was happening, hidden by default
|
let input = <EditDataInput>this.input;
|
||||||
*/
|
let hideResults = this.hideQueryResultsView;
|
||||||
public hideSpinner(): void {
|
this.hideQueryResultsView = !this.hideQueryResultsView;
|
||||||
this._spinnerElement.style.visibility = 'hidden';
|
if (!input.results) {
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this editor and the sub-editors to visible.
|
|
||||||
*/
|
|
||||||
public setEditorVisible(visible: boolean, position: Position): void {
|
|
||||||
super.setEditorVisible(visible, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the position of the editor.
|
|
||||||
*/
|
|
||||||
public changePosition(position: Position): void {
|
|
||||||
super.changePosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to indicate to the editor that the input should be cleared and resources associated with the
|
|
||||||
* input should be freed.
|
|
||||||
*/
|
|
||||||
public clearInput(): void {
|
|
||||||
this._disposeEditors();
|
|
||||||
super.clearInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the internal variable keeping track of the editor's size, and re-calculates the sash position.
|
|
||||||
* To be called when the container of this editor changes size.
|
|
||||||
*/
|
|
||||||
public layout(dimension: Dimension): void {
|
|
||||||
this._dimension = dimension;
|
|
||||||
let input: EditDataInput = <EditDataInput>this.input;
|
|
||||||
if (input) {
|
|
||||||
let uri: string = input.uri;
|
|
||||||
if (uri) {
|
|
||||||
this._queryModelService.resizeResultsets(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
this._disposeEditors();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public close(): void {
|
|
||||||
this.input.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the results table for the current edit data session is visible
|
|
||||||
* Public for testing only.
|
|
||||||
*/
|
|
||||||
public _isResultsEditorVisible(): boolean {
|
|
||||||
if (!this.editDataInput) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.editDataInput.visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes visible the results table for the current edit data session
|
|
||||||
*/
|
|
||||||
private _showTableView(): void {
|
|
||||||
if (this._isResultsEditorVisible()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.resultsEditorVisibility = hideResults;
|
||||||
this._createTableViewContainer();
|
this._doLayout();
|
||||||
this._setTableViewVisible();
|
|
||||||
this.setInput(this.editDataInput, this.options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE METHODS ////////////////////////////////////////////////////////////
|
// PRIVATE METHODS ////////////////////////////////////////////////////////////
|
||||||
private _updateTaskbar(owner: EditDataInput): void {
|
private _createEditor(editorInput: EditorInput, container: HTMLElement): TPromise<BaseEditor> {
|
||||||
// Update the taskbar if the owner of this call is being presented
|
const descriptor = this._editorDescriptorService.getEditor(editorInput);
|
||||||
if (owner.matches(this.editDataInput)) {
|
if (!descriptor) {
|
||||||
this._refreshTableAction.enabled = owner.refreshButtonEnabled;
|
return TPromise.wrapError(new Error(strings.format('Can not find a registered editor for the input {0}', editorInput)));
|
||||||
this._stopRefreshTableAction.enabled = owner.stopButtonEnabled;
|
|
||||||
this._changeMaxRowsActionItem.setCurrentOptionIndex = owner.rowLimit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let editor = descriptor.instantiate(this._instantiationService);
|
||||||
|
editor.create(new Builder(container));
|
||||||
|
editor.setVisible(this.isVisible(), this.position);
|
||||||
|
return TPromise.as(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the HTML for the EditDataResultsEditor to the EditDataEditor. If the HTML has not yet been
|
||||||
|
* created, it creates it and appends it. If it has already been created, it locates it and
|
||||||
|
* appends it.
|
||||||
|
*/
|
||||||
|
private _createResultsEditorContainer() {
|
||||||
|
this._createSash();
|
||||||
|
|
||||||
|
const parentElement = this.getContainer().getHTMLElement();
|
||||||
|
let input = <EditDataInput>this.input;
|
||||||
|
|
||||||
|
if (!input.results.container) {
|
||||||
|
this._resultsEditorContainer = DOM.append(parentElement, DOM.$('.editDataContainer-horizontal'));
|
||||||
|
this._resultsEditorContainer.style.position = 'absolute';
|
||||||
|
|
||||||
|
input.results.container = this._resultsEditorContainer;
|
||||||
|
} else {
|
||||||
|
this._resultsEditorContainer = DOM.append(parentElement, input.results.container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the sash with the requested orientation and registers sash callbacks
|
||||||
|
*/
|
||||||
|
private _createSash(): void {
|
||||||
|
if (!this._sash) {
|
||||||
|
let parentElement: HTMLElement = this.getContainer().getHTMLElement();
|
||||||
|
|
||||||
|
this._sash = this._register(new HorizontalFlexibleSash(parentElement, this._minEditorSize));
|
||||||
|
this._setSashDimension();
|
||||||
|
|
||||||
|
this._register(this._sash.onPositionChange(position => this._doLayout()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._sash.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the HTML for the SQL editor. Creates new HTML every time.
|
||||||
|
*/
|
||||||
|
private _createSqlEditorContainer() {
|
||||||
|
const parentElement = this.getContainer().getHTMLElement();
|
||||||
|
this._sqlEditorContainer = DOM.append(parentElement, DOM.$('.details-editor-container'));
|
||||||
|
this._sqlEditorContainer.style.position = 'absolute';
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createTaskbar(parentElement: HTMLElement): void {
|
private _createTaskbar(parentElement: HTMLElement): void {
|
||||||
@@ -222,22 +338,25 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create Actions for the toolbar
|
// Create Actions for the toolbar
|
||||||
this._stopRefreshTableAction = this._instantiationService.createInstance(StopRefreshTableAction, this);
|
|
||||||
this._refreshTableAction = this._instantiationService.createInstance(RefreshTableAction, this);
|
this._refreshTableAction = this._instantiationService.createInstance(RefreshTableAction, this);
|
||||||
|
this._stopRefreshTableAction = this._instantiationService.createInstance(StopRefreshTableAction, this);
|
||||||
this._changeMaxRowsAction = this._instantiationService.createInstance(ChangeMaxRowsAction, this);
|
this._changeMaxRowsAction = this._instantiationService.createInstance(ChangeMaxRowsAction, this);
|
||||||
|
this._showQueryPaneAction = this._instantiationService.createInstance(ShowQueryPaneAction, this);
|
||||||
|
|
||||||
// Create HTML Elements for the taskbar
|
// Create HTML Elements for the taskbar
|
||||||
let separator = Taskbar.createTaskbarSeparator();
|
let separator = Taskbar.createTaskbarSeparator();
|
||||||
let textSeperator = Taskbar.createTaskbarText(nls.localize('maxRowTaskbar', 'Max Rows:'));
|
let textSeparator = Taskbar.createTaskbarText(nls.localize('maxRowTaskbar', 'Max Rows:'));
|
||||||
|
|
||||||
this._spinnerElement = Taskbar.createTaskbarSpinner();
|
this._spinnerElement = Taskbar.createTaskbarSpinner();
|
||||||
|
|
||||||
// Set the content in the order we desire
|
// Set the content in the order we desire
|
||||||
let content: ITaskbarContent[] = [
|
let content: ITaskbarContent[] = [
|
||||||
{ action: this._stopRefreshTableAction },
|
|
||||||
{ action: this._refreshTableAction },
|
{ action: this._refreshTableAction },
|
||||||
|
{ action: this._stopRefreshTableAction },
|
||||||
{ element: separator },
|
{ element: separator },
|
||||||
{ element: textSeperator },
|
{ element: textSeparator },
|
||||||
{ action: this._changeMaxRowsAction },
|
{ action: this._changeMaxRowsAction },
|
||||||
|
{ action: this._showQueryPaneAction },
|
||||||
{ element: this._spinnerElement }
|
{ element: this._spinnerElement }
|
||||||
];
|
];
|
||||||
this._taskbar.setContent(content);
|
this._taskbar.setContent(content);
|
||||||
@@ -258,32 +377,181 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private _disposeEditors(): void {
|
||||||
* Handles setting input for this editor. If this new input does not match the old input (e.g. a new file
|
if (this._sqlEditor) {
|
||||||
* has been opened with the same editor, or we are opening the editor for the first time).
|
this._sqlEditor.dispose();
|
||||||
*/
|
this._sqlEditor = null;
|
||||||
private _updateInput(oldInput: EditDataInput, newInput: EditDataInput, options?: EditorOptions): TPromise<void> {
|
}
|
||||||
let returnValue: TPromise<void>;
|
if (this._resultsEditor) {
|
||||||
|
this._resultsEditor.dispose();
|
||||||
|
this._resultsEditor = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!newInput.matches(oldInput)) {
|
let thisEditorParent: HTMLElement = this.getContainer().getHTMLElement();
|
||||||
this._disposeEditors();
|
|
||||||
|
|
||||||
if (this._isResultsEditorVisible()) {
|
if (this._sqlEditorContainer) {
|
||||||
this._createTableViewContainer();
|
let sqlEditorParent: HTMLElement = this._sqlEditorContainer.parentElement;
|
||||||
let uri: string = newInput.uri;
|
if (sqlEditorParent && sqlEditorParent === thisEditorParent) {
|
||||||
if (uri) {
|
this._sqlEditorContainer.parentElement.removeChild(this._sqlEditorContainer);
|
||||||
this._queryModelService.refreshResultsets(uri);
|
}
|
||||||
|
this._sqlEditorContainer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._resultsEditorContainer) {
|
||||||
|
let resultsEditorParent: HTMLElement = this._resultsEditorContainer.parentElement;
|
||||||
|
if (resultsEditorParent && resultsEditorParent === thisEditorParent) {
|
||||||
|
this._resultsEditorContainer.parentElement.removeChild(this._resultsEditorContainer);
|
||||||
|
}
|
||||||
|
this._resultsEditorContainer = null;
|
||||||
|
this.hideQueryResultsView = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
returnValue = this._setNewInput(newInput, options);
|
private _doLayout(skipResizeGridContent: boolean = false): void {
|
||||||
|
if (!this._isResultsEditorVisible() && this._sqlEditor) {
|
||||||
|
this._doLayoutSql();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this._sqlEditor || !this._resultsEditor || !this._dimension || !this._sash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._doLayoutHorizontal();
|
||||||
|
|
||||||
|
if (!skipResizeGridContent) {
|
||||||
|
this._resizeGridContents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _doLayoutHorizontal(): void {
|
||||||
|
let splitPointTop: number = this._sash.getSplitPoint();
|
||||||
|
let parent: ClientRect = this.getContainer().getHTMLElement().getBoundingClientRect();
|
||||||
|
|
||||||
|
let sqlEditorHeight: number;
|
||||||
|
let sqlEditorTop: number;
|
||||||
|
let resultsEditorHeight: number;
|
||||||
|
let resultsEditorTop: number;
|
||||||
|
|
||||||
|
let editorTopOffset = parent.top + this._getTaskBarHeight();
|
||||||
|
|
||||||
|
this._resultsEditorContainer.hidden = false;
|
||||||
|
|
||||||
|
let titleBar = withElementById('workbench.parts.titlebar');
|
||||||
|
if (this.queryPaneEnabled()) {
|
||||||
|
this._sqlEditorContainer.hidden = false;
|
||||||
|
|
||||||
|
sqlEditorTop = editorTopOffset;
|
||||||
|
sqlEditorHeight = splitPointTop - sqlEditorTop;
|
||||||
|
|
||||||
|
resultsEditorTop = splitPointTop;
|
||||||
|
resultsEditorHeight = parent.bottom - resultsEditorTop;
|
||||||
|
|
||||||
|
if (titleBar) {
|
||||||
|
sqlEditorHeight += DOM.getContentHeight(titleBar.getHTMLElement());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._setNewInput(newInput, options);
|
this._sqlEditorContainer.hidden = true;
|
||||||
returnValue = TPromise.as(null);
|
|
||||||
|
sqlEditorTop = editorTopOffset;
|
||||||
|
sqlEditorHeight = 0;
|
||||||
|
|
||||||
|
resultsEditorTop = editorTopOffset;
|
||||||
|
resultsEditorHeight = parent.bottom - resultsEditorTop;
|
||||||
|
|
||||||
|
if (titleBar) {
|
||||||
|
resultsEditorHeight += DOM.getContentHeight(titleBar.getHTMLElement());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._updateTaskbar(newInput);
|
this._sqlEditorContainer.style.height = `${sqlEditorHeight}px`;
|
||||||
return returnValue;
|
this._sqlEditorContainer.style.width = `${this._dimension.width}px`;
|
||||||
|
this._sqlEditorContainer.style.top = `${sqlEditorTop}px`;
|
||||||
|
|
||||||
|
this._resultsEditorContainer.style.height = `${resultsEditorHeight}px`;
|
||||||
|
this._resultsEditorContainer.style.width = `${this._dimension.width}px`;
|
||||||
|
this._resultsEditorContainer.style.top = `${resultsEditorTop}px`;
|
||||||
|
|
||||||
|
this._sqlEditor.layout(new Dimension(this._dimension.width, sqlEditorHeight));
|
||||||
|
this._resultsEditor.layout(new Dimension(this._dimension.width, resultsEditorHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _doLayoutSql() {
|
||||||
|
if (this._resultsEditorContainer) {
|
||||||
|
this._resultsEditorContainer.style.width = '0px';
|
||||||
|
this._resultsEditorContainer.style.height = '0px';
|
||||||
|
this._resultsEditorContainer.style.left = '0px';
|
||||||
|
this._resultsEditorContainer.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._dimension) {
|
||||||
|
let sqlEditorHeight: number;
|
||||||
|
|
||||||
|
if (this.queryPaneEnabled()) {
|
||||||
|
this._sqlEditorContainer.hidden = false;
|
||||||
|
sqlEditorHeight = this._dimension.height - this._getTaskBarHeight();
|
||||||
|
} else {
|
||||||
|
this._sqlEditorContainer.hidden = true;
|
||||||
|
sqlEditorHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._sqlEditorContainer.style.height = `${sqlEditorHeight}px`;
|
||||||
|
this._sqlEditorContainer.style.width = `${this._dimension.width}px`;
|
||||||
|
|
||||||
|
this._sqlEditor.layout(new Dimension(this._dimension.width, sqlEditorHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTaskBarHeight(): number {
|
||||||
|
let taskBarElement = this._taskbar.getContainer().getHTMLElement();
|
||||||
|
return DOM.getContentHeight(taskBarElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the results table for the current edit data session is visible
|
||||||
|
* Public for testing only.
|
||||||
|
*/
|
||||||
|
private _isResultsEditorVisible(): boolean {
|
||||||
|
let input: EditDataInput = <EditDataInput>this.input;
|
||||||
|
|
||||||
|
if (!input) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return input.results.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEditorInitializingChanged(initializing: boolean): void {
|
||||||
|
if (initializing) {
|
||||||
|
this.showSpinner();
|
||||||
|
} else {
|
||||||
|
this._initialized = true;
|
||||||
|
this.hideSpinner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets input for the results editor after it has been created.
|
||||||
|
*/
|
||||||
|
private _onResultsEditorCreated(resultsEditor: EditDataResultsEditor, resultsInput: EditDataResultsInput, options: EditorOptions): TPromise<void> {
|
||||||
|
this._resultsEditor = resultsEditor;
|
||||||
|
return this._resultsEditor.setInput(resultsInput, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets input for the SQL editor after it has been created.
|
||||||
|
*/
|
||||||
|
private _onSqlEditorCreated(sqlEditor: TextResourceEditor, sqlInput: UntitledEditorInput, options: EditorOptions): TPromise<void> {
|
||||||
|
this._sqlEditor = sqlEditor;
|
||||||
|
return this._sqlEditor.setInput(sqlInput, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _resizeGridContents(): void {
|
||||||
|
if (this._isResultsEditorVisible()) {
|
||||||
|
let queryInput: EditDataInput = <EditDataInput>this.input;
|
||||||
|
let uri: string = queryInput.uri;
|
||||||
|
if (uri) {
|
||||||
|
this._queryModelService.resizeResultsets(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,68 +559,177 @@ export class EditDataEditor extends BaseEditor {
|
|||||||
* - Opened for the first time
|
* - Opened for the first time
|
||||||
* - Opened with a new EditDataInput
|
* - Opened with a new EditDataInput
|
||||||
*/
|
*/
|
||||||
private _setNewInput(newInput: EditDataInput, options?: EditorOptions): TPromise<void> {
|
private _setNewInput(newInput: EditDataInput, options?: EditorOptions): TPromise<any> {
|
||||||
|
|
||||||
|
// Promises that will ensure proper ordering of editor creation logic
|
||||||
|
let createEditors: () => TPromise<any>;
|
||||||
|
let onEditorsCreated: (result) => TPromise<any>;
|
||||||
|
|
||||||
|
// If both editors exist, create joined promises - one for each editor
|
||||||
if (this._isResultsEditorVisible()) {
|
if (this._isResultsEditorVisible()) {
|
||||||
// If both editors exist, create a joined promise and wait for both editors to be created
|
createEditors = () => {
|
||||||
return this._bootstrapAngularAndResults(newInput, options);
|
return TPromise.join([
|
||||||
}
|
this._createEditor(<EditDataResultsInput>newInput.results, this._resultsEditorContainer),
|
||||||
|
this._createEditor(<UntitledEditorInput>newInput.sql, this._sqlEditorContainer)
|
||||||
return TPromise.as(undefined);
|
]);
|
||||||
}
|
};
|
||||||
/**
|
onEditorsCreated = (result: IEditor[]) => {
|
||||||
* Appends the HTML for the edit data table view
|
return TPromise.join([
|
||||||
*/
|
this._onResultsEditorCreated(<EditDataResultsEditor>result[0], newInput.results, options),
|
||||||
private _createTableViewContainer() {
|
this._onSqlEditorCreated(<TextResourceEditor>result[1], newInput.sql, options)
|
||||||
if (!this.editDataInput.container) {
|
]);
|
||||||
this.editDataInput.container = DOM.append(this._container, DOM.$('.editDataContainer'));
|
};
|
||||||
this.editDataInput.container.style.height = '100%';
|
|
||||||
} else {
|
// If only the sql editor exists, create a promise and wait for the sql editor to be created
|
||||||
DOM.append(this._container, this.editDataInput.container);
|
} else {
|
||||||
}
|
createEditors = () => {
|
||||||
}
|
return this._createEditor(<UntitledEditorInput>newInput.sql, this._sqlEditorContainer);
|
||||||
|
};
|
||||||
private _disposeEditors(): void {
|
onEditorsCreated = (result: TextResourceEditor) => {
|
||||||
if (this._container) {
|
return this._onSqlEditorCreated(result, newInput.sql, options);
|
||||||
new Builder(this._container).clearChildren();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the angular components and record for this input that we have done so
|
|
||||||
*/
|
|
||||||
private _bootstrapAngularAndResults(input: EditDataInput, options: EditorOptions): TPromise<void> {
|
|
||||||
super.setInput(input, options);
|
|
||||||
if (!input.hasBootstrapped) {
|
|
||||||
let uri = this.editDataInput.uri;
|
|
||||||
|
|
||||||
// Pass the correct DataService to the new angular component
|
|
||||||
let dataService = this._queryModelService.getDataService(uri);
|
|
||||||
if (!dataService) {
|
|
||||||
throw new Error('DataService not found for URI: ' + uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark that we have bootstrapped
|
|
||||||
input.setBootstrappedTrue();
|
|
||||||
|
|
||||||
// Get the bootstrap params and perform the bootstrap
|
|
||||||
// Note: pass in input so on disposal this is cleaned up.
|
|
||||||
// Otherwise many components will be left around and be subscribed
|
|
||||||
// to events from the backing data service
|
|
||||||
const parent = this.editDataInput.container;
|
|
||||||
let params: EditDataComponentParams = {
|
|
||||||
dataService: dataService
|
|
||||||
};
|
};
|
||||||
this._bootstrapService.bootstrap(
|
|
||||||
EditDataModule,
|
|
||||||
parent,
|
|
||||||
EDITDATA_SELECTOR,
|
|
||||||
params,
|
|
||||||
this.editDataInput);
|
|
||||||
}
|
|
||||||
return TPromise.wrap<void>(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setTableViewVisible(): void {
|
// Create a promise to re render the layout after the editor creation logic
|
||||||
this.editDataInput.setVisibleTrue();
|
let doLayout: () => TPromise<any> = () => {
|
||||||
|
this._doLayout();
|
||||||
|
return TPromise.as(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run all three steps synchronously
|
||||||
|
return createEditors()
|
||||||
|
.then(onEditorsCreated)
|
||||||
|
.then(doLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setSashDimension(): void {
|
||||||
|
if (!this._dimension) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._sash.setDimenesion(this._dimension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes visible the results table for the current edit data session
|
||||||
|
*/
|
||||||
|
private _showResultsEditor(): void {
|
||||||
|
if (this._isResultsEditorVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._editorGroupService.pinEditor(this.position, this.input);
|
||||||
|
|
||||||
|
let input = <EditDataInput>this.input;
|
||||||
|
this._createResultsEditorContainer();
|
||||||
|
|
||||||
|
this._createEditor(<EditDataResultsInput>input.results, this._resultsEditorContainer)
|
||||||
|
.then(result => {
|
||||||
|
this._onResultsEditorCreated(<EditDataResultsEditor>result, input.results, this.options);
|
||||||
|
this.resultsEditorVisibility = true;
|
||||||
|
this.hideQueryResultsView = false;
|
||||||
|
this._doLayout(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles setting input for this editor. If this new input does not match the old input (e.g. a new file
|
||||||
|
* has been opened with the same editor, or we are opening the editor for the first time).
|
||||||
|
*/
|
||||||
|
private _updateInput(oldInput: EditDataInput, newInput: EditDataInput, options?: EditorOptions): TPromise<void> {
|
||||||
|
|
||||||
|
if (this._sqlEditor) {
|
||||||
|
this._sqlEditor.clearInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldInput) {
|
||||||
|
this._disposeEditors();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._createSqlEditorContainer();
|
||||||
|
if (this._isResultsEditorVisible()) {
|
||||||
|
this._createResultsEditorContainer();
|
||||||
|
|
||||||
|
let uri: string = newInput.uri;
|
||||||
|
if (uri) {
|
||||||
|
this._queryModelService.refreshResultsets(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._sash) {
|
||||||
|
if (this._isResultsEditorVisible()) {
|
||||||
|
this._sash.show();
|
||||||
|
} else {
|
||||||
|
this._sash.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateTaskbar(newInput);
|
||||||
|
return this._setNewInput(newInput, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateQueryEditorVisible(currentEditorIsVisible: boolean): void {
|
||||||
|
if (this._queryEditorVisible) {
|
||||||
|
let visible = currentEditorIsVisible;
|
||||||
|
if (!currentEditorIsVisible) {
|
||||||
|
// Current editor is closing but still tracked as visible. Check if any other editor is visible
|
||||||
|
const candidates = [...this._editorService.getVisibleEditors()].filter(e => {
|
||||||
|
if (e && e.getId) {
|
||||||
|
return e.getId() === EditDataEditor.ID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
// Note: require 2 or more candidates since current is closing but still
|
||||||
|
// counted as visible
|
||||||
|
visible = candidates.length > 1;
|
||||||
|
}
|
||||||
|
this._queryEditorVisible.set(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateTaskbar(owner: EditDataInput): void {
|
||||||
|
// Update the taskbar if the owner of this call is being presented
|
||||||
|
if (owner.matches(this.editDataInput)) {
|
||||||
|
this._refreshTableAction.enabled = owner.refreshButtonEnabled;
|
||||||
|
this._stopRefreshTableAction.enabled = owner.stopButtonEnabled;
|
||||||
|
this._changeMaxRowsActionItem.setCurrentOptionIndex = owner.rowLimit;
|
||||||
|
this._showQueryPaneAction.queryPaneEnabled = owner.queryPaneEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the run method of this editor's RunQueryAction
|
||||||
|
*/
|
||||||
|
public runQuery(): void {
|
||||||
|
this._refreshTableAction.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the run method of this editor's CancelQueryAction
|
||||||
|
*/
|
||||||
|
public cancelQuery(): void {
|
||||||
|
this._stopRefreshTableAction.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleQueryPane(): void {
|
||||||
|
this.editDataInput.queryPaneEnabled = !this.queryPaneEnabled();
|
||||||
|
if (this.queryPaneEnabled()) {
|
||||||
|
this._showQueryEditor();
|
||||||
|
} else {
|
||||||
|
this._hideQueryEditor();
|
||||||
|
}
|
||||||
|
this._doLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showQueryEditor(): void {
|
||||||
|
this._sqlEditorContainer.hidden = false;
|
||||||
|
this._changeMaxRowsActionItem.disable();
|
||||||
|
}
|
||||||
|
private _hideQueryEditor(): void {
|
||||||
|
this._sqlEditorContainer.hidden = true;
|
||||||
|
this._changeMaxRowsActionItem.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public queryPaneEnabled(): boolean {
|
||||||
|
return this.editDataInput.queryPaneEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
113
src/sql/parts/editData/editor/editDataResultsEditor.ts
Normal file
113
src/sql/parts/editData/editor/editDataResultsEditor.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import { Dimension, Builder } from 'vs/base/browser/builder';
|
||||||
|
import { EditorOptions } from 'vs/workbench/common/editor';
|
||||||
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
|
import { getZoomLevel } from 'vs/base/browser/browser';
|
||||||
|
import { Configuration } from 'vs/editor/browser/config/configuration';
|
||||||
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
|
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { BareResultsGridInfo } from 'sql/parts/query/editor/queryResultsEditor';
|
||||||
|
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||||
|
import * as dom from 'vs/base/browser/dom';
|
||||||
|
import * as types from 'vs/base/common/types';
|
||||||
|
import { EditDataComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
||||||
|
import { EditDataModule } from 'sql/parts/grid/views/editData/editData.module';
|
||||||
|
import { EDITDATA_SELECTOR } from 'sql/parts/grid/views/editData/editData.component';
|
||||||
|
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||||
|
|
||||||
|
export class EditDataResultsEditor extends BaseEditor {
|
||||||
|
|
||||||
|
public static ID: string = 'workbench.editor.editDataResultsEditor';
|
||||||
|
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
||||||
|
protected _input: EditDataResultsInput;
|
||||||
|
protected _rawOptions: BareResultsGridInfo;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@ITelemetryService telemetryService: ITelemetryService,
|
||||||
|
@IThemeService themeService: IThemeService,
|
||||||
|
@IQueryModelService private _queryModelService: IQueryModelService,
|
||||||
|
@IBootstrapService private _bootstrapService: IBootstrapService,
|
||||||
|
@IConfigurationService private _configurationService: IConfigurationService
|
||||||
|
) {
|
||||||
|
super(EditDataResultsEditor.ID, telemetryService, themeService);
|
||||||
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
|
this._configurationService.onDidChangeConfiguration(e => {
|
||||||
|
if (e.affectsConfiguration('resultsGrid')) {
|
||||||
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
|
this._applySettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get input(): EditDataResultsInput {
|
||||||
|
return this._input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEditor(parent: Builder): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public layout(dimension: Dimension): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public setInput(input: EditDataResultsInput, options: EditorOptions): TPromise<void> {
|
||||||
|
super.setInput(input, options);
|
||||||
|
this._applySettings();
|
||||||
|
if (!input.hasBootstrapped) {
|
||||||
|
this._bootstrapAngular();
|
||||||
|
}
|
||||||
|
return TPromise.wrap<void>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _applySettings() {
|
||||||
|
if (this.input && this.input.container) {
|
||||||
|
Configuration.applyFontInfoSlow(this.getContainer().getHTMLElement(), this._rawOptions);
|
||||||
|
if (!this.input.css) {
|
||||||
|
this.input.css = dom.createStyleSheet(this.input.container);
|
||||||
|
}
|
||||||
|
let cssRuleText = '';
|
||||||
|
if (types.isNumber(this._rawOptions.cellPadding)) {
|
||||||
|
cssRuleText = this._rawOptions.cellPadding + 'px';
|
||||||
|
} else {
|
||||||
|
cssRuleText = this._rawOptions.cellPadding.join('px ') + 'px;';
|
||||||
|
}
|
||||||
|
let content = `.grid .slick-cell { padding: ${cssRuleText}; }`;
|
||||||
|
this.input.css.innerHTML = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the angular components and record for this input that we have done so
|
||||||
|
*/
|
||||||
|
private _bootstrapAngular(): void {
|
||||||
|
let input = <EditDataResultsInput>this.input;
|
||||||
|
let uri = input.uri;
|
||||||
|
|
||||||
|
// Pass the correct DataService to the new angular component
|
||||||
|
let dataService = this._queryModelService.getDataService(uri);
|
||||||
|
if (!dataService) {
|
||||||
|
throw new Error('DataService not found for URI: ' + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark that we have bootstrapped
|
||||||
|
input.setBootstrappedTrue();
|
||||||
|
|
||||||
|
// Get the bootstrap params and perform the bootstrap
|
||||||
|
// Note: pass in input so on disposal this is cleaned up.
|
||||||
|
// Otherwise many components will be left around and be subscribed
|
||||||
|
// to events from the backing data service
|
||||||
|
const parent = input.container;
|
||||||
|
let params: EditDataComponentParams = { dataService: dataService };
|
||||||
|
this._bootstrapService.bootstrap(
|
||||||
|
EditDataModule,
|
||||||
|
parent,
|
||||||
|
EDITDATA_SELECTOR,
|
||||||
|
params,
|
||||||
|
input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import { Action, IActionItem, IActionRunner } from 'vs/base/common/actions';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
import { EventEmitter } from 'sql/base/common/eventEmitter';
|
import { EventEmitter } from 'sql/base/common/eventEmitter';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { EditDataEditor } from 'sql/parts/editData/editor/editDataEditor';
|
import { EditDataEditor } from 'sql/parts/editData/editor/editDataEditor';
|
||||||
@@ -63,7 +63,7 @@ export abstract class EditDataAction extends Action {
|
|||||||
* Action class that refreshes the table for an edit data session
|
* Action class that refreshes the table for an edit data session
|
||||||
*/
|
*/
|
||||||
export class RefreshTableAction extends EditDataAction {
|
export class RefreshTableAction extends EditDataAction {
|
||||||
private static EnabledClass = 'refresh';
|
private static EnabledClass = 'start';
|
||||||
public static ID = 'refreshTableAction';
|
public static ID = 'refreshTableAction';
|
||||||
|
|
||||||
constructor(editor: EditDataEditor,
|
constructor(editor: EditDataEditor,
|
||||||
@@ -72,14 +72,24 @@ export class RefreshTableAction extends EditDataAction {
|
|||||||
@INotificationService private _notificationService: INotificationService,
|
@INotificationService private _notificationService: INotificationService,
|
||||||
) {
|
) {
|
||||||
super(editor, RefreshTableAction.ID, RefreshTableAction.EnabledClass, _connectionManagementService);
|
super(editor, RefreshTableAction.ID, RefreshTableAction.EnabledClass, _connectionManagementService);
|
||||||
this.label = nls.localize('editData.refresh', 'Refresh');
|
this.label = nls.localize('editData.run', 'Run');
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(): TPromise<void> {
|
public run(): TPromise<void> {
|
||||||
if (this.isConnected(this.editor)) {
|
if (this.isConnected(this.editor)) {
|
||||||
let input = this.editor.editDataInput;
|
let input = this.editor.editDataInput;
|
||||||
|
|
||||||
|
let rowLimit: number = undefined;
|
||||||
|
let queryString: string = undefined;
|
||||||
|
if (input.queryPaneEnabled) {
|
||||||
|
queryString = input.queryString = this.editor.getEditorText();
|
||||||
|
} else {
|
||||||
|
rowLimit = input.rowLimit;
|
||||||
|
}
|
||||||
|
|
||||||
this._queryModelService.disposeEdit(input.uri).then((result) => {
|
this._queryModelService.disposeEdit(input.uri).then((result) => {
|
||||||
this._queryModelService.initializeEdit(input.uri, input.schemaName, input.tableName, input.objectType, input.rowLimit);
|
this._queryModelService.initializeEdit(input.uri, input.schemaName, input.tableName, input.objectType, rowLimit, queryString);
|
||||||
|
input.showResultsEditor();
|
||||||
}, error => {
|
}, error => {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
@@ -162,10 +172,12 @@ export class ChangeMaxRowsActionItem extends EventEmitter implements IActionItem
|
|||||||
this._options = ['200', '1000', '10000'];
|
this._options = ['200', '1000', '10000'];
|
||||||
this._currentOptionsIndex = 0;
|
this._currentOptionsIndex = 0;
|
||||||
this.toDispose = [];
|
this.toDispose = [];
|
||||||
this.selectBox = new SelectBox([], -1, contextViewService);
|
this.selectBox = new SelectBox(this._options, this._options[this._currentOptionsIndex], contextViewService);
|
||||||
this._registerListeners();
|
this._registerListeners();
|
||||||
this._refreshOptions();
|
this._refreshOptions();
|
||||||
this.defaultRowCount = Number(this._options[this._currentOptionsIndex]);
|
this.defaultRowCount = Number(this._options[this._currentOptionsIndex]);
|
||||||
|
|
||||||
|
this.toDispose.push(attachSelectBoxStyler(this.selectBox, _themeService));
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(container: HTMLElement): void {
|
public render(container: HTMLElement): void {
|
||||||
@@ -181,6 +193,14 @@ export class ChangeMaxRowsActionItem extends EventEmitter implements IActionItem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enable(): void {
|
||||||
|
this.selectBox.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public disable(): void {
|
||||||
|
this.selectBox.disable();
|
||||||
|
}
|
||||||
|
|
||||||
public set setCurrentOptionIndex(selection: number) {
|
public set setCurrentOptionIndex(selection: number) {
|
||||||
this._currentOptionsIndex = this._options.findIndex(x => x === selection.toString());
|
this._currentOptionsIndex = this._options.findIndex(x => x === selection.toString());
|
||||||
this._refreshOptions();
|
this._refreshOptions();
|
||||||
@@ -210,3 +230,40 @@ export class ChangeMaxRowsActionItem extends EventEmitter implements IActionItem
|
|||||||
this.toDispose.push(attachSelectBoxStyler(this.selectBox, this._themeService));
|
this.toDispose.push(attachSelectBoxStyler(this.selectBox, this._themeService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action class that is tied with toggling the Query editor
|
||||||
|
*/
|
||||||
|
export class ShowQueryPaneAction extends EditDataAction {
|
||||||
|
|
||||||
|
private static EnabledClass = 'filterLabel';
|
||||||
|
public static ID = 'showQueryPaneAction';
|
||||||
|
private readonly showSqlLabel = nls.localize('editData.showSql', 'Show SQL Pane');
|
||||||
|
private readonly closeSqlLabel = nls.localize('editData.closeSql', 'Close SQL Pane');
|
||||||
|
|
||||||
|
constructor(editor: EditDataEditor,
|
||||||
|
@IQueryModelService private _queryModelService: IQueryModelService,
|
||||||
|
@IConnectionManagementService _connectionManagementService: IConnectionManagementService
|
||||||
|
) {
|
||||||
|
super(editor, ShowQueryPaneAction.ID, ShowQueryPaneAction.EnabledClass, _connectionManagementService);
|
||||||
|
this.label = this.showSqlLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set queryPaneEnabled(value: boolean) {
|
||||||
|
this.updateLabel(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateLabel(queryPaneEnabled: boolean): void {
|
||||||
|
if (queryPaneEnabled) {
|
||||||
|
this.label = this.closeSqlLabel;
|
||||||
|
} else {
|
||||||
|
this.label = this.showSqlLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public run(): TPromise<void> {
|
||||||
|
this.editor.toggleQueryPane();
|
||||||
|
this.updateLabel(this.editor.queryPaneEnabled());
|
||||||
|
return TPromise.as(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@ import { GridParentComponent } from 'sql/parts/grid/views/gridParentComponent';
|
|||||||
import { EditDataGridActionProvider } from 'sql/parts/grid/views/editData/editDataGridActions';
|
import { EditDataGridActionProvider } from 'sql/parts/grid/views/editData/editDataGridActions';
|
||||||
import { error } from 'sql/base/common/log';
|
import { error } from 'sql/base/common/log';
|
||||||
import { clone } from 'sql/base/common/objects';
|
import { clone } from 'sql/base/common/objects';
|
||||||
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import Severity from 'vs/base/common/severity';
|
||||||
|
|
||||||
export const EDITDATA_SELECTOR: string = 'editdata-component';
|
export const EDITDATA_SELECTOR: string = 'editdata-component';
|
||||||
|
|
||||||
@@ -40,7 +42,6 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
// All datasets
|
// All datasets
|
||||||
private dataSet: IGridDataSet;
|
private dataSet: IGridDataSet;
|
||||||
private scrollTimeOut: number;
|
private scrollTimeOut: number;
|
||||||
private messagesAdded = false;
|
|
||||||
private scrollEnabled = true;
|
private scrollEnabled = true;
|
||||||
private firstRender = true;
|
private firstRender = true;
|
||||||
private totalElapsedTimeSpan: number;
|
private totalElapsedTimeSpan: number;
|
||||||
@@ -54,6 +55,8 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
private removingNewRow: boolean;
|
private removingNewRow: boolean;
|
||||||
private rowIdMappings: { [gridRowId: number]: number } = {};
|
private rowIdMappings: { [gridRowId: number]: number } = {};
|
||||||
|
|
||||||
|
private notificationService: INotificationService;
|
||||||
|
|
||||||
// Edit Data functions
|
// Edit Data functions
|
||||||
public onActiveCellChanged: (event: { row: number, column: number }) => void;
|
public onActiveCellChanged: (event: { row: number, column: number }) => void;
|
||||||
public onCellEditEnd: (event: { row: number, column: number, newValue: any }) => void;
|
public onCellEditEnd: (event: { row: number, column: number, newValue: any }) => void;
|
||||||
@@ -75,6 +78,7 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
let editDataParameters: EditDataComponentParams = this._bootstrapService.getBootstrapParams(this._el.nativeElement.tagName);
|
let editDataParameters: EditDataComponentParams = this._bootstrapService.getBootstrapParams(this._el.nativeElement.tagName);
|
||||||
this.dataService = editDataParameters.dataService;
|
this.dataService = editDataParameters.dataService;
|
||||||
this.actionProvider = this._bootstrapService.instantiationService.createInstance(EditDataGridActionProvider, this.dataService, this.onGridSelectAll(), this.onDeleteRow(), this.onRevertRow());
|
this.actionProvider = this._bootstrapService.instantiationService.createInstance(EditDataGridActionProvider, this.dataService, this.onGridSelectAll(), this.onDeleteRow(), this.onRevertRow());
|
||||||
|
this.notificationService = bootstrapService.notificationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +131,6 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
self.renderedDataSets = self.placeHolderDataSets;
|
self.renderedDataSets = self.placeHolderDataSets;
|
||||||
self.totalElapsedTimeSpan = undefined;
|
self.totalElapsedTimeSpan = undefined;
|
||||||
self.complete = false;
|
self.complete = false;
|
||||||
self.messagesAdded = false;
|
|
||||||
|
|
||||||
// Hooking up edit functions
|
// Hooking up edit functions
|
||||||
this.onIsCellEditValid = (row, column, value): boolean => {
|
this.onIsCellEditValid = (row, column, value): boolean => {
|
||||||
@@ -302,7 +305,6 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
handleComplete(self: EditDataComponent, event: any): void {
|
handleComplete(self: EditDataComponent, event: any): void {
|
||||||
self.totalElapsedTimeSpan = event.data;
|
self.totalElapsedTimeSpan = event.data;
|
||||||
self.complete = true;
|
self.complete = true;
|
||||||
self.messagesAdded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEditSessionReady(self, event): void {
|
handleEditSessionReady(self, event): void {
|
||||||
@@ -310,7 +312,12 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMessage(self: EditDataComponent, event: any): void {
|
handleMessage(self: EditDataComponent, event: any): void {
|
||||||
// TODO: what do we do with messages?
|
if (event.data && event.data.isError) {
|
||||||
|
self.notificationService.notify({
|
||||||
|
severity: Severity.Error,
|
||||||
|
message: event.data.message
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleResultSet(self: EditDataComponent, event: any): void {
|
handleResultSet(self: EditDataComponent, event: any): void {
|
||||||
@@ -360,7 +367,6 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
undefinedDataSet.dataRows = undefined;
|
undefinedDataSet.dataRows = undefined;
|
||||||
undefinedDataSet.resized = new EventEmitter();
|
undefinedDataSet.resized = new EventEmitter();
|
||||||
self.placeHolderDataSets.push(undefinedDataSet);
|
self.placeHolderDataSets.push(undefinedDataSet);
|
||||||
self.messagesAdded = true;
|
|
||||||
self.onScroll(0);
|
self.onScroll(0);
|
||||||
|
|
||||||
// Setup the state of the selected cell
|
// Setup the state of the selected cell
|
||||||
|
|||||||
@@ -192,9 +192,10 @@ export class OEEditDataAction extends EditDataAction {
|
|||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService
|
@IInstantiationService private _instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public run(actionContext: any): TPromise<boolean> {
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import { QueryPlanEditor } from 'sql/parts/queryPlan/queryPlanEditor';
|
|||||||
import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput';
|
import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput';
|
||||||
import * as Constants from 'sql/parts/query/common/constants';
|
import * as Constants from 'sql/parts/query/common/constants';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
|
import { EditDataResultsEditor } from 'sql/parts/editData/editor/editDataResultsEditor';
|
||||||
|
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||||
|
|
||||||
const gridCommandsWeightBonus = 100; // give our commands a little bit more weight over other default list/tree commands
|
const gridCommandsWeightBonus = 100; // give our commands a little bit more weight over other default list/tree commands
|
||||||
|
|
||||||
@@ -81,6 +83,16 @@ const editDataEditorDescriptor = new EditorDescriptor(
|
|||||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
||||||
.registerEditor(editDataEditorDescriptor, [new SyncDescriptor(EditDataInput)]);
|
.registerEditor(editDataEditorDescriptor, [new SyncDescriptor(EditDataInput)]);
|
||||||
|
|
||||||
|
// Editor
|
||||||
|
const editDataResultsEditorDescriptor = new EditorDescriptor(
|
||||||
|
EditDataResultsEditor,
|
||||||
|
EditDataResultsEditor.ID,
|
||||||
|
'EditDataResults'
|
||||||
|
);
|
||||||
|
|
||||||
|
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
||||||
|
.registerEditor(editDataResultsEditorDescriptor, [new SyncDescriptor(EditDataResultsInput)]);
|
||||||
|
|
||||||
let actionRegistry = <IWorkbenchActionRegistry>Registry.as(Extensions.WorkbenchActions);
|
let actionRegistry = <IWorkbenchActionRegistry>Registry.as(Extensions.WorkbenchActions);
|
||||||
|
|
||||||
// Query Actions
|
// Query Actions
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export interface IQueryEditorService {
|
|||||||
newQueryPlanEditor(xmlShowPlan: string): Promise<any>;
|
newQueryPlanEditor(xmlShowPlan: string): Promise<any>;
|
||||||
|
|
||||||
// Creates new edit data session
|
// Creates new edit data session
|
||||||
newEditDataEditor(schemaName: string, tableName: string): Promise<IConnectableInput>;
|
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
||||||
|
|
||||||
// Clears any QueryEditor data for the given URI held by this service
|
// Clears any QueryEditor data for the given URI held by this service
|
||||||
onQueryInputClosed(uri: string): void;
|
onQueryInputClosed(uri: string): void;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export interface IQueryManagementService {
|
|||||||
onEditSessionReady(ownerUri: string, success: boolean, message: string): void;
|
onEditSessionReady(ownerUri: string, success: boolean, message: string): void;
|
||||||
|
|
||||||
// Edit Data Functions
|
// Edit Data Functions
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void>;
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
|
||||||
disposeEdit(ownerUri: string): Thenable<void>;
|
disposeEdit(ownerUri: string): Thenable<void>;
|
||||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
||||||
commitEdit(ownerUri): Thenable<void>;
|
commitEdit(ownerUri): Thenable<void>;
|
||||||
@@ -68,7 +68,7 @@ export interface IQueryRequestHandler {
|
|||||||
saveResults(requestParams: sqlops.SaveResultsRequestParams): Thenable<sqlops.SaveResultRequestResult>;
|
saveResults(requestParams: sqlops.SaveResultsRequestParams): Thenable<sqlops.SaveResultRequestResult>;
|
||||||
|
|
||||||
// Edit Data actions
|
// Edit Data actions
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void>;
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
|
||||||
disposeEdit(ownerUri: string): Thenable<void>;
|
disposeEdit(ownerUri: string): Thenable<void>;
|
||||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
||||||
commitEdit(ownerUri): Thenable<void>;
|
commitEdit(ownerUri): Thenable<void>;
|
||||||
@@ -244,9 +244,9 @@ export class QueryManagementService implements IQueryManagementService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Edit Data Functions
|
// Edit Data Functions
|
||||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||||
return this._runAction(ownerUri, (runner) => {
|
return this._runAction(ownerUri, (runner) => {
|
||||||
return runner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
|
return runner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
|||||||
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||||
import * as Constants from 'sql/parts/query/common/constants';
|
import * as Constants from 'sql/parts/query/common/constants';
|
||||||
import * as ConnectionConstants from 'sql/parts/connection/common/constants';
|
import * as ConnectionConstants from 'sql/parts/connection/common/constants';
|
||||||
|
import { EditDataEditor } from 'sql/parts/editData/editor/editDataEditor';
|
||||||
|
|
||||||
const singleQuote = '\'';
|
const singleQuote = '\'';
|
||||||
|
|
||||||
@@ -98,8 +99,8 @@ export class RunQueryKeyboardAction extends Action {
|
|||||||
|
|
||||||
public run(): TPromise<void> {
|
public run(): TPromise<void> {
|
||||||
let editor = this._editorService.getActiveEditor();
|
let editor = this._editorService.getActiveEditor();
|
||||||
if (editor && editor instanceof QueryEditor) {
|
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) {
|
||||||
let queryEditor: QueryEditor = editor;
|
let queryEditor: QueryEditor | EditDataEditor = editor;
|
||||||
queryEditor.runQuery();
|
queryEditor.runQuery();
|
||||||
}
|
}
|
||||||
return TPromise.as(null);
|
return TPromise.as(null);
|
||||||
@@ -174,8 +175,8 @@ export class CancelQueryKeyboardAction extends Action {
|
|||||||
|
|
||||||
public run(): TPromise<void> {
|
public run(): TPromise<void> {
|
||||||
let editor = this._editorService.getActiveEditor();
|
let editor = this._editorService.getActiveEditor();
|
||||||
if (editor && editor instanceof QueryEditor) {
|
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) {
|
||||||
let queryEditor: QueryEditor = editor;
|
let queryEditor: QueryEditor | EditDataEditor = editor;
|
||||||
queryEditor.cancelQuery();
|
queryEditor.cancelQuery();
|
||||||
}
|
}
|
||||||
return TPromise.as(null);
|
return TPromise.as(null);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export interface IQueryModelService {
|
|||||||
|
|
||||||
|
|
||||||
// Edit Data Functions
|
// Edit Data Functions
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): void;
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): void;
|
||||||
disposeEdit(ownerUri: string): Thenable<void>;
|
disposeEdit(ownerUri: string): Thenable<void>;
|
||||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<EditUpdateCellResult>;
|
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<EditUpdateCellResult>;
|
||||||
commitEdit(ownerUri): Thenable<void>;
|
commitEdit(ownerUri): Thenable<void>;
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EDIT DATA METHODS /////////////////////////////////////////////////////
|
// EDIT DATA METHODS /////////////////////////////////////////////////////
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): void {
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): void {
|
||||||
// Reuse existing query runner if it exists
|
// Reuse existing query runner if it exists
|
||||||
let queryRunner: QueryRunner;
|
let queryRunner: QueryRunner;
|
||||||
let info: QueryInfo;
|
let info: QueryInfo;
|
||||||
@@ -368,6 +368,8 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
queryRunner = existingRunner;
|
queryRunner = existingRunner;
|
||||||
} else {
|
} else {
|
||||||
|
info = new QueryInfo();
|
||||||
|
|
||||||
// We do not have a query runner for this editor, so create a new one
|
// We do not have a query runner for this editor, so create a new one
|
||||||
// and map it to the results uri
|
// and map it to the results uri
|
||||||
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri, ownerUri);
|
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri, ownerUri);
|
||||||
@@ -376,15 +378,21 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
});
|
});
|
||||||
queryRunner.addListener(QREvents.BATCH_START, batch => {
|
queryRunner.addListener(QREvents.BATCH_START, batch => {
|
||||||
let link = undefined;
|
let link = undefined;
|
||||||
|
let messageText = LocalizedConstants.runQueryBatchStartMessage;
|
||||||
if (batch.selection) {
|
if (batch.selection) {
|
||||||
|
if (info.selectionSnippet) {
|
||||||
|
// This indicates it's a query string. Do not include line information since it'll be inaccurate, but show some of the
|
||||||
|
// executed query text
|
||||||
|
messageText = nls.localize('runQueryStringBatchStartMessage', 'Started executing query "{0}"', info.selectionSnippet);
|
||||||
|
} else {
|
||||||
link = {
|
link = {
|
||||||
text: strings.format(LocalizedConstants.runQueryBatchStartLine, batch.selection.startLine + 1),
|
text: strings.format(LocalizedConstants.runQueryBatchStartLine, batch.selection.startLine + 1)
|
||||||
uri: ''
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let message = {
|
let message = {
|
||||||
message: LocalizedConstants.runQueryBatchStartMessage,
|
message: messageText,
|
||||||
batchId: undefined,
|
batchId: batch.id,
|
||||||
isError: false,
|
isError: false,
|
||||||
time: new Date().toLocaleTimeString(),
|
time: new Date().toLocaleTimeString(),
|
||||||
link: link
|
link: link
|
||||||
@@ -407,13 +415,20 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
this._fireQueryEvent(e.ownerUri, 'editSessionReady');
|
this._fireQueryEvent(e.ownerUri, 'editSessionReady');
|
||||||
});
|
});
|
||||||
|
|
||||||
info = new QueryInfo();
|
|
||||||
info.queryRunner = queryRunner;
|
info.queryRunner = queryRunner;
|
||||||
info.dataService = this._instantiationService.createInstance(DataService, ownerUri);
|
info.dataService = this._instantiationService.createInstance(DataService, ownerUri);
|
||||||
this._queryInfoMap.set(ownerUri, info);
|
this._queryInfoMap.set(ownerUri, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
queryRunner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
|
if (queryString) {
|
||||||
|
if (queryString.length < selectionSnippetMaxLen) {
|
||||||
|
info.selectionSnippet = queryString;
|
||||||
|
} else {
|
||||||
|
info.selectionSnippet = queryString.substring(0, selectionSnippetMaxLen - 3) + '...';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queryRunner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public cancelInitializeEdit(input: QueryRunner | string): void {
|
public cancelInitializeEdit(input: QueryRunner | string): void {
|
||||||
|
|||||||
@@ -300,13 +300,13 @@ export default class QueryRunner {
|
|||||||
/*
|
/*
|
||||||
* Handle a session ready event for Edit Data
|
* Handle a session ready event for Edit Data
|
||||||
*/
|
*/
|
||||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||||
// Update internal state to show that we're executing the query
|
// Update internal state to show that we're executing the query
|
||||||
this._isExecuting = true;
|
this._isExecuting = true;
|
||||||
this._totalElapsedMilliseconds = 0;
|
this._totalElapsedMilliseconds = 0;
|
||||||
// TODO issue #228 add statusview callbacks here
|
// TODO issue #228 add statusview callbacks here
|
||||||
|
|
||||||
return this._queryManagementService.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit).then(result => {
|
return this._queryManagementService.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString).then(result => {
|
||||||
// The query has started, so lets fire up the result pane
|
// The query has started, so lets fire up the result pane
|
||||||
this._eventEmitter.emit(EventType.START);
|
this._eventEmitter.emit(EventType.START);
|
||||||
this._queryManagementService.registerRunner(this, ownerUri);
|
this._queryManagementService.registerRunner(this, ownerUri);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import paths = require('vs/base/common/paths');
|
|||||||
import { isLinux } from 'vs/base/common/platform';
|
import { isLinux } from 'vs/base/common/platform';
|
||||||
import { Schemas } from 'vs/base/common/network';
|
import { Schemas } from 'vs/base/common/network';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ export class QueryEditorService implements IQueryEditorService {
|
|||||||
/**
|
/**
|
||||||
* Creates new edit data session
|
* Creates new edit data session
|
||||||
*/
|
*/
|
||||||
public newEditDataEditor(schemaName: string, tableName: string): Promise<IConnectableInput> {
|
public newEditDataEditor(schemaName: string, tableName: string, sqlContent: string): Promise<IConnectableInput> {
|
||||||
|
|
||||||
return new Promise<IConnectableInput>((resolve, reject) => {
|
return new Promise<IConnectableInput>((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
@@ -129,8 +130,17 @@ export class QueryEditorService implements IQueryEditorService {
|
|||||||
let filePath = this.createEditDataFileName(objectName);
|
let filePath = this.createEditDataFileName(objectName);
|
||||||
let docUri: URI = URI.from({ scheme: Schemas.untitled, path: filePath });
|
let docUri: URI = URI.from({ scheme: Schemas.untitled, path: filePath });
|
||||||
|
|
||||||
|
// Create a sql document pane with accoutrements
|
||||||
|
const fileInput = this._untitledEditorService.createOrGet(docUri, 'sql');
|
||||||
|
fileInput.resolve().then(m => {
|
||||||
|
if (sqlContent) {
|
||||||
|
m.textEditorModel.setValue(sqlContent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Create an EditDataInput for editing
|
// Create an EditDataInput for editing
|
||||||
let editDataInput: EditDataInput = this._instantiationService.createInstance(EditDataInput, docUri, schemaName, tableName);
|
const resultsInput: EditDataResultsInput = this._instantiationService.createInstance(EditDataResultsInput, docUri.toString());
|
||||||
|
let editDataInput: EditDataInput = this._instantiationService.createInstance(EditDataInput, docUri, schemaName, tableName, fileInput, sqlContent, resultsInput);
|
||||||
|
|
||||||
this._editorService.openEditor(editDataInput, { pinned: true })
|
this._editorService.openEditor(editDataInput, { pinned: true })
|
||||||
.then((editor) => {
|
.then((editor) => {
|
||||||
@@ -212,7 +222,7 @@ export class QueryEditorService implements IQueryEditorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let uri: URI = QueryEditorService._getEditorChangeUri(editor.input, changingToSql);
|
let uri: URI = QueryEditorService._getEditorChangeUri(editor.input, changingToSql);
|
||||||
if(uri.scheme === Schemas.untitled && editor.input instanceof QueryInput)
|
if(uri.scheme === Schemas.untitled && (editor.input instanceof QueryInput || editor.input instanceof EditDataInput))
|
||||||
{
|
{
|
||||||
QueryEditorService.notificationService.notify({
|
QueryEditorService.notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
@@ -299,10 +309,8 @@ export class QueryEditorService implements IQueryEditorService {
|
|||||||
filePath = editDataFileName(counter);
|
filePath = editDataFileName(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if this document name already exists in any open documents tabs
|
let untitledEditors = this._untitledEditorService.getAll();
|
||||||
let fileNames: string[] = [];
|
while (untitledEditors.find(x => x.getName().toUpperCase() === filePath.toUpperCase())) {
|
||||||
this._editorGroupService.getStacksModel().groups.map(group => group.getEditors().map(editor => fileNames.push(editor.getName())));
|
|
||||||
while (fileNames.find(x => x.toUpperCase() === filePath.toUpperCase())) {
|
|
||||||
counter++;
|
counter++;
|
||||||
filePath = editDataFileName(counter);
|
filePath = editDataFileName(counter);
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/sql/sqlops.d.ts
vendored
3
src/sql/sqlops.d.ts
vendored
@@ -651,7 +651,7 @@ declare module 'sqlops' {
|
|||||||
createRow(ownerUri: string): Thenable<EditCreateRowResult>;
|
createRow(ownerUri: string): Thenable<EditCreateRowResult>;
|
||||||
deleteRow(ownerUri: string, rowId: number): Thenable<void>;
|
deleteRow(ownerUri: string, rowId: number): Thenable<void>;
|
||||||
disposeEdit(ownerUri: string): Thenable<void>;
|
disposeEdit(ownerUri: string): Thenable<void>;
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void>;
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
|
||||||
revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<EditRevertCellResult>;
|
revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<EditRevertCellResult>;
|
||||||
revertRow(ownerUri: string, rowId: number): Thenable<void>;
|
revertRow(ownerUri: string, rowId: number): Thenable<void>;
|
||||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<EditUpdateCellResult>;
|
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<EditUpdateCellResult>;
|
||||||
@@ -879,6 +879,7 @@ declare module 'sqlops' {
|
|||||||
objectName: string;
|
objectName: string;
|
||||||
schemaName: string;
|
schemaName: string;
|
||||||
objectType: string;
|
objectType: string;
|
||||||
|
queryString: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -247,8 +247,8 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
return this._resolveProvider<sqlops.QueryProvider>(handle).disposeEdit(ownerUri);
|
return this._resolveProvider<sqlops.QueryProvider>(handle).disposeEdit(ownerUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||||
return this._resolveProvider<sqlops.QueryProvider>(handle).initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
|
return this._resolveProvider<sqlops.QueryProvider>(handle).initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
$revertCell(handle: number, ownerUri: string, rowId: number, columnId: number): Thenable<sqlops.EditRevertCellResult> {
|
$revertCell(handle: number, ownerUri: string, rowId: number, columnId: number): Thenable<sqlops.EditRevertCellResult> {
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
|||||||
return self._serializationService.saveAs(requestParams.resultFormat, requestParams.filePath, undefined, true);
|
return self._serializationService.saveAs(requestParams.resultFormat, requestParams.filePath, undefined, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||||
return self._proxy.$initializeEdit(handle, ownerUri, schemaName, objectName, objectType, rowLimit);
|
return self._proxy.$initializeEdit(handle, ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||||
},
|
},
|
||||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult> {
|
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult> {
|
||||||
return self._proxy.$updateCell(handle, ownerUri, rowId, columnId, newValue);
|
return self._proxy.$updateCell(handle, ownerUri, rowId, columnId, newValue);
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export abstract class ExtHostDataProtocolShape {
|
|||||||
/**
|
/**
|
||||||
* Initializes a new edit data session for the requested table/view
|
* Initializes a new edit data session for the requested table/view
|
||||||
*/
|
*/
|
||||||
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> { throw ni(); }
|
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> { throw ni(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts any pending changes for the requested cell and returns the original value
|
* Reverts any pending changes for the requested cell and returns the original value
|
||||||
|
|||||||
@@ -187,19 +187,20 @@ export class EditDataAction extends Action {
|
|||||||
constructor(
|
constructor(
|
||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
|
@IScriptingService protected _scriptingService: IScriptingService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: BaseActionContext): TPromise<boolean> {
|
public run(actionContext: BaseActionContext): TPromise<boolean> {
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
TaskUtilities.editData(
|
TaskUtilities.scriptEditSelect(
|
||||||
actionContext.profile,
|
actionContext.profile,
|
||||||
actionContext.object.name,
|
actionContext.object,
|
||||||
actionContext.object.schema,
|
|
||||||
this._connectionManagementService,
|
this._connectionManagementService,
|
||||||
this._queryEditorService
|
this._queryEditorService,
|
||||||
|
this._scriptingService
|
||||||
).then(
|
).then(
|
||||||
result => {
|
result => {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
|
|||||||
@@ -169,9 +169,13 @@ export function scriptSelect(connectionProfile: IConnectionProfile, metadata: sq
|
|||||||
/**
|
/**
|
||||||
* Opens a new Edit Data session
|
* Opens a new Edit Data session
|
||||||
*/
|
*/
|
||||||
export function editData(connectionProfile: IConnectionProfile, tableName: string, schemaName: string, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService): Promise<void> {
|
export function scriptEditSelect(connectionProfile: IConnectionProfile, metadata: sqlops.ObjectMetadata, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService, scriptingService: IScriptingService): Promise<void> {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
queryEditorService.newEditDataEditor(schemaName, tableName).then((owner: EditDataInput) => {
|
connectionService.connectIfNotConnected(connectionProfile).then(connectionResult => {
|
||||||
|
let paramDetails: sqlops.ScriptingParamDetails = getScriptingParamDetails(connectionService, connectionResult, metadata);
|
||||||
|
scriptingService.script(connectionResult, metadata, ScriptOperation.Select, paramDetails).then(result => {
|
||||||
|
if (result.script) {
|
||||||
|
queryEditorService.newEditDataEditor(metadata.schema, metadata.name, result.script).then((owner: EditDataInput) => {
|
||||||
// Connect our editor
|
// Connect our editor
|
||||||
let options: IConnectionCompletionOptions = {
|
let options: IConnectionCompletionOptions = {
|
||||||
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: owner },
|
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: owner },
|
||||||
@@ -183,6 +187,16 @@ export function editData(connectionProfile: IConnectionProfile, tableName: strin
|
|||||||
connectionService.connect(connectionProfile, owner.uri, options).then(() => {
|
connectionService.connect(connectionProfile, owner.uri, options).then(() => {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
}).catch(editorError => {
|
||||||
|
reject(editorError);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let errMsg: string = nls.localize('scriptSelectNotFound', 'No script was returned when calling select script on object ');
|
||||||
|
reject(errMsg.concat(metadata.metadataTypeName));
|
||||||
|
}
|
||||||
|
}, scriptError => {
|
||||||
|
reject(scriptError);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,16 @@ export abstract class EditorInput implements IEditorInput {
|
|||||||
return this._onDispose.event;
|
return this._onDispose.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
// Saving is not supported in the EditData query editor, so this can be overriden in its Input.
|
||||||
|
private _savingSupported: boolean = true;
|
||||||
|
public get savingSupported(): boolean {
|
||||||
|
return this._savingSupported;
|
||||||
|
}
|
||||||
|
public disableSaving() {
|
||||||
|
this._savingSupported = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the associated resource of this input if any.
|
* Returns the associated resource of this input if any.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -167,6 +167,11 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isDirty(): boolean {
|
public isDirty(): boolean {
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
if (!this.savingSupported) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.cachedModel) {
|
if (this.cachedModel) {
|
||||||
return this.cachedModel.isDirty();
|
return this.cachedModel.isDirty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||||||
import * as labels from 'vs/base/common/labels';
|
import * as labels from 'vs/base/common/labels';
|
||||||
import URI from 'vs/base/common/uri';
|
import URI from 'vs/base/common/uri';
|
||||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { toResource, IEditorCommandsContext } from 'vs/workbench/common/editor';
|
import { toResource, IEditorCommandsContext, EditorInput } from 'vs/workbench/common/editor';
|
||||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||||
@@ -89,6 +89,11 @@ function save(resource: URI, isSaveAs: boolean, editorService: IWorkbenchEditorS
|
|||||||
textFileService: ITextFileService, editorGroupService: IEditorGroupService, queryEditorService: IQueryEditorService,): TPromise<any> {
|
textFileService: ITextFileService, editorGroupService: IEditorGroupService, queryEditorService: IQueryEditorService,): TPromise<any> {
|
||||||
|
|
||||||
if (resource && (fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) {
|
if (resource && (fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) {
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
let editorInput = editorService.getActiveEditorInput();
|
||||||
|
if (editorInput instanceof EditorInput && !(<EditorInput>editorInput).savingSupported) {
|
||||||
|
return TPromise.as(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Save As (or Save untitled with associated path)
|
// Save As (or Save untitled with associated path)
|
||||||
if (isSaveAs || resource.scheme === Schemas.untitled) {
|
if (isSaveAs || resource.scheme === Schemas.untitled) {
|
||||||
|
|||||||
Reference in New Issue
Block a user