Fix the scrollbar issue in widget container (#1016)

* fix the scrollbar issue in widget container

* move scrollbar to widget content
This commit is contained in:
Abbie Petchtes
2018-04-03 16:16:58 -07:00
committed by GitHub
parent 3d1c1aefb3
commit f9b2136494
7 changed files with 88 additions and 90 deletions

View File

@@ -208,7 +208,7 @@ export abstract class DashboardPage extends AngularDisposable {
configs = cb.apply(this, [configs, this.dashboardService, this.context]);
});
this._gridModifiers.forEach(cb => {
configs = cb.apply(this, [configs, this._originalConfig]);
configs = cb.apply(this, [configs]);
});
if (key === WIDGETS_CONTAINER) {
return { id: v.id, title: v.title, container: { 'widgets-container': configs }, alwaysShow: v.alwaysShow };

View File

@@ -19,15 +19,11 @@ import { ConfigurationTarget } from 'vs/platform/configuration/common/configurat
selector: 'dashboard-home-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }],
template: `
<div class="scroll-container" #scrollContainer>
<div class="scrollable" #scrollable>
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
style="padding-left: 10px; padding-right: 10px; display: block" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
</dashboard-widget-wrapper>
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>
</div>
</div>
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
style="padding-left: 10px; padding-right: 10px; display: block" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
</dashboard-widget-wrapper>
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>
`
})
export class DashboardHomeContainer extends DashboardWidgetContainer {

View File

@@ -5,7 +5,7 @@
import 'vs/css!./dashboardWidgetContainer';
import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, EventEmitter, OnChanges, AfterContentInit } from '@angular/core';
import { Component, Inject, Input, forwardRef, ViewChild, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, EventEmitter, OnChanges, AfterContentInit } from '@angular/core';
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
@@ -19,20 +19,13 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import * as objects from 'vs/base/common/objects';
import Event, { Emitter } from 'vs/base/common/event';
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';
@Component({
selector: 'dashboard-widget-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardWidgetContainer) }],
template: `
<div class="scroll-container" #scrollContainer>
<div class="scrollable" #scrollable>
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>
</div>
</div>
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>
`
})
export class DashboardWidgetContainer extends DashboardTab implements OnDestroy, OnChanges, AfterContentInit {
@@ -41,13 +34,8 @@ export class DashboardWidgetContainer extends DashboardTab implements OnDestroy,
private _onResize = new Emitter<void>();
public readonly onResize: Event<void> = this._onResize.event;
private _scrollableElement: ScrollableElement;
@ViewChild(WidgetContent) protected _widgetContent: WidgetContent;
@ViewChild('scrollable', { read: ElementRef }) private _scrollable: ElementRef;
@ViewChild('scrollContainer', { read: ElementRef }) private _scrollContainer: ElementRef;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) protected _cd: ChangeDetectorRef
) {
@@ -67,50 +55,6 @@ export class DashboardWidgetContainer extends DashboardTab implements OnDestroy,
}));
}
ngAfterViewInit() {
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.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)
});
this._register(addDisposableListener(window, EventType.RESIZE, () => {
// Todo: Need to set timeout because we have to make sure that the grids have already rearraged before the getContentHeight gets called.
setTimeout(() => {
this._scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(scrollable),
height: getContentHeight(container)
});
}, 100);
}));
// 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);
}
ngOnDestroy() {
this.dispose();
}
@@ -124,12 +68,6 @@ export class DashboardWidgetContainer extends DashboardTab implements OnDestroy,
}
public layout() {
let container = this._scrollContainer.nativeElement as HTMLElement;
let scrollable = this._scrollable.nativeElement as HTMLElement;
this._scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(scrollable),
height: getContentHeight(container)
});
this._widgetContent.layout();
}

View File

@@ -7,12 +7,3 @@ dashboard-widget-container {
height: 100%;
width: 100%;
}
.scroll-container {
height: 100%;
width: 100%;
}
.scrollable {
position: relative;
}

View File

@@ -4,7 +4,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<div [ngGrid]="gridConfig" *ngIf="widgets" >
<dashboard-widget-wrapper *ngFor="let widget of widgets" [(ngGridItem)]="widget.gridItemConfig" [_config]="widget">
</dashboard-widget-wrapper>
<div class="scroll-container" #scrollContainer>
<div class="scrollable" #scrollable>
<div [ngGrid]="gridConfig" *ngIf="widgets" >
<dashboard-widget-wrapper *ngFor="let widget of widgets" [(ngGridItem)]="widget.gridItemConfig" [_config]="widget">
</dashboard-widget-wrapper>
</div>
</div>
</div>

View File

@@ -5,18 +5,21 @@
import 'vs/css!./widgetContent';
import { Component, Inject, Input, forwardRef, ViewChild, ViewChildren, QueryList, ChangeDetectorRef } from '@angular/core';
import { Component, Inject, Input, forwardRef, ViewChild, ViewChildren, QueryList, ChangeDetectorRef, ElementRef, AfterViewInit } from '@angular/core';
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
import { subscriptionToDisposable, AngularDisposable } from 'sql/base/common/lifecycle';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import * as objects from 'vs/base/common/objects';
import Event, { Emitter } from 'vs/base/common/event';
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';
/**
* Sorting function for dashboard widgets
@@ -67,10 +70,13 @@ function configSorter(a, b): number {
selector: 'widget-content',
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/contents/widgetContent.component.html'))
})
export class WidgetContent {
export class WidgetContent extends AngularDisposable implements AfterViewInit {
@Input() private widgets: WidgetConfig[];
@Input() private originalConfig: WidgetConfig[];
@Input() private context: string;
private _scrollableElement: ScrollableElement;
private _onResize = new Emitter<void>();
public readonly onResize: Event<void> = this._onResize.event;
@@ -103,10 +109,51 @@ export class WidgetContent {
@ViewChild(NgGrid) private _grid: NgGrid;
@ViewChildren(DashboardWidgetWrapper) private _widgets: QueryList<DashboardWidgetWrapper>;
@ViewChildren(NgGridItem) private _items: QueryList<NgGridItem>;
@ViewChild('scrollable', { read: ElementRef }) private _scrollable: ElementRef;
@ViewChild('scrollContainer', { read: ElementRef }) private _scrollContainer: ElementRef;
constructor(
@Inject(forwardRef(() => DashboardServiceInterface)) protected dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) protected _cd: ChangeDetectorRef
) {
super();
}
ngAfterViewInit() {
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.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)
});
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);
}
public layout() {
@@ -116,6 +163,17 @@ export class WidgetContent {
});
}
this._grid.triggerResize();
this.resetScrollDimensions();
}
private resetScrollDimensions() {
let container = this._scrollContainer.nativeElement as HTMLElement;
let scrollable = this._scrollable.nativeElement as HTMLElement;
this._scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(scrollable),
height: getContentHeight(container)
});
}
public refresh(): void {
@@ -165,6 +223,7 @@ export class WidgetContent {
component.layout();
this._rewriteConfig();
this.resetScrollDimensions();
})));
this._editDispose.push(subscriptionToDisposable(this._grid.onDragStop.subscribe((e: NgGridItem) => {
this._onResize.fire();
@@ -182,6 +241,7 @@ export class WidgetContent {
this.originalConfig.sort(configSorter);
this._rewriteConfig();
this.resetScrollDimensions();
})));
this._widgets.forEach(i => {
if (i.id) {

View File

@@ -6,4 +6,13 @@
widget-content {
height: 100%;
width: 100%;
}
.scroll-container {
height: 100%;
width: 100%;
}
.scrollable {
position: relative;
}