mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-19 11:01:38 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05040425df | ||
|
|
36f7c283b8 | ||
|
|
9fe4237033 | ||
|
|
b03c0a3e2d | ||
|
|
87946996ed | ||
|
|
cc55023440 | ||
|
|
1f19dfc50d | ||
|
|
950a440350 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqlops",
|
"name": "sqlops",
|
||||||
"version": "0.33.4",
|
"version": "0.33.5",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"reflect-metadata": "^0.1.8",
|
"reflect-metadata": "^0.1.8",
|
||||||
"rxjs": "5.4.0",
|
"rxjs": "5.4.0",
|
||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.25",
|
"slickgrid": "github:anthonydresser/SlickGrid#2.3.27",
|
||||||
"spdlog": "0.7.1",
|
"spdlog": "0.7.1",
|
||||||
"sudo-prompt": "8.2.0",
|
"sudo-prompt": "8.2.0",
|
||||||
"svg.js": "^2.2.5",
|
"svg.js": "^2.2.5",
|
||||||
|
|||||||
@@ -180,14 +180,16 @@ export class TabbedPanel extends Disposable implements IThemable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout(dimension: Dimension): void {
|
public layout(dimension: Dimension): void {
|
||||||
this._currentDimensions = dimension;
|
if (dimension) {
|
||||||
this.$parent.style('height', dimension.height + 'px');
|
this._currentDimensions = dimension;
|
||||||
this.$parent.style('width', dimension.width + 'px');
|
this.$parent.style('height', dimension.height + 'px');
|
||||||
this.$header.style('width', dimension.width + 'px');
|
this.$parent.style('width', dimension.width + 'px');
|
||||||
this.$body.style('width', dimension.width + 'px');
|
this.$header.style('width', dimension.width + 'px');
|
||||||
const bodyHeight = dimension.height - (this._headerVisible ? this.headersize : 0);
|
this.$body.style('width', dimension.width + 'px');
|
||||||
this.$body.style('height', bodyHeight + 'px');
|
const bodyHeight = dimension.height - (this._headerVisible ? this.headersize : 0);
|
||||||
this._layoutCurrentTab(new Dimension(dimension.width, bodyHeight));
|
this.$body.style('height', bodyHeight + 'px');
|
||||||
|
this._layoutCurrentTab(new Dimension(dimension.width, bodyHeight));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _layoutCurrentTab(dimension: Dimension): void {
|
private _layoutCurrentTab(dimension: Dimension): void {
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
|||||||
private _onDidSashReset = new Emitter<void>();
|
private _onDidSashReset = new Emitter<void>();
|
||||||
readonly onDidSashReset = this._onDidSashReset.event;
|
readonly onDidSashReset = this._onDidSashReset.event;
|
||||||
|
|
||||||
|
private _onScroll = new Emitter<number>();
|
||||||
|
readonly onScroll = this._onScroll.event;
|
||||||
|
|
||||||
get length(): number {
|
get length(): number {
|
||||||
return this.viewItems.length;
|
return this.viewItems.length;
|
||||||
}
|
}
|
||||||
@@ -124,6 +127,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
|||||||
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => {
|
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => {
|
||||||
this.render(e.scrollTop, e.height);
|
this.render(e.scrollTop, e.height);
|
||||||
this.relayout();
|
this.relayout();
|
||||||
|
this._onScroll.fire(e.scrollTop);
|
||||||
});
|
});
|
||||||
let domNode = this.scrollable.getDomNode();
|
let domNode = this.scrollable.getDomNode();
|
||||||
dom.addClass(this.el, 'monaco-scroll-split-view');
|
dom.addClass(this.el, 'monaco-scroll-split-view');
|
||||||
@@ -330,6 +334,10 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
|||||||
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndex);
|
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setScrollPosition(position: number) {
|
||||||
|
this.scrollable.setScrollPosition({ scrollTop: position });
|
||||||
|
}
|
||||||
|
|
||||||
layout(size: number): void {
|
layout(size: number): void {
|
||||||
const previousSize = this.size;
|
const previousSize = this.size;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
|
|
||||||
require.__$__nodeRequire('slickgrid/plugins/slick.cellrangedecorator');
|
|
||||||
|
|
||||||
const defaultOptions: ICellRangeSelectorOptions = {
|
const defaultOptions: ICellRangeSelectorOptions = {
|
||||||
selectionCss: {
|
selectionCss: {
|
||||||
'border': '2px dashed blue'
|
'border': '2px dashed blue'
|
||||||
@@ -44,6 +42,8 @@ export class CellRangeSelector<T> implements ICellRangeSelector<T> {
|
|||||||
public onCellRangeSelected = new Slick.Event<{ range: Slick.Range }>();
|
public onCellRangeSelected = new Slick.Event<{ range: Slick.Range }>();
|
||||||
|
|
||||||
constructor(private options: ICellRangeSelectorOptions) {
|
constructor(private options: ICellRangeSelectorOptions) {
|
||||||
|
require.__$__nodeRequire('slickgrid/plugins/slick.cellrangedecorator');
|
||||||
|
|
||||||
this.options = mixin(this.options, defaultOptions, false);
|
this.options = mixin(this.options, defaultOptions, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
|
|||||||
|
|
||||||
import { CellRangeSelector, ICellRangeSelector } from 'sql/base/browser/ui/table/plugins/cellRangeSelector';
|
import { CellRangeSelector, ICellRangeSelector } from 'sql/base/browser/ui/table/plugins/cellRangeSelector';
|
||||||
|
|
||||||
require.__$__nodeRequire('slickgrid/plugins/slick.cellrangedecorator');
|
|
||||||
|
|
||||||
export interface ICellSelectionModelOptions {
|
export interface ICellSelectionModelOptions {
|
||||||
cellRangeSelector?: any;
|
cellRangeSelector?: any;
|
||||||
selectActiveCell?: boolean;
|
selectActiveCell?: boolean;
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ export class ConnectionStore {
|
|||||||
.then(savedCred => {
|
.then(savedCred => {
|
||||||
if (savedCred) {
|
if (savedCred) {
|
||||||
credentialsItem.password = savedCred.password;
|
credentialsItem.password = savedCred.password;
|
||||||
|
credentialsItem.options['password'] = savedCred.password;
|
||||||
}
|
}
|
||||||
resolve({ profile: credentialsItem, savedCred: !!savedCred });
|
resolve({ profile: credentialsItem, savedCred: !!savedCred });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ export class ConnectionWidget {
|
|||||||
this._databaseNameInputBox.enabled = false;
|
this._databaseNameInputBox.enabled = false;
|
||||||
this._userNameInputBox.disable();
|
this._userNameInputBox.disable();
|
||||||
this._passwordInputBox.disable();
|
this._passwordInputBox.disable();
|
||||||
|
this._connectionNameInputBox.disable();
|
||||||
this._rememberPasswordCheckBox.enabled = false;
|
this._rememberPasswordCheckBox.enabled = false;
|
||||||
if (this._authTypeSelectBox) {
|
if (this._authTypeSelectBox) {
|
||||||
this._authTypeSelectBox.disable();
|
this._authTypeSelectBox.disable();
|
||||||
@@ -503,6 +504,7 @@ export class ConnectionWidget {
|
|||||||
|
|
||||||
this._serverGroupSelectBox.enable();
|
this._serverGroupSelectBox.enable();
|
||||||
this._serverNameInputBox.enable();
|
this._serverNameInputBox.enable();
|
||||||
|
this._connectionNameInputBox.enable();
|
||||||
this._databaseNameInputBox.enabled = true;
|
this._databaseNameInputBox.enabled = true;
|
||||||
let currentAuthType: AuthenticationType = undefined;
|
let currentAuthType: AuthenticationType = undefined;
|
||||||
if (this._authTypeSelectBox) {
|
if (this._authTypeSelectBox) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ 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, 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 { Color } from 'vs/base/common/color';
|
||||||
@@ -21,29 +22,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||||||
|
|
||||||
declare var Chart: any;
|
declare var Chart: any;
|
||||||
|
|
||||||
export enum ChartType {
|
|
||||||
Bar = 'bar',
|
|
||||||
Doughnut = 'doughnut',
|
|
||||||
HorizontalBar = 'horizontalBar',
|
|
||||||
Line = 'line',
|
|
||||||
Pie = 'pie',
|
|
||||||
TimeSeries = 'timeSeries',
|
|
||||||
Scatter = 'scatter'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum DataDirection {
|
|
||||||
Vertical = 'vertical',
|
|
||||||
Horizontal = 'horizontal'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum LegendPosition {
|
|
||||||
Top = 'top',
|
|
||||||
Bottom = 'bottom',
|
|
||||||
Left = 'left',
|
|
||||||
Right = 'right',
|
|
||||||
None = 'none'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
|
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
|
||||||
if (types.isObject(source)) {
|
if (types.isObject(source)) {
|
||||||
mixin(destination, source, overwrite, customMixin);
|
mixin(destination, source, overwrite, customMixin);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
export enum ChartType {
|
||||||
|
Bar = 'bar',
|
||||||
|
Doughnut = 'doughnut',
|
||||||
|
HorizontalBar = 'horizontalBar',
|
||||||
|
Line = 'line',
|
||||||
|
Pie = 'pie',
|
||||||
|
TimeSeries = 'timeSeries',
|
||||||
|
Scatter = 'scatter'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DataDirection {
|
||||||
|
Vertical = 'vertical',
|
||||||
|
Horizontal = 'horizontal'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LegendPosition {
|
||||||
|
Top = 'top',
|
||||||
|
Bottom = 'bottom',
|
||||||
|
Left = 'left',
|
||||||
|
Right = 'right',
|
||||||
|
None = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DataType {
|
||||||
|
Number = 'number',
|
||||||
|
Point = 'point'
|
||||||
|
}
|
||||||
@@ -3,8 +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, ChartType, customMixin, IChartConfig } 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 } 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';
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* 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 { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
import PieChart from './pieChart.component';
|
import PieChart from './pieChart.component';
|
||||||
|
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
export default class DoughnutChart extends PieChart {
|
export default class DoughnutChart extends PieChart {
|
||||||
protected readonly chartType: ChartType = ChartType.Doughnut;
|
protected readonly chartType: ChartType = ChartType.Doughnut;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* 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 { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
import BarChart from './barChart.component';
|
import BarChart from './barChart.component';
|
||||||
|
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
export default class HorizontalBarChart extends BarChart {
|
export default class HorizontalBarChart extends BarChart {
|
||||||
protected readonly chartType: ChartType = ChartType.HorizontalBar;
|
protected readonly chartType: ChartType = ChartType.HorizontalBar;
|
||||||
|
|||||||
@@ -3,16 +3,13 @@
|
|||||||
* 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 { ChartType, customMixin, defaultChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
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 { mixin } from 'vs/base/common/objects';
|
|
||||||
import { clone } from 'sql/base/common/objects';
|
import { clone } from 'sql/base/common/objects';
|
||||||
|
import { ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
export enum DataType {
|
|
||||||
Number = 'number',
|
|
||||||
Point = 'point'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILineConfig extends IBarChartConfig {
|
export interface ILineConfig extends IBarChartConfig {
|
||||||
dataType?: DataType;
|
dataType?: DataType;
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
* 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, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
import { ChartInsight } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||||
|
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
export default class PieChart extends ChartInsight {
|
export default class PieChart extends ChartInsight {
|
||||||
protected readonly chartType: ChartType = ChartType.Pie;
|
protected readonly chartType: ChartType = ChartType.Pie;
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
* 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 { ChartType, defaultChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
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 { 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 { clone } from 'sql/base/common/objects';
|
|
||||||
|
|
||||||
const defaultScatterConfig = mixin(clone(defaultChartConfig), { dataType: 'point', dataDirection: 'horizontal' }) as ILineConfig;
|
const defaultScatterConfig = mixin(clone(defaultChartConfig), { dataType: 'point', dataDirection: 'horizontal' }) as ILineConfig;
|
||||||
|
|
||||||
|
|||||||
@@ -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, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
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 } 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';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { IGridDataSet } from 'sql/parts/grid/common/interfaces';
|
|||||||
import { IInsightData, IInsightsView, IInsightsConfig } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
import { IInsightData, IInsightsView, IInsightsConfig } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||||
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
||||||
import { QueryEditor } from 'sql/parts/query/editor/queryEditor';
|
import { QueryEditor } from 'sql/parts/query/editor/queryEditor';
|
||||||
import { DataType, ILineConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/types/lineChart.component';
|
import { ILineConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/types/lineChart.component';
|
||||||
import * as PathUtilities from 'sql/common/pathUtilities';
|
import * as PathUtilities from 'sql/common/pathUtilities';
|
||||||
import { IChartViewActionContext, CopyAction, CreateInsightAction, SaveImageAction } from 'sql/parts/grid/views/query/chartViewerActions';
|
import { IChartViewActionContext, CopyAction, CreateInsightAction, SaveImageAction } from 'sql/parts/grid/views/query/chartViewerActions';
|
||||||
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||||
@@ -24,10 +24,11 @@ import * as Constants from 'sql/parts/query/common/constants';
|
|||||||
import { SelectBox as AngularSelectBox } from 'sql/base/browser/ui/selectBox/selectBox.component';
|
import { SelectBox as AngularSelectBox } from 'sql/base/browser/ui/selectBox/selectBox.component';
|
||||||
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
|
||||||
|
import { LegendPosition, DataDirection, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
/* Insights */
|
/* Insights */
|
||||||
import {
|
import {
|
||||||
ChartInsight, DataDirection, LegendPosition
|
ChartInsight
|
||||||
} from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
} from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||||
|
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ export interface IObjectExplorerService {
|
|||||||
getActiveConnectionNodes(): TreeNode[];
|
getActiveConnectionNodes(): TreeNode[];
|
||||||
|
|
||||||
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
||||||
|
|
||||||
|
refreshNodeInView(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SessionStatus {
|
interface SessionStatus {
|
||||||
@@ -476,6 +478,20 @@ export class ObjectExplorerService implements IObjectExplorerService {
|
|||||||
return Object.values(this._activeObjectExplorerNodes);
|
return Object.values(this._activeObjectExplorerNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async refreshNodeInView(connectionId: string, nodePath: string): Promise<TreeNode> {
|
||||||
|
// Get the tree node and call refresh from the provider
|
||||||
|
let treeNode = await this.getTreeNode(connectionId, nodePath);
|
||||||
|
await this.refreshTreeNode(treeNode.getSession(), treeNode);
|
||||||
|
|
||||||
|
// Get the new tree node, refresh it in the view, and expand it if needed
|
||||||
|
treeNode = await this.getTreeNode(connectionId, nodePath);
|
||||||
|
await this._serverTreeView.refreshElement(treeNode);
|
||||||
|
if (treeNode.children.length > 0) {
|
||||||
|
await treeNode.setExpandedState(TreeItemCollapsibleState.Expanded);
|
||||||
|
}
|
||||||
|
return treeNode;
|
||||||
|
}
|
||||||
|
|
||||||
private async setNodeExpandedState(treeNode: TreeNode, expandedState: TreeItemCollapsibleState): Promise<void> {
|
private async setNodeExpandedState(treeNode: TreeNode, expandedState: TreeItemCollapsibleState): Promise<void> {
|
||||||
treeNode = await this.getUpdatedTreeNode(treeNode);
|
treeNode = await this.getUpdatedTreeNode(treeNode);
|
||||||
let expandNode = this.getTreeItem(treeNode);
|
let expandNode = this.getTreeItem(treeNode);
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export class ServerTreeView {
|
|||||||
|
|
||||||
let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG];
|
let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG];
|
||||||
if (expandGroups) {
|
if (expandGroups) {
|
||||||
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root));
|
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root && !root.hasValidConnections) {
|
if (root && !root.hasValidConnections) {
|
||||||
@@ -244,6 +244,10 @@ export class ServerTreeView {
|
|||||||
TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService);
|
TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public refreshElement(element: any): Thenable<void> {
|
||||||
|
return this._tree.refresh(element);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter connections based on view (recent/active)
|
* Filter connections based on view (recent/active)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,22 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||||||
import { EditorInput } from 'vs/workbench/common/editor';
|
import { EditorInput } from 'vs/workbench/common/editor';
|
||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
|
|
||||||
|
import { GridPanelState } from 'sql/parts/query/editor/gridPanel';
|
||||||
|
import { MessagePanelState } from 'sql/parts/query/editor/messagePanel';
|
||||||
|
import { QueryPlanState } from 'sql/parts/queryPlan/queryPlan';
|
||||||
|
import { ChartState } from 'sql/parts/query/editor/charting/chartView';
|
||||||
|
|
||||||
|
export class ResultsViewState {
|
||||||
|
public gridPanelState: GridPanelState = new GridPanelState();
|
||||||
|
public messagePanelState: MessagePanelState = new MessagePanelState();
|
||||||
|
public chartState: ChartState = new ChartState();
|
||||||
|
public queryPlanState: QueryPlanState = new QueryPlanState();
|
||||||
|
public gridPanelSize: number;
|
||||||
|
public messagePanelSize: number;
|
||||||
|
public activeTab: string;
|
||||||
|
public visibleTabs: Set<string> = new Set<string>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input for the QueryResultsEditor. This input helps with logic for the viewing and editing of
|
* Input for the QueryResultsEditor. This input helps with logic for the viewing and editing of
|
||||||
* data in the results grid.
|
* data in the results grid.
|
||||||
@@ -29,6 +45,8 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
||||||
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
||||||
|
|
||||||
|
public readonly state = new ResultsViewState();
|
||||||
|
|
||||||
constructor(private _uri: string) {
|
constructor(private _uri: string) {
|
||||||
super();
|
super();
|
||||||
this._visible = false;
|
this._visible = false;
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
|
||||||
import { ChartType, DataDirection, LegendPosition } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
||||||
import { DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/types/lineChart.component';
|
|
||||||
import { InsightType, IInsightOptions } from './insights/interfaces';
|
import { InsightType, IInsightOptions } from './insights/interfaces';
|
||||||
|
import { DataDirection, ChartType, LegendPosition, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
|
|
||||||
export class ChartTab implements IPanelTab {
|
export class ChartTab implements IPanelTab {
|
||||||
public readonly title = localize('chartTabTitle', 'Chart');
|
public readonly title = localize('chartTabTitle', 'Chart');
|
||||||
public readonly identifier = generateUuid();
|
public readonly identifier = 'ChartTab';
|
||||||
public readonly view: ChartView;
|
public readonly view: ChartView;
|
||||||
|
|
||||||
constructor(@IInstantiationService instantiationService: IInstantiationService) {
|
constructor(@IInstantiationService instantiationService: IInstantiationService) {
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import { Insight } from './insights/insight';
|
|||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||||
import { ChartOptions, IChartOption, ControlType } from './chartOptions';
|
import { ChartOptions, IChartOption, ControlType } from './chartOptions';
|
||||||
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||||
import { IInsightOptions } from './insights/interfaces';
|
import { IInsightOptions } from './insights/interfaces';
|
||||||
import { CopyAction, SaveImageAction, CreateInsightAction, IChartActionContext } from './actions';
|
import { CopyAction, SaveImageAction, CreateInsightAction, IChartActionContext } from './actions';
|
||||||
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
|
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
import { Dimension, $, getContentHeight, getContentWidth } from 'vs/base/browser/dom';
|
import { Dimension, $, getContentHeight, getContentWidth } from 'vs/base/browser/dom';
|
||||||
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
|
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||||
@@ -27,6 +27,14 @@ 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';
|
||||||
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
|
|
||||||
|
export class ChartState {
|
||||||
|
dataId: { batchId: number, resultId: number };
|
||||||
|
options: IInsightOptions = {
|
||||||
|
type: ChartType.Bar
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
declare class Proxy {
|
declare class Proxy {
|
||||||
constructor(object, handler);
|
constructor(object, handler);
|
||||||
@@ -43,6 +51,8 @@ export class ChartView implements IPanelView {
|
|||||||
private _copyAction: CopyAction;
|
private _copyAction: CopyAction;
|
||||||
private _saveAction: SaveImageAction;
|
private _saveAction: SaveImageAction;
|
||||||
|
|
||||||
|
private _state: ChartState;
|
||||||
|
|
||||||
private options: IInsightOptions = {
|
private options: IInsightOptions = {
|
||||||
type: ChartType.Bar
|
type: ChartType.Bar
|
||||||
};
|
};
|
||||||
@@ -61,7 +71,7 @@ export class ChartView implements IPanelView {
|
|||||||
private chartingContainer: HTMLElement;
|
private chartingContainer: HTMLElement;
|
||||||
|
|
||||||
private optionDisposables: IDisposable[] = [];
|
private optionDisposables: IDisposable[] = [];
|
||||||
private optionMap: { [x: string]: HTMLElement } = {};
|
private optionMap: { [x: string]: { element: HTMLElement; set: (val) => void } } = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IContextViewService private _contextViewService: IContextViewService,
|
@IContextViewService private _contextViewService: IContextViewService,
|
||||||
@@ -95,6 +105,10 @@ export class ChartView implements IPanelView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let result = Reflect.set(target, key, value, receiver);
|
let result = Reflect.set(target, key, value, receiver);
|
||||||
|
// mirror the change in our state
|
||||||
|
if (self.state) {
|
||||||
|
Reflect.set(self.state.options, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (change) {
|
if (change) {
|
||||||
self.taskbar.context = <IChartActionContext>{ options: self.options, insight: self.insight ? self.insight.insight : undefined };
|
self.taskbar.context = <IChartActionContext>{ options: self.options, insight: self.insight ? self.insight.insight : undefined };
|
||||||
@@ -138,6 +152,7 @@ export class ChartView implements IPanelView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public chart(dataId: { batchId: number, resultId: number }) {
|
public chart(dataId: { batchId: number, resultId: number }) {
|
||||||
|
this.state.dataId = dataId;
|
||||||
this._currentData = dataId;
|
this._currentData = dataId;
|
||||||
this.shouldGraph();
|
this.shouldGraph();
|
||||||
}
|
}
|
||||||
@@ -172,7 +187,7 @@ export class ChartView implements IPanelView {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we have the necessary information but the information isn't avaiable yet,
|
// if we have the necessary information but the information isn't available yet,
|
||||||
// we should be smart and retrying when the information might be available
|
// we should be smart and retrying when the information might be available
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +195,9 @@ export class ChartView implements IPanelView {
|
|||||||
private buildOptions() {
|
private buildOptions() {
|
||||||
dispose(this.optionDisposables);
|
dispose(this.optionDisposables);
|
||||||
this.optionDisposables = [];
|
this.optionDisposables = [];
|
||||||
this.optionMap = {};
|
this.optionMap = {
|
||||||
|
'type': this.optionMap['type']
|
||||||
|
};
|
||||||
new Builder(this.typeControls).clearChildren();
|
new Builder(this.typeControls).clearChildren();
|
||||||
|
|
||||||
this.updateActionbar();
|
this.updateActionbar();
|
||||||
@@ -200,9 +217,9 @@ export class ChartView implements IPanelView {
|
|||||||
let option = ChartOptions[this.options.type].find(e => e.configEntry === key);
|
let option = ChartOptions[this.options.type].find(e => e.configEntry === key);
|
||||||
if (option && option.if) {
|
if (option && option.if) {
|
||||||
if (option.if(this.options)) {
|
if (option.if(this.options)) {
|
||||||
new Builder(this.optionMap[key]).show();
|
new Builder(this.optionMap[key].element).show();
|
||||||
} else {
|
} else {
|
||||||
new Builder(this.optionMap[key]).hide();
|
new Builder(this.optionMap[key].element).hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,6 +228,7 @@ export class ChartView implements IPanelView {
|
|||||||
|
|
||||||
private updateActionbar() {
|
private updateActionbar() {
|
||||||
if (this.insight && this.insight.isCopyable) {
|
if (this.insight && this.insight.isCopyable) {
|
||||||
|
this.taskbar.context = { insight: this.insight.insight, options: this.options };
|
||||||
this.taskbar.setContent([
|
this.taskbar.setContent([
|
||||||
{ action: this._createInsightAction },
|
{ action: this._createInsightAction },
|
||||||
{ action: this._copyAction },
|
{ action: this._copyAction },
|
||||||
@@ -226,57 +244,104 @@ export class ChartView implements IPanelView {
|
|||||||
label.innerText = option.label;
|
label.innerText = option.label;
|
||||||
let optionContainer = $('div.option-container');
|
let optionContainer = $('div.option-container');
|
||||||
optionContainer.appendChild(label);
|
optionContainer.appendChild(label);
|
||||||
|
let setFunc: (val) => void;
|
||||||
|
let value = this.state ? this.state.options[option.configEntry] || option.default : option.default;
|
||||||
switch (option.type) {
|
switch (option.type) {
|
||||||
case ControlType.checkbox:
|
case ControlType.checkbox:
|
||||||
let checkbox = new Checkbox(optionContainer, {
|
let checkbox = new Checkbox(optionContainer, {
|
||||||
label: '',
|
label: '',
|
||||||
ariaLabel: option.label,
|
ariaLabel: option.label,
|
||||||
checked: option.default,
|
checked: value,
|
||||||
onChange: () => {
|
onChange: () => {
|
||||||
if (this.options[option.configEntry] !== checkbox.checked) {
|
if (this.options[option.configEntry] !== checkbox.checked) {
|
||||||
this.options[option.configEntry] = checkbox.checked;
|
this.options[option.configEntry] = checkbox.checked;
|
||||||
this.insight.options = this.options;
|
if (this.insight) {
|
||||||
|
this.insight.options = this.options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setFunc = (val: boolean) => {
|
||||||
|
checkbox.checked = val;
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case ControlType.combo:
|
case ControlType.combo:
|
||||||
let dropdown = new SelectBox(option.displayableOptions || option.options, 0, this._contextViewService);
|
let dropdown = new SelectBox(option.displayableOptions || option.options, 0, this._contextViewService);
|
||||||
dropdown.select(option.options.indexOf(option.default));
|
dropdown.select(option.options.indexOf(value));
|
||||||
dropdown.render(optionContainer);
|
dropdown.render(optionContainer);
|
||||||
dropdown.onDidSelect(e => {
|
dropdown.onDidSelect(e => {
|
||||||
if (this.options[option.configEntry] !== option.options[e.index]) {
|
if (this.options[option.configEntry] !== option.options[e.index]) {
|
||||||
this.options[option.configEntry] = option.options[e.index];
|
this.options[option.configEntry] = option.options[e.index];
|
||||||
this.insight.options = this.options;
|
if (this.insight) {
|
||||||
|
this.insight.options = this.options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setFunc = (val: string) => {
|
||||||
|
if (!isUndefinedOrNull(val)) {
|
||||||
|
dropdown.select(option.options.indexOf(val));
|
||||||
|
}
|
||||||
|
};
|
||||||
this.optionDisposables.push(attachSelectBoxStyler(dropdown, this._themeService));
|
this.optionDisposables.push(attachSelectBoxStyler(dropdown, this._themeService));
|
||||||
break;
|
break;
|
||||||
case ControlType.input:
|
case ControlType.input:
|
||||||
let input = new InputBox(optionContainer, this._contextViewService);
|
let input = new InputBox(optionContainer, this._contextViewService);
|
||||||
input.value = option.default || '';
|
input.value = value || '';
|
||||||
input.onDidChange(e => {
|
input.onDidChange(e => {
|
||||||
if (this.options[option.configEntry] !== e) {
|
if (this.options[option.configEntry] !== e) {
|
||||||
this.options[option.configEntry] = e;
|
this.options[option.configEntry] = e;
|
||||||
this.insight.options = this.options;
|
if (this.insight) {
|
||||||
|
this.insight.options = this.options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setFunc = (val: string) => {
|
||||||
|
if (!isUndefinedOrNull(val)) {
|
||||||
|
input.value = val;
|
||||||
|
}
|
||||||
|
};
|
||||||
this.optionDisposables.push(attachInputBoxStyler(input, this._themeService));
|
this.optionDisposables.push(attachInputBoxStyler(input, this._themeService));
|
||||||
break;
|
break;
|
||||||
case ControlType.numberInput:
|
case ControlType.numberInput:
|
||||||
let numberInput = new InputBox(optionContainer, this._contextViewService, { type: 'number' });
|
let numberInput = new InputBox(optionContainer, this._contextViewService, { type: 'number' });
|
||||||
numberInput.value = option.default || '';
|
numberInput.value = value || '';
|
||||||
numberInput.onDidChange(e => {
|
numberInput.onDidChange(e => {
|
||||||
if (this.options[option.configEntry] !== Number(e)) {
|
if (this.options[option.configEntry] !== Number(e)) {
|
||||||
this.options[option.configEntry] = Number(e);
|
this.options[option.configEntry] = Number(e);
|
||||||
this.insight.options = this.options;
|
if (this.insight) {
|
||||||
|
this.insight.options = this.options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setFunc = (val: string) => {
|
||||||
|
if (!isUndefinedOrNull(val)) {
|
||||||
|
input.value = val;
|
||||||
|
}
|
||||||
|
};
|
||||||
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.optionMap[option.configEntry] = optionContainer;
|
this.optionMap[option.configEntry] = { element: optionContainer, set: setFunc };
|
||||||
container.appendChild(optionContainer);
|
container.appendChild(optionContainer);
|
||||||
this.options[option.configEntry] = option.default;
|
this.options[option.configEntry] = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public set state(val: ChartState) {
|
||||||
|
this._state = val;
|
||||||
|
if (this.state.options) {
|
||||||
|
for (let key in this.state.options) {
|
||||||
|
if (this.state.options.hasOwnProperty(key)) {
|
||||||
|
this.options[key] = this.state.options[key];
|
||||||
|
this.optionMap[key].set(this.state.options[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.state.dataId) {
|
||||||
|
this.chart(this.state.dataId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): ChartState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ 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';
|
||||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||||
|
|
||||||
import { ChartType, DataDirection, LegendPosition } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
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 } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
|
|
||||||
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { Graph } from './graphInsight';
|
import { Graph } from './graphInsight';
|
||||||
import { ChartType, DataDirection } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
|
||||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||||
|
import { DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
import { Builder } from 'vs/base/browser/builder';
|
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
||||||
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';
|
||||||
import { CountInsight } from './countInsight';
|
import { CountInsight } from './countInsight';
|
||||||
|
|
||||||
|
import { Builder } from 'vs/base/browser/builder';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Dimension } from 'vs/base/browser/dom';
|
import { Dimension } from 'vs/base/browser/dom';
|
||||||
|
|
||||||
const defaultOptions: IInsightOptions = {
|
const defaultOptions: IInsightOptions = {
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import { Dimension } from 'vs/base/browser/dom';
|
||||||
|
|
||||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||||
import { ChartType, LegendPosition, DataDirection } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
import { DataDirection, ChartType, LegendPosition, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||||
import { Dimension } from 'vs/base/browser/dom';
|
|
||||||
import { DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/types/lineChart.component';
|
|
||||||
|
|
||||||
export interface IInsightOptions {
|
export interface IInsightOptions {
|
||||||
type: InsightType | ChartType;
|
type: InsightType | ChartType;
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const ACTIONBAR_HEIGHT = 100;
|
|||||||
// this handles min size if rows is greater than the min grid visible rows
|
// this handles min size if rows is greater than the min grid visible rows
|
||||||
const MIN_GRID_HEIGHT = (MIN_GRID_HEIGHT_ROWS * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
|
const MIN_GRID_HEIGHT = (MIN_GRID_HEIGHT_ROWS * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
|
||||||
|
|
||||||
|
export class GridPanelState {
|
||||||
|
public tableStates: GridTableState[] = [];
|
||||||
|
public scrollPosition: number;
|
||||||
|
public collapsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGridTableState {
|
export interface IGridTableState {
|
||||||
canBeMaximized: boolean;
|
canBeMaximized: boolean;
|
||||||
@@ -73,11 +78,12 @@ export class GridTableState {
|
|||||||
|
|
||||||
private _canBeMaximized: boolean;
|
private _canBeMaximized: boolean;
|
||||||
|
|
||||||
constructor(state?: IGridTableState) {
|
/* The top row of the current scroll */
|
||||||
if (state) {
|
public scrollPosition = 0;
|
||||||
this._maximized = state.maximized;
|
public selection: Slick.Range[];
|
||||||
this._canBeMaximized = state.canBeMaximized;
|
public activeCell: Slick.Cell;
|
||||||
}
|
|
||||||
|
constructor(public readonly resultId: number, public readonly batchId: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get canBeMaximized(): boolean {
|
public get canBeMaximized(): boolean {
|
||||||
@@ -103,10 +109,6 @@ export class GridTableState {
|
|||||||
this._maximized = val;
|
this._maximized = val;
|
||||||
this._onMaximizedChange.fire(val);
|
this._onMaximizedChange.fire(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public clone(): GridTableState {
|
|
||||||
return new GridTableState({ canBeMaximized: this.canBeMaximized, maximized: this.maximized });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GridPanel extends ViewletPanel {
|
export class GridPanel extends ViewletPanel {
|
||||||
@@ -120,6 +122,7 @@ export class GridPanel extends ViewletPanel {
|
|||||||
private runner: QueryRunner;
|
private runner: QueryRunner;
|
||||||
|
|
||||||
private maximizedGrid: GridTable<any>;
|
private maximizedGrid: GridTable<any>;
|
||||||
|
private _state: GridPanelState;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
options: IViewletPanelOptions,
|
options: IViewletPanelOptions,
|
||||||
@@ -131,6 +134,16 @@ export class GridPanel extends ViewletPanel {
|
|||||||
) {
|
) {
|
||||||
super(options, keybindingService, contextMenuService, configurationService);
|
super(options, keybindingService, contextMenuService, configurationService);
|
||||||
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false });
|
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false });
|
||||||
|
this.splitView.onScroll(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.scrollPosition = e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.onDidChange(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.collapsed = !this.isExpanded();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderBody(container: HTMLElement): void {
|
protected renderBody(container: HTMLElement): void {
|
||||||
@@ -168,6 +181,10 @@ export class GridPanel extends ViewletPanel {
|
|||||||
this.maximumBodySize = this.tables.reduce((p, c) => {
|
this.maximumBodySize = this.tables.reduce((p, c) => {
|
||||||
return p + c.maximumSize;
|
return p + c.maximumSize;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
if (this.state && this.state.scrollPosition) {
|
||||||
|
this.splitView.setScrollPosition(this.state.scrollPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
|
private addResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
|
||||||
@@ -181,8 +198,18 @@ export class GridPanel extends ViewletPanel {
|
|||||||
let tables: GridTable<any>[] = [];
|
let tables: GridTable<any>[] = [];
|
||||||
|
|
||||||
for (let set of resultsToAdd) {
|
for (let set of resultsToAdd) {
|
||||||
let tableState = new GridTableState();
|
let tableState: GridTableState;
|
||||||
let table = this.instantiationService.createInstance(GridTable, this.runner, tableState, set);
|
if (this._state) {
|
||||||
|
tableState = this.state.tableStates.find(e => e.batchId === set.batchId && e.resultId === set.id);
|
||||||
|
}
|
||||||
|
if (!tableState) {
|
||||||
|
tableState = new GridTableState(set.id, set.batchId);
|
||||||
|
if (this._state) {
|
||||||
|
this._state.tableStates.push(tableState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
|
||||||
|
table.state = tableState;
|
||||||
tableState.onMaximizedChange(e => {
|
tableState.onMaximizedChange(e => {
|
||||||
if (e) {
|
if (e) {
|
||||||
this.maximizeTable(table.id);
|
this.maximizeTable(table.id);
|
||||||
@@ -241,6 +268,24 @@ export class GridPanel extends ViewletPanel {
|
|||||||
this.splitView.addViews(this.tables, this.tables.map(i => i.minimumSize));
|
this.splitView.addViews(this.tables, this.tables.map(i => i.minimumSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set state(val: GridPanelState) {
|
||||||
|
this._state = val;
|
||||||
|
this.tables.map(t => {
|
||||||
|
let state = this.state.tableStates.find(s => s.batchId === t.resultSet.batchId && s.resultId === t.resultSet.id);
|
||||||
|
if (!state) {
|
||||||
|
this.state.tableStates.push(t.state);
|
||||||
|
}
|
||||||
|
if (state) {
|
||||||
|
t.state = state;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setExpanded(!this.state.collapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): GridPanelState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridTable<T> extends Disposable implements IView {
|
class GridTable<T> extends Disposable implements IView {
|
||||||
@@ -259,13 +304,14 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
public id = generateUuid();
|
public id = generateUuid();
|
||||||
readonly element: HTMLElement = this.container;
|
readonly element: HTMLElement = this.container;
|
||||||
|
|
||||||
|
private _state: GridTableState;
|
||||||
|
|
||||||
// this handles if the row count is small, like 4-5 rows
|
// this handles if the row count is small, like 4-5 rows
|
||||||
private readonly maxSize = ((this.resultSet.rowCount) * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
|
private readonly maxSize = ((this.resultSet.rowCount) * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private runner: QueryRunner,
|
private runner: QueryRunner,
|
||||||
public state: GridTableState,
|
public readonly resultSet: sqlops.ResultSetSummary,
|
||||||
private resultSet: sqlops.ResultSetSummary,
|
|
||||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||||
@IInstantiationService private instantiationService: IInstantiationService,
|
@IInstantiationService private instantiationService: IInstantiationService,
|
||||||
@IEditorService private editorService: IEditorService,
|
@IEditorService private editorService: IEditorService,
|
||||||
@@ -357,10 +403,52 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
});
|
});
|
||||||
this.actionBar.push(actions, { icon: true, label: false });
|
this.actionBar.push(actions, { icon: true, label: false });
|
||||||
|
|
||||||
|
this.selectionModel.onSelectedRangesChanged.subscribe(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.selection = this.selectionModel.getSelectedRanges();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.table.grid.onScroll.subscribe(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.scrollPosition = this.table.grid.getViewport().top;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.table.grid.onActiveCellChanged.subscribe(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.activeCell = this.table.grid.getActiveCell();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setupState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupState() {
|
||||||
// change actionbar on maximize change
|
// change actionbar on maximize change
|
||||||
this.state.onMaximizedChange(this.rebuildActionBar, this);
|
this.state.onMaximizedChange(this.rebuildActionBar, this);
|
||||||
|
|
||||||
this.state.onCanBeMaximizedChange(this.rebuildActionBar, this);
|
this.state.onCanBeMaximizedChange(this.rebuildActionBar, this);
|
||||||
|
|
||||||
|
if (this.state.scrollPosition) {
|
||||||
|
this.table.grid.scrollRowToTop(this.state.scrollPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.selection) {
|
||||||
|
this.selectionModel.setSelectedRanges(this.state.selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.activeCell) {
|
||||||
|
this.table.setActiveCell(this.state.activeCell.row, this.state.activeCell.cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): GridTableState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set state(val: GridTableState) {
|
||||||
|
this._state = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onTableClick(event: ITableMouseEvent) {
|
private onTableClick(event: ITableMouseEvent) {
|
||||||
|
|||||||
5
src/sql/parts/query/editor/media/queryActions.css
Normal file
5
src/sql/parts/query/editor/media/queryActions.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.monaco-select-box {
|
||||||
|
cursor: pointer;
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
@@ -59,6 +59,11 @@ const TemplateIds = {
|
|||||||
ERROR: 'error'
|
ERROR: 'error'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export class MessagePanelState {
|
||||||
|
public scrollPosition: number;
|
||||||
|
public collapsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
export class MessagePanel extends ViewletPanel {
|
export class MessagePanel extends ViewletPanel {
|
||||||
private ds = new MessageDataSource();
|
private ds = new MessageDataSource();
|
||||||
private renderer = new MessageRenderer();
|
private renderer = new MessageRenderer();
|
||||||
@@ -67,6 +72,7 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
private container = $('div message-tree').getHTMLElement();
|
private container = $('div message-tree').getHTMLElement();
|
||||||
|
|
||||||
private queryRunnerDisposables: IDisposable[] = [];
|
private queryRunnerDisposables: IDisposable[] = [];
|
||||||
|
private _state: MessagePanelState;
|
||||||
|
|
||||||
private tree: ITree;
|
private tree: ITree;
|
||||||
|
|
||||||
@@ -86,6 +92,16 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
renderer: this.renderer,
|
renderer: this.renderer,
|
||||||
controller: this.controller
|
controller: this.controller
|
||||||
}, { keyboardSupport: false });
|
}, { keyboardSupport: false });
|
||||||
|
this.tree.onDidScroll(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.scrollPosition = this.tree.getScrollPosition();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.onDidChange(e => {
|
||||||
|
if (this.state) {
|
||||||
|
this.state.collapsed = !this.isExpanded();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderBody(container: HTMLElement): void {
|
protected renderBody(container: HTMLElement): void {
|
||||||
@@ -99,8 +115,12 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
protected layoutBody(size: number): void {
|
protected layoutBody(size: number): void {
|
||||||
const previousScrollPosition = this.tree.getScrollPosition();
|
const previousScrollPosition = this.tree.getScrollPosition();
|
||||||
this.tree.layout(size);
|
this.tree.layout(size);
|
||||||
if (previousScrollPosition === 1) {
|
if (this.state && this.state.scrollPosition) {
|
||||||
this.tree.setScrollPosition(1);
|
this.tree.setScrollPosition(this.state.scrollPosition);
|
||||||
|
} else {
|
||||||
|
if (previousScrollPosition === 1) {
|
||||||
|
this.tree.setScrollPosition(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,12 +144,19 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
if (hasError) {
|
if (hasError) {
|
||||||
this.setExpanded(true);
|
this.setExpanded(true);
|
||||||
}
|
}
|
||||||
const previousScrollPosition = this.tree.getScrollPosition();
|
if (this.state.scrollPosition) {
|
||||||
this.tree.refresh(this.model).then(() => {
|
this.tree.refresh(this.model).then(() => {
|
||||||
if (previousScrollPosition === 1) {
|
|
||||||
this.tree.setScrollPosition(1);
|
this.tree.setScrollPosition(1);
|
||||||
}
|
});
|
||||||
});
|
} else {
|
||||||
|
const previousScrollPosition = this.tree.getScrollPosition();
|
||||||
|
this.tree.refresh(this.model).then(() => {
|
||||||
|
if (previousScrollPosition === 1) {
|
||||||
|
this.tree.setScrollPosition(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.maximumBodySize = this.model.messages.length * 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
private reset() {
|
private reset() {
|
||||||
@@ -137,6 +164,17 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
this.model.totalExecuteMessage = undefined;
|
this.model.totalExecuteMessage = undefined;
|
||||||
this.tree.refresh(this.model);
|
this.tree.refresh(this.model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set state(val: MessagePanelState) {
|
||||||
|
this._state = val;
|
||||||
|
if (this.state.scrollPosition) {
|
||||||
|
this.tree.setScrollPosition(this.state.scrollPosition);
|
||||||
|
}
|
||||||
|
this.setExpanded(!this.state.collapsed);
|
||||||
|
}
|
||||||
|
public get state(): MessagePanelState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageDataSource implements IDataSource {
|
class MessageDataSource implements IDataSource {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ import {
|
|||||||
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
import { IEditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
|
import { IEditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
@@ -500,7 +499,7 @@ export class QueryEditor extends BaseEditor {
|
|||||||
public get listDatabasesActionItem(): ListDatabasesActionItem {
|
public get listDatabasesActionItem(): ListDatabasesActionItem {
|
||||||
if (!this._listDatabasesActionItem) {
|
if (!this._listDatabasesActionItem) {
|
||||||
this._listDatabasesActionItem = this._instantiationService.createInstance(ListDatabasesActionItem, this, this._listDatabasesAction);
|
this._listDatabasesActionItem = this._instantiationService.createInstance(ListDatabasesActionItem, this, this._listDatabasesAction);
|
||||||
this._register(attachEditableDropdownStyler(this._listDatabasesActionItem, this.themeService));
|
this._register(this._listDatabasesActionItem.attachStyler(this.themeService));
|
||||||
}
|
}
|
||||||
return this._listDatabasesActionItem;
|
return this._listDatabasesActionItem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { QueryResultsInput } from 'sql/parts/query/common/queryResultsInput';
|
import { QueryResultsInput, ResultsViewState } from 'sql/parts/query/common/queryResultsInput';
|
||||||
import { TabbedPanel, IPanelTab, IPanelView } from 'sql/base/browser/ui/panel/panel';
|
import { TabbedPanel, IPanelTab, IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||||
import { IQueryModelService } from '../execution/queryModel';
|
import { IQueryModelService } from '../execution/queryModel';
|
||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
@@ -14,11 +14,10 @@ import { ChartTab } from './charting/chartTab';
|
|||||||
import { QueryPlanTab } from 'sql/parts/queryPlan/queryPlan';
|
import { QueryPlanTab } from 'sql/parts/queryPlan/queryPlan';
|
||||||
|
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import * as UUID from 'vs/base/common/uuid';
|
|
||||||
import { PanelViewlet } from 'vs/workbench/browser/parts/views/panelViewlet';
|
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 } from 'vs/base/common/event';
|
import { once, anyEvent } from 'vs/base/common/event';
|
||||||
|
|
||||||
class ResultsView implements IPanelView {
|
class ResultsView implements IPanelView {
|
||||||
private panelViewlet: PanelViewlet;
|
private panelViewlet: PanelViewlet;
|
||||||
@@ -26,61 +25,72 @@ class ResultsView implements IPanelView {
|
|||||||
private messagePanel: MessagePanel;
|
private messagePanel: MessagePanel;
|
||||||
private container = document.createElement('div');
|
private container = document.createElement('div');
|
||||||
private currentDimension: DOM.Dimension;
|
private currentDimension: DOM.Dimension;
|
||||||
private isGridRendered = false;
|
|
||||||
private needsGridResize = false;
|
private needsGridResize = false;
|
||||||
private lastGridHeight: number;
|
private _state: ResultsViewState;
|
||||||
|
|
||||||
constructor(instantiationService: IInstantiationService) {
|
constructor(private instantiationService: IInstantiationService) {
|
||||||
this.panelViewlet = instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false });
|
|
||||||
this.gridPanel = instantiationService.createInstance(GridPanel, { title: nls.localize('gridPanel', 'Results'), id: 'gridPanel' });
|
this.panelViewlet = this.instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false });
|
||||||
this.messagePanel = instantiationService.createInstance(MessagePanel, { title: nls.localize('messagePanel', 'Messages'), minimumBodySize: 0, id: 'messagePanel' });
|
this.gridPanel = this.instantiationService.createInstance(GridPanel, { title: nls.localize('gridPanel', 'Results'), id: 'gridPanel' });
|
||||||
|
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(() => {
|
||||||
|
this.gridPanel.setVisible(false);
|
||||||
this.panelViewlet.addPanels([
|
this.panelViewlet.addPanels([
|
||||||
{ panel: this.messagePanel, size: this.messagePanel.minimumSize, index: 1 }
|
{ panel: this.messagePanel, size: this.messagePanel.minimumSize, index: 1 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
this.gridPanel.onDidChange(e => {
|
anyEvent(this.gridPanel.onDidChange, this.messagePanel.onDidChange)(e => {
|
||||||
let size = this.gridPanel.maximumBodySize;
|
let size = this.gridPanel.maximumBodySize;
|
||||||
if (this.isGridRendered) {
|
if (size < 1 && this.gridPanel.isVisible()) {
|
||||||
if (size < 1) {
|
this.gridPanel.setVisible(false);
|
||||||
this.lastGridHeight = this.panelViewlet.getPanelSize(this.gridPanel);
|
this.panelViewlet.removePanels([this.gridPanel]);
|
||||||
this.panelViewlet.removePanels([this.gridPanel]);
|
this.gridPanel.layout(0);
|
||||||
// tell the panel is has been removed.
|
} else if (size > 0 && !this.gridPanel.isVisible()) {
|
||||||
this.gridPanel.layout(0);
|
this.gridPanel.setVisible(true);
|
||||||
this.isGridRendered = false;
|
let panelSize: number;
|
||||||
}
|
if (this.state && this.state.gridPanelSize) {
|
||||||
} else {
|
panelSize = this.state.gridPanelSize;
|
||||||
if (this.currentDimension) {
|
} else if (this.currentDimension) {
|
||||||
this.needsGridResize = false;
|
panelSize = Math.round(this.currentDimension.height * .7);
|
||||||
if (size > 0) {
|
|
||||||
this.panelViewlet.addPanels([
|
|
||||||
{ panel: this.gridPanel, index: 0, size: this.lastGridHeight || Math.round(this.currentDimension.height * .7) }
|
|
||||||
]);
|
|
||||||
this.isGridRendered = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.panelViewlet.addPanels([
|
panelSize = 200;
|
||||||
{ panel: this.gridPanel, index: 0, size: this.lastGridHeight || 200 }
|
|
||||||
]);
|
|
||||||
this.isGridRendered = true;
|
|
||||||
this.needsGridResize = true;
|
this.needsGridResize = true;
|
||||||
}
|
}
|
||||||
|
this.panelViewlet.addPanels([{ panel: this.gridPanel, index: 0, size: panelSize }]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let gridResizeList = this.gridPanel.onDidChange(e => {
|
let resizeList = anyEvent(this.gridPanel.onDidChange, this.messagePanel.onDidChange)(() => {
|
||||||
if (this.currentDimension) {
|
let panelSize: number;
|
||||||
this.needsGridResize = false;
|
if (this.state && this.state.gridPanelSize) {
|
||||||
this.panelViewlet.resizePanel(this.gridPanel, Math.round(this.currentDimension.height * .7));
|
panelSize = this.state.gridPanelSize;
|
||||||
|
} else if (this.currentDimension) {
|
||||||
|
panelSize = Math.round(this.currentDimension.height * .7);
|
||||||
} else {
|
} else {
|
||||||
|
panelSize = 200;
|
||||||
this.needsGridResize = true;
|
this.needsGridResize = true;
|
||||||
}
|
}
|
||||||
});
|
if (this.state.messagePanelSize) {
|
||||||
|
this.panelViewlet.resizePanel(this.gridPanel, this.state.messagePanelSize);
|
||||||
|
}
|
||||||
|
this.panelViewlet.resizePanel(this.gridPanel, panelSize);
|
||||||
|
})
|
||||||
// once the user changes the sash we should stop trying to resize the grid
|
// once the user changes the sash we should stop trying to resize the grid
|
||||||
once(this.panelViewlet.onDidSashChange)(e => {
|
once(this.panelViewlet.onDidSashChange)(e => {
|
||||||
this.needsGridResize = false;
|
this.needsGridResize = false;
|
||||||
gridResizeList.dispose();
|
resizeList.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.panelViewlet.onDidSashChange(e => {
|
||||||
|
if (this.state) {
|
||||||
|
if (this.gridPanel.isExpanded()) {
|
||||||
|
this.state.gridPanelSize = this.panelViewlet.getPanelSize(this.gridPanel);
|
||||||
|
}
|
||||||
|
if (this.messagePanel.isExpanded()) {
|
||||||
|
this.state.messagePanelSize = this.panelViewlet.getPanelSize(this.messagePanel);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +106,7 @@ class ResultsView implements IPanelView {
|
|||||||
}
|
}
|
||||||
this.currentDimension = dimension;
|
this.currentDimension = dimension;
|
||||||
if (this.needsGridResize) {
|
if (this.needsGridResize) {
|
||||||
this.panelViewlet.resizePanel(this.gridPanel, Math.round(this.currentDimension.height * .7));
|
this.panelViewlet.resizePanel(this.gridPanel, this.state.gridPanelSize || Math.round(this.currentDimension.height * .7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,11 +122,21 @@ class ResultsView implements IPanelView {
|
|||||||
public hideResultHeader() {
|
public hideResultHeader() {
|
||||||
this.gridPanel.headerVisible = false;
|
this.gridPanel.headerVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set state(val: ResultsViewState) {
|
||||||
|
this._state = val;
|
||||||
|
this.gridPanel.state = val.gridPanelState;
|
||||||
|
this.messagePanel.state = val.messagePanelState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): ResultsViewState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResultsTab implements IPanelTab {
|
class ResultsTab implements IPanelTab {
|
||||||
public readonly title = nls.localize('resultsTabTitle', 'Results');
|
public readonly title = nls.localize('resultsTabTitle', 'Results');
|
||||||
public readonly identifier = UUID.generateUuid();
|
public readonly identifier = 'resultsTab';
|
||||||
public readonly view: ResultsView;
|
public readonly view: ResultsView;
|
||||||
|
|
||||||
constructor(instantiationService: IInstantiationService) {
|
constructor(instantiationService: IInstantiationService) {
|
||||||
@@ -144,6 +164,12 @@ export class QueryResultsView {
|
|||||||
this.chartTab = new ChartTab(instantiationService);
|
this.chartTab = new ChartTab(instantiationService);
|
||||||
this._panelView = new TabbedPanel(container, { showHeaderWhenSingleView: false });
|
this._panelView = new TabbedPanel(container, { showHeaderWhenSingleView: false });
|
||||||
this.qpTab = new QueryPlanTab();
|
this.qpTab = new QueryPlanTab();
|
||||||
|
this._panelView.pushTab(this.resultsTab);
|
||||||
|
this._panelView.onTabChange(e => {
|
||||||
|
if (this.input) {
|
||||||
|
this.input.state.activeTab = e;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public style() {
|
public style() {
|
||||||
@@ -151,11 +177,24 @@ export class QueryResultsView {
|
|||||||
|
|
||||||
public set input(input: QueryResultsInput) {
|
public set input(input: QueryResultsInput) {
|
||||||
this._input = input;
|
this._input = input;
|
||||||
|
this.resultsTab.view.state = this.input.state;
|
||||||
|
this.qpTab.view.state = this.input.state.queryPlanState;
|
||||||
|
this.chartTab.view.state = this.input.state.chartState;
|
||||||
let queryRunner = this.queryModelService._getQueryInfo(input.uri).queryRunner;
|
let queryRunner = this.queryModelService._getQueryInfo(input.uri).queryRunner;
|
||||||
this.resultsTab.queryRunner = queryRunner;
|
this.resultsTab.queryRunner = queryRunner;
|
||||||
this.chartTab.queryRunner = queryRunner;
|
this.chartTab.queryRunner = queryRunner;
|
||||||
if (!this._panelView.contains(this.resultsTab)) {
|
if (this.input.state.visibleTabs.has(this.chartTab.identifier)) {
|
||||||
this._panelView.pushTab(this.resultsTab);
|
if (!this._panelView.contains(this.chartTab)) {
|
||||||
|
this._panelView.pushTab(this.chartTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.input.state.visibleTabs.has(this.qpTab.identifier)) {
|
||||||
|
if (!this._panelView.contains(this.qpTab)) {
|
||||||
|
this._panelView.pushTab(this.qpTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.input.state.activeTab) {
|
||||||
|
this._panelView.showTab(this.input.state.activeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +211,7 @@ export class QueryResultsView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public chartData(dataId: { resultId: number, batchId: number }): void {
|
public chartData(dataId: { resultId: number, batchId: number }): void {
|
||||||
|
this.input.state.visibleTabs.add(this.chartTab.identifier);
|
||||||
if (!this._panelView.contains(this.chartTab)) {
|
if (!this._panelView.contains(this.chartTab)) {
|
||||||
this._panelView.pushTab(this.chartTab);
|
this._panelView.pushTab(this.chartTab);
|
||||||
}
|
}
|
||||||
@@ -181,6 +221,7 @@ export class QueryResultsView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public showPlan(xml: string) {
|
public showPlan(xml: string) {
|
||||||
|
this.input.state.visibleTabs.add(this.qpTab.identifier);
|
||||||
if (!this._panelView.contains(this.qpTab)) {
|
if (!this._panelView.contains(this.qpTab)) {
|
||||||
this._panelView.pushTab(this.qpTab);
|
this._panelView.pushTab(this.qpTab);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* 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 'vs/css!sql/parts/query/editor/media/queryActions';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { Builder, $ } from 'vs/base/browser/builder';
|
import { Builder, $ } from 'vs/base/browser/builder';
|
||||||
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
||||||
@@ -12,6 +13,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { attachEditableDropdownStyler, attachSelectBoxStyler } from 'sql/common/theme/styler';
|
||||||
|
|
||||||
import { ISelectionData } from 'sqlops';
|
import { ISelectionData } from 'sqlops';
|
||||||
import {
|
import {
|
||||||
@@ -25,6 +27,8 @@ import { QueryEditor } from 'sql/parts/query/editor/queryEditor';
|
|||||||
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action class that query-based Actions will extend. This base class automatically handles activating and
|
* Action class that query-based Actions will extend. This base class automatically handles activating and
|
||||||
@@ -431,6 +435,9 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
private _isConnected: boolean;
|
private _isConnected: boolean;
|
||||||
private $databaseListDropdown: Builder;
|
private $databaseListDropdown: Builder;
|
||||||
private _dropdown: Dropdown;
|
private _dropdown: Dropdown;
|
||||||
|
private _databaseSelectBox: SelectBox;
|
||||||
|
private _isInAccessibilityMode: boolean;
|
||||||
|
private readonly _selectDatabaseString: string = nls.localize("selectDatabase", "Select Database");
|
||||||
|
|
||||||
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
||||||
constructor(
|
constructor(
|
||||||
@@ -439,23 +446,33 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@INotificationService private _notificationService: INotificationService,
|
@INotificationService private _notificationService: INotificationService,
|
||||||
@IContextViewService contextViewProvider: IContextViewService,
|
@IContextViewService contextViewProvider: IContextViewService,
|
||||||
@IThemeService themeService: IThemeService
|
@IThemeService themeService: IThemeService,
|
||||||
|
@IConfigurationService private readonly _configurationService: IConfigurationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._toDispose = [];
|
this._toDispose = [];
|
||||||
this.$databaseListDropdown = $('.databaseListDropdown');
|
this.$databaseListDropdown = $('.databaseListDropdown');
|
||||||
let selectString = nls.localize("selectDatabase", "Select Database");
|
this._isInAccessibilityMode = this._configurationService.getValue('editor.accessibilitySupport') === 'on';
|
||||||
this._dropdown = new Dropdown(this.$databaseListDropdown.getHTMLElement(), contextViewProvider, themeService, {
|
|
||||||
strictSelection: true,
|
if (this._isInAccessibilityMode) {
|
||||||
placeholder: selectString,
|
this._databaseSelectBox = new SelectBox([this._selectDatabaseString], this._selectDatabaseString, contextViewProvider, undefined, { ariaLabel: this._selectDatabaseString });
|
||||||
ariaLabel: selectString,
|
this._databaseSelectBox.render(this.$databaseListDropdown.getHTMLElement());
|
||||||
actionLabel: nls.localize('listDatabases.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
|
this._databaseSelectBox.onDidSelect(e => { this.databaseSelected(e.selected); });
|
||||||
});
|
this._databaseSelectBox.disable();
|
||||||
this._dropdown.onValueChange(s => this.databaseSelected(s));
|
|
||||||
|
} else {
|
||||||
|
this._dropdown = new Dropdown(this.$databaseListDropdown.getHTMLElement(), contextViewProvider, themeService, {
|
||||||
|
strictSelection: true,
|
||||||
|
placeholder: this._selectDatabaseString,
|
||||||
|
ariaLabel: this._selectDatabaseString,
|
||||||
|
actionLabel: nls.localize('listDatabases.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
|
||||||
|
});
|
||||||
|
this._dropdown.onValueChange(s => this.databaseSelected(s));
|
||||||
|
this._toDispose.push(this._dropdown.onFocus(() => { self.onDropdownFocus(); }));
|
||||||
|
}
|
||||||
|
|
||||||
// Register event handlers
|
// Register event handlers
|
||||||
let self = this;
|
let self = this;
|
||||||
this._toDispose.push(this._dropdown.onFocus(() => { self.onDropdownFocus(); }));
|
|
||||||
this._toDispose.push(this._connectionManagementService.onConnectionChanged(params => { self.onConnectionChanged(params); }));
|
this._toDispose.push(this._connectionManagementService.onConnectionChanged(params => { self.onConnectionChanged(params); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +482,12 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
public style(styles) {
|
public style(styles) {
|
||||||
this._dropdown.style(styles);
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.style(styles);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._dropdown.style(styles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setActionContext(context: any): void {
|
public setActionContext(context: any): void {
|
||||||
@@ -477,11 +499,27 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
this._dropdown.focus();
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.focus();
|
||||||
|
} else {
|
||||||
|
this._dropdown.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public blur(): void {
|
public blur(): void {
|
||||||
this._dropdown.blur();
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.blur();
|
||||||
|
} else {
|
||||||
|
this._dropdown.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public attachStyler(themeService: IThemeService): IDisposable {
|
||||||
|
if (this._isInAccessibilityMode) {
|
||||||
|
return attachSelectBoxStyler(this, themeService);
|
||||||
|
} else {
|
||||||
|
return attachEditableDropdownStyler(this, themeService);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
@@ -496,9 +534,15 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
|
|
||||||
public onDisconnect(): void {
|
public onDisconnect(): void {
|
||||||
this._isConnected = false;
|
this._isConnected = false;
|
||||||
this._dropdown.enabled = false;
|
|
||||||
this._currentDatabaseName = undefined;
|
this._currentDatabaseName = undefined;
|
||||||
this._dropdown.value = '';
|
|
||||||
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.disable();
|
||||||
|
this._databaseSelectBox.setOptions([this._selectDatabaseString]);
|
||||||
|
} else {
|
||||||
|
this._dropdown.enabled = false;
|
||||||
|
this._dropdown.value = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE HELPERS /////////////////////////////////////////////////////
|
// PRIVATE HELPERS /////////////////////////////////////////////////////
|
||||||
@@ -515,22 +559,22 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
|
|
||||||
this._connectionManagementService.changeDatabase(this._editor.uri, dbName)
|
this._connectionManagementService.changeDatabase(this._editor.uri, dbName)
|
||||||
.then(
|
.then(
|
||||||
result => {
|
result => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
this.resetDatabaseName();
|
||||||
|
this._notificationService.notify({
|
||||||
|
severity: Severity.Error,
|
||||||
|
message: nls.localize('changeDatabase.failed', "Failed to change database")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
this.resetDatabaseName();
|
this.resetDatabaseName();
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
message: nls.localize('changeDatabase.failed', "Failed to change database")
|
message: nls.localize('changeDatabase.failedWithError', "Failed to change database {0}", error)
|
||||||
});
|
});
|
||||||
}
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.resetDatabaseName();
|
|
||||||
this._notificationService.notify({
|
|
||||||
severity: Severity.Error,
|
|
||||||
message: nls.localize('changeDatabase.failedWithError', "Failed to change database {0}", error)
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCurrentDatabaseName() {
|
private getCurrentDatabaseName() {
|
||||||
@@ -545,7 +589,11 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private resetDatabaseName() {
|
private resetDatabaseName() {
|
||||||
this._dropdown.value = this.getCurrentDatabaseName();
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.selectWithOptionName(this.getCurrentDatabaseName());
|
||||||
|
} else {
|
||||||
|
this._dropdown.value = this.getCurrentDatabaseName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onConnectionChanged(connParams: IConnectionParams): void {
|
private onConnectionChanged(connParams: IConnectionParams): void {
|
||||||
@@ -579,9 +627,26 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
|
|
||||||
private updateConnection(databaseName: string) {
|
private updateConnection(databaseName: string) {
|
||||||
this._isConnected = true;
|
this._isConnected = true;
|
||||||
this._dropdown.enabled = true;
|
|
||||||
this._currentDatabaseName = databaseName;
|
this._currentDatabaseName = databaseName;
|
||||||
this._dropdown.value = databaseName;
|
|
||||||
|
if (this._isInAccessibilityMode) {
|
||||||
|
this._databaseSelectBox.enable();
|
||||||
|
let self = this;
|
||||||
|
let uri = self._editor.connectedUri;
|
||||||
|
if (!uri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self._connectionManagementService.listDatabases(uri)
|
||||||
|
.then(result => {
|
||||||
|
if (result && result.databaseNames) {
|
||||||
|
this._databaseSelectBox.setOptions(result.databaseNames);
|
||||||
|
}
|
||||||
|
this._databaseSelectBox.selectWithOptionName(databaseName);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._dropdown.enabled = true;
|
||||||
|
this._dropdown.value = databaseName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTING PROPERTIES //////////////////////////////////////////////////
|
// TESTING PROPERTIES //////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -13,9 +13,13 @@ import { localize } from 'vs/nls';
|
|||||||
import * as UUID from 'vs/base/common/uuid';
|
import * as UUID from 'vs/base/common/uuid';
|
||||||
import { Builder } from 'vs/base/browser/builder';
|
import { Builder } from 'vs/base/browser/builder';
|
||||||
|
|
||||||
|
export class QueryPlanState {
|
||||||
|
xml: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class QueryPlanTab implements IPanelTab {
|
export class QueryPlanTab implements IPanelTab {
|
||||||
public readonly title = localize('queryPlanTitle', 'Query Plan');
|
public readonly title = localize('queryPlanTitle', 'Query Plan');
|
||||||
public readonly identifier = UUID.generateUuid();
|
public readonly identifier = 'QueryPlanTab';
|
||||||
public readonly view: QueryPlanView;
|
public readonly view: QueryPlanView;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -27,6 +31,7 @@ export class QueryPlanView implements IPanelView {
|
|||||||
private qp: QueryPlan;
|
private qp: QueryPlan;
|
||||||
private xml: string;
|
private xml: string;
|
||||||
private container = document.createElement('div');
|
private container = document.createElement('div');
|
||||||
|
private _state: QueryPlanState;
|
||||||
|
|
||||||
public render(container: HTMLElement): void {
|
public render(container: HTMLElement): void {
|
||||||
if (!this.qp) {
|
if (!this.qp) {
|
||||||
@@ -47,6 +52,20 @@ export class QueryPlanView implements IPanelView {
|
|||||||
} else {
|
} else {
|
||||||
this.xml = xml;
|
this.xml = xml;
|
||||||
}
|
}
|
||||||
|
if (this.state) {
|
||||||
|
this.state.xml = xml;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public set state(val: QueryPlanState) {
|
||||||
|
this._state = val;
|
||||||
|
if (this.state.xml) {
|
||||||
|
this.showPlan(this.state.xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): QueryPlanState {
|
||||||
|
return this._state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
src/sql/sqlops.d.ts
vendored
5
src/sql/sqlops.d.ts
vendored
@@ -185,6 +185,11 @@ declare module 'sqlops' {
|
|||||||
* Get the parent node. Returns undefined if there is none.
|
* Get the parent node. Returns undefined if there is none.
|
||||||
*/
|
*/
|
||||||
getParent(): Thenable<ObjectExplorerNode>;
|
getParent(): Thenable<ObjectExplorerNode>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the node, expanding it if it has children
|
||||||
|
*/
|
||||||
|
refresh(): Thenable<void>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ExtHostObjectExplorerShape, SqlMainContext, MainThreadObjectExplorerSha
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape {
|
export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape {
|
||||||
|
|
||||||
private _proxy: MainThreadObjectExplorerShape;
|
private _proxy: MainThreadObjectExplorerShape;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerN
|
|||||||
public errorMessage: string;
|
public errorMessage: string;
|
||||||
|
|
||||||
constructor(nodeInfo: sqlops.NodeInfo, connectionId: string, private _proxy: MainThreadObjectExplorerShape) {
|
constructor(nodeInfo: sqlops.NodeInfo, connectionId: string, private _proxy: MainThreadObjectExplorerShape) {
|
||||||
Object.entries(nodeInfo).forEach(([key, value]) => this[key] = value);
|
this.getDetailsFromInfo(nodeInfo);
|
||||||
this.connectionId = connectionId;
|
this.connectionId = connectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,4 +71,12 @@ class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerN
|
|||||||
}
|
}
|
||||||
return this._proxy.$getNode(this.connectionId, this.nodePath.slice(0, parentPathEndIndex)).then(nodeInfo => nodeInfo ? new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy) : undefined);
|
return this._proxy.$getNode(this.connectionId, this.nodePath.slice(0, parentPathEndIndex)).then(nodeInfo => nodeInfo ? new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy) : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh(): Thenable<void> {
|
||||||
|
return this._proxy.$refresh(this.connectionId, this.nodePath).then(nodeInfo => this.getDetailsFromInfo(nodeInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDetailsFromInfo(nodeInfo: sqlops.NodeInfo): void {
|
||||||
|
Object.entries(nodeInfo).forEach(([key, value]) => this[key] = value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
|
|||||||
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
|
|
||||||
@extHostNamedCustomer(SqlMainContext.MainThreadObjectExplorer)
|
@extHostNamedCustomer(SqlMainContext.MainThreadObjectExplorer)
|
||||||
export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
|
export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
|
||||||
@@ -50,7 +51,7 @@ export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
|
|||||||
public $getActiveConnectionNodes(): Thenable<NodeInfoWithConnection[]> {
|
public $getActiveConnectionNodes(): Thenable<NodeInfoWithConnection[]> {
|
||||||
let connectionNodes = this._objectExplorerService.getActiveConnectionNodes();
|
let connectionNodes = this._objectExplorerService.getActiveConnectionNodes();
|
||||||
return Promise.resolve(connectionNodes.map(node => {
|
return Promise.resolve(connectionNodes.map(node => {
|
||||||
return {connectionId: node.connection.id, nodeInfo: node.toNodeInfo()};
|
return { connectionId: node.connection.id, nodeInfo: node.toNodeInfo() };
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,4 +74,8 @@ export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
|
|||||||
public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]> {
|
public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]> {
|
||||||
return this._objectExplorerService.findNodes(connectionId, type, schema, name, database, parentObjectNames);
|
return this._objectExplorerService.findNodes(connectionId, type, schema, name, database, parentObjectNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo> {
|
||||||
|
return this._objectExplorerService.refreshNodeInView(connectionId, nodePath).then(node => node.toNodeInfo());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export abstract class ExtHostAccountManagementShape {
|
|||||||
|
|
||||||
export abstract class ExtHostConnectionManagementShape {
|
export abstract class ExtHostConnectionManagementShape {
|
||||||
$onConnectionOpened(handleId: string, connection: sqlops.connection.Connection): void { throw ni; }
|
$onConnectionOpened(handleId: string, connection: sqlops.connection.Connection): void { throw ni; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ExtHostDataProtocolShape {
|
export abstract class ExtHostDataProtocolShape {
|
||||||
|
|
||||||
@@ -663,6 +663,7 @@ export interface MainThreadObjectExplorerShape extends IDisposable {
|
|||||||
$getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>;
|
$getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>;
|
||||||
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
|
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
|
||||||
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
|
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
|
||||||
|
$refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtHostModelViewDialogShape {
|
export interface ExtHostModelViewDialogShape {
|
||||||
|
|||||||
@@ -301,7 +301,8 @@ suite('SQL Object Explorer Service tests', () => {
|
|||||||
reveal: element => Promise.resolve() as Thenable<void>,
|
reveal: element => Promise.resolve() as Thenable<void>,
|
||||||
setSelected: (element, selected, clearOtherSelections) => undefined,
|
setSelected: (element, selected, clearOtherSelections) => undefined,
|
||||||
isExpanded: element => undefined,
|
isExpanded: element => undefined,
|
||||||
onSelectionOrFocusChange: Event.None
|
onSelectionOrFocusChange: Event.None,
|
||||||
|
refreshElement: (element) => Promise.resolve() as Thenable<void>
|
||||||
} as ServerTreeView);
|
} as ServerTreeView);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -738,4 +739,22 @@ suite('SQL Object Explorer Service tests', () => {
|
|||||||
}, err => done(err));
|
}, err => done(err));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('refreshInView refreshes the node, expands it, and returns the refreshed node', async () => {
|
||||||
|
// Set up the session and tree view
|
||||||
|
await objectExplorerService.createNewSession('MSSQL', connection);
|
||||||
|
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||||
|
serverTreeView.setup(x => x.refreshElement(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||||
|
objectExplorerService.registerServerTreeView(serverTreeView.object);
|
||||||
|
|
||||||
|
// Refresh the node
|
||||||
|
let nodePath = objectExplorerSession.rootNode.nodePath;
|
||||||
|
let refreshedNode = await objectExplorerService.refreshNodeInView(connection.id, nodePath);
|
||||||
|
|
||||||
|
// Verify that it was refreshed, expanded, and the refreshed detailed were returned
|
||||||
|
sqlOEProvider.verify(x => x.refreshNode(TypeMoq.It.is(refreshNode => refreshNode.nodePath === nodePath)), TypeMoq.Times.once());
|
||||||
|
refreshedNode.children.forEach((childNode, index) => {
|
||||||
|
assert.equal(childNode.nodePath, objectExplorerExpandInfoRefresh.nodes[index].nodePath);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -28,6 +28,7 @@ import { ConnectionManagementService } from 'sql/parts/connection/common/connect
|
|||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
|
||||||
import { TestThemeService } from 'sqltest/stubs/themeTestService';
|
import { TestThemeService } from 'sqltest/stubs/themeTestService';
|
||||||
|
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
||||||
|
|
||||||
import * as TypeMoq from 'typemoq';
|
import * as TypeMoq from 'typemoq';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
@@ -40,6 +41,7 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
let editor: TypeMoq.Mock<QueryEditor>;
|
let editor: TypeMoq.Mock<QueryEditor>;
|
||||||
let calledRunQueryOnInput: boolean = undefined;
|
let calledRunQueryOnInput: boolean = undefined;
|
||||||
let testQueryInput: TypeMoq.Mock<QueryInput>;
|
let testQueryInput: TypeMoq.Mock<QueryInput>;
|
||||||
|
let configurationService: TypeMoq.Mock<ConfigurationService>;
|
||||||
|
|
||||||
setup(() => {
|
setup(() => {
|
||||||
// Setup a reusable mock QueryInput
|
// Setup a reusable mock QueryInput
|
||||||
@@ -56,6 +58,13 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
editor.setup(x => x.getSelection()).returns(() => undefined);
|
editor.setup(x => x.getSelection()).returns(() => undefined);
|
||||||
editor.setup(x => x.getSelection(false)).returns(() => undefined);
|
editor.setup(x => x.getSelection(false)).returns(() => undefined);
|
||||||
editor.setup(x => x.isSelectionEmpty()).returns(() => false);
|
editor.setup(x => x.isSelectionEmpty()).returns(() => false);
|
||||||
|
configurationService = TypeMoq.Mock.ofInstance({
|
||||||
|
getValue: () => undefined,
|
||||||
|
onDidChangeConfiguration: () => undefined
|
||||||
|
} as any);
|
||||||
|
configurationService.setup(x => x.getValue(TypeMoq.It.isAny())).returns(() => {
|
||||||
|
return {};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('setClass sets child CSS class correctly', (done) => {
|
test('setClass sets child CSS class correctly', (done) => {
|
||||||
@@ -463,7 +472,7 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// If I query without having initialized anything, state should be clear
|
// If I query without having initialized anything, state should be clear
|
||||||
listItem = new ListDatabasesActionItem(editor.object, undefined, connectionManagementService.object, undefined, undefined, undefined);
|
listItem = new ListDatabasesActionItem(editor.object, undefined, connectionManagementService.object, undefined, undefined, undefined, configurationService.object);
|
||||||
|
|
||||||
assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected');
|
assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected');
|
||||||
assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected');
|
assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected');
|
||||||
@@ -498,7 +507,7 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
|
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
|
||||||
|
|
||||||
// ... Create a database dropdown that has been connected
|
// ... Create a database dropdown that has been connected
|
||||||
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null);
|
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null, configurationService.object);
|
||||||
listItem.onConnected();
|
listItem.onConnected();
|
||||||
|
|
||||||
// If: I raise a connection changed event
|
// If: I raise a connection changed event
|
||||||
@@ -522,7 +531,7 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
|
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
|
||||||
|
|
||||||
// ... Create a database dropdown that has been connected
|
// ... Create a database dropdown that has been connected
|
||||||
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null);
|
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null, configurationService.object);
|
||||||
listItem.onConnected();
|
listItem.onConnected();
|
||||||
|
|
||||||
// If: I raise a connection changed event for the 'wrong' URI
|
// If: I raise a connection changed event for the 'wrong' URI
|
||||||
@@ -549,7 +558,7 @@ suite('SQL QueryAction Tests', () => {
|
|||||||
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
|
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
|
||||||
|
|
||||||
// ... Create a database dropdown
|
// ... Create a database dropdown
|
||||||
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null);
|
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null, configurationService.object);
|
||||||
|
|
||||||
// If: I raise a connection changed event
|
// If: I raise a connection changed event
|
||||||
let eventParams = <IConnectionParams>{
|
let eventParams = <IConnectionParams>{
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => {
|
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => {
|
||||||
if (classDef.ID) {
|
if (classDef.ID) {
|
||||||
if (classDef.ID === 'listDatabaseQueryActionItem') {
|
if (classDef.ID === 'listDatabaseQueryActionItem') {
|
||||||
return new ListDatabasesActionItem(editor, action, connectionManagementService.object, undefined, undefined, undefined);
|
return new ListDatabasesActionItem(editor, action, connectionManagementService.object, undefined, undefined, undefined, configurationService.object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Default
|
// Default
|
||||||
@@ -344,7 +344,7 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
.returns((definition, editor, action, selectBox) => {
|
.returns((definition, editor, action, selectBox) => {
|
||||||
if (definition.ID === 'listDatabaseQueryActionItem') {
|
if (definition.ID === 'listDatabaseQueryActionItem') {
|
||||||
let item = new ListDatabasesActionItem(editor, action, queryConnectionService.object, undefined, undefined, undefined);
|
let item = new ListDatabasesActionItem(editor, action, queryConnectionService.object, undefined, undefined, undefined,configurationService.object);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
// Default
|
// Default
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ function main() {
|
|||||||
'bootstrap': `../${ out }/bootstrap`
|
'bootstrap': `../${ out }/bootstrap`
|
||||||
},
|
},
|
||||||
catchError: true,
|
catchError: true,
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
nodeModules: [
|
nodeModules: [
|
||||||
'@angular/common',
|
'@angular/common',
|
||||||
'@angular/core',
|
'@angular/core',
|
||||||
@@ -70,6 +70,7 @@ function main() {
|
|||||||
'@angular/platform-browser-dynamic',
|
'@angular/platform-browser-dynamic',
|
||||||
'@angular/router',
|
'@angular/router',
|
||||||
'angular2-grid',
|
'angular2-grid',
|
||||||
|
'ng2-charts/ng2-charts',
|
||||||
'rxjs/add/observable/of',
|
'rxjs/add/observable/of',
|
||||||
'rxjs/Observable',
|
'rxjs/Observable',
|
||||||
'rxjs/Subject',
|
'rxjs/Subject',
|
||||||
|
|||||||
@@ -6111,9 +6111,9 @@ slice-ansi@0.0.4:
|
|||||||
version "0.0.4"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
||||||
|
|
||||||
"slickgrid@github:anthonydresser/SlickGrid#2.3.25":
|
"slickgrid@github:anthonydresser/SlickGrid#2.3.27":
|
||||||
version "2.3.25"
|
version "2.3.27"
|
||||||
resolved "https://codeload.github.com/anthonydresser/SlickGrid/tar.gz/5fa498a3df7ed671958bedeac1863c41352c7825"
|
resolved "https://codeload.github.com/anthonydresser/SlickGrid/tar.gz/712a59307942c8fdb18708b6d1a501880a74db8d"
|
||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.8.0"
|
jquery ">=1.8.0"
|
||||||
jquery-ui ">=1.8.0"
|
jquery-ui ">=1.8.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user