Scroll properties (#1244)

* properties isn't scrolling

* working on edge cases

* formatting

* formatting

* formatting
This commit is contained in:
Anthony Dresser
2018-04-26 14:10:08 -07:00
committed by GitHub
parent b1752ea635
commit a78fa9c0f2
4 changed files with 132 additions and 41 deletions

View File

@@ -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() {
}
}

View File

@@ -5,33 +5,37 @@
import 'vs/css!./dashboardHomeContainer'; 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 { DashboardWidgetContainer } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.component';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget'; import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.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 { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
@Component({ @Component({
selector: 'dashboard-home-container', selector: 'dashboard-home-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }], providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }],
template: ` template: `
<div class="fullsize" style="display: flex; flex-direction: column"> <div class="fullsize" style="display: flex; flex-direction: column">
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties" <div scrollable>
style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'"> <dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
</dashboard-widget-wrapper> style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
<widget-content style="flex: 1" [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context"> </dashboard-widget-wrapper>
</widget-content> <widget-content style="flex: 1" [scrollContent]="false" [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>
</div>
</div> </div>
` `
}) })
export class DashboardHomeContainer extends DashboardWidgetContainer { export class DashboardHomeContainer extends DashboardWidgetContainer {
@Input() private properties: WidgetConfig; @Input() private properties: WidgetConfig;
@ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper; @ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper;
@ContentChild(ScrollableDirective) private _scrollable;
constructor( constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
@@ -56,4 +60,9 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
} }
}); });
} }
public layout() {
super.layout();
this._scrollable.layout();
}
} }

View File

@@ -75,6 +75,7 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit {
@Input() private widgets: WidgetConfig[]; @Input() private widgets: WidgetConfig[];
@Input() private originalConfig: WidgetConfig[]; @Input() private originalConfig: WidgetConfig[];
@Input() private context: string; @Input() private context: string;
@Input() private scrollContent = true;
private _scrollableElement: ScrollableElement; private _scrollableElement: ScrollableElement;
@@ -123,41 +124,43 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit {
} }
ngAfterViewInit() { ngAfterViewInit() {
let container = this._scrollContainer.nativeElement as HTMLElement; if (this.scrollContent) {
let scrollable = this._scrollable.nativeElement as HTMLElement; let container = this._scrollContainer.nativeElement as HTMLElement;
container.removeChild(scrollable); let scrollable = this._scrollable.nativeElement as HTMLElement;
container.removeChild(scrollable);
this._scrollableElement = new ScrollableElement(scrollable, { this._scrollableElement = new ScrollableElement(scrollable, {
horizontal: ScrollbarVisibility.Hidden, horizontal: ScrollbarVisibility.Hidden,
vertical: ScrollbarVisibility.Auto, vertical: ScrollbarVisibility.Auto,
useShadows: false useShadows: false
}); });
this._scrollableElement.onScroll(e => { this._scrollableElement.onScroll(e => {
scrollable.style.bottom = e.scrollTop + 'px'; scrollable.style.bottom = e.scrollTop + 'px';
}); });
container.appendChild(this._scrollableElement.getDomNode()); container.appendChild(this._scrollableElement.getDomNode());
let initalHeight = getContentHeight(scrollable); let initalHeight = getContentHeight(scrollable);
this._scrollableElement.setScrollDimensions({ this._scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(scrollable), scrollHeight: getContentHeight(scrollable),
height: getContentHeight(container) height: getContentHeight(container)
}); });
this._register(addDisposableListener(window, EventType.RESIZE, () => { this._register(addDisposableListener(window, EventType.RESIZE, () => {
this.resetScrollDimensions(); this.resetScrollDimensions();
})); }));
// unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point // unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point
setTimeout(() => { setTimeout(() => {
let currentheight = getContentHeight(scrollable); let currentheight = getContentHeight(scrollable);
if (initalHeight !== currentheight) { if (initalHeight !== currentheight) {
this._scrollableElement.setScrollDimensions({ this._scrollableElement.setScrollDimensions({
scrollHeight: currentheight, scrollHeight: currentheight,
height: getContentHeight(container) height: getContentHeight(container)
}); });
} }
}, 200); }, 200);
}
} }
public layout() { public layout() {
@@ -167,7 +170,9 @@ export class WidgetContent extends AngularDisposable implements AfterViewInit {
}); });
} }
this._grid.triggerResize(); this._grid.triggerResize();
this.resetScrollDimensions(); if (this.scrollContent) {
this.resetScrollDimensions();
}
} }
private resetScrollDimensions() { private resetScrollDimensions() {

View File

@@ -54,9 +54,10 @@ import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.comp
import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component'; import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component';
let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer, let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer,
DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, ModelViewContent, WebviewContent, WidgetContent, DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, ModelViewContent, WebviewContent, WidgetContent,
ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer, ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer,
JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper]; JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper,
ScrollableDirective];
/* Panel */ /* Panel */
import { PanelModule } from 'sql/base/browser/ui/panel/panel.module'; 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 { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component';
import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component'; import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component';
import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component'; import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
let widgetComponents = [ let widgetComponents = [
PropertiesWidgetComponent, PropertiesWidgetComponent,