mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Fix few dashboard panel issues (#801)
* home tab is shown by default when the dashboard is opened * add scroll bar when tab list is overflow * fix regression in other tab panels * address comments
This commit is contained in:
@@ -29,6 +29,8 @@ panel {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
line-height: 35px;
|
line-height: 35px;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel .tabList .tab {
|
.tabbedPanel .tabList .tab {
|
||||||
@@ -61,7 +63,7 @@ panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.composite.title .title-actions {
|
.composite.title .title-actions {
|
||||||
flex: 1;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab > .tabLabel.active {
|
.tab > .tabLabel.active {
|
||||||
@@ -87,6 +89,10 @@ panel {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabbedPanel.vertical .tabList {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.tabbedPanel > .tab-content {
|
.tabbedPanel > .tab-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -99,3 +105,8 @@ panel {
|
|||||||
.tabbedPanel.horizontal > .title > .tabList {
|
.tabbedPanel.horizontal > .title > .tabList {
|
||||||
flex-flow: row;
|
flex-flow: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabbedPanel > .title > .monaco-scrollable-element {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ 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 { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||||
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
export interface IPanelOptions {
|
export interface IPanelOptions {
|
||||||
/**
|
/**
|
||||||
@@ -40,9 +44,10 @@ let idPool = 0;
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'panel',
|
selector: 'panel',
|
||||||
template: `
|
template: `
|
||||||
|
|
||||||
<div class="tabbedPanel fullsize" #tabbedPanel>
|
<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="tabList">
|
<div class="tabList" #tabList>
|
||||||
<div *ngFor="let tab of _tabs">
|
<div *ngFor="let tab of _tabs">
|
||||||
<tab-header [tab]="tab" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'> </tab-header>
|
<tab-header [tab]="tab" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'> </tab-header>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,7 +65,7 @@ let idPool = 0;
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
|
export class PanelComponent extends Disposable implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
|
||||||
@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>;
|
||||||
@@ -72,10 +77,15 @@ export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDe
|
|||||||
private _activeTab: TabComponent;
|
private _activeTab: TabComponent;
|
||||||
private _actionbar: ActionBar;
|
private _actionbar: ActionBar;
|
||||||
private _mru: TabComponent[];
|
private _mru: TabComponent[];
|
||||||
|
private _scrollableElement: ScrollableElement;
|
||||||
|
|
||||||
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
|
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
|
||||||
@ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
|
@ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
|
||||||
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) { }
|
@ViewChild('titleContainer', { read: ElementRef }) private _titleContainer: ElementRef;
|
||||||
|
@ViewChild('tabList', { read: ElementRef }) private _tabList: ElementRef;
|
||||||
|
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.options = mixin(this.options || {}, defaultOptions, false);
|
this.options = mixin(this.options || {}, defaultOptions, false);
|
||||||
@@ -90,6 +100,39 @@ export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
|
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) {
|
if (this.options.layout === NavigationBarLayout.horizontal) {
|
||||||
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(horizontalLayout);
|
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(horizontalLayout);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this._tabsDispose.push(this.dashboardService.onAddNewTabs(e => {
|
this._tabsDispose.push(this.dashboardService.onAddNewTabs(e => {
|
||||||
this.loadNewTabs(e);
|
this.loadNewTabs(e, true);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
|
|||||||
this.dashboardService.writeSettings([this.context, 'tabs'].join('.'), writeableConfig, target);
|
this.dashboardService.writeSettings([this.context, 'tabs'].join('.'), writeableConfig, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadNewTabs(dashboardTabs: IDashboardTab[]) {
|
private loadNewTabs(dashboardTabs: IDashboardTab[], openLastTab: boolean = false) {
|
||||||
if (dashboardTabs && dashboardTabs.length > 0) {
|
if (dashboardTabs && dashboardTabs.length > 0) {
|
||||||
let selectedTabs = dashboardTabs.map(v => {
|
let selectedTabs = dashboardTabs.map(v => {
|
||||||
let container = dashboardHelper.getDashboardContainer(v.container);
|
let container = dashboardHelper.getDashboardContainer(v.container);
|
||||||
@@ -226,10 +226,12 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
|
|||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
|
|
||||||
// put this immediately on the stack so that is ran *after* the tab is rendered
|
if (openLastTab) {
|
||||||
setTimeout(() => {
|
// put this immediately on the stack so that is ran *after* the tab is rendered
|
||||||
this._panel.selectTab(selectedTabs.pop().id);
|
setTimeout(() => {
|
||||||
});
|
this._panel.selectTab(selectedTabs.pop().id);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ panel.dashboard-panel > .tabbedPanel {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header .tab > .tabLabel.active {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header .tab > .tabLabel.active {
|
||||||
border-bottom: 0px solid;
|
border-bottom: 0px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .title-actions,
|
panel.dashboard-panel > .tabbedPanel > .title > .title-actions,
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
@@ -15,21 +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 > .tabList .tab:hover .tabLabel,
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab:hover .tabLabel,
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab .tabLabel.active {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel.active {
|
||||||
color: ${tabActiveForeground};
|
color: ${tabActiveForeground};
|
||||||
border-bottom: 0px solid;
|
border-bottom: 0px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
||||||
background-color: ${tabActiveBackground};
|
background-color: ${tabActiveBackground};
|
||||||
|
outline-color: ${tabActiveBackground};
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel.horizontal > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
||||||
border-bottom-color: transparent;
|
border-bottom-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.vertical > .title > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel.vertical > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -38,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 > .tabList .tab-header.active {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
|
||||||
box-shadow: ${activeTabBorderColor} 0 -1px inset;
|
box-shadow: ${activeTabBorderColor} 0 -1px inset;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -49,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 > .tabList .tab .tabLabel {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel {
|
||||||
color: ${tabInactiveForeground};
|
color: ${tabInactiveForeground};
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
||||||
background-color: ${tabInactiveBackground};
|
background-color: ${tabInactiveBackground};
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -73,18 +74,10 @@ 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 > .tabList .tab-header {
|
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
||||||
border-right-color: ${tabBoarder};
|
border-right-color: ${tabBoarder};
|
||||||
border-bottom-color: ${tabBoarder};
|
border-bottom-color: ${tabBoarder};
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title > .title-actions {
|
|
||||||
border-bottom-color: ${tabBoarder};
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.dashboard-panel > .tabbedPanel.vertical > .title > .title-actions {
|
|
||||||
border-right-color: ${tabBoarder};
|
|
||||||
}
|
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user