mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Change angular panel display behavior (#1344)
* got it working * remove unneeded code * formatting * added scrollable, dashboard tabs don't scroll correctly though * fix all bugs I could find * address comments
This commit is contained in:
@@ -21,6 +21,12 @@ panel {
|
|||||||
.tabbedPanel .composite.title {
|
.tabbedPanel .composite.title {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabbedPanel .tabContainer {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel .tabList {
|
.tabbedPanel .tabList {
|
||||||
@@ -31,6 +37,7 @@ panel {
|
|||||||
line-height: 35px;
|
line-height: 35px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel .tabList .tab {
|
.tabbedPanel .tabList .tab {
|
||||||
@@ -88,17 +95,13 @@ panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.composite.title .title-actions {
|
.composite.title .title-actions {
|
||||||
flex: 1 1 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab > .tabLabel.active {
|
.tab > .tabLabel.active {
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.composite.title ~ tab.fullsize > :first-child {
|
|
||||||
height: calc(100% - 38px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabbedPanel .title-actions .panel-actions .actions-container {
|
.tabbedPanel .title-actions .panel-actions .actions-container {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import { Component, ContentChildren, QueryList, AfterContentInit, Inject, forwar
|
|||||||
|
|
||||||
import { TabComponent } from './tab.component';
|
import { TabComponent } from './tab.component';
|
||||||
import { TabHeaderComponent } from './tabHeader.component';
|
import { TabHeaderComponent } from './tabHeader.component';
|
||||||
|
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
|
||||||
import './panelStyles';
|
import './panelStyles';
|
||||||
|
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
@@ -46,12 +46,13 @@ let idPool = 0;
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'panel',
|
selector: 'panel',
|
||||||
template: `
|
template: `
|
||||||
|
<div class="tabbedPanel fullsize" [ngClass]="options.layout === NavigationBarLayout.vertical ? 'vertical' : 'horizontal'">
|
||||||
<div class="tabbedPanel fullsize" #tabbedPanel>
|
<div *ngIf="!options.showTabsWhenOne ? _tabs.length !== 1 : true" class="composite title">
|
||||||
<div *ngIf="!options.showTabsWhenOne ? _tabs.length !== 1 : true" class="composite title" #titleContainer>
|
<div class="tabContainer">
|
||||||
<div class="tabList" #tabList role="tablist">
|
<div class="tabList" role="tablist" scrollable [horizontalScroll]="ScrollbarVisibility.Auto" [verticalScroll]="ScrollbarVisibility.Hidden" [scrollYToX]="true">
|
||||||
<div *ngFor="let tab of _tabs">
|
<div *ngFor="let tab of _tabs">
|
||||||
<tab-header [tab]="tab" [showIcon]="options.showIcon" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'> </tab-header>
|
<tab-header [active]="_activeTab === tab" [tab]="tab" [showIcon]="options.showIcon" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'> </tab-header>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="title-actions">
|
<div class="title-actions">
|
||||||
@@ -67,11 +68,12 @@ let idPool = 0;
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class PanelComponent extends Disposable implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
|
export class PanelComponent extends Disposable {
|
||||||
@Input() public options: IPanelOptions;
|
@Input() public options: IPanelOptions;
|
||||||
@Input() public actions: Array<Action>;
|
@Input() public actions: Array<Action>;
|
||||||
@ContentChildren(TabComponent) private _tabs: QueryList<TabComponent>;
|
@ContentChildren(TabComponent) private _tabs: QueryList<TabComponent>;
|
||||||
@ViewChildren(TabHeaderComponent) private _headerTabs: QueryList<TabHeaderComponent>;
|
@ViewChildren(TabHeaderComponent) private _headerTabs: QueryList<TabHeaderComponent>;
|
||||||
|
@ViewChild(ScrollableDirective) private scrollable: ScrollableDirective;
|
||||||
|
|
||||||
@Output() public onTabChange = new EventEmitter<TabComponent>();
|
@Output() public onTabChange = new EventEmitter<TabComponent>();
|
||||||
@Output() public onTabClose = new EventEmitter<TabComponent>();
|
@Output() public onTabClose = new EventEmitter<TabComponent>();
|
||||||
@@ -79,12 +81,11 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
|
|||||||
private _activeTab: TabComponent;
|
private _activeTab: TabComponent;
|
||||||
private _actionbar: ActionBar;
|
private _actionbar: ActionBar;
|
||||||
private _mru: TabComponent[];
|
private _mru: TabComponent[];
|
||||||
private _scrollableElement: ScrollableElement;
|
|
||||||
|
private ScrollbarVisibility = ScrollbarVisibility;
|
||||||
|
private NavigationBarLayout = NavigationBarLayout;
|
||||||
|
|
||||||
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
|
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
|
||||||
@ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
|
|
||||||
@ViewChild('titleContainer', { read: ElementRef }) private _titleContainer: ElementRef;
|
|
||||||
@ViewChild('tabList', { read: ElementRef }) private _tabList: ElementRef;
|
|
||||||
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
|
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -96,51 +97,14 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
|
|||||||
|
|
||||||
ngAfterContentInit(): void {
|
ngAfterContentInit(): void {
|
||||||
if (this._tabs && this._tabs.length > 0) {
|
if (this._tabs && this._tabs.length > 0) {
|
||||||
this._activeTab = this._tabs.first;
|
this.selectTab(this._tabs.first);
|
||||||
this._activeTab.active = true;
|
} else {
|
||||||
}
|
const sub = this._tabs.changes.subscribe(() => {
|
||||||
}
|
if (this._tabs && this._tabs.length > 0) {
|
||||||
|
this.selectTab(this._tabs.first);
|
||||||
ngAfterViewInit(): void {
|
sub.unsubscribe();
|
||||||
if (!this.options.showTabsWhenOne ? this._tabs.length !== 1 : true) {
|
}
|
||||||
let container = this._titleContainer.nativeElement as HTMLElement;
|
|
||||||
let tabList = this._tabList.nativeElement as HTMLElement;
|
|
||||||
container.removeChild(tabList);
|
|
||||||
|
|
||||||
this._scrollableElement = new ScrollableElement(tabList, {
|
|
||||||
horizontal: ScrollbarVisibility.Auto,
|
|
||||||
vertical: ScrollbarVisibility.Hidden,
|
|
||||||
scrollYToX: true,
|
|
||||||
useShadows: false,
|
|
||||||
horizontalScrollbarSize: 3
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this._scrollableElement.onScroll(e => {
|
|
||||||
tabList.scrollLeft = e.scrollLeft;
|
|
||||||
});
|
|
||||||
|
|
||||||
container.insertBefore(this._scrollableElement.getDomNode(), container.firstChild);
|
|
||||||
|
|
||||||
this._scrollableElement.setScrollDimensions({
|
|
||||||
width: tabList.offsetWidth,
|
|
||||||
scrollWidth: tabList.scrollWidth
|
|
||||||
});
|
|
||||||
|
|
||||||
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({
|
|
||||||
width: tabList.offsetWidth,
|
|
||||||
scrollWidth: tabList.scrollWidth
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (this.options.layout === NavigationBarLayout.horizontal) {
|
|
||||||
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(horizontalLayout);
|
|
||||||
} else {
|
|
||||||
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(verticalLayout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +118,17 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this._tabs.changes.subscribe(() => {
|
||||||
|
if (this.scrollable) {
|
||||||
|
this.scrollable.layout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.scrollable) {
|
||||||
|
this.scrollable.layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this._actionbar) {
|
if (this._actionbar) {
|
||||||
this._actionbar.dispose();
|
this._actionbar.dispose();
|
||||||
@@ -210,12 +185,6 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
|
|||||||
this.setMostRecentlyUsed(tab);
|
this.setMostRecentlyUsed(tab);
|
||||||
this._activeTab.active = true;
|
this._activeTab.active = true;
|
||||||
|
|
||||||
// Make the tab header focus on the new selected tab
|
|
||||||
let activeTabHeader = this._headerTabs.find(i => i.tab === this._activeTab);
|
|
||||||
if (activeTabHeader) {
|
|
||||||
activeTabHeader.focusOnTabHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onTabChange.emit(tab);
|
this.onTabChange.emit(tab);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ import { TabComponent } from './tab.component';
|
|||||||
import { TabHeaderComponent } from './tabHeader.component';
|
import { TabHeaderComponent } from './tabHeader.component';
|
||||||
import { PanelComponent } from './panel.component';
|
import { PanelComponent } from './panel.component';
|
||||||
|
|
||||||
|
import { ScrollableModule } from 'sql/base/browser/ui/scrollable/scrollable.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule],
|
imports: [CommonModule, ScrollableModule],
|
||||||
exports: [TabComponent, PanelComponent],
|
exports: [TabComponent, PanelComponent],
|
||||||
declarations: [TabComponent, TabHeaderComponent, PanelComponent]
|
declarations: [TabComponent, TabHeaderComponent, PanelComponent]
|
||||||
})
|
})
|
||||||
export class PanelModule { }
|
export class PanelModule { }
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
|
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
|
||||||
if (titleActive || titleActiveBorder) {
|
if (titleActive || titleActiveBorder) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
.tabbedPanel > .title > .tabList .tab:hover .tabLabel,
|
.tabbedPanel > .title .tabList .tab:hover .tabLabel,
|
||||||
.tabbedPanel > .title > .tabList .tab .tabLabel.active {
|
.tabbedPanel > .title .tabList .tab .tabLabel.active {
|
||||||
color: ${titleActive};
|
color: ${titleActive};
|
||||||
border-bottom-color: ${titleActiveBorder};
|
border-bottom-color: ${titleActiveBorder};
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel > .title > .tabList .tab-header.active {
|
.tabbedPanel > .title .tabList .tab-header.active {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -31,7 +31,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const titleInactive = theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND);
|
const titleInactive = theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND);
|
||||||
if (titleInactive) {
|
if (titleInactive) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
.tabbedPanel > .title > .tabList .tab .tabLabel {
|
.tabbedPanel > .title .tabList .tab .tabLabel {
|
||||||
color: ${titleInactive};
|
color: ${titleInactive};
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -41,7 +41,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const focusBorderColor = theme.getColor(focusBorder);
|
const focusBorderColor = theme.getColor(focusBorder);
|
||||||
if (focusBorderColor) {
|
if (focusBorderColor) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
.tabbedPanel > .title > .tabList .tab .tabLabel:focus {
|
.tabbedPanel > .title .tabList .tab .tabLabel:focus {
|
||||||
color: ${titleActive};
|
color: ${titleActive};
|
||||||
border-bottom-color: ${focusBorderColor} !important;
|
border-bottom-color: ${focusBorderColor} !important;
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
@@ -54,8 +54,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const outline = theme.getColor(activeContrastBorder);
|
const outline = theme.getColor(activeContrastBorder);
|
||||||
if (outline) {
|
if (outline) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
.tabbedPanel > .title > .tabList .tab-header.active,
|
.tabbedPanel > .title .tabList .tab-header.active,
|
||||||
.tabbedPanel > .title > .tabList .tab-header:hover {
|
.tabbedPanel > .title .tabList .tab-header:hover {
|
||||||
outline-color: ${outline};
|
outline-color: ${outline};
|
||||||
outline-width: 1px;
|
outline-width: 1px;
|
||||||
outline-style: solid;
|
outline-style: solid;
|
||||||
@@ -63,7 +63,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
outline-offset: -5px;
|
outline-offset: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel > .title > .tabList .tab-header:hover:not(.active) {
|
.tabbedPanel > .title .tabList .tab-header:hover:not(.active) {
|
||||||
outline-style: dashed;
|
outline-style: dashed;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import { Component, Input, ContentChild, OnDestroy } from '@angular/core';
|
import { Component, Input, ContentChild, OnDestroy, TemplateRef, ChangeDetectorRef, forwardRef, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
|
|
||||||
@@ -13,13 +13,14 @@ export abstract class TabChild {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'tab',
|
selector: 'tab',
|
||||||
template: `
|
template: `
|
||||||
<div class="visibility" [class.hidden]="!active && visibilityType == 'visibility'" *ngIf="visibilityType == 'visibility' || active" class="fullsize">
|
<div class="visibility" [class.hidden]="shouldBeHidden()" *ngIf="shouldBeIfed()" class="fullsize">
|
||||||
<ng-content class="body fullsize"></ng-content>
|
<ng-container *ngTemplateOutlet="templateRef"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class TabComponent implements OnDestroy {
|
export class TabComponent implements OnDestroy {
|
||||||
@ContentChild(TabChild) private _child: TabChild;
|
@ContentChild(TabChild) private _child: TabChild;
|
||||||
|
@ContentChild(TemplateRef) templateRef;
|
||||||
@Input() public title: string;
|
@Input() public title: string;
|
||||||
@Input() public canClose: boolean;
|
@Input() public canClose: boolean;
|
||||||
@Input() public actions: Array<Action>;
|
@Input() public actions: Array<Action>;
|
||||||
@@ -27,9 +28,18 @@ export class TabComponent implements OnDestroy {
|
|||||||
public _active = false;
|
public _active = false;
|
||||||
@Input() public identifier: string;
|
@Input() public identifier: string;
|
||||||
@Input() private visibilityType: 'if' | 'visibility' = 'if';
|
@Input() private visibilityType: 'if' | 'visibility' = 'if';
|
||||||
|
private rendered = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
|
||||||
|
) { }
|
||||||
|
|
||||||
public set active(val: boolean) {
|
public set active(val: boolean) {
|
||||||
this._active = val;
|
this._active = val;
|
||||||
|
if (this.active) {
|
||||||
|
this.rendered = true;
|
||||||
|
}
|
||||||
|
this._cd.detectChanges();
|
||||||
if (this.active && this._child) {
|
if (this.active && this._child) {
|
||||||
this._child.layout();
|
this._child.layout();
|
||||||
}
|
}
|
||||||
@@ -45,4 +55,21 @@ export class TabComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldBeIfed(): boolean {
|
||||||
|
if (this.active) {
|
||||||
|
return true;
|
||||||
|
} else if (this.visibilityType === 'visibility' && this.rendered) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldBeHidden(): boolean {
|
||||||
|
if (this.visibilityType === 'visibility' && !this.active) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { CloseTabAction } from './tabActions';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'tab-header',
|
selector: 'tab-header',
|
||||||
template: `
|
template: `
|
||||||
<div #actionHeader class="tab-header" style="flex: 0 0; flex-direction: row;" [class.active]="tab.active" tabindex="0" (keyup)="onKey($event)">
|
<div #actionHeader class="tab-header" style="flex: 0 0; flex-direction: row; height: 100%" [class.active]="tab.active" tabindex="0" (keyup)="onKey($event)">
|
||||||
<span class="tab" (click)="selectTab(tab)" role="tab" [attr.aria-selected]="tab.active" [attr.aria-label]="tab.title">
|
<span class="tab" (click)="selectTab(tab)" role="tab" [attr.aria-selected]="tab.active" [attr.aria-label]="tab.title">
|
||||||
<a class="tabLabel" [class.active]="tab.active" #tabLabel>
|
<a class="tabLabel" [class.active]="tab.active" #tabLabel>
|
||||||
</a>
|
</a>
|
||||||
@@ -31,6 +31,7 @@ import { CloseTabAction } from './tabActions';
|
|||||||
export class TabHeaderComponent extends Disposable implements AfterContentInit, OnDestroy {
|
export class TabHeaderComponent extends Disposable implements AfterContentInit, OnDestroy {
|
||||||
@Input() public tab: TabComponent;
|
@Input() public tab: TabComponent;
|
||||||
@Input() public showIcon: boolean;
|
@Input() public showIcon: boolean;
|
||||||
|
@Input() public active: boolean;
|
||||||
@Output() public onSelectTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();
|
@Output() public onSelectTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();
|
||||||
@Output() public onCloseTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();
|
@Output() public onCloseTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { Directive, Inject, forwardRef, ElementRef } from '@angular/core';
|
import { Directive, Inject, forwardRef, ElementRef, Input } from '@angular/core';
|
||||||
|
|
||||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
import { getContentHeight, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
import { getContentHeight, addDisposableListener, EventType, getContentWidth } from 'vs/base/browser/dom';
|
||||||
import { AngularDisposable } from 'sql/base/common/lifecycle';
|
import { AngularDisposable } from 'sql/base/common/lifecycle';
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
@@ -17,33 +17,45 @@ export class ScrollableDirective extends AngularDisposable {
|
|||||||
private scrollableElement: ScrollableElement;
|
private scrollableElement: ScrollableElement;
|
||||||
private parent: HTMLElement;
|
private parent: HTMLElement;
|
||||||
private scrolled: HTMLElement;
|
private scrolled: HTMLElement;
|
||||||
|
@Input() horizontalScroll: ScrollbarVisibility;
|
||||||
|
@Input() verticalScroll: ScrollbarVisibility;
|
||||||
|
@Input() useShadow = false;
|
||||||
|
@Input() scrollYToX = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
|
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.scrolled = this._el.nativeElement as HTMLElement;
|
this.scrolled = this._el.nativeElement as HTMLElement;
|
||||||
this.parent = this.scrolled.parentElement;
|
this.parent = this.scrolled.parentElement;
|
||||||
|
const next = this.scrolled.nextSibling;
|
||||||
this.parent.removeChild(this.scrolled);
|
this.parent.removeChild(this.scrolled);
|
||||||
|
|
||||||
this.scrolled.style.position = 'relative';
|
this.scrolled.style.position = 'relative';
|
||||||
|
|
||||||
this.scrollableElement = new ScrollableElement(this.scrolled, {
|
this.scrollableElement = new ScrollableElement(this.scrolled, {
|
||||||
horizontal: ScrollbarVisibility.Hidden,
|
horizontal: this.horizontalScroll,
|
||||||
vertical: ScrollbarVisibility.Auto,
|
vertical: this.verticalScroll,
|
||||||
useShadows: false
|
useShadows: this.useShadow,
|
||||||
|
scrollYToX: this.scrollYToX,
|
||||||
|
horizontalScrollbarSize: 3
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scrollableElement.onScroll(e => {
|
this.scrollableElement.onScroll(e => {
|
||||||
this.scrolled.style.bottom = e.scrollTop + 'px';
|
if (this.verticalScroll === ScrollbarVisibility.Auto) {
|
||||||
|
this.scrolled.style.bottom = e.scrollTop + 'px';
|
||||||
|
} else if (this.horizontalScroll === ScrollbarVisibility.Auto) {
|
||||||
|
this.scrolled.scrollLeft = e.scrollLeft;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.parent.appendChild(this.scrollableElement.getDomNode());
|
this.parent.insertBefore(this.scrollableElement.getDomNode(), next);
|
||||||
const initialHeight = getContentHeight(this.scrolled);
|
const initialHeight = getContentHeight(this.scrolled);
|
||||||
this.scrollableElement.setScrollDimensions({
|
const initalWidth = getContentWidth(this.scrolled);
|
||||||
scrollHeight: getContentHeight(this.scrolled),
|
this.resetScrollDimensions();
|
||||||
height: getContentHeight(this.parent)
|
|
||||||
});
|
|
||||||
|
|
||||||
this._register(addDisposableListener(window, EventType.RESIZE, () => {
|
this._register(addDisposableListener(window, EventType.RESIZE, () => {
|
||||||
this.resetScrollDimensions();
|
this.resetScrollDimensions();
|
||||||
@@ -52,24 +64,23 @@ export class ScrollableDirective extends AngularDisposable {
|
|||||||
// 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(this.scrolled);
|
let currentheight = getContentHeight(this.scrolled);
|
||||||
if (initialHeight !== currentheight) {
|
let currentWidth = getContentWidth(this.scrolled);
|
||||||
this.scrollableElement.setScrollDimensions({
|
if (initialHeight !== currentheight || initalWidth !== currentWidth) {
|
||||||
scrollHeight: currentheight,
|
this.resetScrollDimensions();
|
||||||
height: getContentHeight(this.parent)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetScrollDimensions() {
|
private resetScrollDimensions() {
|
||||||
this.scrollableElement.setScrollDimensions({
|
this.scrollableElement.setScrollDimensions({
|
||||||
scrollHeight: getContentHeight(this.scrolled),
|
scrollHeight: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.scrolled) : undefined,
|
||||||
height: getContentHeight(this.parent)
|
height: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.parent) : undefined,
|
||||||
|
scrollWidth: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.scrollWidth : undefined,
|
||||||
|
width: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.offsetWidth : undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
|
this.resetScrollDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/sql/base/browser/ui/scrollable/scrollable.module.ts
Normal file
15
src/sql/base/browser/ui/scrollable/scrollable.module.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { ScrollableDirective } from './scrollable.directive';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule],
|
||||||
|
exports: [ScrollableDirective],
|
||||||
|
declarations: [ScrollableDirective]
|
||||||
|
})
|
||||||
|
export class ScrollableModule { }
|
||||||
@@ -6,23 +6,25 @@
|
|||||||
-->
|
-->
|
||||||
<panel class="dashboard-panel" (onTabChange)="handleTabChange($event)" (onTabClose)="handleTabClose($event)" [actions]="panelActions">
|
<panel class="dashboard-panel" (onTabChange)="handleTabChange($event)" (onTabClose)="handleTabClose($event)" [actions]="panelActions">
|
||||||
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize" [identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions">
|
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize" [identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions">
|
||||||
<dashboard-home-container *ngIf="tab.id === 'homeTab'; else not_home" [properties]="propertiesWidget" [tab]="tab">
|
<ng-template>
|
||||||
</dashboard-home-container>
|
<dashboard-home-container *ngIf="tab.id === 'homeTab'; else not_home" [properties]="propertiesWidget" [tab]="tab">
|
||||||
<ng-template #not_home>
|
</dashboard-home-container>
|
||||||
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
|
<ng-template #not_home>
|
||||||
</dashboard-webview-container>
|
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
|
||||||
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
|
</dashboard-webview-container>
|
||||||
</dashboard-widget-container>
|
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
|
||||||
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
|
</dashboard-widget-container>
|
||||||
</dashboard-modelview-container>
|
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
|
||||||
<dashboard-controlhost-container *ngIf="getContentType(tab) === 'controlhost-container'" [tab]="tab">
|
</dashboard-modelview-container>
|
||||||
</dashboard-controlhost-container>
|
<dashboard-controlhost-container *ngIf="getContentType(tab) === 'controlhost-container'" [tab]="tab">
|
||||||
<dashboard-nav-section *ngIf="getContentType(tab) === 'nav-section'" [tab]="tab">
|
</dashboard-controlhost-container>
|
||||||
</dashboard-nav-section>
|
<dashboard-nav-section *ngIf="getContentType(tab) === 'nav-section'" [tab]="tab">
|
||||||
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
|
</dashboard-nav-section>
|
||||||
</dashboard-grid-container>
|
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
|
||||||
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
|
</dashboard-grid-container>
|
||||||
</dashboard-error-container>
|
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
|
||||||
|
</dashboard-error-container>
|
||||||
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
</panel>
|
</panel>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { IPropertiesConfig } from 'sql/parts/dashboard/pages/serverDashboardPage
|
|||||||
import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
|
import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
|
||||||
import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
|
import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
|
||||||
import { PinUnpinTabAction, AddFeatureTabAction } from './actions';
|
import { PinUnpinTabAction, AddFeatureTabAction } from './actions';
|
||||||
import { TabComponent } from 'sql/base/browser/ui/panel/tab.component';
|
import { TabComponent, TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { AngularEventType } from 'sql/services/angularEventing/angularEventingService';
|
import { AngularEventType } from 'sql/services/angularEventing/angularEventingService';
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
@@ -61,7 +61,7 @@ export abstract class DashboardPage extends AngularDisposable {
|
|||||||
private _tabsDispose: Array<IDisposable> = [];
|
private _tabsDispose: Array<IDisposable> = [];
|
||||||
private _tabSettingConfigs: Array<TabSettingConfig> = [];
|
private _tabSettingConfigs: Array<TabSettingConfig> = [];
|
||||||
|
|
||||||
@ViewChildren(DashboardTab) private _tabs: QueryList<DashboardTab>;
|
@ViewChildren(TabChild) private _tabs: QueryList<DashboardTab>;
|
||||||
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
||||||
|
|
||||||
private _editEnabled = new Emitter<boolean>();
|
private _editEnabled = new Emitter<boolean>();
|
||||||
@@ -142,7 +142,6 @@ export abstract class DashboardPage extends AngularDisposable {
|
|||||||
actions: []
|
actions: []
|
||||||
};
|
};
|
||||||
this.addNewTab(homeTab);
|
this.addNewTab(homeTab);
|
||||||
this._panel.selectTab(homeTab.id);
|
|
||||||
|
|
||||||
let allTabs = dashboardHelper.filterConfigs(dashboardRegistry.tabs, this.dashboardService);
|
let allTabs = dashboardHelper.filterConfigs(dashboardRegistry.tabs, this.dashboardService);
|
||||||
|
|
||||||
@@ -254,7 +253,6 @@ export abstract class DashboardPage extends AngularDisposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private getContentType(tab: TabConfig): string {
|
private getContentType(tab: TabConfig): string {
|
||||||
return tab.container ? Object.keys(tab.container)[0] : '';
|
return tab.container ? Object.keys(tab.container)[0] : '';
|
||||||
}
|
}
|
||||||
@@ -310,10 +308,10 @@ export abstract class DashboardPage extends AngularDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public handleTabChange(tab: TabComponent): void {
|
public handleTabChange(tab: TabComponent): void {
|
||||||
|
this._cd.detectChanges();
|
||||||
let localtab = this._tabs.find(i => i.id === tab.identifier);
|
let localtab = this._tabs.find(i => i.id === tab.identifier);
|
||||||
this._editEnabled.fire(localtab.editable);
|
this._editEnabled.fire(localtab.editable);
|
||||||
this._cd.detectChanges();
|
this._cd.detectChanges();
|
||||||
localtab.layout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleTabClose(tab: TabComponent): void {
|
public handleTabClose(tab: TabComponent): void {
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const tabActiveForeground = theme.getColor(TAB_ACTIVE_FOREGROUND);
|
const tabActiveForeground = theme.getColor(TAB_ACTIVE_FOREGROUND);
|
||||||
if (tabActiveBackground || tabActiveForeground) {
|
if (tabActiveBackground || tabActiveForeground) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab:hover .tabLabel,
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab:hover .tabLabel,
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel.active {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab .tabLabel.active {
|
||||||
color: ${tabActiveForeground};
|
color: ${tabActiveForeground};
|
||||||
border-bottom: 0px solid;
|
border-bottom: 0px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header.active {
|
||||||
background-color: ${tabActiveBackground};
|
background-color: ${tabActiveBackground};
|
||||||
outline-color: ${tabActiveBackground};
|
outline-color: ${tabActiveBackground};
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header.active {
|
||||||
border-bottom-color: transparent;
|
border-bottom-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.vertical > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel.vertical > .title .tabList .tab-header.active {
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -39,7 +39,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const activeTabBorderColor = theme.getColor(TAB_ACTIVE_BORDER);
|
const activeTabBorderColor = theme.getColor(TAB_ACTIVE_BORDER);
|
||||||
if (activeTabBorderColor) {
|
if (activeTabBorderColor) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header.active {
|
||||||
box-shadow: ${activeTabBorderColor} 0 -1px inset;
|
box-shadow: ${activeTabBorderColor} 0 -1px inset;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -50,11 +50,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const tabInactiveForeground = theme.getColor(TAB_INACTIVE_FOREGROUND);
|
const tabInactiveForeground = theme.getColor(TAB_INACTIVE_FOREGROUND);
|
||||||
if (tabInactiveBackground || tabInactiveForeground) {
|
if (tabInactiveBackground || tabInactiveForeground) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab .tabLabel {
|
||||||
color: ${tabInactiveForeground};
|
color: ${tabInactiveForeground};
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header {
|
||||||
background-color: ${tabInactiveBackground};
|
background-color: ${tabInactiveBackground};
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -74,7 +74,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
const tabBoarder = theme.getColor(TAB_BORDER);
|
const tabBoarder = theme.getColor(TAB_BORDER);
|
||||||
if (tabBoarder) {
|
if (tabBoarder) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header {
|
||||||
border-right-color: ${tabBoarder};
|
border-right-color: ${tabBoarder};
|
||||||
border-bottom-color: ${tabBoarder};
|
border-bottom-color: ${tabBoarder};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,13 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import Event from 'vs/base/common/event';
|
import Event from 'vs/base/common/event';
|
||||||
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
import { AngularDisposable } from 'sql/base/common/lifecycle';
|
import { AngularDisposable } from 'sql/base/common/lifecycle';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
export enum Conditional {
|
export enum Conditional {
|
||||||
'equals',
|
'equals',
|
||||||
@@ -17,7 +21,7 @@ export enum Conditional {
|
|||||||
'always'
|
'always'
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class DashboardTab extends AngularDisposable {
|
export abstract class DashboardTab extends TabChild implements OnDestroy {
|
||||||
public abstract layout(): void;
|
public abstract layout(): void;
|
||||||
public abstract readonly id: string;
|
public abstract readonly id: string;
|
||||||
public abstract readonly editable: boolean;
|
public abstract readonly editable: boolean;
|
||||||
@@ -26,4 +30,23 @@ export abstract class DashboardTab extends AngularDisposable {
|
|||||||
public enableEdit(): void {
|
public enableEdit(): void {
|
||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _toDispose: IDisposable[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
this._toDispose = dispose(this._toDispose);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _register<T extends IDisposable>(t: T): T {
|
||||||
|
this._toDispose.push(t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,17 @@
|
|||||||
import 'vs/css!./dashboardControlHostContainer';
|
import 'vs/css!./dashboardControlHostContainer';
|
||||||
|
|
||||||
import { Component, forwardRef, Input, AfterContentInit, ViewChild, OnChanges } from '@angular/core';
|
import { Component, forwardRef, Input, AfterContentInit, ViewChild, OnChanges } from '@angular/core';
|
||||||
|
|
||||||
import Event, { Emitter } from 'vs/base/common/event';
|
import Event, { Emitter } from 'vs/base/common/event';
|
||||||
|
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { ControlHostContent } from 'sql/parts/dashboard/contents/controlHostContent.component';
|
import { ControlHostContent } from 'sql/parts/dashboard/contents/controlHostContent.component';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-controlhost-container',
|
selector: 'dashboard-controlhost-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardControlHostContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardControlHostContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<controlhost-content [webviewId]="tab.id">
|
<controlhost-content [webviewId]="tab.id">
|
||||||
</controlhost-content>
|
</controlhost-content>
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ChangeDete
|
|||||||
|
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
import Event, { Emitter } from 'vs/base/common/event';
|
import Event, { Emitter } from 'vs/base/common/event';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-error-container',
|
selector: 'dashboard-error-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardErrorContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardErrorContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<div class="error-container">
|
<div class="error-container">
|
||||||
<div class="icon globalError">
|
<div class="icon globalError">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'vs/css!./dashboardGridContainer';
|
|||||||
|
|
||||||
import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, EventEmitter } from '@angular/core';
|
import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, EventEmitter } from '@angular/core';
|
||||||
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
|
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
|
||||||
|
import { concat } from 'rxjs/operator/concat';
|
||||||
|
|
||||||
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';
|
||||||
@@ -14,13 +15,13 @@ import { TabConfig, WidgetConfig } from 'sql/parts/dashboard/common/dashboardWid
|
|||||||
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
|
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
|
||||||
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
|
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
|
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||||
import * as objects from 'vs/base/common/objects';
|
import * as objects from 'vs/base/common/objects';
|
||||||
import Event, { Emitter } from 'vs/base/common/event';
|
import Event, { Emitter } from 'vs/base/common/event';
|
||||||
import { concat } from 'rxjs/operator/concat';
|
|
||||||
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
|
|
||||||
|
|
||||||
export interface GridCellConfig {
|
export interface GridCellConfig {
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -42,7 +43,7 @@ export interface GridWebviewConfig extends GridCellConfig {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-grid-container',
|
selector: 'dashboard-grid-container',
|
||||||
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardGridContainer.component.html')),
|
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardGridContainer.component.html')),
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardGridContainer) }]
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardGridContainer) }]
|
||||||
})
|
})
|
||||||
export class DashboardGridContainer extends DashboardTab implements OnDestroy {
|
export class DashboardGridContainer extends DashboardTab implements OnDestroy {
|
||||||
@Input() private tab: TabConfig;
|
@Input() private tab: TabConfig;
|
||||||
|
|||||||
@@ -14,15 +14,18 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
|
|||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { AngularEventType } from 'sql/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 { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
|
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
|
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-home-container',
|
selector: 'dashboard-home-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardHomeContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<div class="fullsize" style="display: flex; flex-direction: column">
|
<div class="fullsize" style="display: flex; flex-direction: column">
|
||||||
<div scrollable>
|
<div scrollable [horizontalScroll]="ScrollbarVisibility.Hidden" [verticalScroll]="ScrollbarVisibility.Auto">
|
||||||
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
|
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
|
||||||
style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
|
style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
|
||||||
</dashboard-widget-wrapper>
|
</dashboard-widget-wrapper>
|
||||||
@@ -37,6 +40,8 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
|
|||||||
@ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper;
|
@ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper;
|
||||||
@ContentChild(ScrollableDirective) private _scrollable;
|
@ContentChild(ScrollableDirective) private _scrollable;
|
||||||
|
|
||||||
|
private ScrollbarVisibility = ScrollbarVisibility;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface
|
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ import Event, { Emitter } from 'vs/base/common/event';
|
|||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component';
|
import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-modelview-container',
|
selector: 'dashboard-modelview-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardModelViewContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardModelViewContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<modelview-content [modelViewId]="tab.id">
|
<modelview-content [modelViewId]="tab.id">
|
||||||
</modelview-content>
|
</modelview-content>
|
||||||
|
|||||||
@@ -4,18 +4,20 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<panel [options]="panelOpt" style="flex: 1 1 auto;" class="dashboard-panel" (onTabChange)="handleTabChange($event)">
|
<panel [options]="panelOpt" style="flex: 1 1 auto;" class="dashboard-panel">
|
||||||
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize"
|
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize"
|
||||||
[identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions" [iconClass]="tab.iconClass">
|
[identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions" [iconClass]="tab.iconClass">
|
||||||
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
|
<ng-template>
|
||||||
</dashboard-webview-container>
|
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
|
||||||
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
|
</dashboard-webview-container>
|
||||||
</dashboard-widget-container>
|
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
|
||||||
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
|
</dashboard-widget-container>
|
||||||
</dashboard-modelview-container>
|
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
|
||||||
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
|
</dashboard-modelview-container>
|
||||||
</dashboard-grid-container>
|
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
|
||||||
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
|
</dashboard-grid-container>
|
||||||
</dashboard-error-container>
|
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
|
||||||
|
</dashboard-error-container>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
</panel>
|
</panel>
|
||||||
@@ -11,7 +11,7 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
|
|||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { WidgetConfig, TabConfig, NavSectionConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { WidgetConfig, TabConfig, NavSectionConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
|
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
|
||||||
import { TabComponent } from 'sql/base/browser/ui/panel/tab.component';
|
import { TabComponent, TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
import { WIDGETS_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
|
import { WIDGETS_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
|
||||||
import { GRID_CONTAINER } from 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
|
import { GRID_CONTAINER } from 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
|
||||||
@@ -23,7 +23,7 @@ import * as nls from 'vs/nls';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-nav-section',
|
selector: 'dashboard-nav-section',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardNavSection) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardNavSection) }],
|
||||||
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardNavSection.component.html'))
|
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardNavSection.component.html'))
|
||||||
})
|
})
|
||||||
export class DashboardNavSection extends DashboardTab implements OnDestroy, OnChanges, AfterContentInit {
|
export class DashboardNavSection extends DashboardTab implements OnDestroy, OnChanges, AfterContentInit {
|
||||||
@@ -51,7 +51,7 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
|
|||||||
dashboardHelper.validateGridConfig
|
dashboardHelper.validateGridConfig
|
||||||
];
|
];
|
||||||
|
|
||||||
@ViewChildren(DashboardTab) private _tabs: QueryList<DashboardTab>;
|
@ViewChildren(TabChild) private _tabs: QueryList<DashboardTab>;
|
||||||
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: CommonServiceInterface,
|
||||||
@@ -124,11 +124,6 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
|
|||||||
this.addNewTab(config);
|
this.addNewTab(config);
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
|
|
||||||
// put this immediately on the stack so that is ran *after* the tab is rendered
|
|
||||||
setTimeout(() => {
|
|
||||||
this._panel.selectTab(selectedTabs[0].id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,10 +169,4 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleTabChange(tab: TabComponent): void {
|
|
||||||
let localtab = this._tabs.find(i => i.id === tab.identifier);
|
|
||||||
this._cd.detectChanges();
|
|
||||||
localtab.layout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ import Event, { Emitter } from 'vs/base/common/event';
|
|||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
|
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-webview-container',
|
selector: 'dashboard-webview-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardWebviewContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardWebviewContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<webview-content [webviewId]="tab.id">
|
<webview-content [webviewId]="tab.id">
|
||||||
</webview-content>
|
</webview-content>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWi
|
|||||||
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
|
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
||||||
import { WidgetContent } from 'sql/parts/dashboard/contents/widgetContent.component';
|
import { WidgetContent } from 'sql/parts/dashboard/contents/widgetContent.component';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
|
||||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||||
@@ -22,7 +23,7 @@ import Event, { Emitter } from 'vs/base/common/event';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'dashboard-widget-container',
|
selector: 'dashboard-widget-container',
|
||||||
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardWidgetContainer) }],
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardWidgetContainer) }],
|
||||||
template: `
|
template: `
|
||||||
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
|
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
|
||||||
</widget-content>
|
</widget-content>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import Event, { Emitter } from 'vs/base/common/event';
|
|||||||
import { Parts } from 'vs/workbench/services/part/common/partService';
|
import { Parts } from 'vs/workbench/services/part/common/partService';
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } 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';
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
|||||||
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||||
import { memoize } from 'vs/base/common/decorators';
|
import { memoize } from 'vs/base/common/decorators';
|
||||||
|
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } 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';
|
||||||
@@ -37,15 +36,13 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo
|
|||||||
private _onMessageDisposable: IDisposable;
|
private _onMessageDisposable: IDisposable;
|
||||||
private _webview: Webview;
|
private _webview: Webview;
|
||||||
private _html: string;
|
private _html: string;
|
||||||
private _dashboardService: DashboardServiceInterface;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _dashboardService: DashboardServiceInterface,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
|
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._dashboardService = commonService as DashboardServiceInterface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|||||||
@@ -56,12 +56,13 @@ import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.co
|
|||||||
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';
|
||||||
|
|
||||||
|
import { ScrollableModule } from 'sql/base/browser/ui/scrollable/scrollable.module';
|
||||||
|
|
||||||
/* Pages */
|
/* Pages */
|
||||||
import { ServerDashboardPage } from 'sql/parts/dashboard/pages/serverDashboardPage.component';
|
import { ServerDashboardPage } from 'sql/parts/dashboard/pages/serverDashboardPage.component';
|
||||||
import { DatabaseDashboardPage } from 'sql/parts/dashboard/pages/databaseDashboardPage.component';
|
import { DatabaseDashboardPage } from 'sql/parts/dashboard/pages/databaseDashboardPage.component';
|
||||||
@@ -75,7 +76,6 @@ 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,
|
||||||
@@ -126,7 +126,8 @@ const appRoutes: Routes = [
|
|||||||
NgGridModule,
|
NgGridModule,
|
||||||
ChartsModule,
|
ChartsModule,
|
||||||
RouterModule.forRoot(appRoutes),
|
RouterModule.forRoot(appRoutes),
|
||||||
PanelModule
|
PanelModule,
|
||||||
|
ScrollableModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { Dimension } from 'vs/base/browser/builder';
|
|||||||
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||||
import { Table } from 'sql/base/browser/ui/table/table';
|
import { Table } from 'sql/base/browser/ui/table/table';
|
||||||
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||||
import { DragCellSelectionModel } from '../../../../../base/browser/ui/table/plugins/dragCellSelectionModel.plugin';
|
import { DragCellSelectionModel } from 'sql/base/browser/ui/table/plugins/dragCellSelectionModel.plugin';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: '<span></span>'
|
template: '<span></span>'
|
||||||
@@ -62,9 +62,9 @@ export default class TableInsight implements IInsightsView, OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformData(rows: string[][], columns: string[]): {[key: string]: string}[] {
|
function transformData(rows: string[][], columns: string[]): { [key: string]: string }[] {
|
||||||
return rows.map(row => {
|
return rows.map(row => {
|
||||||
let object: {[key: string]: string} = {};
|
let object: { [key: string]: string } = {};
|
||||||
row.forEach((val, index) => {
|
row.forEach((val, index) => {
|
||||||
object[columns[index]] = val;
|
object[columns[index]] = val;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -97,12 +97,12 @@ export class ChartViewerComponent implements OnInit, OnDestroy, IChartViewAction
|
|||||||
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService,
|
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
|
this.setDefaultChartConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.setDefaultChartConfig();
|
|
||||||
this.legendOptions = Object.values(LegendPosition);
|
this.legendOptions = Object.values(LegendPosition);
|
||||||
this.initializeUI();
|
this._initActionBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
private setDefaultChartConfig() {
|
private setDefaultChartConfig() {
|
||||||
@@ -114,11 +114,6 @@ export class ChartViewerComponent implements OnInit, OnDestroy, IChartViewAction
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeUI() {
|
|
||||||
// Initialize the taskbar
|
|
||||||
this._initActionBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDefaultChartType(): string {
|
private getDefaultChartType(): string {
|
||||||
let defaultChartType = Constants.chartTypeHorizontalBar;
|
let defaultChartType = Constants.chartTypeHorizontalBar;
|
||||||
if (this._bootstrapService.configurationService) {
|
if (this._bootstrapService.configurationService) {
|
||||||
@@ -155,6 +150,10 @@ export class ChartViewerComponent implements OnInit, OnDestroy, IChartViewAction
|
|||||||
this.initChart();
|
this.initChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.initChart();
|
||||||
|
}
|
||||||
|
|
||||||
setConfigValue(key: string, value: any, refresh = true): void {
|
setConfigValue(key: string, value: any, refresh = true): void {
|
||||||
this._chartConfig[key] = value;
|
this._chartConfig[key] = value;
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
@@ -316,7 +315,6 @@ export class ChartViewerComponent implements OnInit, OnDestroy, IChartViewAction
|
|||||||
this._executeResult.rows = dataSet.dataRows.getRange(0, dataSet.dataRows.getLength()).map(gridRow => {
|
this._executeResult.rows = dataSet.dataRows.getRange(0, dataSet.dataRows.getLength()).map(gridRow => {
|
||||||
return gridRow.values.map(cell => cell.displayValue);
|
return gridRow.values.map(cell => cell.displayValue);
|
||||||
});
|
});
|
||||||
this.initChart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public initChart() {
|
public initChart() {
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
|
|
||||||
<panel class="dashboard-panel" [options]="panelOpt">
|
<panel class="dashboard-panel" [options]="panelOpt">
|
||||||
<tab [title]="jobsComponentTitle" class="fullsize" [identifier]="jobsTabIdentifier"
|
<tab [title]="jobsComponentTitle" class="fullsize" [identifier]="jobsTabIdentifier"
|
||||||
[iconClass]="jobsIconClass">
|
[iconClass]="jobsIconClass">
|
||||||
<div id="jobsDiv" class="fullsize" *ngIf="showHistory === false">
|
<ng-template>
|
||||||
<jobsview-component></jobsview-component>
|
<div id="jobsDiv" class="fullsize" *ngIf="showHistory === false">
|
||||||
</div>
|
<jobsview-component></jobsview-component>
|
||||||
<div id="historyDiv" class="fullsize" *ngIf="showHistory === true">
|
</div>
|
||||||
<jobhistory-component></jobhistory-component>
|
<div id="historyDiv" class="fullsize" *ngIf="showHistory === true">
|
||||||
</div>
|
<jobhistory-component></jobhistory-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
</panel>
|
</panel>
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ import { Parts } from 'vs/workbench/services/part/common/partService';
|
|||||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||||
import { memoize } from 'vs/base/common/decorators';
|
import { memoize } from 'vs/base/common/decorators';
|
||||||
import nls = require('vs/nls');
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
|
|
||||||
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { IModelView } from 'sql/services/model/modelViewService';
|
import { IModelView } from 'sql/services/model/modelViewService';
|
||||||
|
|||||||
@@ -6,28 +6,36 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<panel class="fullsize" [options]="panelOpt">
|
<panel class="fullsize" [options]="panelOpt">
|
||||||
<tab [title]="queryComponentTitle" class="fullsize" [identifier]="resultsTabIdentifier">
|
<tab [visibilityType]="'visibility'" [title]="queryComponentTitle" class="fullsize" [identifier]="resultsTabIdentifier">
|
||||||
<div id="queryDiv" class="fullsize">
|
<ng-template>
|
||||||
<query-component id="queryComp" #queryComponent class="fullsize" [queryParameters]="queryParameters"></query-component>
|
<div id="queryDiv" class="fullsize">
|
||||||
</div>
|
<query-component id="queryComp" class="fullsize" [queryParameters]="queryParameters"></query-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
|
|
||||||
<tab *ngIf="hasQueryPlan" [title]="queryPlanTitle" [identifier]="queryPlanTabIdentifier">
|
<tab *ngIf="hasQueryPlan" [visibilityType]="'visibility'" [title]="queryPlanTitle" [identifier]="queryPlanTabIdentifier">
|
||||||
<div id="queryPlanDiv" class="headersVisible fullsize" style=" overflow: auto; margin-left: 2px">
|
<ng-template>
|
||||||
<queryplan-component #queryPlanComponent class="fullsize" style="display: block"></queryplan-component>
|
<div id="queryPlanDiv" class="headersVisible fullsize" style=" overflow: auto; margin-left: 2px">
|
||||||
</div>
|
<queryplan-component class="fullsize" style="display: block"></queryplan-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
|
|
||||||
<tab *ngIf="hasQueryPlan" class="fullsize" [title]="topOperationsTitle">
|
<tab *ngIf="hasQueryPlan" [visibilityType]="'visibility'" class="fullsize" [title]="topOperationsTitle">
|
||||||
<div id="topOperationsDiv" class="fullsize">
|
<ng-template>
|
||||||
<top-operations-component #topOperationsComponent class="fullsize" style="display: block" [queryParameters]="queryParameters"></top-operations-component>
|
<div id="topOperationsDiv" class="fullsize">
|
||||||
</div>
|
<top-operations-component class="fullsize" style="display: block" [queryParameters]="queryParameters"></top-operations-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
|
|
||||||
<tab *ngIf="showChartView" [title]="chartViewerTitle" [identifier]="chartViewerTabIdentifier">
|
<tab *ngIf="showChartView" [visibilityType]="'visibility'" [title]="chartViewerTitle" [identifier]="chartViewerTabIdentifier">
|
||||||
<div id="chartViewerDiv" class="headersVisible fullsize" >
|
<ng-template>
|
||||||
<chart-viewer #chartViewerComponent class="fullsize" style="display: block">
|
<div id="chartViewerDiv" class="headersVisible fullsize" >
|
||||||
</chart-viewer>
|
<chart-viewer [dataSet]="activeDataSet" class="fullsize" style="display: block">
|
||||||
</div>
|
</chart-viewer>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</tab>
|
</tab>
|
||||||
</panel>
|
</panel>
|
||||||
@@ -32,18 +32,16 @@ declare type PaneType = 'messages' | 'results';
|
|||||||
selector: QUERY_OUTPUT_SELECTOR,
|
selector: QUERY_OUTPUT_SELECTOR,
|
||||||
templateUrl: decodeURI(require.toUrl('sql/parts/query/views/queryOutput.component.html'))
|
templateUrl: decodeURI(require.toUrl('sql/parts/query/views/queryOutput.component.html'))
|
||||||
})
|
})
|
||||||
export class QueryOutputComponent implements OnInit, OnDestroy {
|
export class QueryOutputComponent implements OnDestroy {
|
||||||
|
|
||||||
@ViewChild('queryComponent') queryComponent: QueryComponent;
|
@ViewChild(QueryComponent) queryComponent: QueryComponent;
|
||||||
|
@ViewChild(QueryPlanComponent) queryPlanComponent: QueryPlanComponent;
|
||||||
@ViewChild('queryPlanComponent') queryPlanComponent: QueryPlanComponent;
|
@ViewChild(TopOperationsComponent) topOperationsComponent: TopOperationsComponent;
|
||||||
|
|
||||||
@ViewChild('topOperationsComponent') topOperationsComponent: TopOperationsComponent;
|
|
||||||
|
|
||||||
@ViewChild('chartViewerComponent') chartViewerComponent: ChartViewerComponent;
|
|
||||||
|
|
||||||
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
||||||
|
|
||||||
|
private activeDataSet: any;
|
||||||
|
|
||||||
// tslint:disable:no-unused-variable
|
// tslint:disable:no-unused-variable
|
||||||
private readonly queryComponentTitle: string = nls.localize('results', 'Results');
|
private readonly queryComponentTitle: string = nls.localize('results', 'Results');
|
||||||
private readonly queryPlanTitle: string = nls.localize('queryPlan', 'Query Plan');
|
private readonly queryPlanTitle: string = nls.localize('queryPlan', 'Query Plan');
|
||||||
@@ -78,7 +76,7 @@ export class QueryOutputComponent implements OnInit, OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* Called by Angular when the object is initialized
|
* Called by Angular when the object is initialized
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngAfterViewInit(): void {
|
||||||
this._disposables.push(toDisposableSubscription(this.queryComponent.queryPlanAvailable.subscribe((xml) => {
|
this._disposables.push(toDisposableSubscription(this.queryComponent.queryPlanAvailable.subscribe((xml) => {
|
||||||
this.hasQueryPlan = true;
|
this.hasQueryPlan = true;
|
||||||
this._cd.detectChanges();
|
this._cd.detectChanges();
|
||||||
@@ -90,7 +88,7 @@ export class QueryOutputComponent implements OnInit, OnDestroy {
|
|||||||
this._disposables.push(toDisposableSubscription(this.queryComponent.showChartRequested.subscribe((dataSet) => {
|
this._disposables.push(toDisposableSubscription(this.queryComponent.showChartRequested.subscribe((dataSet) => {
|
||||||
this.showChartView = true;
|
this.showChartView = true;
|
||||||
this._cd.detectChanges();
|
this._cd.detectChanges();
|
||||||
this.chartViewerComponent.dataSet = dataSet;
|
this.activeDataSet = dataSet;
|
||||||
this._panel.selectTab(this.chartViewerTabIdentifier);
|
this._panel.selectTab(this.chartViewerTabIdentifier);
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user