diff --git a/src/sql/base/browser/ui/scrollable/scrollable.directive.ts b/src/sql/base/browser/ui/scrollable/scrollable.directive.ts new file mode 100644 index 0000000000..f2488871e3 --- /dev/null +++ b/src/sql/base/browser/ui/scrollable/scrollable.directive.ts @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Directive, Inject, forwardRef, ElementRef } from '@angular/core'; + +import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { getContentHeight, addDisposableListener, EventType } from 'vs/base/browser/dom'; +import { AngularDisposable } from 'sql/base/common/lifecycle'; + +@Directive({ + selector: '[scrollable]' +}) +export class ScrollableDirective extends AngularDisposable { + private scrollableElement: ScrollableElement; + private parent: HTMLElement; + private scrolled: HTMLElement; + + constructor( + @Inject(forwardRef(() => ElementRef)) private _el: ElementRef + ) { + super(); + this.scrolled = this._el.nativeElement as HTMLElement; + this.parent = this.scrolled.parentElement; + this.parent.removeChild(this.scrolled); + + this.scrolled.style.position = 'relative'; + + this.scrollableElement = new ScrollableElement(this.scrolled, { + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Auto, + useShadows: false + }); + + this.scrollableElement.onScroll(e => { + this.scrolled.style.bottom = e.scrollTop + 'px'; + }); + + this.parent.appendChild(this.scrollableElement.getDomNode()); + const initialHeight = getContentHeight(this.scrolled); + this.scrollableElement.setScrollDimensions({ + scrollHeight: getContentHeight(this.scrolled), + height: getContentHeight(this.parent) + }); + + this._register(addDisposableListener(window, EventType.RESIZE, () => { + this.resetScrollDimensions(); + })); + + // unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point + setTimeout(() => { + let currentheight = getContentHeight(this.scrolled); + if (initialHeight !== currentheight) { + this.scrollableElement.setScrollDimensions({ + scrollHeight: currentheight, + height: getContentHeight(this.parent) + }); + } + }, 200); + + } + + private resetScrollDimensions() { + this.scrollableElement.setScrollDimensions({ + scrollHeight: getContentHeight(this.scrolled), + height: getContentHeight(this.parent) + }); + } + + public layout() { + + } +} diff --git a/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts index 2685243ae1..7e224e975c 100644 --- a/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardHomeContainer.component.ts @@ -5,33 +5,37 @@ import 'vs/css!./dashboardHomeContainer'; -import { Component, forwardRef, Input, ChangeDetectorRef, Inject, ViewChild } from '@angular/core'; +import { Component, forwardRef, Input, ChangeDetectorRef, Inject, ViewChild, ContentChild } 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 { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; -import { AngularEventType } from '../../../services/angularEventing/angularEventingService'; +import { AngularEventType } from 'sql/services/angularEventing/angularEventingService'; import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive'; @Component({ selector: 'dashboard-home-container', providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }], template: `
- - - - +
+ + + + +
` }) export class DashboardHomeContainer extends DashboardWidgetContainer { @Input() private properties: WidgetConfig; @ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper; + @ContentChild(ScrollableDirective) private _scrollable; constructor( @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, @@ -56,4 +60,9 @@ export class DashboardHomeContainer extends DashboardWidgetContainer { } }); } + + public layout() { + super.layout(); + this._scrollable.layout(); + } } diff --git a/src/sql/parts/dashboard/contents/widgetContent.component.ts b/src/sql/parts/dashboard/contents/widgetContent.component.ts index dbd313ad64..1498f691fb 100644 --- a/src/sql/parts/dashboard/contents/widgetContent.component.ts +++ b/src/sql/parts/dashboard/contents/widgetContent.component.ts @@ -75,6 +75,7 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit { @Input() private widgets: WidgetConfig[]; @Input() private originalConfig: WidgetConfig[]; @Input() private context: string; + @Input() private scrollContent = true; private _scrollableElement: ScrollableElement; @@ -123,41 +124,43 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit { } ngAfterViewInit() { - let container = this._scrollContainer.nativeElement as HTMLElement; - let scrollable = this._scrollable.nativeElement as HTMLElement; - container.removeChild(scrollable); + if (this.scrollContent) { + let container = this._scrollContainer.nativeElement as HTMLElement; + let scrollable = this._scrollable.nativeElement as HTMLElement; + container.removeChild(scrollable); - this._scrollableElement = new ScrollableElement(scrollable, { - horizontal: ScrollbarVisibility.Hidden, - vertical: ScrollbarVisibility.Auto, - useShadows: false - }); + this._scrollableElement = new ScrollableElement(scrollable, { + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Auto, + useShadows: false + }); - this._scrollableElement.onScroll(e => { - scrollable.style.bottom = e.scrollTop + 'px'; - }); + this._scrollableElement.onScroll(e => { + scrollable.style.bottom = e.scrollTop + 'px'; + }); - container.appendChild(this._scrollableElement.getDomNode()); - let initalHeight = getContentHeight(scrollable); - this._scrollableElement.setScrollDimensions({ - scrollHeight: getContentHeight(scrollable), - height: getContentHeight(container) - }); + container.appendChild(this._scrollableElement.getDomNode()); + let initalHeight = getContentHeight(scrollable); + this._scrollableElement.setScrollDimensions({ + scrollHeight: getContentHeight(scrollable), + height: getContentHeight(container) + }); - this._register(addDisposableListener(window, EventType.RESIZE, () => { - this.resetScrollDimensions(); - })); + this._register(addDisposableListener(window, EventType.RESIZE, () => { + this.resetScrollDimensions(); + })); - // unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point - setTimeout(() => { - let currentheight = getContentHeight(scrollable); - if (initalHeight !== currentheight) { - this._scrollableElement.setScrollDimensions({ - scrollHeight: currentheight, - height: getContentHeight(container) - }); - } - }, 200); + // unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point + setTimeout(() => { + let currentheight = getContentHeight(scrollable); + if (initalHeight !== currentheight) { + this._scrollableElement.setScrollDimensions({ + scrollHeight: currentheight, + height: getContentHeight(container) + }); + } + }, 200); + } } public layout() { @@ -167,7 +170,9 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit { }); } this._grid.triggerResize(); - this.resetScrollDimensions(); + if (this.scrollContent) { + this.resetScrollDimensions(); + } } private resetScrollDimensions() { diff --git a/src/sql/parts/dashboard/dashboard.module.ts b/src/sql/parts/dashboard/dashboard.module.ts index 20dde955ae..2f904218e4 100644 --- a/src/sql/parts/dashboard/dashboard.module.ts +++ b/src/sql/parts/dashboard/dashboard.module.ts @@ -54,9 +54,10 @@ import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.comp import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component'; let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer, - DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, ModelViewContent, WebviewContent, WidgetContent, - ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer, - JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper]; + DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, ModelViewContent, WebviewContent, WidgetContent, + ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer, + JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper, + ScrollableDirective]; /* Panel */ import { PanelModule } from 'sql/base/browser/ui/panel/panel.module'; @@ -74,6 +75,7 @@ import { TasksWidget } from 'sql/parts/dashboard/widgets/tasks/tasksWidget.compo import { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component'; import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component'; import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component'; +import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive'; let widgetComponents = [ PropertiesWidgetComponent,