Compare commits

...

7 Commits
1.3.8 ... 1.3.9

Author SHA1 Message Date
kisantia
cacf0777c7 Moving onValidityChanged listener to showPage() so that it gets added to pages that are added to the wizard after the initial start up (#3691) 2019-01-14 15:01:54 -08:00
Karl Burtram
cb433fbeac Bump Azure Data Studio to 1.3.9 2019-01-14 14:24:28 -08:00
Kevin Cunnane
8f6736df5e Fix #3736 Notebook: cannot connect to SQL big data cluster due to empty config.json file (#3738)
- Writing the config file in the core for now, will look to move to the extension in Feb release
2019-01-14 14:19:45 -08:00
Anthony Dresser
ef76d730e3 fix html formatting in grid (#3722) 2019-01-14 14:15:25 -08:00
Karl Burtram
aabbeeffa9 Add connection dialog icon dark theme and HC styles (#3721) 2019-01-14 14:13:43 -08:00
Anthony Dresser
7a513de543 Duplicate Result sets (fix merge conflicts) 2019-01-14 14:12:29 -08:00
Karl Burtram
abbd5ec037 Add Idera extension to recommendation list (#3709) 2019-01-14 14:09:08 -08:00
10 changed files with 112 additions and 92 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "azuredatastudio", "name": "azuredatastudio",
"version": "1.3.8", "version": "1.3.9",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee", "distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": { "author": {
"name": "Microsoft Corporation" "name": "Microsoft Corporation"

View File

@@ -42,7 +42,8 @@
"Microsoft.server-report", "Microsoft.server-report",
"Microsoft.sql-vnext", "Microsoft.sql-vnext",
"Microsoft.whoisactive", "Microsoft.whoisactive",
"Redgate.sql-search" "Redgate.sql-search",
"IDERA.sqldm-performance-insights"
], ],
"extensionsGallery": { "extensionsGallery": {
"serviceUrl": "https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json" "serviceUrl": "https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json"

View File

@@ -90,6 +90,8 @@
margin: 0px 13px; margin: 0px 13px;
} }
.vs-dark .connection-dialog .connection-history-actions .action-label.icon,
.hc-black .connection-dialog .connection-history-actions .action-label.icon,
.connection-dialog .connection-history-actions .action-label.icon { .connection-dialog .connection-history-actions .action-label.icon {
display: block; display: block;
height: 20px; height: 20px;

View File

@@ -48,13 +48,13 @@ export function textFormatter(row: number, cell: any, value: any, columnDef: any
if (!value.isNull) { if (!value.isNull) {
valueToDisplay = value.displayValue.replace(/(\r\n|\n|\r)/g, ' '); valueToDisplay = value.displayValue.replace(/(\r\n|\n|\r)/g, ' ');
valueToDisplay = escape(valueToDisplay.length > 250 ? valueToDisplay.slice(0, 250) + '...' : valueToDisplay); valueToDisplay = escape(valueToDisplay.length > 250 ? valueToDisplay.slice(0, 250) + '...' : valueToDisplay);
titleValue = value.displayValue; titleValue = valueToDisplay;
} else { } else {
cellClasses += ' missing-value'; cellClasses += ' missing-value';
} }
} else if (typeof value === 'string') { } else if (typeof value === 'string') {
valueToDisplay = escape(value.length > 250 ? value.slice(0, 250) + '...' : value); valueToDisplay = escape(value.length > 250 ? value.slice(0, 250) + '...' : value);
titleValue = value; titleValue = valueToDisplay;
} }
return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`; return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`;

View File

@@ -350,7 +350,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
if (!newConnection && this._activeContexts.defaultConnection.options['host'] === host) { if (!newConnection && this._activeContexts.defaultConnection.options['host'] === host) {
newConnection = this._activeContexts.defaultConnection; newConnection = this._activeContexts.defaultConnection;
} }
SparkMagicContexts.configureContext(this.notebookOptions); SparkMagicContexts.configureContext();
this._hadoopConnection = new NotebookConnection(newConnection); this._hadoopConnection = new NotebookConnection(newConnection);
this.refreshConnections(newConnection); this.refreshConnections(newConnection);
this._clientSession.updateConnection(this._hadoopConnection); this._clientSession.updateConnection(this._hadoopConnection);

View File

@@ -8,7 +8,6 @@
import * as path from 'path'; import * as path from 'path';
import { nb } from 'sqlops'; import { nb } from 'sqlops';
import * as json from 'vs/base/common/json';
import * as pfs from 'vs/base/node/pfs'; import * as pfs from 'vs/base/node/pfs';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
@@ -17,11 +16,48 @@ import * as notebookUtils from '../notebookUtils';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
const configBase = {
'kernel_python_credentials': {
'url': ''
},
'kernel_scala_credentials': {
'url': ''
},
'kernel_r_credentials': {
'url': ''
},
'ignore_ssl_errors': true,
'logging_config': {
'version': 1,
'formatters': {
'magicsFormatter': {
'format': '%(asctime)s\t%(levelname)s\t%(message)s',
'datefmt': ''
}
},
'handlers': {
'magicsHandler': {
'class': 'hdijupyterutils.filehandler.MagicsFileHandler',
'formatter': 'magicsFormatter',
'home_path': ''
}
},
'loggers': {
'magicsLogger': {
'handlers': ['magicsHandler'],
'level': 'DEBUG',
'propagate': 0
}
}
}
};
export class SparkMagicContexts { export class SparkMagicContexts {
public static get DefaultContext(): IDefaultConnection { public static get DefaultContext(): IDefaultConnection {
// TODO NOTEBOOK REFACTOR fix default connection handling // TODO NOTEBOOK REFACTOR fix default connection handling
let defaultConnection: IConnectionProfile = <any> { let defaultConnection: IConnectionProfile = <any>{
providerName: notebookConstants.hadoopKnoxProviderName, providerName: notebookConstants.hadoopKnoxProviderName,
id: '-1', id: '-1',
options: options:
@@ -47,7 +83,7 @@ export class SparkMagicContexts {
let connections: IDefaultConnection = this.DefaultContext; let connections: IDefaultConnection = this.DefaultContext;
if (!profile) { if (!profile) {
if (!kernelChangedArgs || !kernelChangedArgs.newValue || if (!kernelChangedArgs || !kernelChangedArgs.newValue ||
(kernelChangedArgs.oldValue && kernelChangedArgs.newValue.id === kernelChangedArgs.oldValue.id)) { (kernelChangedArgs.oldValue && kernelChangedArgs.newValue.id === kernelChangedArgs.oldValue.id)) {
// nothing to do, kernels are the same or new kernel is undefined // nothing to do, kernels are the same or new kernel is undefined
return connections; return connections;
} }
@@ -55,7 +91,7 @@ export class SparkMagicContexts {
if (kernelChangedArgs && kernelChangedArgs.newValue && kernelChangedArgs.newValue.name) { if (kernelChangedArgs && kernelChangedArgs.newValue && kernelChangedArgs.newValue.name) {
switch (kernelChangedArgs.newValue.name) { switch (kernelChangedArgs.newValue.name) {
case (notebookConstants.python3): case (notebookConstants.python3):
// python3 case, use this.DefaultContext for the only connection // python3 case, use this.DefaultContext for the only connection
break; break;
//TO DO: Handle server connections based on kernel type. Right now, we call the same method for all kernel types. //TO DO: Handle server connections based on kernel type. Right now, we call the same method for all kernel types.
default: default:
@@ -76,13 +112,13 @@ export class SparkMagicContexts {
let defaultConnection: IConnectionProfile = SparkMagicContexts.DefaultContext.defaultConnection; let defaultConnection: IConnectionProfile = SparkMagicContexts.DefaultContext.defaultConnection;
let activeConnections: IConnectionProfile[] = await connectionService.getActiveConnections(); let activeConnections: IConnectionProfile[] = await connectionService.getActiveConnections();
// If no connections exist, only show 'n/a' // If no connections exist, only show 'n/a'
if (activeConnections && activeConnections.length > 0) { if (activeConnections && activeConnections.length > 0) {
// Remove all non-Spark connections // Remove all non-Spark connections
activeConnections = activeConnections.filter(conn => conn.providerName === notebookConstants.hadoopKnoxProviderName); activeConnections = activeConnections.filter(conn => conn.providerName === notebookConstants.hadoopKnoxProviderName);
} }
if (activeConnections.length === 0) { if (activeConnections.length === 0) {
return SparkMagicContexts.DefaultContext; return SparkMagicContexts.DefaultContext;
} }
// If launched from the right click or server dashboard, connection profile data exists, so use that as default // If launched from the right click or server dashboard, connection profile data exists, so use that as default
if (profile && profile.options) { if (profile && profile.options) {
@@ -95,7 +131,7 @@ export class SparkMagicContexts {
defaultConnection = activeConnections[0]; defaultConnection = activeConnections[0];
} else { } else {
// TODO NOTEBOOK REFACTOR change this so it's no longer incompatible with IConnectionProfile // TODO NOTEBOOK REFACTOR change this so it's no longer incompatible with IConnectionProfile
defaultConnection = <IConnectionProfile> <any>{ defaultConnection = <IConnectionProfile><any>{
providerName: notebookConstants.hadoopKnoxProviderName, providerName: notebookConstants.hadoopKnoxProviderName,
id: '-1', id: '-1',
options: options:
@@ -107,31 +143,28 @@ export class SparkMagicContexts {
} }
} }
return { return {
otherConnections: activeConnections, otherConnections: activeConnections,
defaultConnection: defaultConnection defaultConnection: defaultConnection
}; };
} }
public static async configureContext(options: INotebookModelOptions): Promise<object> { public static async configureContext(): Promise<object> {
let sparkmagicConfDir = path.join(notebookUtils.getUserHome(), '.sparkmagic'); let sparkmagicConfDir = path.join(notebookUtils.getUserHome(), '.sparkmagic');
// TODO NOTEBOOK REFACTOR re-enable this or move to extension. Requires config files to be available in order to work // TODO NOTEBOOK REFACTOR re-enable this or move to extension. Requires config files to be available in order to work
// await notebookUtils.mkDir(sparkmagicConfDir); await notebookUtils.mkDir(sparkmagicConfDir);
// // Default to localhost in config file. // Default to localhost in config file.
// let creds: ICredentials = { let creds: ICredentials = {
// 'url': 'http://localhost:8088' 'url': 'http://localhost:8088'
// }; };
// let configPath = notebookUtils.getTemplatePath(options.extensionContext.extensionPath, path.join('jupyter_config', 'sparkmagic_config.json')); let config: ISparkMagicConfig = Object.assign({}, configBase);
// let fileBuffer: Buffer = await pfs.readFile(configPath); SparkMagicContexts.updateConfig(config, creds, sparkmagicConfDir);
// let fileContents: string = fileBuffer.toString();
// let config: ISparkMagicConfig = json.parse(fileContents);
// SparkMagicContexts.updateConfig(config, creds, sparkmagicConfDir);
// let configFilePath = path.join(sparkmagicConfDir, 'config.json'); let configFilePath = path.join(sparkmagicConfDir, 'config.json');
// await pfs.writeFile(configFilePath, JSON.stringify(config)); await pfs.writeFile(configFilePath, JSON.stringify(config));
return {'SPARKMAGIC_CONF_DIR': sparkmagicConfDir}; return { 'SPARKMAGIC_CONF_DIR': sparkmagicConfDir };
} }
/** /**
* *
@@ -186,10 +219,13 @@ interface ISparkMagicConfig {
kernel_python_credentials: ICredentials; kernel_python_credentials: ICredentials;
kernel_scala_credentials: ICredentials; kernel_scala_credentials: ICredentials;
kernel_r_credentials: ICredentials; kernel_r_credentials: ICredentials;
ignore_ssl_errors?: boolean;
logging_config: { logging_config: {
handlers: { handlers: {
magicsHandler: { magicsHandler: {
home_path: string; home_path: string;
class?: string;
formatter?: string
} }
} }
}; };

View File

@@ -144,6 +144,7 @@ export class MessagePanel extends ViewletPanel {
this.reset(); this.reset();
this.queryRunnerDisposables.push(runner.onQueryStart(() => this.reset())); this.queryRunnerDisposables.push(runner.onQueryStart(() => this.reset()));
this.queryRunnerDisposables.push(runner.onMessage(e => this.onMessage(e))); this.queryRunnerDisposables.push(runner.onMessage(e => this.onMessage(e)));
this.onMessage(runner.messages);
} }
private onMessage(message: IResultMessage | IResultMessage[]) { private onMessage(message: IResultMessage | IResultMessage[]) {

View File

@@ -391,10 +391,8 @@ export class QueryModelService implements IQueryModelService {
queryRunner.addListener(QREvents.RESULT_SET, resultSet => { queryRunner.addListener(QREvents.RESULT_SET, resultSet => {
this._fireQueryEvent(ownerUri, resultSetEventType, resultSet); this._fireQueryEvent(ownerUri, resultSetEventType, resultSet);
}); });
queryRunner.onResultSetUpdate(resultSetSummaries => { queryRunner.onResultSetUpdate(resultSetSummary => {
resultSetSummaries.forEach(resultSet => { this._fireQueryEvent(ownerUri, resultSetEventType, resultSetSummary);
this._fireQueryEvent(ownerUri, resultSetEventType, resultSet);
})
}); });
queryRunner.addListener(QREvents.BATCH_START, batch => { queryRunner.addListener(QREvents.BATCH_START, batch => {
let link = undefined; let link = undefined;

View File

@@ -13,6 +13,7 @@ import { IQueryManagementService } from 'sql/parts/query/common/queryManagement'
import * as Utils from 'sql/parts/connection/common/utils'; import * as Utils from 'sql/parts/connection/common/utils';
import { SaveFormat } from 'sql/parts/grid/common/interfaces'; import { SaveFormat } from 'sql/parts/grid/common/interfaces';
import { echo, debounceEvent } from 'sql/base/common/event'; import { echo, debounceEvent } from 'sql/base/common/event';
import { Deferred } from 'sql/base/common/promise';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
@@ -26,7 +27,6 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ResultSerializer } from 'sql/parts/query/common/resultSerializer'; import { ResultSerializer } from 'sql/parts/query/common/resultSerializer';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { Deferred } from 'sql/base/common/promise';
export interface IEditSessionReadyEvent { export interface IEditSessionReadyEvent {
ownerUri: string; ownerUri: string;
@@ -69,6 +69,7 @@ export default class QueryRunner extends Disposable {
private _isExecuting: boolean = false; private _isExecuting: boolean = false;
private _hasCompleted: boolean = false; private _hasCompleted: boolean = false;
private _batchSets: sqlops.BatchSummary[] = []; private _batchSets: sqlops.BatchSummary[] = [];
private _messages: sqlops.IResultMessage[] = [];
private _eventEmitter = new EventEmitter(); private _eventEmitter = new EventEmitter();
private _isQueryPlan: boolean; private _isQueryPlan: boolean;
@@ -77,40 +78,13 @@ export default class QueryRunner extends Disposable {
public get planXml(): Thenable<string> { return this._planXml.promise; } public get planXml(): Thenable<string> { return this._planXml.promise; }
private _onMessage = this._register(new Emitter<sqlops.IResultMessage>()); private _onMessage = this._register(new Emitter<sqlops.IResultMessage>());
private _debouncedMessage = debounceEvent<sqlops.IResultMessage, sqlops.IResultMessage[]>(this._onMessage.event, (l, e) => { public readonly onMessage = this._onMessage.event;
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
private _echoedMessages = echo(this._debouncedMessage.event);
public readonly onMessage = this._echoedMessages.event;
private _onResultSet = this._register(new Emitter<sqlops.ResultSetSummary>()); private _onResultSet = this._register(new Emitter<sqlops.ResultSetSummary>());
private _debouncedResultSet = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSet.event, (l, e) => { public readonly onResultSet = this._onResultSet.event;
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
// private _echoedResultSet = echo(this._debouncedResultSet.event);
public readonly onResultSet = this._debouncedResultSet.event;
private _onResultSetUpdate = this._register(new Emitter<sqlops.ResultSetSummary>()); private _onResultSetUpdate = this._register(new Emitter<sqlops.ResultSetSummary>());
private _debouncedResultSetUpdate = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSetUpdate.event, (l, e) => { public readonly onResultSetUpdate = this._onResultSetUpdate.event;
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
// private _echoedResultSetUpdate = echo(this._debouncedResultSetUpdate.event);
public readonly onResultSetUpdate = this._debouncedResultSetUpdate.event;
private _onQueryStart = this._register(new Emitter<void>()); private _onQueryStart = this._register(new Emitter<void>());
public readonly onQueryStart: Event<void> = this._onQueryStart.event; public readonly onQueryStart: Event<void> = this._onQueryStart.event;
@@ -153,8 +127,18 @@ export default class QueryRunner extends Disposable {
return this._hasCompleted; return this._hasCompleted;
} }
get batchSets(): sqlops.BatchSummary[] { /**
return this._batchSets; * For public use only, for private use, directly access the member
*/
public get batchSets(): sqlops.BatchSummary[] {
return this._batchSets.slice(0);
}
/**
* For public use only, for private use, directly access the member
*/
public get messages(): sqlops.IResultMessage[] {
return this._messages.slice(0);
} }
// PUBLIC METHODS ====================================================== // PUBLIC METHODS ======================================================
@@ -202,10 +186,6 @@ export default class QueryRunner extends Disposable {
if (this.isExecuting) { if (this.isExecuting) {
return TPromise.as(undefined); return TPromise.as(undefined);
} }
this._echoedMessages.clear();
// this._echoedResultSet.clear();
this._debouncedMessage.clear();
// this._debouncedResultSet.clear();
this._planXml = new Deferred<string>(); this._planXml = new Deferred<string>();
this._batchSets = []; this._batchSets = [];
this._hasCompleted = false; this._hasCompleted = false;
@@ -274,7 +254,7 @@ export default class QueryRunner extends Disposable {
this._hasCompleted = true; this._hasCompleted = true;
this._batchSets = result.batchSummaries ? result.batchSummaries : []; this._batchSets = result.batchSummaries ? result.batchSummaries : [];
this.batchSets.map(batch => { this._batchSets.map(batch => {
if (batch.selection) { if (batch.selection) {
batch.selection.startLine = batch.selection.startLine + this._resultLineOffset; batch.selection.startLine = batch.selection.startLine + this._resultLineOffset;
batch.selection.endLine = batch.selection.endLine + this._resultLineOffset; batch.selection.endLine = batch.selection.endLine + this._resultLineOffset;
@@ -291,6 +271,7 @@ export default class QueryRunner extends Disposable {
isError: false, isError: false,
time: undefined time: undefined
}; };
this._messages.push(message);
this._onQueryEnd.fire(timeStamp); this._onQueryEnd.fire(timeStamp);
this._onMessage.fire(message); this._onMessage.fire(message);
@@ -312,7 +293,7 @@ export default class QueryRunner extends Disposable {
batch.resultSetSummaries = []; batch.resultSetSummaries = [];
// Store the batch // Store the batch
this.batchSets[batch.id] = batch; this._batchSets[batch.id] = batch;
let message = { let message = {
// account for index by 1 // account for index by 1
@@ -321,6 +302,7 @@ export default class QueryRunner extends Disposable {
selection: batch.selection, selection: batch.selection,
isError: false isError: false
}; };
this._messages.push(message);
this._eventEmitter.emit(EventType.BATCH_START, batch); this._eventEmitter.emit(EventType.BATCH_START, batch);
this._onMessage.fire(message); this._onMessage.fire(message);
this._onBatchStart.fire(batch); this._onBatchStart.fire(batch);
@@ -333,7 +315,7 @@ export default class QueryRunner extends Disposable {
let batch: sqlops.BatchSummary = result.batchSummary; let batch: sqlops.BatchSummary = result.batchSummary;
// Store the batch again to get the rest of the data // Store the batch again to get the rest of the data
this.batchSets[batch.id] = batch; this._batchSets[batch.id] = batch;
let executionTime = <number>(Utils.parseTimeString(batch.executionElapsed) || 0); let executionTime = <number>(Utils.parseTimeString(batch.executionElapsed) || 0);
this._totalElapsedMilliseconds += executionTime; this._totalElapsedMilliseconds += executionTime;
if (executionTime > 0) { if (executionTime > 0) {
@@ -355,8 +337,8 @@ export default class QueryRunner extends Disposable {
if (!resultSet.batchId) { if (!resultSet.batchId) {
// Missing the batchId. In this case, default to always using the first batch in the list // Missing the batchId. In this case, default to always using the first batch in the list
// or create one in the case the DMP extension didn't obey the contract perfectly // or create one in the case the DMP extension didn't obey the contract perfectly
if (this.batchSets.length > 0) { if (this._batchSets.length > 0) {
batchSet = this.batchSets[0]; batchSet = this._batchSets[0];
} else { } else {
batchSet = <sqlops.BatchSummary>{ batchSet = <sqlops.BatchSummary>{
id: 0, id: 0,
@@ -364,10 +346,10 @@ export default class QueryRunner extends Disposable {
hasError: false, hasError: false,
resultSetSummaries: [] resultSetSummaries: []
}; };
this.batchSets[0] = batchSet; this._batchSets[0] = batchSet;
} }
} else { } else {
batchSet = this.batchSets[resultSet.batchId]; batchSet = this._batchSets[resultSet.batchId];
} }
// handle getting queryPlanxml if we need too // handle getting queryPlanxml if we need too
if (this.isQueryPlan) { if (this.isQueryPlan) {
@@ -392,7 +374,7 @@ export default class QueryRunner extends Disposable {
if (result && result.resultSetSummary) { if (result && result.resultSetSummary) {
let resultSet = result.resultSetSummary; let resultSet = result.resultSetSummary;
let batchSet: sqlops.BatchSummary; let batchSet: sqlops.BatchSummary;
batchSet = this.batchSets[resultSet.batchId]; batchSet = this._batchSets[resultSet.batchId];
// handle getting queryPlanxml if we need too // handle getting queryPlanxml if we need too
if (this.isQueryPlan) { if (this.isQueryPlan) {
// check if this result has show plan, this needs work, it won't work for any other provider // check if this result has show plan, this needs work, it won't work for any other provider
@@ -415,6 +397,7 @@ export default class QueryRunner extends Disposable {
public handleMessage(obj: sqlops.QueryExecuteMessageParams): void { public handleMessage(obj: sqlops.QueryExecuteMessageParams): void {
let message = obj.message; let message = obj.message;
message.time = new Date(message.time).toLocaleTimeString(); message.time = new Date(message.time).toLocaleTimeString();
this._messages.push(message);
// Send the message to the results pane // Send the message to the results pane
this._eventEmitter.emit(EventType.MESSAGE, message); this._eventEmitter.emit(EventType.MESSAGE, message);
@@ -636,7 +619,7 @@ export default class QueryRunner extends Disposable {
private getColumnHeaders(batchId: number, resultId: number, range: Slick.Range): string[] { private getColumnHeaders(batchId: number, resultId: number, range: Slick.Range): string[] {
let headers: string[] = undefined; let headers: string[] = undefined;
let batchSummary: sqlops.BatchSummary = this.batchSets[batchId]; let batchSummary: sqlops.BatchSummary = this._batchSets[batchId];
if (batchSummary !== undefined) { if (batchSummary !== undefined) {
let resultSetSummary = batchSummary.resultSetSummaries[resultId]; let resultSetSummary = batchSummary.resultSetSummaries[resultId];
headers = resultSetSummary.columnInfo.slice(range.fromCell, range.toCell + 1).map((info, i) => { headers = resultSetSummary.columnInfo.slice(range.fromCell, range.toCell + 1).map((info, i) => {
@@ -669,6 +652,7 @@ export default class QueryRunner extends Disposable {
time: undefined, time: undefined,
isError: false isError: false
}; };
this._messages.push(message);
// Send the message to the results pane // Send the message to the results pane
this._onMessage.fire(message); this._onMessage.fire(message);
} }

View File

@@ -97,15 +97,6 @@ export class WizardModal extends Modal {
messageChangeHandler(this._wizard.message); messageChangeHandler(this._wizard.message);
this._wizard.onMessageChange(message => messageChangeHandler(message)); this._wizard.onMessageChange(message => messageChangeHandler(message));
this._wizard.pages.forEach((page, index) => {
page.onValidityChanged(valid => {
if (index === this._wizard.currentPage) {
this._nextButton.enabled = this._wizard.nextButton.enabled && page.valid;
this._doneButton.enabled = this._wizard.doneButton.enabled && page.valid;
}
});
});
} }
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true, requirePageValid: boolean = false): Button { private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true, requirePageValid: boolean = false): Button {
@@ -198,6 +189,13 @@ export class WizardModal extends Modal {
let currentPageValid = this._wizard.pages[this._wizard.currentPage].valid; let currentPageValid = this._wizard.pages[this._wizard.currentPage].valid;
this._nextButton.enabled = this._wizard.nextButton.enabled && currentPageValid; this._nextButton.enabled = this._wizard.nextButton.enabled && currentPageValid;
this._doneButton.enabled = this._wizard.doneButton.enabled && currentPageValid; this._doneButton.enabled = this._wizard.doneButton.enabled && currentPageValid;
pageToShow.onValidityChanged(valid => {
if (index === this._wizard.currentPage) {
this._nextButton.enabled = this._wizard.nextButton.enabled && pageToShow.valid;
this._doneButton.enabled = this._wizard.doneButton.enabled && pageToShow.valid;
}
});
} }
private setButtonsForPage(index: number) { private setButtonsForPage(index: number) {