mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Scroll properties (#1244)
* properties isn't scrolling * working on edge cases * formatting * formatting * formatting
This commit is contained in:
75
src/sql/base/browser/ui/scrollable/scrollable.directive.ts
Normal file
75
src/sql/base/browser/ui/scrollable/scrollable.directive.ts
Normal 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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user