From 852ec4456720593eab32a9361fb2fb6311ebb5fb Mon Sep 17 00:00:00 2001 From: Karl Burtram Date: Mon, 10 Dec 2018 16:26:06 -0800 Subject: [PATCH 1/8] Fix DataTier wizard null ref looking up provider with no active connection (#3528) --- .../import/src/wizard/dataTierApplicationWizard.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/extensions/import/src/wizard/dataTierApplicationWizard.ts b/extensions/import/src/wizard/dataTierApplicationWizard.ts index 1af7254046..e91ff59381 100644 --- a/extensions/import/src/wizard/dataTierApplicationWizard.ts +++ b/extensions/import/src/wizard/dataTierApplicationWizard.ts @@ -202,7 +202,7 @@ export class DataTierApplicationWizard { } private async deploy() { - let service = await DataTierApplicationWizard.getService(); + let service = await DataTierApplicationWizard.getService(this.model.server.providerName); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let result = await service.deployDacpac(this.model.filePath, this.model.database, this.model.upgradeExisting, ownerUri, sqlops.TaskExecutionMode.execute); @@ -213,7 +213,7 @@ export class DataTierApplicationWizard { } private async extract() { - let service = await DataTierApplicationWizard.getService(); + let service = await DataTierApplicationWizard.getService(this.model.server.providerName); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let result = await service.extractDacpac(this.model.database, this.model.filePath, this.model.database, this.model.version, ownerUri, sqlops.TaskExecutionMode.execute); @@ -224,7 +224,7 @@ export class DataTierApplicationWizard { } private async export() { - let service = await DataTierApplicationWizard.getService(); + let service = await DataTierApplicationWizard.getService(this.model.server.providerName); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let result = await service.exportBacpac(this.model.database, this.model.filePath, ownerUri, sqlops.TaskExecutionMode.execute); @@ -235,7 +235,7 @@ export class DataTierApplicationWizard { } private async import() { - let service = await DataTierApplicationWizard.getService(); + let service = await DataTierApplicationWizard.getService(this.model.server.providerName); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let result = await service.importBacpac(this.model.filePath, this.model.database, ownerUri, sqlops.TaskExecutionMode.execute); @@ -245,9 +245,8 @@ export class DataTierApplicationWizard { } } - public static async getService(): Promise { - let currentConnection = await sqlops.connection.getCurrentConnection(); - let service = sqlops.dataprotocol.getProvider(currentConnection.providerName, sqlops.DataProviderType.DacFxServicesProvider); + private static async getService(providerName: string): Promise { + let service = sqlops.dataprotocol.getProvider(providerName, sqlops.DataProviderType.DacFxServicesProvider); return service; } } From a92dd2d4e455ed287aaadc21fe5089f2d5125aed Mon Sep 17 00:00:00 2001 From: Chris LaFreniere <40371649+chlafreniere@users.noreply.github.com> Date: Mon, 10 Dec 2018 16:26:57 -0800 Subject: [PATCH 2/8] Fix for PySpark3 not being selected by default (#3554) --- src/sql/parts/notebook/models/sparkMagicContexts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/parts/notebook/models/sparkMagicContexts.ts b/src/sql/parts/notebook/models/sparkMagicContexts.ts index edffd5b70c..8753c64508 100644 --- a/src/sql/parts/notebook/models/sparkMagicContexts.ts +++ b/src/sql/parts/notebook/models/sparkMagicContexts.ts @@ -149,10 +149,10 @@ export class SparkMagicContexts { } } let profile = connectionInfo as IConnectionProfile; - if (foundSavedKernelInSpecs && specs && connectionInfo && profile.providerName === notebookConstants.hadoopKnoxProviderName) { + if (specs && connectionInfo && profile.providerName === notebookConstants.hadoopKnoxProviderName) { // set default kernel to default spark kernel if profile exists // otherwise, set default to kernel info loaded from existing file - defaultKernel = !savedKernelInfo ? specs.kernels.find((spec) => spec.name === notebookConstants.defaultSparkKernel) : savedKernelInfo; + defaultKernel = !foundSavedKernelInSpecs ? specs.kernels.find((spec) => spec.name === notebookConstants.defaultSparkKernel) : foundSavedKernelInSpecs; } else { // Handle kernels if (savedKernelInfo && savedKernelInfo.name.toLowerCase().indexOf('spark') > -1) { From 8b447e361f2c8f05d64e8ec1f3bf552a546e8918 Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Mon, 10 Dec 2018 16:29:02 -0800 Subject: [PATCH 3/8] change cancelation in the async data loader to correctly cancel requests (#3516) --- .../base/browser/ui/table/asyncDataView.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/sql/base/browser/ui/table/asyncDataView.ts b/src/sql/base/browser/ui/table/asyncDataView.ts index 8681a5b637..de4833ee93 100644 --- a/src/sql/base/browser/ui/table/asyncDataView.ts +++ b/src/sql/base/browser/ui/table/asyncDataView.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; export interface IObservableCollection { getLength(): number; @@ -14,16 +15,12 @@ export interface IObservableCollection { dispose(): void; } -class LoadCancellationToken { - isCancelled: boolean; -} - class DataWindow { private _data: T[]; private _length: number = 0; private _offsetFromDataSource: number = -1; - private lastLoadCancellationToken: LoadCancellationToken; + private cancellationToken = new CancellationTokenSource(); constructor( private loadFunction: (offset: number, count: number) => Thenable, @@ -36,9 +33,7 @@ class DataWindow { this.loadFunction = undefined; this.placeholderItemGenerator = undefined; this.loadCompleteCallback = undefined; - if (this.lastLoadCancellationToken) { - this.lastLoadCancellationToken.isCancelled = true; - } + this.cancellationToken.cancel(); } public getStartIndex(): number { @@ -65,17 +60,16 @@ class DataWindow { this._length = length; this._data = undefined; - if (this.lastLoadCancellationToken) { - this.lastLoadCancellationToken.isCancelled = true; - } + this.cancellationToken.cancel(); + this.cancellationToken = new CancellationTokenSource(); + const currentCancellation = this.cancellationToken; if (length === 0) { return; } - this.lastLoadCancellationToken = new LoadCancellationToken(); this.loadFunction(offset, length).then(data => { - if (!this.lastLoadCancellationToken.isCancelled) { + if (!currentCancellation.token.isCancellationRequested) { this._data = data; this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length); } From 88e24e92b51fb22ea7b75755cd51178758f11c03 Mon Sep 17 00:00:00 2001 From: Aditya Bist Date: Mon, 10 Dec 2018 16:36:41 -0800 Subject: [PATCH 4/8] Agent: features and suggestions (#3512) * removed row highlighting overlap with scrollbars * fixed more styling suggestions * made async calls parallel and improved UI * cleared style --- extensions/agent/src/data/alertData.ts | 4 +-- .../parts/jobManagement/common/media/jobs.css | 15 ++++---- .../views/jobHistory.component.html | 4 +-- .../views/jobHistory.component.ts | 1 - .../parts/jobManagement/views/jobHistory.css | 15 +++++--- .../jobManagement/views/jobStepsView.css | 7 ++++ .../jobManagement/views/jobsView.component.ts | 35 +++++++------------ 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/extensions/agent/src/data/alertData.ts b/extensions/agent/src/data/alertData.ts index 295661b2cc..bdaa6e3ed5 100644 --- a/extensions/agent/src/data/alertData.ts +++ b/extensions/agent/src/data/alertData.ts @@ -69,7 +69,7 @@ export class AlertData implements IAgentDialogData { this.eventDescriptionKeyword = alertInfo.eventDescriptionKeyword; this.eventSource = alertInfo.eventSource; this.hasNotification = alertInfo.hasNotification; - this.includeEventDescription = alertInfo.includeEventDescription.toString(); + this.includeEventDescription = alertInfo.includeEventDescription ? alertInfo.includeEventDescription.toString() : null; this.isEnabled = alertInfo.isEnabled; this.jobId = alertInfo.jobId; this.lastOccurrenceDate = alertInfo.lastOccurrenceDate; @@ -82,7 +82,7 @@ export class AlertData implements IAgentDialogData { this.databaseName = alertInfo.databaseName; this.countResetDate = alertInfo.countResetDate; this.categoryName = alertInfo.categoryName; - this.alertType = alertInfo.alertType.toString(); + this.alertType = alertInfo.alertType ? alertInfo.alertType.toString() : null; this.wmiEventNamespace = alertInfo.wmiEventNamespace; this.wmiEventQuery = alertInfo.wmiEventQuery; } diff --git a/src/sql/parts/jobManagement/common/media/jobs.css b/src/sql/parts/jobManagement/common/media/jobs.css index d98d01a3d3..27162b976d 100644 --- a/src/sql/parts/jobManagement/common/media/jobs.css +++ b/src/sql/parts/jobManagement/common/media/jobs.css @@ -304,14 +304,6 @@ table.jobprevruns > tbody { background-image: url('refresh_inverse.svg'); } -.agent-actionbar-container .monaco-action-bar > ul.actions-container { - padding-top: 10px; -} - -jobsview-component .agent-actionbar-container { - height: 40px; -} - .agent-actionbar-container .monaco-action-bar > ul.actions-container > li.action-item { padding-left: 20px; } @@ -414,4 +406,11 @@ jobsview-component .jobview-grid .slick-cell.error-row { #proxiesDiv .proxyview-proxynameindicatordisabled { width: 5px; background: red; +} + +#jobsDiv jobsview-component .monaco-toolbar.carbon-taskbar, +#operatorsDiv joboperatorsview-component .monaco-toolbar.carbon-taskbar, +#alertsDiv jobalertsview-component .monaco-toolbar.carbon-taskbar, +#proxiesDiv jobproxiesview-component .monaco-toolbar.carbon-taskbar { + margin: 10px 0px 10px 0px; } \ No newline at end of file diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.html b/src/sql/parts/jobManagement/views/jobHistory.component.html index 3aaef5cb8c..4e2534151d 100644 --- a/src/sql/parts/jobManagement/views/jobHistory.component.html +++ b/src/sql/parts/jobManagement/views/jobHistory.component.html @@ -156,8 +156,8 @@ -
- +
+

No Steps Available

diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.ts b/src/sql/parts/jobManagement/views/jobHistory.component.ts index 46a3d8d0b3..4e536c6ae6 100644 --- a/src/sql/parts/jobManagement/views/jobHistory.component.ts +++ b/src/sql/parts/jobManagement/views/jobHistory.component.ts @@ -65,7 +65,6 @@ export class JobHistoryComponent extends JobManagementView implements OnInit { private _agentJobInfo: sqlops.AgentJobInfo; private _noJobsAvailable: boolean = false; - private static readonly INITIAL_TREE_HEIGHT: number = 780; private static readonly HEADING_HEIGHT: number = 24; constructor( diff --git a/src/sql/parts/jobManagement/views/jobHistory.css b/src/sql/parts/jobManagement/views/jobHistory.css index ab68b21412..ae3e94e079 100644 --- a/src/sql/parts/jobManagement/views/jobHistory.css +++ b/src/sql/parts/jobManagement/views/jobHistory.css @@ -7,7 +7,6 @@ .all-jobs { display: inline; font-size: 15px; - padding-bottom: 15px; } .overview-container .overview-tab .resultsViewCollapsible { @@ -266,14 +265,22 @@ jobhistory-component > .jobhistory-heading-container > .icon.in-progress { padding-left: 20px; } -jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { +jobhistory-component > .agent-actionbar-container { border-top: 3px solid #f4f4f4; } -.vs-dark jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { +.vs-dark jobhistory-component > .agent-actionbar-container { border-top: 3px solid #444444; } -.hc-black jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { +.hc-black jobhistory-component > .agent-actionbar-container { border-top: 3px solid #2b56f2; +} + +jobhistory-component .step-table.prev-run-list .monaco-tree-wrapper .monaco-tree-row { + width: 96%; +} + +jobhistory-component .agent-actionbar-container > .monaco-toolbar.carbon-taskbar { + margin: 10px 0px 5px 0px; } \ No newline at end of file diff --git a/src/sql/parts/jobManagement/views/jobStepsView.css b/src/sql/parts/jobManagement/views/jobStepsView.css index 15a84c81da..aadff202c2 100644 --- a/src/sql/parts/jobManagement/views/jobStepsView.css +++ b/src/sql/parts/jobManagement/views/jobStepsView.css @@ -80,4 +80,11 @@ jobstepsview-component { display: flex; flex-direction: column; + position: absolute; + height: 100%; + width: 100%; } + +jobstepsview-component .steps-tree .monaco-tree-wrapper .monaco-tree-row { + width: 99.2%; +} \ No newline at end of file diff --git a/src/sql/parts/jobManagement/views/jobsView.component.ts b/src/sql/parts/jobManagement/views/jobsView.component.ts index 7eae1f13ac..c52f3fb442 100644 --- a/src/sql/parts/jobManagement/views/jobsView.component.ts +++ b/src/sql/parts/jobManagement/views/jobsView.component.ts @@ -591,7 +591,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe private async curateJobHistory(jobs: sqlops.AgentJobInfo[], ownerUri: string) { const self = this; - jobs.forEach(async (job) => { + await Promise.all(jobs.map(async (job) => { await this._jobManagementService.getJobHistory(ownerUri, job.jobId, job.name).then(async(result) => { if (result) { self.jobSteps[job.jobId] = result.steps ? result.steps : []; @@ -622,32 +622,23 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe } } }); - }); + })); } private createJobChart(jobId: string, jobHistories: sqlops.AgentJobHistoryInfo[]): void { let chartHeights = this.getChartHeights(jobHistories); let runCharts = []; - for (let i = 0; i < jobHistories.length; i++) { + for (let i = 0; i < chartHeights.length; i++) { let runGraph = $(`table#${jobId}.jobprevruns > tbody > tr > td > div.bar${i}`); - if (jobHistories && jobHistories.length > 0) { - runGraph.css('height', chartHeights[i]); - let bgColor = jobHistories[i].runStatus === 0 ? 'red' : 'green'; - runGraph.css('background', bgColor); - runGraph.hover((e) => { - let currentTarget = e.currentTarget; - currentTarget.title = jobHistories[i].runDuration; - }); - if (runGraph.get(0)) { - runCharts.push(runGraph.get(0).outerHTML); - } - } else { - runGraph.css('height', '5px'); - runGraph.css('background', 'red'); - runGraph.hover((e) => { - let currentTarget = e.currentTarget; - currentTarget.title = 'Job not run.'; - }); + runGraph.css('height', chartHeights[i]); + let bgColor = jobHistories[i].runStatus === 0 ? 'red' : 'green'; + runGraph.css('background', bgColor); + runGraph.hover((e) => { + let currentTarget = e.currentTarget; + currentTarget.title = jobHistories[i].runDuration; + }); + if (runGraph.get(0)) { + runCharts.push(runGraph.get(0).outerHTML); } } if (runCharts.length > 0) { @@ -658,7 +649,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe // chart height normalization logic private getChartHeights(jobHistories: sqlops.AgentJobHistoryInfo[]): string[] { if (!jobHistories || jobHistories.length === 0) { - return ['5px', '5px', '5px', '5px', '5px']; + return []; } let maxDuration: number = 0; jobHistories.forEach(history => { From 7f6cd514a5c5b6b61a16d95e185497a683c6c509 Mon Sep 17 00:00:00 2001 From: Alan Ren Date: Mon, 10 Dec 2018 16:43:58 -0800 Subject: [PATCH 5/8] Alanren/profiler search (#3525) * further improve the search experience for profiler * change the default value for parameter --- .../base/browser/ui/table/tableDataView.ts | 10 +++++--- .../editor/controller/profilerFindWidget.ts | 23 ++++++++++++++----- .../editor/controller/profilerTableEditor.ts | 3 ++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/sql/base/browser/ui/table/tableDataView.ts b/src/sql/base/browser/ui/table/tableDataView.ts index 0507a18d8b..d962742158 100644 --- a/src/sql/base/browser/ui/table/tableDataView.ts +++ b/src/sql/base/browser/ui/table/tableDataView.ts @@ -78,7 +78,7 @@ export class TableDataView implements IDisposableData this._onRowCountChange.fire(); } - find(exp: string): Thenable { + find(exp: string, maxMatches: number = 0): Thenable { if (!this._findFn) { return TPromise.wrapError(new Error('no find function provided')); } @@ -87,7 +87,8 @@ export class TableDataView implements IDisposableData this._onFindCountChange.fire(this._findArray.length); if (exp) { this._findObs = Observable.create((observer: Observer) => { - this._data.forEach((item, i) => { + for (let i = 0; i < this._data.length; i++) { + let item = this._data[i]; let result = this._findFn(item, exp); if (result) { result.forEach(pos => { @@ -96,8 +97,11 @@ export class TableDataView implements IDisposableData observer.next(index); this._onFindCountChange.fire(this._findArray.length); }); + if (maxMatches > 0 && this._findArray.length > maxMatches) { + break; + } } - }); + } }); return this._findObs.take(1).toPromise().then(() => { return this._findArray[this._findIndex]; diff --git a/src/sql/parts/profiler/editor/controller/profilerFindWidget.ts b/src/sql/parts/profiler/editor/controller/profilerFindWidget.ts index adce88b264..deda9a2361 100644 --- a/src/sql/parts/profiler/editor/controller/profilerFindWidget.ts +++ b/src/sql/parts/profiler/editor/controller/profilerFindWidget.ts @@ -22,7 +22,7 @@ import { Widget } from 'vs/base/browser/ui/widget'; import { Sash, IHorizontalSashLayoutProvider, ISashEvent, Orientation } from 'vs/base/browser/ui/sash/sash'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; -import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; +import { FIND_IDS, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITheme, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; @@ -36,7 +36,7 @@ const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous match"); const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next match"); const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); -const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Only the first 999 results are highlighted, but all find operations work on the entire text."); +const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Your search returned a large number of results, only the first 999 matches will be highlighted."); const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}"); const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results"); @@ -46,6 +46,8 @@ const FIND_INPUT_AREA_WIDTH = PART_WIDTH - 54; let MAX_MATCHES_COUNT_WIDTH = 69; +export const PROFILER_MAX_MATCHES = 999; + export const ACTION_IDS = { FIND_NEXT: 'findNext', FIND_PREVIOUS: 'findPrev' @@ -86,6 +88,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas private _resizeSash: Sash; + private searchTimeoutHandle: number; + constructor( tableController: ITableController, state: FindReplaceState, @@ -213,7 +217,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas private _updateMatchesCount(): void { this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; - if (this._state.matchesCount >= MATCHES_LIMIT) { + if (this._state.matchesCount >= PROFILER_MAX_MATCHES) { this._matchesCount.title = NLS_MATCHES_COUNT_LIMIT_TITLE; } else { this._matchesCount.title = ''; @@ -227,8 +231,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas let label: string; if (this._state.matchesCount > 0) { let matchesCount: string = String(this._state.matchesCount); - if (this._state.matchesCount >= MATCHES_LIMIT) { - matchesCount += '+'; + if (this._state.matchesCount >= PROFILER_MAX_MATCHES) { + matchesCount = PROFILER_MAX_MATCHES + '+'; } let matchesPosition: string = String(this._state.matchesPosition); if (matchesPosition === '0') { @@ -401,7 +405,14 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas this._findInput.setWholeWords(!!this._state.wholeWord); this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); this._register(this._findInput.onInput(() => { - this._state.change({ searchString: this._findInput.getValue() }, true); + let self = this; + if (self.searchTimeoutHandle) { + clearTimeout(self.searchTimeoutHandle); + } + + this.searchTimeoutHandle = setTimeout(function () { + self._state.change({ searchString: self._findInput.getValue() }, true); + }, 300); })); this._register(this._findInput.onDidOptionChange(() => { this._state.change({ diff --git a/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts b/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts index 1771ba588e..50a9ce14d2 100644 --- a/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts +++ b/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts @@ -27,6 +27,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Dimension } from 'vs/base/browser/dom'; import { textFormatter } from 'sql/parts/grid/services/sharedServices'; +import { PROFILER_MAX_MATCHES } from 'sql/parts/profiler/editor/controller/profilerFindWidget'; export interface ProfilerTableViewState { scrollTop: number; @@ -214,7 +215,7 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll if (e.searchString) { if (this._input && this._input.data) { if (this._findState.searchString) { - this._input.data.find(this._findState.searchString).then(p => { + this._input.data.find(this._findState.searchString, PROFILER_MAX_MATCHES).then(p => { if (p) { this._profilerTable.setActiveCell(p.row, p.col); this._updateFinderMatchState(); From ca3146d38fdc1771fc37298a6ef8eab1dc4485a2 Mon Sep 17 00:00:00 2001 From: Raj <44002319+rajmusuku@users.noreply.github.com> Date: Mon, 10 Dec 2018 17:02:16 -0800 Subject: [PATCH 6/8] Filetype while prmopting for save #3552 (#3575) --- src/sql/parts/notebook/notebook.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sql/parts/notebook/notebook.component.ts b/src/sql/parts/notebook/notebook.component.ts index 51937c8b22..86cb4248dd 100644 --- a/src/sql/parts/notebook/notebook.component.ts +++ b/src/sql/parts/notebook/notebook.component.ts @@ -391,7 +391,10 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe } promptForPath(defaultPath: string): TPromise { - return this.windowService.showSaveDialog({ defaultPath }); + return this.windowService.showSaveDialog({ + defaultPath: defaultPath, + filters: [{ name: localize('notebookFile', 'Notebook'), extensions: ['ipynb']}] + }); } // Entry point to save notebook From 42e55dd2ddc14622446546396bbe904661c1d017 Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Mon, 10 Dec 2018 17:36:35 -0800 Subject: [PATCH 7/8] Result Streaming settings (#3537) * add setting control for result streaming * change default result streaming to true --- .../parts/query/common/query.contribution.ts | 5 ++ src/sql/parts/query/editor/gridPanel.ts | 66 ++++++++++++------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/sql/parts/query/common/query.contribution.ts b/src/sql/parts/query/common/query.contribution.ts index 75a2ee130e..5792d01e00 100644 --- a/src/sql/parts/query/common/query.contribution.ts +++ b/src/sql/parts/query/common/query.contribution.ts @@ -305,6 +305,11 @@ let registryProperties = { 'description': localize('sql.saveAsCsv.encoding', '[Optional] File encoding used when saving results as CSV'), 'default': 'utf-8' }, + 'sql.results.streaming': { + 'type': 'boolean', + 'description': localize('sql.results.streaming', 'Enable results streaming; contains few minor visual issues'), + 'default': true + }, 'sql.copyIncludeHeaders': { 'type': 'boolean', 'description': localize('sql.copyIncludeHeaders', '[Optional] Configuration options for copying results from the Results View'), diff --git a/src/sql/parts/query/editor/gridPanel.ts b/src/sql/parts/query/editor/gridPanel.ts index abe28a5ba1..fe19fcaa0b 100644 --- a/src/sql/parts/query/editor/gridPanel.ts +++ b/src/sql/parts/query/editor/gridPanel.ts @@ -188,23 +188,24 @@ export class GridPanel extends ViewletPanel { } private onResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) { - this.addResultSet(resultSet); + if (this.configurationService.getValue('sql.results.streaming')) { + this.addResultSet(resultSet); - this.tables.map(t => { - t.state.canBeMaximized = this.tables.length > 1; - }); + this.tables.map(t => { + t.state.canBeMaximized = this.tables.length > 1; + }); - this.maximumBodySize = this.tables.reduce((p, c) => { - return p + c.maximumSize; - }, 0); + this.maximumBodySize = this.tables.reduce((p, c) => { + return p + c.maximumSize; + }, 0); - if (this.state && this.state.scrollPosition) { - this.splitView.setScrollPosition(this.state.scrollPosition); + if (this.state && this.state.scrollPosition) { + this.splitView.setScrollPosition(this.state.scrollPosition); + } } } private updateResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) { - let resultsToUpdate: sqlops.ResultSetSummary[]; if (!Array.isArray(resultSet)) { resultsToUpdate = [resultSet]; @@ -212,21 +213,42 @@ export class GridPanel extends ViewletPanel { resultsToUpdate = resultSet; } - for (let set of resultsToUpdate) { - let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id); - if (table) { - table.updateResult(set); - } else { - warn('Got result set update request for non-existant table'); + if (this.configurationService.getValue('sql.results.streaming')) { + for (let set of resultsToUpdate) { + let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id); + if (table) { + table.updateResult(set); + } else { + warn('Got result set update request for non-existant table'); + } } - } - this.maximumBodySize = this.tables.reduce((p, c) => { - return p + c.maximumSize; - }, 0); + this.maximumBodySize = this.tables.reduce((p, c) => { + return p + c.maximumSize; + }, 0); - if (this.state && this.state.scrollPosition) { - this.splitView.setScrollPosition(this.state.scrollPosition); + if (this.state && this.state.scrollPosition) { + this.splitView.setScrollPosition(this.state.scrollPosition); + } + } else { + let change = false; + + for (let set of resultsToUpdate) { + if (set.complete) { + this.addResultSet(resultSet); + change = true; + } + } + + if (change) { + this.maximumBodySize = this.tables.reduce((p, c) => { + return p + c.maximumSize; + }, 0); + + if (this.state && this.state.scrollPosition) { + this.splitView.setScrollPosition(this.state.scrollPosition); + } + } } } From a93a173183e850b9279ae67775e04eecf001139f Mon Sep 17 00:00:00 2001 From: Yurong He <43652751+YurongHe@users.noreply.github.com> Date: Mon, 10 Dec 2018 17:36:58 -0800 Subject: [PATCH 8/8] The CSS class is overwritten by the previous change. Add it back (#3583) --- src/sql/parts/notebook/cellViews/textCell.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql/parts/notebook/cellViews/textCell.component.html b/src/sql/parts/notebook/cellViews/textCell.component.html index f19ee0c609..e2bc42f96e 100644 --- a/src/sql/parts/notebook/cellViews/textCell.component.html +++ b/src/sql/parts/notebook/cellViews/textCell.component.html @@ -11,7 +11,7 @@
-
+