diff --git a/src/sql/parts/dashboard/common/actions.ts b/src/sql/parts/dashboard/common/actions.ts index b060b3966a..67fbd3f00f 100644 --- a/src/sql/parts/dashboard/common/actions.ts +++ b/src/sql/parts/dashboard/common/actions.ts @@ -197,3 +197,36 @@ export class AddFeatureTabAction extends Action { } } } + +export class CollapseWidgetAction extends Action { + private static readonly ID = 'collapseWidget'; + private static readonly COLLPASE_LABEL = nls.localize('collapseWidget', "Collapse"); + private static readonly EXPAND_LABEL = nls.localize('expandWidget', "Expand"); + private static readonly COLLAPSE_ICON = 'maximize-panel-action'; + private static readonly EXPAND_ICON = 'minimize-panel-action'; + + constructor( + private _uri: string, + private _widgetUuid: string, + private collpasedState: boolean, + @IAngularEventingService private _angularEventService: IAngularEventingService + ) { + super( + CollapseWidgetAction.ID, + collpasedState ? CollapseWidgetAction.EXPAND_LABEL : CollapseWidgetAction.COLLPASE_LABEL, + collpasedState ? CollapseWidgetAction.EXPAND_ICON : CollapseWidgetAction.COLLAPSE_ICON + ); + } + + run(): TPromise { + this._toggleState(); + this._angularEventService.sendAngularEvent(this._uri, AngularEventType.COLLAPSE_WIDGET, this._widgetUuid); + return TPromise.as(true); + } + + private _toggleState(): void { + this.collpasedState = !this.collpasedState; + this._setClass(this.collpasedState ? CollapseWidgetAction.EXPAND_ICON : CollapseWidgetAction.COLLAPSE_ICON); + this._setLabel(this.collpasedState ? CollapseWidgetAction.EXPAND_LABEL : CollapseWidgetAction.COLLPASE_LABEL); + } +} diff --git a/src/sql/parts/dashboard/common/dashboardPage.component.ts b/src/sql/parts/dashboard/common/dashboardPage.component.ts index f9f734e8cd..bc961bb7ea 100644 --- a/src/sql/parts/dashboard/common/dashboardPage.component.ts +++ b/src/sql/parts/dashboard/common/dashboardPage.component.ts @@ -89,7 +89,6 @@ export abstract class DashboardPage extends Disposable implements OnDestroy { constructor( @Inject(forwardRef(() => DashboardServiceInterface)) protected dashboardService: DashboardServiceInterface, - @Inject(BOOTSTRAP_SERVICE_ID) protected bootstrapService: IBootstrapService, @Inject(forwardRef(() => ElementRef)) protected _el: ElementRef, @Inject(forwardRef(() => ChangeDetectorRef)) protected _cd: ChangeDetectorRef ) { @@ -252,12 +251,14 @@ export abstract class DashboardPage extends Disposable implements OnDestroy { } private getProperties(): Array { - let properties = this.dashboardService.getSettings([this.context, 'properties'].join('.')); + let properties = this.dashboardService.getSettings([this.context, 'properties'].join('.')); this._propertiesConfigLocation = 'default'; if (types.isUndefinedOrNull(properties)) { return [this.propertiesWidget]; } else if (types.isBoolean(properties)) { return properties ? [this.propertiesWidget] : []; + } else if (types.isString(properties) && properties === 'collapsed') { + return [this.propertiesWidget]; } else if (types.isArray(properties)) { return properties.map((item) => { let retVal = Object.assign({}, this.propertiesWidget); @@ -302,6 +303,6 @@ export abstract class DashboardPage extends Disposable implements OnDestroy { let index = this.tabs.findIndex(i => i.id === tab.identifier); this.tabs.splice(index, 1); this._cd.detectChanges(); - this.bootstrapService.angularEventingService.sendAngularEvent(this.dashboardService.getUnderlyingUri(), AngularEventType.CLOSE_TAB, { id: tab.identifier }); + this.dashboardService.angularEventingService.sendAngularEvent(this.dashboardService.getUnderlyingUri(), AngularEventType.CLOSE_TAB, { id: tab.identifier }); } } diff --git a/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts index 42baf086da..f4af4c096b 100644 --- a/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts @@ -5,11 +5,15 @@ import 'vs/css!./dashboardHomeContainer'; -import { Component, forwardRef, Input } from '@angular/core'; +import { Component, forwardRef, Input, ChangeDetectorRef, Inject, ViewChild } from '@angular/core'; import { DashboardWidgetContainer } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.component'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget'; +import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; +import { AngularEventType } from '../../../services/angularEventing/angularEventingService'; +import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @Component({ selector: 'dashboard-home-container', @@ -17,7 +21,8 @@ import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget'; template: `
- + @@ -27,4 +32,30 @@ import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget'; }) export class DashboardHomeContainer extends DashboardWidgetContainer { @Input() private properties: WidgetConfig; + @ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper; + + constructor( + @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, + @Inject(forwardRef(() => DashboardServiceInterface)) protected dashboardService: DashboardServiceInterface, + + ) { + super(_cd); + } + + ngAfterContentInit() { + let collapsedVal = this.dashboardService.getSettings(`${this.properties.context}.properties`); + if (collapsedVal === 'collapsed') { + this._propertiesClass.collapsed = true; + } + this.dashboardService.angularEventingService.onAngularEvent(this.dashboardService.getUnderlyingUri(), event => { + if (event.event === AngularEventType.COLLAPSE_WIDGET && this._propertiesClass && event.payload === this._propertiesClass.guid) { + this._propertiesClass.collapsed = !this._propertiesClass.collapsed; + this._cd.detectChanges(); + this.dashboardService.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { + key: `dashboard.${this.properties.context}.properties`, + value: this._propertiesClass.collapsed ? 'collapsed' : true + }); + } + }); + } } diff --git a/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts index 6374ebf0b1..d5a3053157 100644 --- a/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts @@ -43,7 +43,7 @@ export class DashboardWidgetContainer extends DashboardTab implements OnDestroy, private _scrollableElement: ScrollableElement; - @ViewChild(WidgetContent) private _widgetContent: WidgetContent; + @ViewChild(WidgetContent) protected _widgetContent: WidgetContent; @ViewChild('scrollable', { read: ElementRef }) private _scrollable: ElementRef; @ViewChild('scrollContainer', { read: ElementRef }) private _scrollContainer: ElementRef; diff --git a/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.html b/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.html index 26a6340105..97a10d1655 100644 --- a/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.html +++ b/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.html @@ -13,6 +13,8 @@
- + + + diff --git a/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.ts b/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.ts index 7a5aff66cd..2f48792211 100644 --- a/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.ts +++ b/src/sql/parts/dashboard/contents/dashboardWidgetWrapper.component.ts @@ -14,7 +14,7 @@ import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost import { WidgetConfig, WIDGET_CONFIG, IDashboardWidget } from 'sql/parts/dashboard/common/dashboardWidget'; import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry'; import { error } from 'sql/base/common/log'; -import { RefreshWidgetAction, ToggleMoreWidgetAction, DeleteWidgetAction } from 'sql/parts/dashboard/common/actions'; +import { RefreshWidgetAction, ToggleMoreWidgetAction, DeleteWidgetAction, CollapseWidgetAction } from 'sql/parts/dashboard/common/actions'; /* Widgets */ import { PropertiesWidgetComponent } from 'sql/parts/dashboard/widgets/properties/propertiesWidget.component'; @@ -32,6 +32,8 @@ import * as themeColors from 'vs/workbench/common/theme'; import { Action } from 'vs/base/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { memoize } from 'vs/base/common/decorators'; +import { generateUuid } from 'vs/base/common/uuid'; const componentMap: { [x: string]: Type } = { 'properties-widget': PropertiesWidgetComponent, @@ -45,8 +47,32 @@ const componentMap: { [x: string]: Type } = { selector: 'dashboard-widget-wrapper', templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/contents/dashboardWidgetWrapper.component.html')) }) -export class DashboardWidgetWrapper implements AfterContentInit, OnInit, OnDestroy { +export class DashboardWidgetWrapper implements OnInit, OnDestroy { @Input() private _config: WidgetConfig; + @Input() private collapsable = false; + + private _collapsed = false; + + public get collapsed(): boolean { + return this._collapsed; + } + + public set collapsed(val: boolean) { + if (val === this._collapsed) { + return; + } + this._collapsed = val; + this._changeref.detectChanges(); + if (!val) { + this.loadWidget(); + } + } + + @memoize + public get guid(): string { + return generateUuid(); + } + private _themeDispose: IDisposable; private _actions: Array; private _component: IDashboardWidget; @@ -71,12 +97,17 @@ export class DashboardWidgetWrapper implements AfterContentInit, OnInit, OnDestr }); } - ngAfterContentInit() { + ngAfterViewInit() { this.updateTheme(this._bootstrap.themeService.getColorTheme()); - this.loadWidget(); + if (this.componentHost) { + this.loadWidget(); + } this._changeref.detectChanges(); this._actionbar = new ActionBar(this._actionbarRef.nativeElement); if (this._actions) { + if (this.collapsable) { + this._actionbar.push(this._bootstrap.instantiationService.createInstance(CollapseWidgetAction, this._bootstrap.getUnderlyingUri(), this.guid, this.collapsed), { icon: true, label: false }); + } this._actionbar.push(this._bootstrap.instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, this._component.actionsContext), { icon: true, label: false }); } this.layout(); diff --git a/src/sql/parts/dashboard/pages/databaseDashboardPage.component.ts b/src/sql/parts/dashboard/pages/databaseDashboardPage.component.ts index ea8106c241..e03fb9d382 100644 --- a/src/sql/parts/dashboard/pages/databaseDashboardPage.component.ts +++ b/src/sql/parts/dashboard/pages/databaseDashboardPage.component.ts @@ -35,12 +35,11 @@ export class DatabaseDashboardPage extends DashboardPage implements OnInit { constructor( @Inject(forwardRef(() => IBreadcrumbService)) private _breadcrumbService: IBreadcrumbService, - @Inject(BOOTSTRAP_SERVICE_ID) bootstrapService: IBootstrapService, @Inject(forwardRef(() => DashboardServiceInterface)) dashboardService: DashboardServiceInterface, @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, @Inject(forwardRef(() => ElementRef)) el: ElementRef ) { - super(dashboardService, bootstrapService, el, _cd); + super(dashboardService, el, _cd); this._register(dashboardService.onUpdatePage(() => { this.refresh(true); this._cd.detectChanges(); diff --git a/src/sql/parts/dashboard/pages/databaseDashboardPage.contribution.ts b/src/sql/parts/dashboard/pages/databaseDashboardPage.contribution.ts index 9f8e5e3a58..d45054827f 100644 --- a/src/sql/parts/dashboard/pages/databaseDashboardPage.contribution.ts +++ b/src/sql/parts/dashboard/pages/databaseDashboardPage.contribution.ts @@ -12,6 +12,10 @@ export const databaseDashboardPropertiesSchema: IJSONSchema = { default: true, oneOf: [ { type: 'boolean' }, + { + type: 'string', + enum: ['collapsed'] + }, { type: 'array', items: { diff --git a/src/sql/parts/dashboard/pages/serverDashboardPage.component.ts b/src/sql/parts/dashboard/pages/serverDashboardPage.component.ts index 80719ff325..d690b6cf76 100644 --- a/src/sql/parts/dashboard/pages/serverDashboardPage.component.ts +++ b/src/sql/parts/dashboard/pages/serverDashboardPage.component.ts @@ -36,12 +36,11 @@ export class ServerDashboardPage extends DashboardPage implements OnInit { constructor( @Inject(forwardRef(() => IBreadcrumbService)) private breadcrumbService: IBreadcrumbService, - @Inject(BOOTSTRAP_SERVICE_ID) bootstrapService: IBootstrapService, @Inject(forwardRef(() => DashboardServiceInterface)) dashboardService: DashboardServiceInterface, @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, @Inject(forwardRef(() => ElementRef)) el: ElementRef ) { - super(dashboardService, bootstrapService, el, _cd); + super(dashboardService, el, _cd); // revert back to default database this._letDashboardPromise = this.dashboardService.connectionManagementService.changeDatabase('master'); } diff --git a/src/sql/parts/dashboard/pages/serverDashboardPage.contribution.ts b/src/sql/parts/dashboard/pages/serverDashboardPage.contribution.ts index bbeeb211ab..a1771af529 100644 --- a/src/sql/parts/dashboard/pages/serverDashboardPage.contribution.ts +++ b/src/sql/parts/dashboard/pages/serverDashboardPage.contribution.ts @@ -20,6 +20,10 @@ export const serverDashboardPropertiesSchema: IJSONSchema = { default: true, oneOf: [ { type: 'boolean' }, + { + type: 'string', + enum: ['collapsed'] + }, { type: 'object', properties: { diff --git a/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts b/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts index 80bbd30130..efde92d62c 100644 --- a/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts +++ b/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts @@ -20,7 +20,7 @@ import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils'; import { IInsightsDialogService } from 'sql/parts/insights/common/interfaces'; import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; -import { AngularEventType, IAngularEvent } from 'sql/services/angularEventing/angularEventingService'; +import { AngularEventType, IAngularEvent, IAngularEventingService } from 'sql/services/angularEventing/angularEventingService'; import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry'; import { PinConfig } from 'sql/parts/dashboard/common/dashboardWidget'; @@ -137,6 +137,7 @@ export class DashboardServiceInterface implements OnDestroy { private _commandService: ICommandService; private _dashboardWebviewService: IDashboardWebviewService; private _partService: IPartService; + private _angularEventingService: IAngularEventingService; private _updatePage = new Emitter(); public readonly onUpdatePage: Event = this._updatePage.event; @@ -171,6 +172,7 @@ export class DashboardServiceInterface implements OnDestroy { this._commandService = this._bootstrapService.commandService; this._dashboardWebviewService = this._bootstrapService.dashboardWebviewService; this._partService = this._bootstrapService.partService; + this._angularEventingService = this._bootstrapService.angularEventingService; } ngOnDestroy() { @@ -241,6 +243,10 @@ export class DashboardServiceInterface implements OnDestroy { return this._capabilitiesService; } + public get angularEventingService(): IAngularEventingService { + return this._angularEventingService; + } + /** * Set the selector for this dashboard instance, should only be set once */ diff --git a/src/sql/parts/dashboard/widgets/explorer/explorerWidget.component.ts b/src/sql/parts/dashboard/widgets/explorer/explorerWidget.component.ts index 88d619edb9..f4cf153eee 100644 --- a/src/sql/parts/dashboard/widgets/explorer/explorerWidget.component.ts +++ b/src/sql/parts/dashboard/widgets/explorer/explorerWidget.component.ts @@ -43,6 +43,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, private _treeDataSource = new ExplorerDataSource(); private _treeFilter = new ExplorerFilter(); + private _inited = false; + @ViewChild('input') private _inputContainer: ElementRef; @ViewChild('table') private _tableContainer: ElementRef; @@ -58,6 +60,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, } ngOnInit() { + this._inited = true; + let inputOptions: IInputOptions = { placeholder: this._config.context === 'database' ? nls.localize('seachObjects', 'Search by name of type (a:, t:, v:, f:, or sp:)') : nls.localize('searchDatabases', 'Search databases') }; @@ -120,6 +124,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, } public layout(): void { - this._tree.layout(getContentHeight(this._tableContainer.nativeElement)); + if (this._inited) { + this._tree.layout(getContentHeight(this._tableContainer.nativeElement)); + } } } diff --git a/src/sql/parts/dashboard/widgets/tasks/tasksWidget.component.ts b/src/sql/parts/dashboard/widgets/tasks/tasksWidget.component.ts index dcce7455d2..a09cfe62f7 100644 --- a/src/sql/parts/dashboard/widgets/tasks/tasksWidget.component.ts +++ b/src/sql/parts/dashboard/widgets/tasks/tasksWidget.component.ts @@ -46,6 +46,8 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On private _scrollableElement: ScrollableElement; private $container: Builder; + private _inited = false; + @ViewChild('container', { read: ElementRef }) private _container: ElementRef; constructor( @@ -67,6 +69,7 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On } ngOnInit() { + this._inited = true; this._register(registerThemingParticipant(this.registerThemeing)); this._computeContainer(); @@ -137,11 +140,13 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On } public layout(): void { - this._computeContainer(); - // Update scrollbar - this._scrollableElement.setScrollDimensions({ - width: DOM.getContentWidth(this._container.nativeElement), - scrollWidth: DOM.getContentWidth(this.$container.getHTMLElement()) + 18 // right padding - }); + if (this._inited) { + this._computeContainer(); + // Update scrollbar + this._scrollableElement.setScrollDimensions({ + width: DOM.getContentWidth(this._container.nativeElement), + scrollWidth: DOM.getContentWidth(this.$container.getHTMLElement()) + 18 // right padding + }); + } } } diff --git a/src/sql/services/angularEventing/angularEventingService.ts b/src/sql/services/angularEventing/angularEventingService.ts index fa355f9dcb..86f8773c6f 100644 --- a/src/sql/services/angularEventing/angularEventingService.ts +++ b/src/sql/services/angularEventing/angularEventingService.ts @@ -17,7 +17,8 @@ export enum AngularEventType { DELETE_WIDGET, PINUNPIN_TAB, NEW_TABS, - CLOSE_TAB + CLOSE_TAB, + COLLAPSE_WIDGET } export interface IDeleteWidgetPayload {