Compare commits

..

9 Commits
1.1.4 ... 1.2.0

Author SHA1 Message Date
Karl Burtram
201174e293 Bump Azure Data Studio to 1.2.1 2018-10-22 17:11:41 -07:00
Karl Burtram
dc2f6235a1 Update SQL Tools Service to 1.5.0-alpha.46 2018-10-22 17:04:54 -07:00
Todd Ortmann
0824c779db Fixed sync issue with my forked master so this commit is correct (#2948) 2018-10-19 16:16:40 -07:00
Anthony Dresser
e002ad3b6a fix test errors (#2938) 2018-10-18 13:27:30 -07:00
kenvanhyning
8a570069f8 Kenvh/editdatatabname (#2906)
* Remove unnecessary string encoding on edit data naming

* Cleaning up duplication in the naming methods.

* fix typo in method name
2018-10-18 12:58:07 -07:00
Karl Burtram
bfe44c1621 Update README for October release (#2950) 2018-10-18 07:35:44 -07:00
Karl Burtram
b17882a1c1 Bump agent and import extension versions (#2949) 2018-10-17 21:41:18 -07:00
Gene Lee
f309979126 Added feature to disable checkbox of checkboxTreeNode (#2942) 2018-10-17 19:26:56 -07:00
Matt Irvine
5a0490e81f Display multi-line messages correctly in query results (#2935) 2018-10-17 15:43:00 -07:00
28 changed files with 208 additions and 334 deletions

View File

@@ -1,5 +1,21 @@
# Change Log # Change Log
## Version 1.1.3
* Release date: October 18, 2018
* Release status: General Availability
## What's new in this version
* Introducing the Azure Resource Explorer to browse Azure SQL Databases
* Improve Object Explorer and Query Editor connectivity robustness
* SQL Server 2019 and SQL Agent extension improvements
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* philoushka for `center the icon #2760`
* anthonypants for `Typo #2775`
* kstolte for `Fix Invalid Configuration in Launch.json #2789`
* kstolte for `Fixing a reference to SQL Ops Studio #2788`
## Version 1.0.0 ## Version 1.0.0
* Release date: September 24, 2018 * Release date: September 24, 2018

View File

@@ -4,16 +4,16 @@
Azure Data Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux. Azure Data Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
**Download Azure Data Studio August Public Preview** **Download the latest Azure Data Studio release**
Platform | Link Platform | Link
-- | -- -- | --
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2024683 Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2030731
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2024680 Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2030736
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2024677 macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2030738
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2024675 Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2030741
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2024672 Linux RPM | https://go.microsoft.com/fwlink/?linkid=2030746
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2024668 Linux DEB | https://go.microsoft.com/fwlink/?linkid=2030750
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions. Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
@@ -61,6 +61,10 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
## Contributions and "Thank You" ## Contributions and "Thank You"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes: We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* philoushka for `center the icon #2760`
* anthonypants for `Typo #2775`
* kstolte for `Fix Invalid Configuration in Launch.json #2789`
* kstolte for `Fixing a reference to SQL Ops Studio #2788`
* AlexFsmn `Feature: Ability to add connection name #2332` * AlexFsmn `Feature: Ability to add connection name #2332`
* AlexFsmn `Disabled connection name input when connecting to a server. #2566` * AlexFsmn `Disabled connection name input when connecting to a server. #2566`
* SebastianPfliegel `Added more saveAsCsv options #2099` * SebastianPfliegel `Added more saveAsCsv options #2099`

View File

@@ -2,7 +2,7 @@
"name": "agent", "name": "agent",
"displayName": "SQL Server Agent", "displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Server Agent jobs", "description": "Manage and troubleshoot SQL Server Agent jobs",
"version": "0.33.0", "version": "0.34.0",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt", "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",

View File

@@ -2,7 +2,7 @@
"name": "import", "name": "import",
"displayName": "SQL Server Import", "displayName": "SQL Server Import",
"description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.", "description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.",
"version": "0.2.0", "version": "0.3.0",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"engines": { "engines": {

View File

@@ -1,18 +1,18 @@
{ {
"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.5.0-alpha.48", "version": "1.5.0-alpha.46",
"downloadFileNames": { "downloadFileNames": {
"Windows_86": "win-x86-netcoreapp2.2.zip", "Windows_86": "win-x86-netcoreapp2.1.zip",
"Windows_64": "win-x64-netcoreapp2.2.zip", "Windows_64": "win-x64-netcoreapp2.1.zip",
"OSX": "osx-x64-netcoreapp2.2.tar.gz", "OSX": "osx-x64-netcoreapp2.1.tar.gz",
"CentOS_7": "rhel-x64-netcoreapp2.2.tar.gz", "CentOS_7": "rhel-x64-netcoreapp2.1.tar.gz",
"Debian_8": "rhel-x64-netcoreapp2.2.tar.gz", "Debian_8": "rhel-x64-netcoreapp2.1.tar.gz",
"Fedora_23": "rhel-x64-netcoreapp2.2.tar.gz", "Fedora_23": "rhel-x64-netcoreapp2.1.tar.gz",
"OpenSUSE_13_2": "rhel-x64-netcoreapp2.2.tar.gz", "OpenSUSE_13_2": "rhel-x64-netcoreapp2.1.tar.gz",
"RHEL_7": "rhel-x64-netcoreapp2.2.tar.gz", "RHEL_7": "rhel-x64-netcoreapp2.1.tar.gz",
"SLES_12_2": "rhel-x64-netcoreapp2.2.tar.gz", "SLES_12_2": "rhel-x64-netcoreapp2.1.tar.gz",
"Ubuntu_14": "rhel-x64-netcoreapp2.2.tar.gz", "Ubuntu_14": "rhel-x64-netcoreapp2.1.tar.gz",
"Ubuntu_16": "rhel-x64-netcoreapp2.2.tar.gz" "Ubuntu_16": "rhel-x64-netcoreapp2.1.tar.gz"
}, },
"installDirectory": "../sqltoolsservice/{#platform#}/{#version#}", "installDirectory": "../sqltoolsservice/{#platform#}/{#version#}",
"executableFiles": ["MicrosoftSqlToolsServiceLayer.exe", "MicrosoftSqlToolsServiceLayer"] "executableFiles": ["MicrosoftSqlToolsServiceLayer.exe", "MicrosoftSqlToolsServiceLayer"]

View File

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

View File

@@ -6,7 +6,7 @@
import { IThemable } from 'vs/platform/theme/common/styler'; import { IThemable } from 'vs/platform/theme/common/styler';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { Dimension, EventType, $, addDisposableListener } from 'vs/base/browser/dom'; import { Dimension, EventType, $, addDisposableListener } from 'vs/base/browser/dom';
import { $ as quickBuilder } from 'vs/base/browser/builder'; import { $ as qb } from 'vs/base/browser/builder';
import { IAction } from 'vs/base/common/actions'; import { IAction } from 'vs/base/common/actions';
import { IActionOptions, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IActionOptions, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -63,7 +63,7 @@ export class TabbedPanel extends Disposable implements IThemable {
private tabHistory: string[] = []; private tabHistory: string[] = [];
constructor(container: HTMLElement, private options: IPanelOptions = defaultOptions) { constructor(private container: HTMLElement, private options: IPanelOptions = defaultOptions) {
super(); super();
this.parent = $('.tabbedPanel'); this.parent = $('.tabbedPanel');
container.appendChild(this.parent); container.appendChild(this.parent);
@@ -87,13 +87,6 @@ export class TabbedPanel extends Disposable implements IThemable {
this.parent.appendChild(this.body); this.parent.appendChild(this.body);
} }
public dispose() {
this.header.remove();
this.tabList.remove();
this.body.remove();
this.parent.remove();
}
public contains(tab: IPanelTab): boolean { public contains(tab: IPanelTab): boolean {
return this._tabMap.has(tab.identifier); return this._tabMap.has(tab.identifier);
} }
@@ -153,18 +146,18 @@ export class TabbedPanel extends Disposable implements IThemable {
} }
if (this._shownTab) { if (this._shownTab) {
this._tabMap.get(this._shownTab).label.classList.remove('active'); qb(this._tabMap.get(this._shownTab).label).removeClass('active');
this._tabMap.get(this._shownTab).header.classList.remove('active'); qb(this._tabMap.get(this._shownTab).header).removeClass('active');
this._tabMap.get(this._shownTab).header.setAttribute('aria-selected', 'false'); this._tabMap.get(this._shownTab).header.setAttribute('aria-selected', 'false');
} }
this._shownTab = id; this._shownTab = id;
this.tabHistory.push(id); this.tabHistory.push(id);
quickBuilder(this.body).empty(); qb(this.body).empty();
let tab = this._tabMap.get(this._shownTab); let tab = this._tabMap.get(this._shownTab);
this.body.setAttribute('aria-labelledby', tab.identifier); this.body.setAttribute('aria-labelledby', tab.identifier);
tab.label.classList.add('active'); qb(tab.label).addClass('active');
tab.header.classList.add('active'); qb(tab.header).addClass('active');
tab.header.setAttribute('aria-selected', 'true'); tab.header.setAttribute('aria-selected', 'true');
tab.view.render(this.body); tab.view.render(this.body);
this._onTabChange.fire(id); this._onTabChange.fire(id);
@@ -175,11 +168,11 @@ export class TabbedPanel extends Disposable implements IThemable {
public removeTab(tab: PanelTabIdentifier) { public removeTab(tab: PanelTabIdentifier) {
let actualTab = this._tabMap.get(tab); let actualTab = this._tabMap.get(tab);
quickBuilder(actualTab.header).destroy(); qb(actualTab.header).destroy();
if (actualTab.view.remove) { if (actualTab.view.remove) {
actualTab.view.remove(); actualTab.view.remove();
} }
quickBuilder(this._tabMap.get(tab).header).destroy(); qb(this._tabMap.get(tab).header).destroy();
this._tabMap.delete(tab); this._tabMap.delete(tab);
if (this._shownTab === tab) { if (this._shownTab === tab) {
this._shownTab = undefined; this._shownTab = undefined;

View File

@@ -10,9 +10,10 @@ import * as TelemetryUtils from 'sql/common/telemetryUtilities';
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces'; import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { memoize, unmemoize } from 'sql/base/common/decorators'; import { memoize, unmemoize } from 'sql/base/common/decorators';
import { mixin } from 'sql/base/common/objects'; import { mixin } from 'sql/base/common/objects';
import { LegendPosition, ChartType, defaultChartConfig, IChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { LegendPosition, DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
import * as colors from 'vs/platform/theme/common/colorRegistry'; import * as colors from 'vs/platform/theme/common/colorRegistry';
import { Color } from 'vs/base/common/color';
import * as types from 'vs/base/common/types'; import * as types from 'vs/base/common/types';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
@@ -21,6 +22,51 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
declare var Chart: any; declare var Chart: any;
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
if (types.isObject(source)) {
mixin(destination, source, overwrite, customMixin);
} else if (types.isArray(source)) {
for (let i = 0; i < source.length; i++) {
if (destination[i]) {
mixin(destination[i], source[i], overwrite, customMixin);
} else {
destination[i] = source[i];
}
}
} else {
destination = source;
}
return destination;
}
export interface IDataSet {
data: Array<number>;
label?: string;
}
export interface IPointDataSet {
data: Array<{ x: number | string, y: number }>;
label?: string;
fill: boolean;
backgroundColor?: Color;
}
export interface IChartConfig {
colorMap?: { [column: string]: string };
labelFirstColumn?: boolean;
legendPosition?: LegendPosition;
dataDirection?: DataDirection;
columnsAsLabels?: boolean;
showTopNData?: number;
}
export const defaultChartConfig: IChartConfig = {
labelFirstColumn: true,
columnsAsLabels: true,
legendPosition: LegendPosition.Top,
dataDirection: DataDirection.Vertical
};
@Component({ @Component({
template: ` <div style="display: block; width: 100%; height: 100%; position: relative"> template: ` <div style="display: block; width: 100%; height: 100%; position: relative">
<canvas #canvas *ngIf="_isDataAvailable && _hasInit" <canvas #canvas *ngIf="_isDataAvailable && _hasInit"

View File

@@ -3,11 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Color } from 'vs/base/common/color';
import * as types from 'vs/base/common/types';
import { mixin } from 'sql/base/common/objects';
export enum ChartType { export enum ChartType {
Bar = 'bar', Bar = 'bar',
Doughnut = 'doughnut', Doughnut = 'doughnut',
@@ -34,49 +29,4 @@ export enum LegendPosition {
export enum DataType { export enum DataType {
Number = 'number', Number = 'number',
Point = 'point' Point = 'point'
} }
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
if (types.isObject(source)) {
mixin(destination, source, overwrite, customMixin);
} else if (types.isArray(source)) {
for (let i = 0; i < source.length; i++) {
if (destination[i]) {
mixin(destination[i], source[i], overwrite, customMixin);
} else {
destination[i] = source[i];
}
}
} else {
destination = source;
}
return destination;
}
export interface IDataSet {
data: Array<number>;
label?: string;
}
export interface IPointDataSet {
data: Array<{ x: number | string, y: number }>;
label?: string;
fill: boolean;
backgroundColor?: Color;
}
export interface IChartConfig {
colorMap?: { [column: string]: string };
labelFirstColumn?: boolean;
legendPosition?: LegendPosition;
dataDirection?: DataDirection;
columnsAsLabels?: boolean;
showTopNData?: number;
}
export const defaultChartConfig: IChartConfig = {
labelFirstColumn: true,
columnsAsLabels: true,
legendPosition: LegendPosition.Top,
dataDirection: DataDirection.Vertical
};

View File

@@ -3,9 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ChartInsight } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component'; import { ChartInsight, customMixin, IChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
import { mixin } from 'sql/base/common/objects'; import { mixin } from 'sql/base/common/objects';
import { ChartType, IChartConfig, customMixin } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as colors from 'vs/platform/theme/common/colorRegistry'; import * as colors from 'vs/platform/theme/common/colorRegistry';

View File

@@ -5,10 +5,11 @@
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { defaultChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
import BarChart, { IBarChartConfig } from './barChart.component'; import BarChart, { IBarChartConfig } from './barChart.component';
import { memoize, unmemoize } from 'sql/base/common/decorators'; import { memoize, unmemoize } from 'sql/base/common/decorators';
import { clone } from 'sql/base/common/objects'; import { clone } from 'sql/base/common/objects';
import { ChartType, DataType, defaultChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
export interface ILineConfig extends IBarChartConfig { export interface ILineConfig extends IBarChartConfig {
dataType?: DataType; dataType?: DataType;

View File

@@ -3,9 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { defaultChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
import LineChart, { ILineConfig } from './lineChart.component'; import LineChart, { ILineConfig } from './lineChart.component';
import { clone } from 'sql/base/common/objects'; import { clone } from 'sql/base/common/objects';
import { ChartType, defaultChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';

View File

@@ -3,9 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { defaultChartConfig, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
import LineChart, { ILineConfig } from './lineChart.component'; import LineChart, { ILineConfig } from './lineChart.component';
import { clone } from 'sql/base/common/objects'; import { clone } from 'sql/base/common/objects';
import { ChartType, defaultChartConfig, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { Color } from 'vs/base/common/color'; import { Color } from 'vs/base/common/color';

View File

@@ -71,6 +71,13 @@ export class TreeDataTemplate extends Disposable {
} }
} }
public set enableCheckbox(value: boolean) {
if (value === undefined) {
value = true;
}
this._checkbox.disabled = !value;
}
public get checkbox(): HTMLInputElement { public get checkbox(): HTMLInputElement {
return this._checkbox; return this._checkbox;
} }
@@ -155,6 +162,7 @@ export class TreeComponentRenderer extends Disposable implements IRenderer {
templateData.label.textContent = label; templateData.label.textContent = label;
templateData.root.title = label; templateData.root.title = label;
templateData.checkboxState = this.getCheckboxState(treeNode); templateData.checkboxState = this.getCheckboxState(treeNode);
templateData.enableCheckbox = treeNode.enabled;
} }
private getCheckboxState(treeNode: ITreeComponentItem): TreeCheckboxState { private getCheckboxState(treeNode: ITreeComponentItem): TreeCheckboxState {

View File

@@ -18,8 +18,7 @@ export enum ControlType {
combo, combo,
numberInput, numberInput,
input, input,
checkbox, checkbox
dateInput
} }
export interface IChartOption { export interface IChartOption {
@@ -116,20 +115,6 @@ const xAxisMaxInput: IChartOption = {
default: undefined default: undefined
}; };
const xAxisMinDateInput: IChartOption = {
label: localize('xAxisMinDate', 'X Axis Minimum Date'),
type: ControlType.dateInput,
configEntry: 'xAxisMin',
default: undefined
};
const xAxisMaxDateInput: IChartOption = {
label: localize('xAxisMaxDate', 'X Axis Maximum Date'),
type: ControlType.dateInput,
configEntry: 'xAxisMax',
default: undefined
};
const dataTypeInput: IChartOption = { const dataTypeInput: IChartOption = {
label: localize('dataTypeLabel', 'Data Type'), label: localize('dataTypeLabel', 'Data Type'),
type: ControlType.combo, type: ControlType.combo,
@@ -165,11 +150,7 @@ export const ChartOptions: IChartOptions = {
[ChartType.TimeSeries]: [ [ChartType.TimeSeries]: [
legendInput, legendInput,
yAxisLabelInput, yAxisLabelInput,
yAxisMinInput, xAxisLabelInput
yAxisMaxInput,
xAxisLabelInput,
xAxisMinDateInput,
xAxisMaxDateInput,
], ],
[ChartType.Bar]: [ [ChartType.Bar]: [
dataDirectionOption, dataDirectionOption,

View File

@@ -18,7 +18,7 @@ export class ChartTab implements IPanelTab {
public readonly identifier = 'ChartTab'; public readonly identifier = 'ChartTab';
public readonly view: ChartView; public readonly view: ChartView;
constructor( @IInstantiationService instantiationService: IInstantiationService) { constructor(@IInstantiationService instantiationService: IInstantiationService) {
this.view = instantiationService.createInstance(ChartView); this.view = instantiationService.createInstance(ChartView);
} }
@@ -26,11 +26,7 @@ export class ChartTab implements IPanelTab {
this.view.queryRunner = runner; this.view.queryRunner = runner;
} }
public chart(dataId: { batchId: number, resultId: number }): void { public chart(dataId: { batchId: number, resultId: number}): void {
this.view.chart(dataId); this.view.chart(dataId);
} }
public dispose() {
this.view.dispose();
}
} }

View File

@@ -24,7 +24,7 @@ import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { Builder } from 'vs/base/browser/builder'; import { Builder } from 'vs/base/browser/builder';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { attachSelectBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { attachSelectBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -43,7 +43,7 @@ declare class Proxy {
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution); const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
export class ChartView extends Disposable implements IPanelView { export class ChartView implements IPanelView {
private insight: Insight; private insight: Insight;
private _queryRunner: QueryRunner; private _queryRunner: QueryRunner;
private _data: IInsightData; private _data: IInsightData;
@@ -82,7 +82,6 @@ export class ChartView extends Disposable implements IPanelView {
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IContextMenuService contextMenuService: IContextMenuService @IContextMenuService contextMenuService: IContextMenuService
) { ) {
super();
this.taskbarContainer = $('div.taskbar-container'); this.taskbarContainer = $('div.taskbar-container');
this.taskbar = new Taskbar(this.taskbarContainer, contextMenuService); this.taskbar = new Taskbar(this.taskbarContainer, contextMenuService);
this.optionsControl = $('div.options-container'); this.optionsControl = $('div.options-container');
@@ -325,24 +324,6 @@ export class ChartView extends Disposable implements IPanelView {
}; };
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService)); this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
break; break;
case ControlType.dateInput:
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'date' });
dateInput.value = value || '';
dateInput.onDidChange(e => {
if (this.options[option.configEntry] !== e) {
this.options[option.configEntry] = e;
if (this.insight) {
this.insight.options = this.options;
}
}
});
setFunc = (val: string) => {
if (!isUndefinedOrNull(val)) {
dateInput.value = val;
}
};
this.optionDisposables.push(attachInputBoxStyler(dateInput, this._themeService));
break;
} }
this.optionMap[option.configEntry] = { element: optionContainer, set: setFunc }; this.optionMap[option.configEntry] = { element: optionContainer, set: setFunc };
container.appendChild(optionContainer); container.appendChild(optionContainer);

View File

@@ -7,7 +7,7 @@
import { Chart as ChartJs } from 'chart.js'; import { Chart as ChartJs } from 'chart.js';
import { mixin } from 'sql/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import * as colors from 'vs/platform/theme/common/colorRegistry'; import * as colors from 'vs/platform/theme/common/colorRegistry';
import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry'; import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
@@ -15,28 +15,10 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces'; import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { IInsightOptions, IInsight } from './interfaces'; import { IInsightOptions, IInsight } from './interfaces';
import { ChartType, DataDirection, LegendPosition, DataType, IPointDataSet, customMixin } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { ChartType, DataDirection, LegendPosition } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie]; const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
const timeSeriesScales = {
scales: {
xAxes: [{
type: 'time',
display: true,
ticks: {
autoSkip: false,
maxRotation: 45,
minRotation: 45
}
}],
yAxes: [{
display: true,
}]
}
};
const defaultOptions: IInsightOptions = { const defaultOptions: IInsightOptions = {
type: ChartType.Bar, type: ChartType.Bar,
dataDirection: DataDirection.Horizontal dataDirection: DataDirection.Horizontal
@@ -48,8 +30,6 @@ export class Graph implements IInsight {
private chartjs: ChartJs; private chartjs: ChartJs;
private _data: IInsightData; private _data: IInsightData;
private originalType: ChartType;
public static readonly types = [ChartType.Bar, ChartType.Doughnut, ChartType.HorizontalBar, ChartType.Line, ChartType.Pie, ChartType.Scatter, ChartType.TimeSeries]; public static readonly types = [ChartType.Bar, ChartType.Doughnut, ChartType.HorizontalBar, ChartType.Line, ChartType.Pie, ChartType.Scatter, ChartType.TimeSeries];
public readonly types = Graph.types; public readonly types = Graph.types;
@@ -103,51 +83,37 @@ export class Graph implements IInsight {
labels = data.rows.map(row => row[0]); labels = data.rows.map(row => row[0]);
} }
if (this.originalType === ChartType.TimeSeries) { if (this.options.dataDirection === DataDirection.Horizontal) {
let dataSetMap: { [label: string]: IPointDataSet } = {}; if (this.options.labelFirstColumn) {
this._data.rows.map(row => { chartData = data.rows.map((row) => {
if (row && row.length >= 3) { return {
let legend = row[0]; data: row.map(item => Number(item)).slice(1),
if (!dataSetMap[legend]) { label: row[0]
dataSetMap[legend] = { label: legend, data: [], fill: false }; };
} });
dataSetMap[legend].data.push({ x: row[1], y: Number(row[2]) });
}
});
chartData = Object.values(dataSetMap);
} else {
if (this.options.dataDirection === DataDirection.Horizontal) {
if (this.options.labelFirstColumn) {
chartData = data.rows.map((row) => {
return {
data: row.map(item => Number(item)).slice(1),
label: row[0]
};
});
} else {
chartData = data.rows.map((row, i) => {
return {
data: row.map(item => Number(item)),
label: localize('series', 'Series {0}', i)
};
});
}
} else { } else {
if (this.options.columnsAsLabels) { chartData = data.rows.map((row, i) => {
chartData = data.rows[0].slice(1).map((row, i) => { return {
return { data: row.map(item => Number(item)),
data: data.rows.map(row => Number(row[i + 1])), label: localize('series', 'Series {0}', i)
label: data.columns[i + 1] };
}; });
}); }
} else { } else {
chartData = data.rows[0].slice(1).map((row, i) => { if (this.options.columnsAsLabels) {
return { chartData = data.rows[0].slice(1).map((row, i) => {
data: data.rows.map(row => Number(row[i + 1])), return {
label: localize('series', 'Series {0}', i + 1) data: data.rows.map(row => Number(row[i + 1])),
}; label: data.columns[i + 1]
}); };
} });
} else {
chartData = data.rows[0].slice(1).map((row, i) => {
return {
data: data.rows.map(row => Number(row[i + 1])),
label: localize('series', 'Series {0}', i + 1)
};
});
} }
} }
@@ -221,35 +187,6 @@ export class Graph implements IInsight {
color: gridLines color: gridLines
} }
}]; }];
if (this.originalType === ChartType.TimeSeries) {
retval = mixin(retval, timeSeriesScales, true, customMixin);
if (options.xAxisMax) {
retval = mixin(retval, {
scales: {
xAxes: [{
type: 'time',
time: {
max: options.xAxisMax
}
}],
}
}, true, customMixin);
}
if (options.xAxisMin) {
retval = mixin(retval, {
scales: {
xAxes: [{
type: 'time',
time: {
min: options.xAxisMin
}
}],
}
}, true, customMixin);
}
}
} }
retval.legend = <ChartJs.ChartLegendOptions>{ retval.legend = <ChartJs.ChartLegendOptions>{
@@ -271,12 +208,6 @@ export class Graph implements IInsight {
public set options(options: IInsightOptions) { public set options(options: IInsightOptions) {
this._options = options; this._options = options;
this.originalType = options.type as ChartType;
if (this.options.type === ChartType.TimeSeries) {
this.options.type = ChartType.Line;
this.options.dataType = DataType.Point;
this.options.dataDirection = DataDirection.Horizontal;
}
this.data = this._data; this.data = this._data;
} }

View File

@@ -7,7 +7,7 @@
import { Graph } from './graphInsight'; import { Graph } from './graphInsight';
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces'; import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { DataDirection, ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces'; import { DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
import { ImageInsight } from './imageInsight'; import { ImageInsight } from './imageInsight';
import { TableInsight } from './tableInsight'; import { TableInsight } from './tableInsight';
import { IInsightOptions, IInsight, InsightType, IInsightCtor } from './interfaces'; import { IInsightOptions, IInsight, InsightType, IInsightCtor } from './interfaces';
@@ -16,7 +16,6 @@ import { CountInsight } from './countInsight';
import { Builder } from 'vs/base/browser/builder'; import { Builder } from 'vs/base/browser/builder';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Dimension } from 'vs/base/browser/dom'; import { Dimension } from 'vs/base/browser/dom';
import { deepClone } from 'vs/base/common/objects';
const defaultOptions: IInsightOptions = { const defaultOptions: IInsightOptions = {
type: ChartType.Bar, type: ChartType.Bar,
@@ -48,13 +47,13 @@ export class Insight {
} }
public set options(val: IInsightOptions) { public set options(val: IInsightOptions) {
this._options = deepClone(val); this._options = val;
if (this.insight) { if (this.insight) {
// check to see if we need to change the insight type // check to see if we need to change the insight type
if (!this.insight.types.includes(this.options.type)) { if (!this.insight.types.includes(val.type)) {
this.buildInsight(); this.buildInsight();
} else { } else {
this.insight.options = this.options; this.insight.options = val;
} }
} }
} }

View File

@@ -21,7 +21,6 @@ import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugi
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin'; import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import * as pretty from 'pretty-data';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -478,27 +477,7 @@ class GridTable<T> extends Disposable implements IView {
if (column && (column.isXml || column.isJson)) { if (column && (column.isXml || column.isJson)) {
this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(d => { this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(d => {
let value = d.resultSubset.rows[0][event.cell.cell - 1]; let value = d.resultSubset.rows[0][event.cell.cell - 1];
let content = value.displayValue; let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', value.displayValue);
if (column.isXml) {
try {
content = pretty.pd.xml(content);
} catch (e) {
// If Xml fails to parse, fall back on original Xml content
}
} else {
let jsonContent: string = undefined;
try {
jsonContent = JSON.parse(content);
} catch (e) {
// If Json fails to parse, fall back on original Json content
}
if (jsonContent) {
// If Json content was valid and parsed, pretty print content to a string
content = JSON.stringify(jsonContent, undefined, 4);
}
}
let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content);
this.editorService.openEditor(input); this.editorService.openEditor(input);
}); });
} }

View File

@@ -74,8 +74,9 @@ export class MessagePanelState {
} }
export class MessagePanel extends ViewletPanel { export class MessagePanel extends ViewletPanel {
private messageLineCountMap = new Map<IResultMessage, number>();
private ds = new MessageDataSource(); private ds = new MessageDataSource();
private renderer = new MessageRenderer(); private renderer = new MessageRenderer(this.messageLineCountMap);
private model = new Model(); private model = new Model();
private controller: MessageController; private controller: MessageController;
private container = $('div message-tree').getHTMLElement(); private container = $('div message-tree').getHTMLElement();
@@ -143,29 +144,40 @@ export class MessagePanel extends ViewletPanel {
private onMessage(message: IResultMessage | IResultMessage[]) { private onMessage(message: IResultMessage | IResultMessage[]) {
let hasError = false; let hasError = false;
let lines: number;
if (isArray(message)) { if (isArray(message)) {
hasError = message.find(e => e.isError) ? true : false; hasError = message.find(e => e.isError) ? true : false;
lines = message.reduce((currentTotal, resultMessage) => currentTotal + this.countMessageLines(resultMessage), 0);
this.model.messages.push(...message); this.model.messages.push(...message);
} else { } else {
hasError = message.isError; hasError = message.isError;
lines = this.countMessageLines(message);
this.model.messages.push(message); this.model.messages.push(message);
} }
this.maximumBodySize += lines * 22;
if (hasError) { if (hasError) {
this.setExpanded(true); this.setExpanded(true);
} }
if (this.state.scrollPosition) { if (this.state.scrollPosition) {
this.tree.refresh(this.model).then(() => { this.tree.refresh(this.model).then(() => {
this.tree.setScrollPosition(1); // Restore the previous scroll position when switching between tabs
this.tree.setScrollPosition(this.state.scrollPosition);
}); });
} else { } else {
const previousScrollPosition = this.tree.getScrollPosition(); const previousScrollPosition = this.tree.getScrollPosition();
this.tree.refresh(this.model).then(() => { this.tree.refresh(this.model).then(() => {
// Scroll to the end if the user was already at the end otherwise leave the current scroll position
if (previousScrollPosition === 1) { if (previousScrollPosition === 1) {
this.tree.setScrollPosition(1); this.tree.setScrollPosition(1);
} }
}); });
} }
this.maximumBodySize = this.model.messages.length * 22; }
private countMessageLines(resultMessage: IResultMessage): number {
let lines = resultMessage.message.split('\n').length;
this.messageLineCountMap.set(resultMessage, lines);
return lines;
} }
private reset() { private reset() {
@@ -220,8 +232,15 @@ class MessageDataSource implements IDataSource {
} }
class MessageRenderer implements IRenderer { class MessageRenderer implements IRenderer {
constructor(private messageLineCountMap: Map<IResultMessage, number>) {
}
getHeight(tree: ITree, element: any): number { getHeight(tree: ITree, element: any): number {
return 22; const lineHeight = 22;
if (this.messageLineCountMap.has(element)) {
return lineHeight * this.messageLineCountMap.get(element);
}
return lineHeight;
} }
getTemplateId(tree: ITree, element: any): string { getTemplateId(tree: ITree, element: any): string {
@@ -258,7 +277,7 @@ class MessageRenderer implements IRenderer {
renderElement(tree: ITree, element: IResultMessage, templateId: string, templateData: IMessageTemplate | IBatchTemplate): void { renderElement(tree: ITree, element: IResultMessage, templateId: string, templateData: IMessageTemplate | IBatchTemplate): void {
if (templateId === TemplateIds.MESSAGE || templateId === TemplateIds.ERROR) { if (templateId === TemplateIds.MESSAGE || templateId === TemplateIds.ERROR) {
let data: IMessageTemplate = templateData; let data: IMessageTemplate = templateData;
data.message.innerText = element.message.replace(/(\r\n|\n|\r)/g, ' '); data.message.innerText = element.message;
} else if (templateId === TemplateIds.BATCH) { } else if (templateId === TemplateIds.BATCH) {
let data = templateData as IBatchTemplate; let data = templateData as IBatchTemplate;
data.timeStamp.innerText = element.time; data.timeStamp.innerText = element.time;

View File

@@ -18,9 +18,9 @@ import { PanelViewlet } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import * as DOM from 'vs/base/browser/dom'; import * as DOM from 'vs/base/browser/dom';
import { once, anyEvent } from 'vs/base/common/event'; import { once, anyEvent } from 'vs/base/common/event';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle';
class ResultsView extends Disposable implements IPanelView { class ResultsView implements IPanelView {
private panelViewlet: PanelViewlet; private panelViewlet: PanelViewlet;
private gridPanel: GridPanel; private gridPanel: GridPanel;
private messagePanel: MessagePanel; private messagePanel: MessagePanel;
@@ -30,10 +30,10 @@ class ResultsView extends Disposable implements IPanelView {
private _state: ResultsViewState; private _state: ResultsViewState;
constructor(private instantiationService: IInstantiationService) { constructor(private instantiationService: IInstantiationService) {
super();
this.panelViewlet = this._register(this.instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false })); this.panelViewlet = this.instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false });
this.gridPanel = this._register(this.instantiationService.createInstance(GridPanel, { title: nls.localize('gridPanel', 'Results'), id: 'gridPanel' })); this.gridPanel = this.instantiationService.createInstance(GridPanel, { title: nls.localize('gridPanel', 'Results'), id: 'gridPanel' });
this.messagePanel = this._register(this.instantiationService.createInstance(MessagePanel, { title: nls.localize('messagePanel', 'Messages'), minimumBodySize: 0, id: 'messagePanel' })); this.messagePanel = this.instantiationService.createInstance(MessagePanel, { title: nls.localize('messagePanel', 'Messages'), minimumBodySize: 0, id: 'messagePanel' });
this.gridPanel.render(); this.gridPanel.render();
this.messagePanel.render(); this.messagePanel.render();
this.panelViewlet.create(this.container).then(() => { this.panelViewlet.create(this.container).then(() => {
@@ -147,13 +147,9 @@ class ResultsTab implements IPanelTab {
public set queryRunner(runner: QueryRunner) { public set queryRunner(runner: QueryRunner) {
this.view.queryRunner = runner; this.view.queryRunner = runner;
} }
public dispose() {
dispose(this.view);
}
} }
export class QueryResultsView extends Disposable { export class QueryResultsView {
private _panelView: TabbedPanel; private _panelView: TabbedPanel;
private _input: QueryResultsInput; private _input: QueryResultsInput;
private resultsTab: ResultsTab; private resultsTab: ResultsTab;
@@ -167,17 +163,16 @@ export class QueryResultsView extends Disposable {
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@IQueryModelService private queryModelService: IQueryModelService @IQueryModelService private queryModelService: IQueryModelService
) { ) {
super(); this.resultsTab = new ResultsTab(instantiationService);
this.resultsTab = this._register(new ResultsTab(instantiationService)); this.chartTab = new ChartTab(instantiationService);
this.chartTab = this._register(new ChartTab(instantiationService)); this._panelView = new TabbedPanel(container, { showHeaderWhenSingleView: false });
this._panelView = this._register(new TabbedPanel(container, { showHeaderWhenSingleView: false })); this.qpTab = new QueryPlanTab();
this.qpTab = this._register(new QueryPlanTab());
this._panelView.pushTab(this.resultsTab); this._panelView.pushTab(this.resultsTab);
this._register(this._panelView.onTabChange(e => { this._panelView.onTabChange(e => {
if (this.input) { if (this.input) {
this.input.state.activeTab = e; this.input.state.activeTab = e;
} }
})); });
} }
public style() { public style() {

View File

@@ -124,7 +124,7 @@ export class QueryEditorService implements IQueryEditorService {
try { try {
// Create file path and file URI // Create file path and file URI
let objectName = schemaName ? schemaName + '.' + tableName : tableName; let objectName = schemaName ? schemaName + '.' + tableName : tableName;
let filePath = this.createEditDataFileName(objectName); let filePath = this.createPrefixedSqlFilePath(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 // Create a sql document pane with accoutrements
@@ -265,45 +265,26 @@ export class QueryEditorService implements IQueryEditorService {
////// Private functions ////// Private functions
private createUntitledSqlFilePath(): string { private createUntitledSqlFilePath(): string {
let sqlFileName = (counter: number): string => { return this.createPrefixedSqlFilePath(untitledFilePrefix);
return `${untitledFilePrefix}${counter}`;
};
let counter = 1;
// Get document name and check if it exists
let filePath = sqlFileName(counter);
while (fs.existsSync(filePath)) {
counter++;
filePath = sqlFileName(counter);
}
// check if this document name already exists in any open documents
let untitledEditors = this._untitledEditorService.getAll();
while (untitledEditors.find(x => x.getName().toUpperCase() === filePath.toUpperCase())) {
counter++;
filePath = sqlFileName(counter);
}
return filePath;
} }
private createEditDataFileName(tableName: string): string { private createPrefixedSqlFilePath(prefix: string): string {
let editDataFileName = (counter: number): string => { let prefixFileName = (counter: number): string => {
return encodeURIComponent(`${tableName}_${counter}`); return `${prefix}_${counter}`;
}; };
let counter = 1; let counter = 1;
// Get document name and check if it exists // Get document name and check if it exists
let filePath = editDataFileName(counter); let filePath = prefixFileName(counter);
while (fs.existsSync(filePath)) { while (fs.existsSync(filePath)) {
counter++; counter++;
filePath = editDataFileName(counter); filePath = prefixFileName(counter);
} }
let untitledEditors = this._untitledEditorService.getAll(); let untitledEditors = this._untitledEditorService.getAll();
while (untitledEditors.find(x => x.getName().toUpperCase() === filePath.toUpperCase())) { while (untitledEditors.find(x => x.getName().toUpperCase() === filePath.toUpperCase())) {
counter++; counter++;
filePath = editDataFileName(counter); filePath = prefixFileName(counter);
} }
return filePath; return filePath;

View File

@@ -10,8 +10,8 @@ import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
import { Dimension } from 'vs/base/browser/dom'; import { Dimension } from 'vs/base/browser/dom';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import * as UUID from 'vs/base/common/uuid';
import { Builder } from 'vs/base/browser/builder'; import { Builder } from 'vs/base/browser/builder';
import { dispose, Disposable } from 'vs/base/common/lifecycle';
export class QueryPlanState { export class QueryPlanState {
xml: string; xml: string;
@@ -25,10 +25,6 @@ export class QueryPlanTab implements IPanelTab {
constructor() { constructor() {
this.view = new QueryPlanView(); this.view = new QueryPlanView();
} }
public dispose() {
dispose(this.view);
}
} }
export class QueryPlanView implements IPanelView { export class QueryPlanView implements IPanelView {
@@ -48,12 +44,6 @@ export class QueryPlanView implements IPanelView {
this.container.style.overflow = 'scroll'; this.container.style.overflow = 'scroll';
} }
dispose() {
this.container.remove();
this.qp = undefined;
this.container = undefined;
}
public layout(dimension: Dimension): void { public layout(dimension: Dimension): void {
this.container.style.width = dimension.width + 'px'; this.container.style.width = dimension.width + 'px';
this.container.style.height = dimension.height + 'px'; this.container.style.height = dimension.height + 'px';

View File

@@ -58,6 +58,7 @@ declare module 'sqlops' {
export class TreeComponentItem extends vscode.TreeItem { export class TreeComponentItem extends vscode.TreeItem {
checked?: boolean; checked?: boolean;
enabled?: boolean;
} }
export interface ComponentBuilder<T extends Component> { export interface ComponentBuilder<T extends Component> {

View File

@@ -164,7 +164,7 @@ export class ExtHostTreeView<T> extends vsTreeExt.ExtHostTreeView<T> {
protected createTreeItem(element: T, extensionTreeItem: sqlops.TreeComponentItem, parent?: vsTreeExt.TreeNode): ITreeComponentItem { protected createTreeItem(element: T, extensionTreeItem: sqlops.TreeComponentItem, parent?: vsTreeExt.TreeNode): ITreeComponentItem {
let item = super.createTreeItem(element, extensionTreeItem, parent); let item = super.createTreeItem(element, extensionTreeItem, parent);
item = Object.assign({}, item, { checked: extensionTreeItem.checked }); item = Object.assign({}, item, { checked: extensionTreeItem.checked, enabled: extensionTreeItem.enabled });
return item; return item;
} }
} }

View File

@@ -7,6 +7,7 @@ import { ITreeViewDataProvider, ITreeItem } from 'vs/workbench/common/views';
export interface ITreeComponentItem extends ITreeItem { export interface ITreeComponentItem extends ITreeItem {
checked?: boolean; checked?: boolean;
enabled?: boolean;
onCheckedChanged?: (checked: boolean) => void; onCheckedChanged?: (checked: boolean) => void;
children?: ITreeComponentItem[]; children?: ITreeComponentItem[];
} }

View File

@@ -298,7 +298,7 @@ ${this.description}
if (!changelogUrl) { if (!changelogUrl) {
if (this.type === LocalExtensionType.System) { if (this.type === LocalExtensionType.System) {
return TPromise.as('Please check the [VS Code Release Notes](command:update.showCurrentReleaseNotes) for changes to the built-in extensions.'); return TPromise.as('Please check the [Azure Data Studio Release Notes](command:update.showCurrentReleaseNotes) for changes to the built-in extensions.');
} }
return TPromise.wrapError<string>(new Error('not available')); return TPromise.wrapError<string>(new Error('not available'));