mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 17:23:56 -05:00
Merge remote-tracking branch 'origin/master' into feature/nativeNotebook
This commit is contained in:
@@ -27,6 +27,7 @@ export class Checkbox extends Widget {
|
||||
|
||||
this._el = document.createElement('input');
|
||||
this._el.type = 'checkbox';
|
||||
this._el.style.verticalAlign = 'middle';
|
||||
|
||||
if (opts.ariaLabel) {
|
||||
this._el.setAttribute('aria-label', opts.ariaLabel);
|
||||
@@ -44,6 +45,7 @@ export class Checkbox extends Widget {
|
||||
});
|
||||
|
||||
this._label = document.createElement('span');
|
||||
this._label.style.verticalAlign = 'middle';
|
||||
|
||||
this.label = opts.label;
|
||||
this.enabled = opts.enabled || true;
|
||||
|
||||
@@ -167,17 +167,20 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal.flyout-dialog .dialog-message.error {
|
||||
.vs .modal.flyout-dialog .dialog-message.error,
|
||||
.vs-dark .modal.flyout-dialog .dialog-message.error {
|
||||
background-color:#B62E00 !important;
|
||||
color:#FFFFFF !important;
|
||||
}
|
||||
|
||||
.modal.flyout-dialog .dialog-message.warning {
|
||||
.vs .modal.flyout-dialog .dialog-message.warning,
|
||||
.vs-dark .modal.flyout-dialog .dialog-message.warning {
|
||||
background-color:#F9E385 !important;
|
||||
color:#4A4A4A !important;
|
||||
}
|
||||
|
||||
.modal.flyout-dialog .dialog-message.info {
|
||||
.vs .modal.flyout-dialog .dialog-message.info,
|
||||
.vs-dark .modal.flyout-dialog .dialog-message.info {
|
||||
background-color:#0078D7 !important;
|
||||
color:#FFFFFF !important;
|
||||
}
|
||||
@@ -243,6 +246,7 @@
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.hc-black .dialog-message.warning .close-message-icon,
|
||||
.close-message-icon {
|
||||
background: url('close_inverse.svg') center center no-repeat;
|
||||
}
|
||||
@@ -251,6 +255,7 @@
|
||||
background: url('close.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .dialog-message.warning .copy-message-icon,
|
||||
.copy-message-icon {
|
||||
background: url('copy_inverse.svg') center center no-repeat;
|
||||
}
|
||||
@@ -259,6 +264,7 @@
|
||||
background: url('copy.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .dialog-message.warning .message-details-icon,
|
||||
.message-details-icon {
|
||||
background: url('show_details_inverse.svg') center center no-repeat;
|
||||
}
|
||||
@@ -271,6 +277,10 @@
|
||||
background: url('info_notification_inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .dialog-message.warning .dialog-message-icon {
|
||||
background: url('warning_notification_inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.dialog-message.warning .dialog-message-icon {
|
||||
background: url('warning_notification.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import 'vs/css!./media/modal';
|
||||
import { IThemable } from 'vs/platform/theme/common/styler';
|
||||
import { IThemable, attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
@@ -23,6 +23,7 @@ import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
||||
import { localize } from 'vs/nls';
|
||||
import { MessageLevel } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import * as os from 'os';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export const MODAL_SHOWING_KEY = 'modalShowing';
|
||||
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
||||
@@ -153,6 +154,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
||||
private _partService: IPartService,
|
||||
private _telemetryService: ITelemetryService,
|
||||
protected _clipboardService: IClipboardService,
|
||||
protected _themeService: IThemeService,
|
||||
_contextKeyService: IContextKeyService,
|
||||
options?: IModalOptions
|
||||
) {
|
||||
@@ -228,6 +230,10 @@ export abstract class Modal extends Disposable implements IThemable {
|
||||
this.setError(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
attachButtonStyler(this._toggleMessageDetailButton, this._themeService);
|
||||
attachButtonStyler(this._copyMessageButton, this._themeService);
|
||||
attachButtonStyler(this._closeMessageButton, this._themeService);
|
||||
});
|
||||
messageContainer.div({ class: 'dialog-message-body' }, (messageBody) => {
|
||||
messageBody.div({ class: 'dialog-message-summary' }, (summaryContainer) => {
|
||||
@@ -601,6 +607,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
||||
this._modalDialog.style('border-style', border ? 'solid' : null);
|
||||
this._modalDialog.style('border-color', border);
|
||||
}
|
||||
|
||||
if (this._modalHeaderSection) {
|
||||
this._modalHeaderSection.style('background-color', headerAndFooterBackground);
|
||||
this._modalHeaderSection.style('border-bottom-width', border ? '1px' : null);
|
||||
@@ -608,6 +615,13 @@ export abstract class Modal extends Disposable implements IThemable {
|
||||
this._modalHeaderSection.style('border-bottom-color', border);
|
||||
}
|
||||
|
||||
if (this._modalMessageSection) {
|
||||
this._modalMessageSection.style('background-color', headerAndFooterBackground);
|
||||
this._modalMessageSection.style('border-bottom-width', border ? '1px' : null);
|
||||
this._modalMessageSection.style('border-bottom-style', border ? 'solid' : null);
|
||||
this._modalMessageSection.style('border-bottom-color', border);
|
||||
}
|
||||
|
||||
if (this._modalBodySection) {
|
||||
this._modalBodySection.style.backgroundColor = bodyBackground;
|
||||
}
|
||||
|
||||
@@ -93,13 +93,13 @@ export class OptionsDialog extends Modal {
|
||||
name: string,
|
||||
options: IModalOptions,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(title, name, partService, telemetryService, clipboardService, contextKeyService, options);
|
||||
super(title, name, partService, telemetryService, clipboardService, _workbenchThemeService, contextKeyService, options);
|
||||
}
|
||||
|
||||
public render() {
|
||||
@@ -115,8 +115,8 @@ export class OptionsDialog extends Modal {
|
||||
attachButtonStyler(this._okButton, this._themeService);
|
||||
attachButtonStyler(this._closeButton, this._themeService);
|
||||
let self = this;
|
||||
this._register(self._themeService.onDidColorThemeChange(e => self.updateTheme(e)));
|
||||
self.updateTheme(self._themeService.getColorTheme());
|
||||
this._register(self._workbenchThemeService.onDidColorThemeChange(e => self.updateTheme(e)));
|
||||
self.updateTheme(self._workbenchThemeService.getColorTheme());
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement) {
|
||||
|
||||
@@ -45,7 +45,7 @@ export class WebViewDialog extends Modal {
|
||||
protected findInputFocusContextKey: IContextKey<boolean>;
|
||||
|
||||
constructor(
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
@IPartService private _webViewPartService: IPartService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -54,7 +54,7 @@ export class WebViewDialog extends Modal {
|
||||
@IEnvironmentService private _environmentService: IEnvironmentService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService
|
||||
) {
|
||||
super('', TelemetryKeys.WebView, _webViewPartService, telemetryService, clipboardService, contextKeyService, { isFlyout: false, hasTitleIcon: true });
|
||||
super('', TelemetryKeys.WebView, _webViewPartService, telemetryService, clipboardService, themeService, contextKeyService, { isFlyout: false, hasTitleIcon: true });
|
||||
this._okLabel = localize('webViewDialog.ok', 'OK');
|
||||
this._closeLabel = localize('webViewDialog.close', 'Close');
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class TabbedPanel extends Disposable implements IThemable {
|
||||
|
||||
private tabHistory: string[] = [];
|
||||
|
||||
constructor(private container: HTMLElement, private options: IPanelOptions = defaultOptions) {
|
||||
constructor(container: HTMLElement, private options: IPanelOptions = defaultOptions) {
|
||||
super();
|
||||
this.parent = $('.tabbedPanel');
|
||||
container.appendChild(this.parent);
|
||||
@@ -87,6 +87,13 @@ export class TabbedPanel extends Disposable implements IThemable {
|
||||
this.parent.appendChild(this.body);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.header.remove();
|
||||
this.tabList.remove();
|
||||
this.body.remove();
|
||||
this.parent.remove();
|
||||
}
|
||||
|
||||
public contains(tab: IPanelTab): boolean {
|
||||
return this._tabMap.has(tab.identifier);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,13 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen
|
||||
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
|
||||
import { ArrayIterator } from 'vs/base/common/iterator';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
|
||||
export interface ISplitViewOptions {
|
||||
orientation?: Orientation; // default Orientation.VERTICAL
|
||||
enableResizing?: boolean;
|
||||
verticalScrollbarVisibility?: ScrollbarVisibility;
|
||||
}
|
||||
|
||||
const defaultOptions: ISplitViewOptions = {
|
||||
@@ -127,7 +129,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
||||
this.options = mixin(options, defaultOptions, false);
|
||||
|
||||
this.el = document.createElement('div');
|
||||
this.scrollable = new ScrollableElement(this.el, {});
|
||||
this.scrollable = new ScrollableElement(this.el, { vertical: options.verticalScrollbarVisibility });
|
||||
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => {
|
||||
this.render(e.scrollTop, e.height);
|
||||
this.relayout();
|
||||
|
||||
@@ -67,7 +67,7 @@ export class AccountDialog extends Modal {
|
||||
|
||||
constructor(
|
||||
@IPartService partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IListService private _listService: IListService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IContextMenuService private _contextMenuService: IContextMenuService,
|
||||
@@ -82,6 +82,7 @@ export class AccountDialog extends Modal {
|
||||
partService,
|
||||
telemetryService,
|
||||
clipboardService,
|
||||
themeService,
|
||||
contextKeyService,
|
||||
{ hasSpinner: true }
|
||||
);
|
||||
|
||||
@@ -43,7 +43,7 @@ export class AutoOAuthDialog extends Modal {
|
||||
|
||||
constructor(
|
||||
@IPartService partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@@ -55,6 +55,7 @@ export class AutoOAuthDialog extends Modal {
|
||||
partService,
|
||||
telemetryService,
|
||||
clipboardService,
|
||||
themeService,
|
||||
contextKeyService,
|
||||
{
|
||||
isFlyout: true,
|
||||
|
||||
@@ -65,7 +65,7 @@ export class FirewallRuleDialog extends Modal {
|
||||
constructor(
|
||||
@IAccountPickerService private _accountPickerService: IAccountPickerService,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -79,6 +79,7 @@ export class FirewallRuleDialog extends Modal {
|
||||
partService,
|
||||
telemetryService,
|
||||
clipboardService,
|
||||
_workbenchThemeService,
|
||||
contextKeyService,
|
||||
{
|
||||
isFlyout: true,
|
||||
@@ -205,8 +206,8 @@ export class FirewallRuleDialog extends Modal {
|
||||
builder.append(firewallRuleSection);
|
||||
});
|
||||
|
||||
this._register(this._themeService.onDidColorThemeChange(e => this.updateTheme(e)));
|
||||
this.updateTheme(this._themeService.getColorTheme());
|
||||
this._register(this._workbenchThemeService.onDidColorThemeChange(e => this.updateTheme(e)));
|
||||
this.updateTheme(this._workbenchThemeService.getColorTheme());
|
||||
|
||||
$(this._IPAddressInput).on(DOM.EventType.CLICK, () => {
|
||||
this.onFirewallRuleOptionSelected(true);
|
||||
|
||||
@@ -23,9 +23,7 @@ export class ConnectionStatusbarItem implements IStatusbarItem {
|
||||
|
||||
constructor(
|
||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private _editorService: EditorServiceImpl,
|
||||
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export function parseTimeString(value: string): number | boolean {
|
||||
* @param value The number of milliseconds to convert to a timespan string
|
||||
* @returns A properly formatted timespan string.
|
||||
*/
|
||||
export function parseNumAsTimeString(value: number): string {
|
||||
export function parseNumAsTimeString(value: number, includeFraction: boolean = true): string {
|
||||
let tempVal = value;
|
||||
let h = Math.floor(tempVal / msInH);
|
||||
tempVal %= msInH;
|
||||
@@ -85,7 +85,7 @@ export function parseNumAsTimeString(value: number): string {
|
||||
|
||||
let rs = hs + ':' + ms + ':' + ss;
|
||||
|
||||
return tempVal > 0 ? rs + '.' + mss : rs;
|
||||
return tempVal > 0 && includeFraction ? rs + '.' + mss : rs;
|
||||
}
|
||||
|
||||
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
||||
|
||||
@@ -87,16 +87,32 @@ export class ConnectionDialogService implements IConnectionDialogService {
|
||||
@IClipboardService private _clipboardService: IClipboardService,
|
||||
@ICommandService private _commandService: ICommandService
|
||||
) { }
|
||||
|
||||
private getDefaultProviderName() {
|
||||
/**
|
||||
* Gets the default provider with the following actions
|
||||
* 1. Checks if master provider(map) has data
|
||||
* 2. If so, filters provider paramter against master map
|
||||
* 3. Fetches the result array and extracts the first element
|
||||
* 4. If none of the above data exists, returns 'MSSQL'
|
||||
* @returns: Default provider as string
|
||||
*/
|
||||
private getDefaultProviderName(): string {
|
||||
let defaultProvider: string;
|
||||
if (this._providerNameToDisplayNameMap) {
|
||||
let keys = Object.keys(this._providerNameToDisplayNameMap);
|
||||
let filteredKeys: string[];
|
||||
if (keys && keys.length > 0) {
|
||||
defaultProvider = keys[0];
|
||||
if (this._params && this._params.providers && this._params.providers.length > 0) {
|
||||
//Filter providers from master keys.
|
||||
filteredKeys = keys.filter(key => this._params.providers.includes(key));
|
||||
}
|
||||
if (filteredKeys && filteredKeys.length > 0) {
|
||||
defaultProvider = filteredKeys[0];
|
||||
}
|
||||
else {
|
||||
defaultProvider = keys[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!defaultProvider && this._workspaceConfigurationService) {
|
||||
defaultProvider = WorkbenchUtils.getSqlConfigValue<string>(this._workspaceConfigurationService, Constants.defaultEngine);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export class ConnectionDialogWidget extends Modal {
|
||||
private providerNameToDisplayNameMap: { [providerDisplayName: string]: string },
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
|
||||
@IPartService _partService: IPartService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@@ -96,7 +96,7 @@ export class ConnectionDialogWidget extends Modal {
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(localize('connection', 'Connection'), TelemetryKeys.Connection, _partService, telemetryService, clipboardService, contextKeyService, { hasSpinner: true, hasErrors: true });
|
||||
super(localize('connection', 'Connection'), TelemetryKeys.Connection, _partService, telemetryService, clipboardService, _workbenchThemeService, contextKeyService, { hasSpinner: true, hasErrors: true });
|
||||
}
|
||||
|
||||
public refresh(): void {
|
||||
@@ -194,8 +194,8 @@ export class ConnectionDialogWidget extends Modal {
|
||||
this.$connectionUIContainer.appendTo(this._bodyBuilder);
|
||||
|
||||
let self = this;
|
||||
this._register(self._themeService.onDidColorThemeChange(e => self.updateTheme(e)));
|
||||
self.updateTheme(self._themeService.getColorTheme());
|
||||
this._register(self._workbenchThemeService.onDidColorThemeChange(e => self.updateTheme(e)));
|
||||
self.updateTheme(self._workbenchThemeService.getColorTheme());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,7 +83,7 @@ export class ConnectionWidget {
|
||||
};
|
||||
public NoneServerGroup: IConnectionProfileGroup = {
|
||||
id: '',
|
||||
name: localize('noneServerGroup', '<None>'),
|
||||
name: localize('noneServerGroup', '<Do not save>'),
|
||||
parentId: undefined,
|
||||
color: undefined,
|
||||
description: undefined,
|
||||
|
||||
@@ -120,7 +120,7 @@ export class NewDashboardTabDialog extends Modal {
|
||||
|
||||
constructor(
|
||||
@IPartService partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IListService private _listService: IListService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IContextMenuService private _contextMenuService: IContextMenuService,
|
||||
@@ -135,6 +135,7 @@ export class NewDashboardTabDialog extends Modal {
|
||||
partService,
|
||||
telemetryService,
|
||||
clipboardService,
|
||||
themeService,
|
||||
contextKeyService,
|
||||
{ hasSpinner: true }
|
||||
);
|
||||
|
||||
@@ -10,10 +10,9 @@ import * as TelemetryUtils from 'sql/common/telemetryUtilities';
|
||||
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { memoize, unmemoize } from 'sql/base/common/decorators';
|
||||
import { mixin } from 'sql/base/common/objects';
|
||||
import { LegendPosition, DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { LegendPosition, ChartType, defaultChartConfig, IChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
@@ -22,51 +21,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
declare var Chart: any;
|
||||
|
||||
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
|
||||
if (types.isObject(source)) {
|
||||
mixin(destination, source, overwrite, customMixin);
|
||||
} else if (types.isArray(source)) {
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
if (destination[i]) {
|
||||
mixin(destination[i], source[i], overwrite, customMixin);
|
||||
} else {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
destination = source;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
export interface IDataSet {
|
||||
data: Array<number>;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface IPointDataSet {
|
||||
data: Array<{ x: number | string, y: number }>;
|
||||
label?: string;
|
||||
fill: boolean;
|
||||
backgroundColor?: Color;
|
||||
}
|
||||
|
||||
export interface IChartConfig {
|
||||
colorMap?: { [column: string]: string };
|
||||
labelFirstColumn?: boolean;
|
||||
legendPosition?: LegendPosition;
|
||||
dataDirection?: DataDirection;
|
||||
columnsAsLabels?: boolean;
|
||||
showTopNData?: number;
|
||||
}
|
||||
|
||||
export const defaultChartConfig: IChartConfig = {
|
||||
labelFirstColumn: true,
|
||||
columnsAsLabels: true,
|
||||
legendPosition: LegendPosition.Top,
|
||||
dataDirection: DataDirection.Vertical
|
||||
};
|
||||
|
||||
@Component({
|
||||
template: ` <div style="display: block; width: 100%; height: 100%; position: relative">
|
||||
<canvas #canvas *ngIf="_isDataAvailable && _hasInit"
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import * as types from 'vs/base/common/types';
|
||||
|
||||
import { mixin } from 'sql/base/common/objects';
|
||||
|
||||
export enum ChartType {
|
||||
Bar = 'bar',
|
||||
Doughnut = 'doughnut',
|
||||
@@ -29,4 +34,49 @@ export enum LegendPosition {
|
||||
export enum DataType {
|
||||
Number = 'number',
|
||||
Point = 'point'
|
||||
}
|
||||
}
|
||||
|
||||
export function customMixin(destination: any, source: any, overwrite?: boolean): any {
|
||||
if (types.isObject(source)) {
|
||||
mixin(destination, source, overwrite, customMixin);
|
||||
} else if (types.isArray(source)) {
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
if (destination[i]) {
|
||||
mixin(destination[i], source[i], overwrite, customMixin);
|
||||
} else {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
destination = source;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
export interface IDataSet {
|
||||
data: Array<number>;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface IPointDataSet {
|
||||
data: Array<{ x: number | string, y: number }>;
|
||||
label?: string;
|
||||
fill: boolean;
|
||||
backgroundColor?: Color;
|
||||
}
|
||||
|
||||
export interface IChartConfig {
|
||||
colorMap?: { [column: string]: string };
|
||||
labelFirstColumn?: boolean;
|
||||
legendPosition?: LegendPosition;
|
||||
dataDirection?: DataDirection;
|
||||
columnsAsLabels?: boolean;
|
||||
showTopNData?: number;
|
||||
}
|
||||
|
||||
export const defaultChartConfig: IChartConfig = {
|
||||
labelFirstColumn: true,
|
||||
columnsAsLabels: true,
|
||||
legendPosition: LegendPosition.Top,
|
||||
dataDirection: DataDirection.Vertical
|
||||
};
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ChartInsight, customMixin, IChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||
import { ChartInsight } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||
import { mixin } from 'sql/base/common/objects';
|
||||
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, IChartConfig, customMixin } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
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 { memoize, unmemoize } from 'sql/base/common/decorators';
|
||||
import { clone } from 'sql/base/common/objects';
|
||||
import { ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, DataType, defaultChartConfig, IDataSet, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
export interface ILineConfig extends IBarChartConfig {
|
||||
dataType?: DataType;
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { defaultChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||
import LineChart, { ILineConfig } from './lineChart.component';
|
||||
import { clone } from 'sql/base/common/objects';
|
||||
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, defaultChartConfig } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { defaultChartConfig, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/chartInsight.component';
|
||||
import LineChart, { ILineConfig } from './lineChart.component';
|
||||
import { clone } from 'sql/base/common/objects';
|
||||
import { ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, defaultChartConfig, IPointDataSet } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
|
||||
@@ -27,7 +27,7 @@ export class BackupDialog extends Modal {
|
||||
private _moduleRef: any;
|
||||
|
||||
constructor(
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IPartService partService: IPartService,
|
||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -35,7 +35,7 @@ export class BackupDialog extends Modal {
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super('', TelemetryKeys.Backup, partService, telemetryService, clipboardService, contextKeyService, { isAngular: true, hasErrors: true });
|
||||
super('', TelemetryKeys.Backup, partService, telemetryService, clipboardService, themeService, contextKeyService, { isAngular: true, hasErrors: true });
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement) {
|
||||
|
||||
@@ -130,14 +130,14 @@ export class RestoreDialog extends Modal {
|
||||
constructor(
|
||||
optionsMetadata: sqlops.ServiceOption[],
|
||||
@IPartService partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IFileBrowserDialogController private fileBrowserDialogService: IFileBrowserDialogController,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(localize('RestoreDialogTitle', 'Restore database'), TelemetryKeys.Restore, partService, telemetryService, clipboardService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true });
|
||||
super(localize('RestoreDialogTitle', 'Restore database'), TelemetryKeys.Restore, partService, telemetryService, clipboardService, themeService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true });
|
||||
this._restoreTitle = localize('restoreDialog.restoreTitle', 'Restore database');
|
||||
this._databaseTitle = localize('restoreDialog.database', 'Database');
|
||||
this._backupFileTitle = localize('restoreDialog.backupFile', 'Backup file');
|
||||
|
||||
@@ -53,14 +53,14 @@ export class FileBrowserDialog extends Modal {
|
||||
|
||||
constructor(title: string,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService private _workbenchthemeService: IWorkbenchThemeService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(title, TelemetryKeys.Backup, partService, telemetryService, clipboardService, contextKeyService, { isFlyout: true, hasTitleIcon: false, hasBackButton: true, hasSpinner: true });
|
||||
super(title, TelemetryKeys.Backup, partService, telemetryService, clipboardService, _workbenchthemeService, contextKeyService, { isFlyout: true, hasTitleIcon: false, hasBackButton: true, hasSpinner: true });
|
||||
this._viewModel = this._instantiationService.createInstance(FileBrowserViewModel);
|
||||
this._viewModel.onAddFileTree(args => this.handleOnAddFileTree(args.rootNode, args.selectedNode, args.expandedNodes));
|
||||
this._viewModel.onPathValidate(args => this.handleOnValidate(args.succeeded, args.message));
|
||||
@@ -238,7 +238,7 @@ export class FileBrowserDialog extends Modal {
|
||||
this._register(attachButtonStyler(this._okButton, this._themeService));
|
||||
this._register(attachButtonStyler(this._cancelButton, this._themeService));
|
||||
|
||||
this._register(this._themeService.onDidColorThemeChange(e => this.updateTheme()));
|
||||
this._register(this._workbenchthemeService.onDidColorThemeChange(e => this.updateTheme()));
|
||||
}
|
||||
|
||||
// Update theming that is specific to file browser
|
||||
|
||||
@@ -125,7 +125,7 @@ export class InsightsDialogView extends Modal {
|
||||
constructor(
|
||||
private _model: IInsightsDialogModel,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IListService private _listService: IListService,
|
||||
@IPartService partService: IPartService,
|
||||
@IContextMenuService private _contextMenuService: IContextMenuService,
|
||||
@@ -135,7 +135,7 @@ export class InsightsDialogView extends Modal {
|
||||
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(nls.localize("InsightsDialogTitle", "Insights"), TelemetryKeys.Insights, partService, telemetryService, clipboardService, contextKeyService);
|
||||
super(nls.localize("InsightsDialogTitle", "Insights"), TelemetryKeys.Insights, partService, telemetryService, clipboardService, themeService, contextKeyService);
|
||||
this._model.onDataChange(e => this.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import * as sqlops from 'sqlops';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { JobCacheObject } from './jobManagementService';
|
||||
import { JobCacheObject, AlertsCacheObject, ProxiesCacheObject, OperatorsCacheObject } from './jobManagementService';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
||||
export const SERVICE_ID = 'jobManagementService';
|
||||
@@ -39,6 +39,10 @@ export interface IJobManagementService {
|
||||
getCredentials(connectionUri: string): Thenable<sqlops.GetCredentialsResult>;
|
||||
|
||||
jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus>;
|
||||
addToCache(server: string, cache: JobCacheObject);
|
||||
addToCache(server: string, cache: JobCacheObject | OperatorsCacheObject);
|
||||
jobCacheObjectMap: { [server: string]: JobCacheObject; };
|
||||
operatorsCacheObjectMap: { [server: string]: OperatorsCacheObject; };
|
||||
alertsCacheObjectMap: { [server: string]: AlertsCacheObject; };
|
||||
proxiesCacheObjectMap: {[server: string]: ProxiesCacheObject };
|
||||
addToCache(server: string, cache: JobCacheObject | ProxiesCacheObject | AlertsCacheObject | OperatorsCacheObject);
|
||||
}
|
||||
@@ -19,7 +19,10 @@ export class JobManagementService implements IJobManagementService {
|
||||
public readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
private _providers: { [handle: string]: sqlops.AgentServicesProvider; } = Object.create(null);
|
||||
private _jobCacheObject : {[server: string]: JobCacheObject; } = {};
|
||||
private _jobCacheObjectMap : {[server: string]: JobCacheObject; } = {};
|
||||
private _operatorsCacheObjectMap: {[server: string]: OperatorsCacheObject; } = {};
|
||||
private _alertsCacheObject: {[server: string]: AlertsCacheObject; } = {};
|
||||
private _proxiesCacheObjectMap: {[server: string]: ProxiesCacheObject; } = {};
|
||||
|
||||
constructor(
|
||||
@IConnectionManagementService private _connectionService: IConnectionManagementService
|
||||
@@ -127,16 +130,36 @@ export class JobManagementService implements IJobManagementService {
|
||||
}
|
||||
|
||||
public get jobCacheObjectMap(): {[server: string]: JobCacheObject;} {
|
||||
return this._jobCacheObject;
|
||||
return this._jobCacheObjectMap;
|
||||
}
|
||||
|
||||
public addToCache(server: string, cacheObject: JobCacheObject) {
|
||||
this._jobCacheObject[server] = cacheObject;
|
||||
public get alertsCacheObjectMap(): {[server: string]: AlertsCacheObject; } {
|
||||
return this._alertsCacheObject;
|
||||
}
|
||||
|
||||
public get proxiesCacheObjectMap(): {[server: string]: ProxiesCacheObject; } {
|
||||
return this._proxiesCacheObjectMap;
|
||||
}
|
||||
|
||||
public get operatorsCacheObjectMap(): {[server: string]: OperatorsCacheObject} {
|
||||
return this._operatorsCacheObjectMap;
|
||||
}
|
||||
|
||||
public addToCache(server: string, cacheObject: JobCacheObject | OperatorsCacheObject | ProxiesCacheObject | AlertsCacheObject) {
|
||||
if (cacheObject instanceof JobCacheObject) {
|
||||
this._jobCacheObjectMap[server] = cacheObject;
|
||||
} else if (cacheObject instanceof OperatorsCacheObject) {
|
||||
this._operatorsCacheObjectMap[server] = cacheObject;
|
||||
} else if (cacheObject instanceof AlertsCacheObject) {
|
||||
this._alertsCacheObject[server] = cacheObject;
|
||||
} else if (cacheObject instanceof ProxiesCacheObject) {
|
||||
this._proxiesCacheObjectMap[server] = cacheObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server level caching of jobs/job histories
|
||||
* Server level caching of jobs/job histories and their views
|
||||
*/
|
||||
export class JobCacheObject {
|
||||
_serviceBrand: any;
|
||||
@@ -231,4 +254,117 @@ export class JobCacheObject {
|
||||
public setJobSchedules(jobID: string, value: sqlops.AgentJobScheduleInfo[]) {
|
||||
this._jobSchedules[jobID] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server level caching of Operators
|
||||
*/
|
||||
export class OperatorsCacheObject {
|
||||
_serviceBrand: any;
|
||||
private _operators: sqlops.AgentOperatorInfo[];
|
||||
private _dataView: Slick.Data.DataView<any>;
|
||||
private _serverName: string;
|
||||
|
||||
/** Getters */
|
||||
public get operators(): sqlops.AgentOperatorInfo[] {
|
||||
return this._operators;
|
||||
}
|
||||
|
||||
public get dataview(): Slick.Data.DataView<any> {
|
||||
return this._dataView;
|
||||
}
|
||||
|
||||
public get serverName(): string {
|
||||
return this._serverName;
|
||||
}
|
||||
|
||||
/** Setters */
|
||||
public set operators(value: sqlops.AgentOperatorInfo[]) {
|
||||
this._operators = value;
|
||||
}
|
||||
|
||||
public set dataview(value: Slick.Data.DataView<any>) {
|
||||
this._dataView = value;
|
||||
}
|
||||
|
||||
public set serverName(value: string) {
|
||||
this._serverName = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Server level caching of job alerts and the alerts view
|
||||
*/
|
||||
export class AlertsCacheObject {
|
||||
_serviceBrand: any;
|
||||
private _alerts: sqlops.AgentAlertInfo[];
|
||||
private _dataView: Slick.Data.DataView<any>;
|
||||
private _serverName: string;
|
||||
|
||||
/** Getters */
|
||||
public get alerts(): sqlops.AgentAlertInfo[] {
|
||||
return this._alerts;
|
||||
}
|
||||
|
||||
public get dataview(): Slick.Data.DataView<any> {
|
||||
return this._dataView;
|
||||
}
|
||||
|
||||
public get serverName(): string {
|
||||
return this._serverName;
|
||||
}
|
||||
|
||||
/** Setters */
|
||||
public set alerts(value: sqlops.AgentAlertInfo[]) {
|
||||
this._alerts = value;
|
||||
}
|
||||
|
||||
public set dataview(value: Slick.Data.DataView<any>) {
|
||||
this._dataView = value;
|
||||
}
|
||||
|
||||
public set serverName(value: string) {
|
||||
this._serverName = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Server level caching of job proxies and proxies view
|
||||
*/
|
||||
export class ProxiesCacheObject {
|
||||
_serviceBrand: any;
|
||||
private _proxies: sqlops.AgentProxyInfo[];
|
||||
private _dataView: Slick.Data.DataView<any>;
|
||||
private _serverName: string;
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
public get proxies(): sqlops.AgentProxyInfo[] {
|
||||
return this._proxies;
|
||||
}
|
||||
|
||||
public get dataview(): Slick.Data.DataView<any> {
|
||||
return this._dataView;
|
||||
}
|
||||
|
||||
public get serverName(): string {
|
||||
return this._serverName;
|
||||
}
|
||||
|
||||
/** Setters */
|
||||
|
||||
public set proxies(value: sqlops.AgentProxyInfo[]) {
|
||||
this._proxies = value;
|
||||
}
|
||||
|
||||
public set dataview(value: Slick.Data.DataView<any>) {
|
||||
this._dataView = value;
|
||||
}
|
||||
|
||||
public set serverName(value: string) {
|
||||
this._serverName = value;
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,16 @@ jobhistory-component {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#operatorsDiv .joboperatorsview-grid .slick-cell.l1.r1 .operatorview-operatornametext,
|
||||
#alertsDiv .jobalertsview-grid .slick-cell.l1.r1 .alertview-alertnametext,
|
||||
#proxiesDiv .jobproxiesview-grid .slick-cell.l1.r1 .proxyview-proxynametext {
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#jobsDiv .job-with-error {
|
||||
border-bottom: none;
|
||||
}
|
||||
@@ -390,4 +400,18 @@ jobsview-component .jobview-grid .slick-cell.error-row {
|
||||
|
||||
.overview-container > .overview-tab > label {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#operatorsDiv .operatorview-operatornameindicatorenabled,
|
||||
#alertsDiv .alertview-alertnameindicatorenabled,
|
||||
#proxiesDiv .proxyview-proxynameindicatorenabled {
|
||||
width: 5px;
|
||||
background: green;
|
||||
}
|
||||
|
||||
#operatorsDiv .operatorview-operatornameindicatordisabled,
|
||||
#alertsDiv .alertview-alertnameindicatordisabled,
|
||||
#proxiesDiv .proxyview-proxynameindicatordisabled {
|
||||
width: 5px;
|
||||
background: red;
|
||||
}
|
||||
@@ -30,9 +30,11 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||
import { AlertsCacheObject } from 'sql/parts/jobManagement/common/jobManagementService';
|
||||
import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowdetailview';
|
||||
|
||||
export const VIEW_SELECTOR: string = 'jobalertsview-component';
|
||||
export const ROW_HEIGHT: number = 30;
|
||||
export const ROW_HEIGHT: number = 45;
|
||||
|
||||
@Component({
|
||||
selector: VIEW_SELECTOR,
|
||||
@@ -42,11 +44,17 @@ export const ROW_HEIGHT: number = 30;
|
||||
export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
|
||||
private columns: Array<Slick.Column<any>> = [
|
||||
{ name: nls.localize('jobAlertColumns.name', 'Name'), field: 'name', width: 200, id: 'name' },
|
||||
{ name: nls.localize('jobAlertColumns.lastOccurrenceDate', 'Last Occurrence'), field: 'lastOccurrenceDate', width: 200, id: 'lastOccurrenceDate' },
|
||||
{ name: nls.localize('jobAlertColumns.enabled', 'Enabled'), field: 'enabled', width: 200, id: 'enabled' },
|
||||
{ name: nls.localize('jobAlertColumns.databaseName', 'Database Name'), field: 'databaseName', width: 200, id: 'databaseName' },
|
||||
{ name: nls.localize('jobAlertColumns.categoryName', 'Category Name'), field: 'categoryName', width: 200, id: 'categoryName' },
|
||||
{
|
||||
name: nls.localize('jobAlertColumns.name', 'Name'),
|
||||
field: 'name',
|
||||
formatter: (row, cell, value, columnDef, dataContext) => this.renderName(row, cell, value, columnDef, dataContext),
|
||||
width: 500,
|
||||
id: 'name'
|
||||
},
|
||||
{ name: nls.localize('jobAlertColumns.lastOccurrenceDate', 'Last Occurrence'), field: 'lastOccurrenceDate', width: 150, id: 'lastOccurrenceDate' },
|
||||
{ name: nls.localize('jobAlertColumns.enabled', 'Enabled'), field: 'enabled', width: 80, id: 'enabled' },
|
||||
{ name: nls.localize('jobAlertColumns.delayBetweenResponses', 'Delay Between Responses (in secs)'), field: 'delayBetweenResponses', width: 200, id: 'delayBetweenResponses' },
|
||||
{ name: nls.localize('jobAlertColumns.categoryName', 'Category Name'), field: 'categoryName', width: 250, id: 'categoryName' },
|
||||
];
|
||||
|
||||
private options: Slick.GridOptions<any> = {
|
||||
@@ -59,6 +67,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
|
||||
private dataView: any;
|
||||
private _isCloud: boolean;
|
||||
private _alertsCacheObject: AlertsCacheObject;
|
||||
|
||||
@ViewChild('jobalertsgrid') _gridEl: ElementRef;
|
||||
|
||||
@@ -78,6 +87,15 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
@Inject(IDashboardService) _dashboardService: IDashboardService) {
|
||||
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||
let alertsCacheObjectMap = this._jobManagementService.alertsCacheObjectMap;
|
||||
let alertsCache = alertsCacheObjectMap[this._serverName];
|
||||
if (alertsCache) {
|
||||
this._alertsCacheObject = alertsCache;
|
||||
} else {
|
||||
this._alertsCacheObject = new AlertsCacheObject();
|
||||
this._alertsCacheObject.serverName = this._serverName;
|
||||
this._jobManagementService.addToCache(this._serverName, this._alertsCacheObject);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(){
|
||||
@@ -92,44 +110,67 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
height = 0;
|
||||
}
|
||||
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
if (this._table) {
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
}
|
||||
}
|
||||
|
||||
onFirstVisible() {
|
||||
let self = this;
|
||||
let cached: boolean = false;
|
||||
if (this._alertsCacheObject.serverName === this._serverName) {
|
||||
if (this._alertsCacheObject.alerts && this._alertsCacheObject.alerts.length > 0) {
|
||||
cached = true;
|
||||
this.alerts = this._alertsCacheObject.alerts;
|
||||
}
|
||||
}
|
||||
|
||||
let columns = this.columns.map((column) => {
|
||||
column.rerenderOnResize = true;
|
||||
return column;
|
||||
});
|
||||
|
||||
this.dataView = new Slick.Data.DataView();
|
||||
|
||||
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
|
||||
let rowDetail = new RowDetailView({
|
||||
cssClass: '_detail_selector',
|
||||
useRowClick: false,
|
||||
panelRows: 1
|
||||
});
|
||||
columns.unshift(rowDetail.getColumnDefinition());
|
||||
$(this._gridEl.nativeElement).empty();
|
||||
$(this.actionBarContainer.nativeElement).empty();
|
||||
this.initActionBar();
|
||||
this._table = new Table(this._gridEl.nativeElement, {columns}, this.options);
|
||||
this._table.grid.setData(this.dataView, true);
|
||||
|
||||
this._register(this._table.onContextMenu(e => {
|
||||
self.openContextMenu(e);
|
||||
}));
|
||||
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getAlerts(ownerUri).then((result) => {
|
||||
if (result && result.alerts) {
|
||||
self.alerts = result.alerts;
|
||||
self.onAlertsAvailable(result.alerts);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
|
||||
// check for cached state
|
||||
if (cached && this._agentViewComponent.refresh !== true) {
|
||||
self.onAlertsAvailable(this.alerts);
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getAlerts(ownerUri).then((result) => {
|
||||
if (result && result.alerts) {
|
||||
self.alerts = result.alerts;
|
||||
self._alertsCacheObject.alerts = result.alerts;
|
||||
self.onAlertsAvailable(result.alerts);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onAlertsAvailable(alerts: sqlops.AgentAlertInfo[]) {
|
||||
@@ -139,7 +180,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
name: item.name,
|
||||
lastOccurrenceDate: item.lastOccurrenceDate,
|
||||
enabled: item.isEnabled,
|
||||
databaseName: item.databaseName,
|
||||
delayBetweenResponses: item.delayBetweenResponses,
|
||||
categoryName: item.categoryName
|
||||
};
|
||||
});
|
||||
@@ -147,6 +188,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
this.dataView.beginUpdate();
|
||||
this.dataView.setItems(items);
|
||||
this.dataView.endUpdate();
|
||||
this._alertsCacheObject.dataview = this.dataView;
|
||||
this._table.autosizeColumns();
|
||||
this._table.resizeCanvas();
|
||||
}
|
||||
@@ -164,6 +206,17 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
|
||||
private renderName(row, cell, value, columnDef, dataContext) {
|
||||
let resultIndicatorClass = dataContext.enabled ? 'alertview-alertnameindicatorenabled' :
|
||||
'alertview-alertnameindicatordisabled';
|
||||
|
||||
return '<table class="alertview-alertnametable"><tr class="alertview-alertnamerow">' +
|
||||
'<td nowrap class=' + resultIndicatorClass + '></td>' +
|
||||
'<td nowrap class="alertview-alertnametext">' + dataContext.name + '</td>' +
|
||||
'</tr></table>';
|
||||
}
|
||||
|
||||
public openCreateAlertDialog() {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getJobs(ownerUri).then((result) => {
|
||||
|
||||
@@ -63,7 +63,6 @@ export class JobHistoryComponent extends JobManagementView implements OnInit {
|
||||
private _jobCacheObject: JobCacheObject;
|
||||
private _agentJobInfo: sqlops.AgentJobInfo;
|
||||
private _noJobsAvailable: boolean = false;
|
||||
private _serverName: string;
|
||||
|
||||
private static readonly INITIAL_TREE_HEIGHT: number = 780;
|
||||
private static readonly HEADING_HEIGHT: number = 24;
|
||||
|
||||
@@ -28,6 +28,7 @@ export abstract class JobManagementView extends TabChild implements AfterContent
|
||||
protected _parentComponent: AgentViewComponent;
|
||||
protected _table: Table<any>;
|
||||
protected _actionBar: Taskbar;
|
||||
protected _serverName: string;
|
||||
public contextAction: any;
|
||||
|
||||
@ViewChild('actionbarContainer') protected actionBarContainer: ElementRef;
|
||||
@@ -41,6 +42,7 @@ export abstract class JobManagementView extends TabChild implements AfterContent
|
||||
super();
|
||||
|
||||
let self = this;
|
||||
this._serverName = this._commonService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
||||
this._dashboardService.onLayout((d) => {
|
||||
self.layout();
|
||||
});
|
||||
|
||||
@@ -78,7 +78,6 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
||||
private rowDetail: RowDetailView;
|
||||
private filterPlugin: any;
|
||||
private dataView: any;
|
||||
private _serverName: string;
|
||||
private _isCloud: boolean;
|
||||
private filterStylingMap: { [columnName: string]: [any]; } = {};
|
||||
private filterStack = ['start'];
|
||||
@@ -109,7 +108,6 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
||||
) {
|
||||
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||
let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap;
|
||||
this._serverName = commonService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
||||
let jobCache = jobCacheObjectMap[this._serverName];
|
||||
if (jobCache) {
|
||||
this._jobCacheObject = jobCache;
|
||||
|
||||
@@ -30,9 +30,11 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||
import { OperatorsCacheObject } from 'sql/parts/jobManagement/common/jobManagementService';
|
||||
import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowdetailview';
|
||||
|
||||
export const VIEW_SELECTOR: string = 'joboperatorsview-component';
|
||||
export const ROW_HEIGHT: number = 30;
|
||||
export const ROW_HEIGHT: number = 45;
|
||||
|
||||
@Component({
|
||||
selector: VIEW_SELECTOR,
|
||||
@@ -43,7 +45,13 @@ export const ROW_HEIGHT: number = 30;
|
||||
export class OperatorsViewComponent extends JobManagementView implements OnInit {
|
||||
|
||||
private columns: Array<Slick.Column<any>> = [
|
||||
{ name: nls.localize('jobOperatorsView.name', 'Name'), field: 'name', width: 200, id: 'name' },
|
||||
{
|
||||
name: nls.localize('jobOperatorsView.name', 'Name'),
|
||||
field: 'name',
|
||||
formatter: (row, cell, value, columnDef, dataContext) => this.renderName(row, cell, value, columnDef, dataContext),
|
||||
width: 200,
|
||||
id: 'name'
|
||||
},
|
||||
{ name: nls.localize('jobOperatorsView.emailAddress', 'Email Address'), field: 'emailAddress', width: 200, id: 'emailAddress' },
|
||||
{ name: nls.localize('jobOperatorsView.enabled', 'Enabled'), field: 'enabled', width: 200, id: 'enabled' },
|
||||
];
|
||||
@@ -57,8 +65,8 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
};
|
||||
|
||||
private dataView: any;
|
||||
private _serverName: string;
|
||||
private _isCloud: boolean;
|
||||
private _operatorsCacheObject: OperatorsCacheObject;
|
||||
|
||||
@ViewChild('operatorsgrid') _gridEl: ElementRef;
|
||||
|
||||
@@ -79,6 +87,15 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
) {
|
||||
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||
let operatorsCacheObject = this._jobManagementService.operatorsCacheObjectMap;
|
||||
let operatorsCache = operatorsCacheObject[this._serverName];
|
||||
if (operatorsCache) {
|
||||
this._operatorsCacheObject = operatorsCache;
|
||||
} else {
|
||||
this._operatorsCacheObject = new OperatorsCacheObject();
|
||||
this._operatorsCacheObject.serverName = this._serverName;
|
||||
this._jobManagementService.addToCache(this._serverName, this._operatorsCacheObject);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(){
|
||||
@@ -93,19 +110,36 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
height = 0;
|
||||
}
|
||||
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
if (this._table) {
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
}
|
||||
}
|
||||
|
||||
onFirstVisible() {
|
||||
let self = this;
|
||||
|
||||
let cached: boolean = false;
|
||||
if (this._operatorsCacheObject.serverName === this._serverName) {
|
||||
if (this._operatorsCacheObject.operators && this._operatorsCacheObject.operators.length > 0) {
|
||||
cached = true;
|
||||
this.operators = this._operatorsCacheObject.operators;
|
||||
}
|
||||
}
|
||||
|
||||
let columns = this.columns.map((column) => {
|
||||
column.rerenderOnResize = true;
|
||||
return column;
|
||||
});
|
||||
|
||||
this.dataView = new Slick.Data.DataView();
|
||||
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
|
||||
let rowDetail = new RowDetailView({
|
||||
cssClass: '_detail_selector',
|
||||
useRowClick: false,
|
||||
panelRows: 1
|
||||
});
|
||||
columns.unshift(rowDetail.getColumnDefinition());
|
||||
|
||||
$(this._gridEl.nativeElement).empty();
|
||||
$(this.actionBarContainer.nativeElement).empty();
|
||||
@@ -117,20 +151,29 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
self.openContextMenu(e);
|
||||
}));
|
||||
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getOperators(ownerUri).then((result) => {
|
||||
if (result && result.operators) {
|
||||
self.operators = result.operators;
|
||||
self.onOperatorsAvailable(result.operators);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
|
||||
// check for cached state
|
||||
if (cached && this._agentViewComponent.refresh !== true) {
|
||||
this.onOperatorsAvailable(this.operators);
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getOperators(ownerUri).then((result) => {
|
||||
if (result && result.operators) {
|
||||
self.operators = result.operators;
|
||||
self._operatorsCacheObject.operators = result.operators;
|
||||
self.onOperatorsAvailable(result.operators);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onOperatorsAvailable(operators: sqlops.AgentOperatorInfo[]) {
|
||||
@@ -146,6 +189,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
this.dataView.beginUpdate();
|
||||
this.dataView.setItems(items);
|
||||
this.dataView.endUpdate();
|
||||
this._operatorsCacheObject.dataview = this.dataView;
|
||||
this._table.autosizeColumns();
|
||||
this._table.resizeCanvas();
|
||||
}
|
||||
@@ -163,6 +207,15 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
||||
: undefined;
|
||||
}
|
||||
|
||||
private renderName(row, cell, value, columnDef, dataContext) {
|
||||
let resultIndicatorClass = dataContext.enabled ? 'operatorview-operatornameindicatorenabled' :
|
||||
'operatorview-operatornameindicatordisabled';
|
||||
return '<table class="operatorview-operatornametable"><tr class="operatorview-operatornamerow">' +
|
||||
'<td nowrap class=' + resultIndicatorClass + '></td>' +
|
||||
'<td nowrap class="operatorview-operatornametext">' + dataContext.name + '</td>' +
|
||||
'</tr></table>';
|
||||
}
|
||||
|
||||
public openCreateOperatorDialog() {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._commandService.executeCommand('agent.openOperatorDialog', ownerUri);
|
||||
|
||||
@@ -30,9 +30,11 @@ import { IAction } from 'vs/base/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||
import { ProxiesCacheObject } from 'sql/parts/jobManagement/common/jobManagementService';
|
||||
import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowdetailview';
|
||||
|
||||
export const VIEW_SELECTOR: string = 'jobproxiesview-component';
|
||||
export const ROW_HEIGHT: number = 30;
|
||||
export const ROW_HEIGHT: number = 45;
|
||||
|
||||
@Component({
|
||||
selector: VIEW_SELECTOR,
|
||||
@@ -46,8 +48,16 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
private RefreshText: string = nls.localize('jobProxyToolbar-Refresh', "Refresh");
|
||||
|
||||
private columns: Array<Slick.Column<any>> = [
|
||||
{ name: nls.localize('jobProxiesView.accountName', 'Account Name'), field: 'accountName', width: 200, id: 'accountName' },
|
||||
{
|
||||
name: nls.localize('jobProxiesView.accountName', 'Account Name'),
|
||||
field: 'accountName',
|
||||
formatter: (row, cell, value, columnDef, dataContext) => this.renderName(row, cell, value, columnDef, dataContext),
|
||||
width: 200,
|
||||
id: 'accountName'
|
||||
},
|
||||
{ name: nls.localize('jobProxiesView.credentialName', 'Credential Name'), field: 'credentialName', width: 200, id: 'credentialName' },
|
||||
{ name: nls.localize('jobProxiesView.description', 'Description'), field: 'description', width: 200, id: 'description'},
|
||||
{ name: nls.localize('jobProxiesView.isEnabled', 'Enabled'), field: 'isEnabled', width: 200, id: 'isEnabled'}
|
||||
];
|
||||
|
||||
private options: Slick.GridOptions<any> = {
|
||||
@@ -59,8 +69,8 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
};
|
||||
|
||||
private dataView: any;
|
||||
private _serverName: string;
|
||||
private _isCloud: boolean;
|
||||
private _proxiesCacheObject: ProxiesCacheObject;
|
||||
|
||||
public proxies: sqlops.AgentProxyInfo[];
|
||||
public readonly contextAction = NewProxyAction;
|
||||
@@ -81,6 +91,15 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
) {
|
||||
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||
let proxiesCacheObjectMap = this._jobManagementService.proxiesCacheObjectMap;
|
||||
let proxiesCacheObject = proxiesCacheObjectMap[this._serverName];
|
||||
if (proxiesCacheObject) {
|
||||
this._proxiesCacheObject = proxiesCacheObject;
|
||||
} else {
|
||||
this._proxiesCacheObject = new ProxiesCacheObject();
|
||||
this._proxiesCacheObject.serverName = this._serverName;
|
||||
this._jobManagementService.addToCache(this._serverName, this._proxiesCacheObject);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(){
|
||||
@@ -95,19 +114,35 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
height = 0;
|
||||
}
|
||||
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
if (this._table) {
|
||||
this._table.layout(new dom.Dimension(
|
||||
dom.getContentWidth(this._gridEl.nativeElement),
|
||||
height));
|
||||
}
|
||||
}
|
||||
|
||||
onFirstVisible() {
|
||||
let self = this;
|
||||
let cached: boolean = false;
|
||||
if (this._proxiesCacheObject.serverName === this._serverName) {
|
||||
if (this._proxiesCacheObject.proxies && this._proxiesCacheObject.proxies.length > 0) {
|
||||
cached = true;
|
||||
this.proxies = this._proxiesCacheObject.proxies;
|
||||
}
|
||||
}
|
||||
|
||||
let columns = this.columns.map((column) => {
|
||||
column.rerenderOnResize = true;
|
||||
return column;
|
||||
});
|
||||
|
||||
this.dataView = new Slick.Data.DataView();
|
||||
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
|
||||
let rowDetail = new RowDetailView({
|
||||
cssClass: '_detail_selector',
|
||||
useRowClick: false,
|
||||
panelRows: 1
|
||||
});
|
||||
columns.unshift(rowDetail.getColumnDefinition());
|
||||
|
||||
$(this._gridEl.nativeElement).empty();
|
||||
$(this.actionBarContainer.nativeElement).empty();
|
||||
@@ -119,20 +154,29 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
self.openContextMenu(e);
|
||||
}));
|
||||
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getProxies(ownerUri).then((result) => {
|
||||
if (result && result.proxies) {
|
||||
self.proxies = result.proxies;
|
||||
self.onProxiesAvailable(result.proxies);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
|
||||
// checked for cached state
|
||||
if (cached && this._agentViewComponent.refresh !== true) {
|
||||
self.onProxiesAvailable(this.proxies);
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getProxies(ownerUri).then((result) => {
|
||||
if (result && result.proxies) {
|
||||
self.proxies = result.proxies;
|
||||
self._proxiesCacheObject.proxies = result.proxies;
|
||||
self.onProxiesAvailable(result.proxies);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
}
|
||||
this._showProgressWheel = false;
|
||||
if (this.isVisible) {
|
||||
this._cd.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onProxiesAvailable(proxies: sqlops.AgentProxyInfo[]) {
|
||||
@@ -140,13 +184,16 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
return {
|
||||
id: item.accountName,
|
||||
accountName: item.accountName,
|
||||
credentialName: item.credentialName
|
||||
credentialName: item.credentialName,
|
||||
description: item.description,
|
||||
isEnabled: item.isEnabled
|
||||
};
|
||||
});
|
||||
|
||||
this.dataView.beginUpdate();
|
||||
this.dataView.setItems(items);
|
||||
this.dataView.endUpdate();
|
||||
this._proxiesCacheObject.dataview = this.dataView;
|
||||
this._table.autosizeColumns();
|
||||
this._table.resizeCanvas();
|
||||
}
|
||||
@@ -164,6 +211,15 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
private renderName(row, cell, value, columnDef, dataContext) {
|
||||
let resultIndicatorClass = dataContext.isEnabled ? 'proxyview-proxynameindicatorenabled' :
|
||||
'proxyview-proxynameindicatordisabled';
|
||||
return '<table class="proxyview-proxynametable"><tr class="proxyview-proxynamerow">' +
|
||||
'<td nowrap class=' + resultIndicatorClass + '></td>' +
|
||||
'<td nowrap class="proxyview-proxynametext">' + dataContext.accountName + '</td>' +
|
||||
'</tr></table>';
|
||||
}
|
||||
|
||||
public openCreateProxyDialog() {
|
||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||
this._jobManagementService.getCredentials(ownerUri).then((result) => {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
.modelview-toolbar-container .modelview-toolbar-title {
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
|
||||
/* Vertical button handling */
|
||||
.modelview-toolbar-container.toolbar-vertical .modelview-toolbar-component modelview-button .monaco-text-button.icon {
|
||||
padding: 22px 16px 22px 16px;
|
||||
background-size: 22px;
|
||||
padding: 20px 16px 20px 16px;
|
||||
background-size: 20px;
|
||||
margin-right: 0.3em;
|
||||
background-position: 50% 50%;
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ export class ServerGroupDialog extends Modal {
|
||||
|
||||
constructor(
|
||||
@IPartService partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(localize('ServerGroupsDialogTitle', 'Server Groups'), TelemetryKeys.ServerGroups, partService, telemetryService, clipboardService, contextKeyService);
|
||||
super(localize('ServerGroupsDialogTitle', 'Server Groups'), TelemetryKeys.ServerGroups, partService, telemetryService, clipboardService, themeService, contextKeyService);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!sql/parts/profiler/media/profiler';
|
||||
import { IProfilerService } from 'sql/parts/profiler/service/interfaces';
|
||||
import { IProfilerController } from 'sql/parts/profiler/editor/controller/interfaces';
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
@@ -157,7 +157,7 @@ export class ProfilerClear extends Action {
|
||||
public static LABEL = nls.localize('profiler.clear', "Clear Data");
|
||||
|
||||
constructor(id: string, label: string) {
|
||||
super(id, label);
|
||||
super(id, label, 'clear-results');
|
||||
}
|
||||
|
||||
run(input: ProfilerInput): TPromise<void> {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
import 'vs/css!./media/profilerDialog';
|
||||
import 'vs/css!sql/parts/profiler/media/profiler';
|
||||
|
||||
import { Modal } from 'sql/base/browser/ui/modal/modal';
|
||||
import { attachModalDialogStyler } from 'sql/common/theme/styler';
|
||||
@@ -314,13 +314,13 @@ export class ProfilerColumnEditorDialog extends Modal {
|
||||
|
||||
constructor(
|
||||
@IPartService _partService: IPartService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(nls.localize('profilerColumnDialog.profiler', 'Profiler'), TelemetryKeys.Profiler, _partService, telemetryService, clipboardService, contextKeyService);
|
||||
super(nls.localize('profilerColumnDialog.profiler', 'Profiler'), TelemetryKeys.Profiler, _partService, telemetryService, clipboardService, themeService, contextKeyService);
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
|
||||
@@ -113,6 +113,7 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll
|
||||
this._stateListener.dispose();
|
||||
}
|
||||
this._stateListener = input.state.addChangeListener(e => this._onStateChange(e));
|
||||
input.data.onRowCountChange(() => { this._profilerTable.updateRowCount(); });
|
||||
|
||||
if (this._findCountChangeListener) {
|
||||
this._findCountChangeListener.dispose();
|
||||
|
||||
@@ -252,6 +252,7 @@ export class ProfilerEditor extends BaseEditor {
|
||||
{ action: this._pauseAction },
|
||||
{ action: this._autoscrollAction },
|
||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
||||
{ element: Taskbar.createTaskbarSeparator() },
|
||||
{ element: viewTemplateContainer },
|
||||
{ element: Taskbar.createTaskbarSeparator() },
|
||||
{ element: this._connectionInfoText }
|
||||
@@ -344,6 +345,10 @@ export class ProfilerEditor extends BaseEditor {
|
||||
]
|
||||
}, { forceFitColumns: true });
|
||||
|
||||
this._detailTableData.onRowCountChange(() => {
|
||||
this._detailTable.updateRowCount();
|
||||
});
|
||||
|
||||
this._tabbedPanel.pushTab({
|
||||
identifier: 'detailTable',
|
||||
title: nls.localize('details', "Details"),
|
||||
|
||||
1
src/sql/parts/profiler/media/clear.svg
Normal file
1
src/sql/parts/profiler/media/clear.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.065 13H15v2H2.056v-2h5.009zm3.661-12H7.385L8.44 2.061 7.505 3H15V1h-4.274zM3.237 9H2.056v2H15V9H3.237zm4.208-4l.995 1-.995 1H15V5H7.445z" fill="#424242"/><path d="M5.072 4.03L7.032 6 5.978 7.061l-1.96-1.97-1.961 1.97L1 6l1.96-1.97L1 2.061 2.056 1l1.96 1.97L5.977 1l1.057 1.061L5.072 4.03z" fill="#A1260D"/></svg>
|
||||
|
After Width: | Height: | Size: 419 B |
1
src/sql/parts/profiler/media/clear_inverse.svg
Normal file
1
src/sql/parts/profiler/media/clear_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.065 13H15v2H2.056v-2h5.009zm3.661-12H7.385L8.44 2.061 7.505 3H15V1h-4.274zM3.237 9H2.056v2H15V9H3.237zm4.208-4l.995 1-.995 1H15V5H7.445z" fill="#C5C5C5"/><path d="M5.072 4.03L7.032 6 5.978 7.061l-1.96-1.97-1.961 1.97L1 6l1.96-1.97L1 2.061 2.056 1l1.96 1.97L5.977 1l1.057 1.061L5.072 4.03z" fill="#F48771"/></svg>
|
||||
|
After Width: | Height: | Size: 419 B |
@@ -11,3 +11,11 @@
|
||||
.tree-row > * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vs .icon.clear-results {
|
||||
background-image: url('clear.svg');
|
||||
}
|
||||
|
||||
.vs-dark .icon.clear-results {
|
||||
background-image: url('clear_inverse.svg');
|
||||
}
|
||||
@@ -120,7 +120,8 @@ actionRegistry.registerWorkbenchAction(
|
||||
new SyncActionDescriptor(
|
||||
RunCurrentQueryWithActualPlanKeyboardAction,
|
||||
RunCurrentQueryWithActualPlanKeyboardAction.ID,
|
||||
RunCurrentQueryWithActualPlanKeyboardAction.LABEL
|
||||
RunCurrentQueryWithActualPlanKeyboardAction.LABEL,
|
||||
{ primary: KeyMod.CtrlCmd | KeyCode.KEY_M }
|
||||
),
|
||||
RunCurrentQueryWithActualPlanKeyboardAction.LABEL
|
||||
);
|
||||
|
||||
@@ -9,7 +9,6 @@ import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||
|
||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||
@@ -25,7 +24,6 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
||||
|
||||
constructor(
|
||||
@IEditorService private _editorService: EditorServiceImpl,
|
||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
||||
@IQueryModelService private _queryModelService: IQueryModelService
|
||||
) { }
|
||||
|
||||
@@ -36,7 +34,7 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
||||
];
|
||||
|
||||
this._element = append(container, $('.query-statusbar-group'));
|
||||
this._flavorElement = append(this._element, $('a.editor-status-selection'));
|
||||
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||
this._flavorElement.title = nls.localize('rowStatus', "Row Count");
|
||||
hide(this._flavorElement);
|
||||
|
||||
@@ -65,11 +63,10 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
||||
if (queryRunner) {
|
||||
if (queryRunner.hasCompleted) {
|
||||
this._displayValue(queryRunner);
|
||||
} else if (queryRunner.isExecuting) {
|
||||
this.dispose = queryRunner.addListener('complete', () => {
|
||||
this._displayValue(queryRunner);
|
||||
});
|
||||
}
|
||||
this.dispose = queryRunner.onQueryEnd(e => {
|
||||
this._displayValue(queryRunner);
|
||||
});
|
||||
} else {
|
||||
this.dispose = this._queryModelService.onRunQueryComplete(e => {
|
||||
if (e === currentUri) {
|
||||
|
||||
107
src/sql/parts/query/common/timeElapsedStatus.ts
Normal file
107
src/sql/parts/query/common/timeElapsedStatus.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||
import { IQueryModelService } from '../execution/queryModel';
|
||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||
import { parseNumAsTimeString } from 'sql/parts/connection/common/utils';
|
||||
|
||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||
import * as nls from 'vs/nls';
|
||||
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { IntervalTimer } from 'vs/base/common/async';
|
||||
|
||||
export class TimeElapsedStatusBarItem implements IStatusbarItem {
|
||||
|
||||
private _element: HTMLElement;
|
||||
private _flavorElement: HTMLElement;
|
||||
|
||||
private dispose: IDisposable[] = [];
|
||||
private intervalTimer = new IntervalTimer();
|
||||
|
||||
constructor(
|
||||
@IEditorService private _editorService: EditorServiceImpl,
|
||||
@IQueryModelService private _queryModelService: IQueryModelService
|
||||
) { }
|
||||
|
||||
render(container: HTMLElement): IDisposable {
|
||||
let disposables = [
|
||||
this._editorService.onDidVisibleEditorsChange(() => this._onEditorsChanged()),
|
||||
this._editorService.onDidCloseEditor(event => this._onEditorClosed(event))
|
||||
];
|
||||
|
||||
this._element = append(container, $('.query-statusbar-group'));
|
||||
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||
this._flavorElement.title = nls.localize('timeElapsed', "Time Elapsed");
|
||||
hide(this._flavorElement);
|
||||
|
||||
this._showStatus();
|
||||
|
||||
return combinedDisposable(disposables);
|
||||
}
|
||||
|
||||
private _onEditorsChanged() {
|
||||
this._showStatus();
|
||||
}
|
||||
|
||||
private _onEditorClosed(event: IEditorCloseEvent) {
|
||||
hide(this._flavorElement);
|
||||
}
|
||||
|
||||
// Show/hide query status for active editor
|
||||
private _showStatus(): void {
|
||||
this.intervalTimer.cancel();
|
||||
hide(this._flavorElement);
|
||||
dispose(this.dispose);
|
||||
this._flavorElement.innerText = '';
|
||||
this.dispose = [];
|
||||
let activeEditor = this._editorService.activeControl;
|
||||
if (activeEditor) {
|
||||
let currentUri = WorkbenchUtils.getEditorUri(activeEditor.input);
|
||||
if (currentUri) {
|
||||
let queryRunner = this._queryModelService.getQueryRunner(currentUri);
|
||||
if (queryRunner) {
|
||||
if (queryRunner.hasCompleted || queryRunner.isExecuting) {
|
||||
this._displayValue(queryRunner);
|
||||
}
|
||||
this.dispose.push(queryRunner.onQueryStart(e => {
|
||||
this._displayValue(queryRunner);
|
||||
}));
|
||||
this.dispose.push(queryRunner.onQueryEnd(e => {
|
||||
this._displayValue(queryRunner);
|
||||
}));
|
||||
} else {
|
||||
this.dispose.push(this._queryModelService.onRunQueryStart(e => {
|
||||
if (e === currentUri) {
|
||||
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||
}
|
||||
}));
|
||||
this.dispose.push(this._queryModelService.onRunQueryComplete(e => {
|
||||
if (e === currentUri) {
|
||||
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _displayValue(runner: QueryRunner) {
|
||||
this.intervalTimer.cancel();
|
||||
if (runner.isExecuting) {
|
||||
this.intervalTimer.cancelAndSet(() => {
|
||||
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||
}, 1000);
|
||||
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||
} else {
|
||||
this._flavorElement.innerText = parseNumAsTimeString(runner.queryEndTime.getTime() - runner.queryStartTime.getTime(), false);
|
||||
}
|
||||
show(this._flavorElement);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,8 @@ export enum ControlType {
|
||||
combo,
|
||||
numberInput,
|
||||
input,
|
||||
checkbox
|
||||
checkbox,
|
||||
dateInput
|
||||
}
|
||||
|
||||
export interface IChartOption {
|
||||
@@ -115,6 +116,20 @@ const xAxisMaxInput: IChartOption = {
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const xAxisMinDateInput: IChartOption = {
|
||||
label: localize('xAxisMinDate', 'X Axis Minimum Date'),
|
||||
type: ControlType.dateInput,
|
||||
configEntry: 'xAxisMin',
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const xAxisMaxDateInput: IChartOption = {
|
||||
label: localize('xAxisMaxDate', 'X Axis Maximum Date'),
|
||||
type: ControlType.dateInput,
|
||||
configEntry: 'xAxisMax',
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const dataTypeInput: IChartOption = {
|
||||
label: localize('dataTypeLabel', 'Data Type'),
|
||||
type: ControlType.combo,
|
||||
@@ -150,7 +165,11 @@ export const ChartOptions: IChartOptions = {
|
||||
[ChartType.TimeSeries]: [
|
||||
legendInput,
|
||||
yAxisLabelInput,
|
||||
xAxisLabelInput
|
||||
yAxisMinInput,
|
||||
yAxisMaxInput,
|
||||
xAxisLabelInput,
|
||||
xAxisMinDateInput,
|
||||
xAxisMaxDateInput,
|
||||
],
|
||||
[ChartType.Bar]: [
|
||||
dataDirectionOption,
|
||||
|
||||
@@ -18,7 +18,7 @@ export class ChartTab implements IPanelTab {
|
||||
public readonly identifier = 'ChartTab';
|
||||
public readonly view: ChartView;
|
||||
|
||||
constructor(@IInstantiationService instantiationService: IInstantiationService) {
|
||||
constructor( @IInstantiationService instantiationService: IInstantiationService) {
|
||||
this.view = instantiationService.createInstance(ChartView);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,11 @@ export class ChartTab implements IPanelTab {
|
||||
this.view.queryRunner = runner;
|
||||
}
|
||||
|
||||
public chart(dataId: { batchId: number, resultId: number}): void {
|
||||
public chart(dataId: { batchId: number, resultId: number }): void {
|
||||
this.view.chart(dataId);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.view.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { attachSelectBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -43,7 +43,7 @@ declare class Proxy {
|
||||
|
||||
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
||||
|
||||
export class ChartView implements IPanelView {
|
||||
export class ChartView extends Disposable implements IPanelView {
|
||||
private insight: Insight;
|
||||
private _queryRunner: QueryRunner;
|
||||
private _data: IInsightData;
|
||||
@@ -82,6 +82,7 @@ export class ChartView implements IPanelView {
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService
|
||||
) {
|
||||
super();
|
||||
this.taskbarContainer = $('div.taskbar-container');
|
||||
this.taskbar = new Taskbar(this.taskbarContainer, contextMenuService);
|
||||
this.optionsControl = $('div.options-container');
|
||||
@@ -324,6 +325,24 @@ export class ChartView implements IPanelView {
|
||||
};
|
||||
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
||||
break;
|
||||
case ControlType.dateInput:
|
||||
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'date' });
|
||||
dateInput.value = value || '';
|
||||
dateInput.onDidChange(e => {
|
||||
if (this.options[option.configEntry] !== e) {
|
||||
this.options[option.configEntry] = e;
|
||||
if (this.insight) {
|
||||
this.insight.options = this.options;
|
||||
}
|
||||
}
|
||||
});
|
||||
setFunc = (val: string) => {
|
||||
if (!isUndefinedOrNull(val)) {
|
||||
dateInput.value = val;
|
||||
}
|
||||
};
|
||||
this.optionDisposables.push(attachInputBoxStyler(dateInput, this._themeService));
|
||||
break;
|
||||
}
|
||||
this.optionMap[option.configEntry] = { element: optionContainer, set: setFunc };
|
||||
container.appendChild(optionContainer);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Chart as ChartJs } from 'chart.js';
|
||||
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { mixin } from 'sql/base/common/objects';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
|
||||
@@ -15,10 +15,28 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { IInsightOptions, IInsight } from './interfaces';
|
||||
import { ChartType, DataDirection, LegendPosition } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, DataDirection, LegendPosition, DataType, IPointDataSet, customMixin } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
||||
|
||||
const timeSeriesScales = {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
display: true,
|
||||
ticks: {
|
||||
autoSkip: false,
|
||||
maxRotation: 45,
|
||||
minRotation: 45
|
||||
}
|
||||
}],
|
||||
|
||||
yAxes: [{
|
||||
display: true,
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const defaultOptions: IInsightOptions = {
|
||||
type: ChartType.Bar,
|
||||
dataDirection: DataDirection.Horizontal
|
||||
@@ -30,6 +48,8 @@ export class Graph implements IInsight {
|
||||
private chartjs: ChartJs;
|
||||
private _data: IInsightData;
|
||||
|
||||
private originalType: ChartType;
|
||||
|
||||
public static readonly types = [ChartType.Bar, ChartType.Doughnut, ChartType.HorizontalBar, ChartType.Line, ChartType.Pie, ChartType.Scatter, ChartType.TimeSeries];
|
||||
public readonly types = Graph.types;
|
||||
|
||||
@@ -83,37 +103,51 @@ export class Graph implements IInsight {
|
||||
labels = data.rows.map(row => row[0]);
|
||||
}
|
||||
|
||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||
if (this.options.labelFirstColumn) {
|
||||
chartData = data.rows.map((row) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)).slice(1),
|
||||
label: row[0]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows.map((row, i) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)),
|
||||
label: localize('series', 'Series {0}', i)
|
||||
};
|
||||
});
|
||||
}
|
||||
if (this.originalType === ChartType.TimeSeries) {
|
||||
let dataSetMap: { [label: string]: IPointDataSet } = {};
|
||||
this._data.rows.map(row => {
|
||||
if (row && row.length >= 3) {
|
||||
let legend = row[0];
|
||||
if (!dataSetMap[legend]) {
|
||||
dataSetMap[legend] = { label: legend, data: [], fill: false };
|
||||
}
|
||||
dataSetMap[legend].data.push({ x: row[1], y: Number(row[2]) });
|
||||
}
|
||||
});
|
||||
chartData = Object.values(dataSetMap);
|
||||
} else {
|
||||
if (this.options.columnsAsLabels) {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: data.columns[i + 1]
|
||||
};
|
||||
});
|
||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||
if (this.options.labelFirstColumn) {
|
||||
chartData = data.rows.map((row) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)).slice(1),
|
||||
label: row[0]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows.map((row, i) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)),
|
||||
label: localize('series', 'Series {0}', i)
|
||||
};
|
||||
});
|
||||
}
|
||||
} else {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: localize('series', 'Series {0}', i + 1)
|
||||
};
|
||||
});
|
||||
if (this.options.columnsAsLabels) {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: data.columns[i + 1]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: localize('series', 'Series {0}', i + 1)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +221,35 @@ export class Graph implements IInsight {
|
||||
color: gridLines
|
||||
}
|
||||
}];
|
||||
|
||||
if (this.originalType === ChartType.TimeSeries) {
|
||||
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
||||
if (options.xAxisMax) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
max: options.xAxisMax
|
||||
}
|
||||
}],
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
|
||||
if (options.xAxisMin) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
min: options.xAxisMin
|
||||
}
|
||||
}],
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval.legend = <ChartJs.ChartLegendOptions>{
|
||||
@@ -208,6 +271,12 @@ export class Graph implements IInsight {
|
||||
|
||||
public set options(options: IInsightOptions) {
|
||||
this._options = options;
|
||||
this.originalType = options.type as ChartType;
|
||||
if (this.options.type === ChartType.TimeSeries) {
|
||||
this.options.type = ChartType.Line;
|
||||
this.options.dataType = DataType.Point;
|
||||
this.options.dataDirection = DataDirection.Horizontal;
|
||||
}
|
||||
this.data = this._data;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Graph } from './graphInsight';
|
||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { DataDirection, ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ImageInsight } from './imageInsight';
|
||||
import { TableInsight } from './tableInsight';
|
||||
import { IInsightOptions, IInsight, InsightType, IInsightCtor } from './interfaces';
|
||||
@@ -16,6 +16,7 @@ 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 { deepClone } from 'vs/base/common/objects';
|
||||
|
||||
const defaultOptions: IInsightOptions = {
|
||||
type: ChartType.Bar,
|
||||
@@ -47,13 +48,13 @@ export class Insight {
|
||||
}
|
||||
|
||||
public set options(val: IInsightOptions) {
|
||||
this._options = val;
|
||||
this._options = deepClone(val);
|
||||
if (this.insight) {
|
||||
// check to see if we need to change the insight type
|
||||
if (!this.insight.types.includes(val.type)) {
|
||||
if (!this.insight.types.includes(this.options.type)) {
|
||||
this.buildInsight();
|
||||
} else {
|
||||
this.insight.options = val;
|
||||
this.insight.options = this.options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugi
|
||||
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
|
||||
|
||||
import * as sqlops from 'sqlops';
|
||||
import * as pretty from 'pretty-data';
|
||||
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
@@ -41,13 +42,14 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
|
||||
const ROW_HEIGHT = 29;
|
||||
const HEADER_HEIGHT = 26;
|
||||
const MIN_GRID_HEIGHT_ROWS = 8;
|
||||
const ESTIMATED_SCROLL_BAR_HEIGHT = 10;
|
||||
const BOTTOM_PADDING = 15;
|
||||
const ACTIONBAR_WIDTH = 26;
|
||||
const ACTIONBAR_WIDTH = 36;
|
||||
|
||||
// minimum height needed to show the full actionbar
|
||||
const ACTIONBAR_HEIGHT = 100;
|
||||
@@ -133,7 +135,7 @@ export class GridPanel extends ViewletPanel {
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService);
|
||||
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false });
|
||||
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false, verticalScrollbarVisibility: ScrollbarVisibility.Visible });
|
||||
this.splitView.onScroll(e => {
|
||||
if (this.state) {
|
||||
this.state.scrollPosition = e;
|
||||
@@ -477,7 +479,27 @@ class GridTable<T> extends Disposable implements IView {
|
||||
if (column && (column.isXml || column.isJson)) {
|
||||
this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(d => {
|
||||
let value = d.resultSubset.rows[0][event.cell.cell - 1];
|
||||
let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', value.displayValue);
|
||||
let content = value.displayValue;
|
||||
if (column.isXml) {
|
||||
try {
|
||||
content = pretty.pd.xml(content);
|
||||
} catch (e) {
|
||||
// If Xml fails to parse, fall back on original Xml content
|
||||
}
|
||||
} else {
|
||||
let jsonContent: string = undefined;
|
||||
try {
|
||||
jsonContent = JSON.parse(content);
|
||||
} catch (e) {
|
||||
// If Json fails to parse, fall back on original Json content
|
||||
}
|
||||
if (jsonContent) {
|
||||
// If Json content was valid and parsed, pretty print content to a string
|
||||
content = JSON.stringify(jsonContent, undefined, 4);
|
||||
}
|
||||
}
|
||||
|
||||
let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content);
|
||||
this.editorService.openEditor(input);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ import { PanelViewlet } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { once, anyEvent } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
class ResultsView implements IPanelView {
|
||||
class ResultsView extends Disposable implements IPanelView {
|
||||
private panelViewlet: PanelViewlet;
|
||||
private gridPanel: GridPanel;
|
||||
private messagePanel: MessagePanel;
|
||||
@@ -30,10 +30,10 @@ class ResultsView implements IPanelView {
|
||||
private _state: ResultsViewState;
|
||||
|
||||
constructor(private instantiationService: IInstantiationService) {
|
||||
|
||||
this.panelViewlet = this.instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false });
|
||||
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' });
|
||||
super();
|
||||
this.panelViewlet = this._register(this.instantiationService.createInstance(PanelViewlet, 'resultsView', { showHeaderInTitleWhenSingleView: false }));
|
||||
this.gridPanel = this._register(this.instantiationService.createInstance(GridPanel, { title: nls.localize('gridPanel', 'Results'), id: 'gridPanel' }));
|
||||
this.messagePanel = this._register(this.instantiationService.createInstance(MessagePanel, { title: nls.localize('messagePanel', 'Messages'), minimumBodySize: 0, id: 'messagePanel' }));
|
||||
this.gridPanel.render();
|
||||
this.messagePanel.render();
|
||||
this.panelViewlet.create(this.container).then(() => {
|
||||
@@ -147,9 +147,13 @@ class ResultsTab implements IPanelTab {
|
||||
public set queryRunner(runner: QueryRunner) {
|
||||
this.view.queryRunner = runner;
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
dispose(this.view);
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryResultsView {
|
||||
export class QueryResultsView extends Disposable {
|
||||
private _panelView: TabbedPanel;
|
||||
private _input: QueryResultsInput;
|
||||
private resultsTab: ResultsTab;
|
||||
@@ -163,16 +167,17 @@ export class QueryResultsView {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IQueryModelService private queryModelService: IQueryModelService
|
||||
) {
|
||||
this.resultsTab = new ResultsTab(instantiationService);
|
||||
this.chartTab = new ChartTab(instantiationService);
|
||||
this._panelView = new TabbedPanel(container, { showHeaderWhenSingleView: false });
|
||||
this.qpTab = new QueryPlanTab();
|
||||
super();
|
||||
this.resultsTab = this._register(new ResultsTab(instantiationService));
|
||||
this.chartTab = this._register(new ChartTab(instantiationService));
|
||||
this._panelView = this._register(new TabbedPanel(container, { showHeaderWhenSingleView: false }));
|
||||
this.qpTab = this._register(new QueryPlanTab());
|
||||
this._panelView.pushTab(this.resultsTab);
|
||||
this._panelView.onTabChange(e => {
|
||||
this._register(this._panelView.onTabChange(e => {
|
||||
if (this.input) {
|
||||
this.input.state.activeTab = e;
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public style() {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||
import { QueryStatusbarItem } from 'sql/parts/query/execution/queryStatus';
|
||||
import { SqlFlavorStatusbarItem } from 'sql/parts/query/common/flavorStatus';
|
||||
import { RowCountStatusBarItem } from 'sql/parts/query/common/rowCountStatus';
|
||||
import { TimeElapsedStatusBarItem } from 'sql/parts/query/common/timeElapsedStatus';
|
||||
|
||||
import * as sqlops from 'sqlops';
|
||||
|
||||
@@ -86,6 +87,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
// Register Statusbar items
|
||||
|
||||
(<statusbar.IStatusbarRegistry>platform.Registry.as(statusbar.Extensions.Statusbar)).registerStatusbarItem(new statusbar.StatusbarItemDescriptor(
|
||||
TimeElapsedStatusBarItem,
|
||||
statusbar.StatusbarAlignment.RIGHT,
|
||||
100 /* Should appear to the right of the SQL editor status */
|
||||
));
|
||||
|
||||
(<statusbar.IStatusbarRegistry>platform.Registry.as(statusbar.Extensions.Statusbar)).registerStatusbarItem(new statusbar.StatusbarItemDescriptor(
|
||||
RowCountStatusBarItem,
|
||||
statusbar.StatusbarAlignment.RIGHT,
|
||||
@@ -352,7 +359,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public disposeQuery(ownerUri: string): void {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
queryRunner.disposeQuery();
|
||||
}
|
||||
@@ -444,7 +451,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public disposeEdit(ownerUri: string): Thenable<void> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.disposeEdit(ownerUri);
|
||||
}
|
||||
@@ -453,7 +460,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.updateCell(ownerUri, rowId, columnId, newValue).then((result) => result, error => {
|
||||
this._notificationService.notify({
|
||||
@@ -468,7 +475,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public commitEdit(ownerUri): Thenable<void> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.commitEdit(ownerUri).then(() => { }, error => {
|
||||
this._notificationService.notify({
|
||||
@@ -483,7 +490,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public createRow(ownerUri: string): Thenable<sqlops.EditCreateRowResult> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.createRow(ownerUri);
|
||||
}
|
||||
@@ -492,7 +499,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public deleteRow(ownerUri: string, rowId: number): Thenable<void> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.deleteRow(ownerUri, rowId);
|
||||
}
|
||||
@@ -501,7 +508,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<sqlops.EditRevertCellResult> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.revertCell(ownerUri, rowId, columnId);
|
||||
}
|
||||
@@ -510,16 +517,25 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
public revertRow(ownerUri: string, rowId: number): Thenable<void> {
|
||||
// Get existing query runner
|
||||
let queryRunner = this.getQueryRunner(ownerUri);
|
||||
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||
if (queryRunner) {
|
||||
return queryRunner.revertRow(ownerUri, rowId);
|
||||
}
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
public getQueryRunner(ownerUri): QueryRunner {
|
||||
let queryRunner: QueryRunner = undefined;
|
||||
if (this._queryInfoMap.has(ownerUri)) {
|
||||
queryRunner = this._getQueryInfo(ownerUri).queryRunner;
|
||||
}
|
||||
// return undefined if not found or is already executing
|
||||
return queryRunner;
|
||||
}
|
||||
|
||||
// PRIVATE METHODS //////////////////////////////////////////////////////
|
||||
|
||||
public getQueryRunner(ownerUri): QueryRunner {
|
||||
private internalGetQueryRunner(ownerUri): QueryRunner {
|
||||
let queryRunner: QueryRunner = undefined;
|
||||
if (this._queryInfoMap.has(ownerUri)) {
|
||||
let existingRunner = this._getQueryInfo(ownerUri).queryRunner;
|
||||
|
||||
@@ -112,6 +112,15 @@ export default class QueryRunner {
|
||||
private _onBatchEnd = new Emitter<sqlops.BatchSummary>();
|
||||
public readonly onBatchEnd: Event<sqlops.BatchSummary> = this._onBatchEnd.event;
|
||||
|
||||
private _queryStartTime: Date;
|
||||
public get queryStartTime(): Date {
|
||||
return this._queryStartTime;
|
||||
}
|
||||
private _queryEndTime: Date;
|
||||
public get queryEndTime(): Date {
|
||||
return this._queryEndTime;
|
||||
}
|
||||
|
||||
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
||||
constructor(
|
||||
public uri: string,
|
||||
@@ -185,9 +194,10 @@ export default class QueryRunner {
|
||||
this._debouncedMessage.clear();
|
||||
this._debouncedResultSet.clear();
|
||||
this._planXml = new Deferred<string>();
|
||||
let ownerUri = this.uri;
|
||||
this._batchSets = [];
|
||||
this._hasCompleted = false;
|
||||
this._queryStartTime = undefined;
|
||||
this._queryEndTime = undefined;
|
||||
if (types.isObject(input) || types.isUndefinedOrNull(input)) {
|
||||
// Update internal state to show that we're executing the query
|
||||
this._resultLineOffset = input ? input.startLine : 0;
|
||||
@@ -203,20 +213,22 @@ export default class QueryRunner {
|
||||
|
||||
// Send the request to execute the query
|
||||
return runCurrentStatement
|
||||
? this._queryManagementService.runQueryStatement(ownerUri, input.startLine, input.startColumn).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e))
|
||||
: this._queryManagementService.runQuery(ownerUri, input, runOptions).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||
? this._queryManagementService.runQueryStatement(this.uri, input.startLine, input.startColumn).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e))
|
||||
: this._queryManagementService.runQuery(this.uri, input, runOptions).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||
} else if (types.isString(input)) {
|
||||
// Update internal state to show that we're executing the query
|
||||
this._isExecuting = true;
|
||||
this._totalElapsedMilliseconds = 0;
|
||||
|
||||
return this._queryManagementService.runQueryString(ownerUri, input).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||
return this._queryManagementService.runQueryString(this.uri, input).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||
} else {
|
||||
return Promise.reject('Unknown input');
|
||||
}
|
||||
}
|
||||
|
||||
private handleSuccessRunQueryResult() {
|
||||
// this isn't exact, but its the best we can do
|
||||
this._queryStartTime = new Date();
|
||||
// The query has started, so lets fire up the result pane
|
||||
this._onQueryStart.fire();
|
||||
this._eventEmitter.emit(EventType.START);
|
||||
@@ -241,6 +253,8 @@ export default class QueryRunner {
|
||||
* Handle a QueryComplete from the service layer
|
||||
*/
|
||||
public handleQueryComplete(result: sqlops.QueryExecuteCompleteNotificationResult): void {
|
||||
// this also isn't exact but its the best we can do
|
||||
this._queryEndTime = new Date();
|
||||
|
||||
// Store the batch sets we got back as a source of "truth"
|
||||
this._isExecuting = false;
|
||||
|
||||
@@ -10,8 +10,8 @@ import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
|
||||
|
||||
import { Dimension } from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as UUID from 'vs/base/common/uuid';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class QueryPlanState {
|
||||
xml: string;
|
||||
@@ -25,6 +25,10 @@ export class QueryPlanTab implements IPanelTab {
|
||||
constructor() {
|
||||
this.view = new QueryPlanView();
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
dispose(this.view);
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryPlanView implements IPanelView {
|
||||
@@ -44,6 +48,12 @@ export class QueryPlanView implements IPanelView {
|
||||
this.container.style.overflow = 'scroll';
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.container.remove();
|
||||
this.qp = undefined;
|
||||
this.container = undefined;
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void {
|
||||
this.container.style.width = dimension.width + 'px';
|
||||
this.container.style.height = dimension.height + 'px';
|
||||
|
||||
@@ -41,13 +41,13 @@ export class DialogModal extends Modal {
|
||||
name: string,
|
||||
options: IModalOptions,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService
|
||||
) {
|
||||
super(_dialog.title, name, partService, telemetryService, clipboardService, contextKeyService, options);
|
||||
super(_dialog.title, name, partService, telemetryService, clipboardService, themeService, contextKeyService, options);
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.dialogModal-hidden {
|
||||
|
||||
@@ -46,13 +46,13 @@ export class WizardModal extends Modal {
|
||||
name: string,
|
||||
options: IModalOptions,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(_wizard.title, name, partService, telemetryService, clipboardService, contextKeyService, options);
|
||||
super(_wizard.title, name, partService, telemetryService, clipboardService, themeService, contextKeyService, options);
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
|
||||
@@ -42,13 +42,13 @@ export class ErrorMessageDialog extends Modal {
|
||||
public onOk: Event<void> = this._onOk.event;
|
||||
|
||||
constructor(
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
@IPartService partService: IPartService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super('', TelemetryKeys.ErrorMessage, partService, telemetryService, clipboardService, contextKeyService, { isFlyout: false, hasTitleIcon: true });
|
||||
super('', TelemetryKeys.ErrorMessage, partService, telemetryService, clipboardService, themeService, contextKeyService, { isFlyout: false, hasTitleIcon: true });
|
||||
this._okLabel = localize('errorMessageDialog.ok', 'OK');
|
||||
this._closeLabel = localize('errorMessageDialog.close', 'Close');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user