From 530ec8c19d4c47ba6e91122f27e23747770fb8ee Mon Sep 17 00:00:00 2001 From: Kim Santiago <31145923+kisantia@users.noreply.github.com> Date: Thu, 16 Apr 2020 20:23:35 -0700 Subject: [PATCH] Update dashboard properties widget style for Reflow (#9976) * layout properties in 2 columns * fix height after collapsing * update with reflow values * set height better * cleanup * fix crashing when resizing while properties widget is loading * Switch to grid layout * Only two columns max * Update comment * Undo color change * Cleanup * Fix test Co-authored-by: chgagnon --- .../dashboardHomeContainer.component.ts | 18 ++++- .../dashboardWidgetWrapper.component.ts | 4 + .../browser/core/dashboardPanelStyles.ts | 12 +-- .../propertiesWidget.component.html | 22 ++---- .../properties/propertiesWidget.component.ts | 74 ++++++++++++------- .../widgets/properties/propertiesWidget.css | 40 +++++++++- .../propertiesWidget.component.test.ts | 6 +- 7 files changed, 123 insertions(+), 53 deletions(-) diff --git a/src/sql/workbench/contrib/dashboard/browser/containers/dashboardHomeContainer.component.ts b/src/sql/workbench/contrib/dashboard/browser/containers/dashboardHomeContainer.component.ts index 87a8b512ca..7bdb37d965 100644 --- a/src/sql/workbench/contrib/dashboard/browser/containers/dashboardHomeContainer.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/containers/dashboardHomeContainer.component.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./dashboardHomeContainer'; +import * as DOM from 'vs/base/browser/dom'; import { Component, forwardRef, Input, ChangeDetectorRef, Inject, ViewChild, ElementRef } from '@angular/core'; @@ -22,6 +23,7 @@ import { DASHBOARD_BORDER } from 'vs/workbench/common/theme'; import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { PropertiesWidgetComponent } from 'sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component'; @Component({ selector: 'dashboard-home-container', @@ -31,7 +33,7 @@ import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
+ class="properties" [style.height.px]="_propertiesClass?.collapsed ? '30' : getHeight()">
@@ -46,6 +48,8 @@ export class DashboardHomeContainer extends DashboardWidgetContainer { @ViewChild('propertiesContainer') private _propertiesContainer: ElementRef; @ViewChild(ScrollableDirective) private _scrollable: ScrollableDirective; + private height = 75; // default initial height + constructor( @Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef, @Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface, @@ -78,6 +82,18 @@ export class DashboardHomeContainer extends DashboardWidgetContainer { this._propertiesClass.collapsed ? 'collapsed' : true, ConfigurationTarget.USER); } })); + + this._register(DOM.addDisposableListener(window, DOM.EventType.RESIZE, e => { + this._cd.detectChanges(); + })); + } + + public getHeight(): number { + if (this._propertiesClass && (this._propertiesClass.component).height) { + this.height = (this._propertiesClass.component).height; + } + + return this.height; } public layout() { diff --git a/src/sql/workbench/contrib/dashboard/browser/contents/dashboardWidgetWrapper.component.ts b/src/sql/workbench/contrib/dashboard/browser/contents/dashboardWidgetWrapper.component.ts index 14f4d0dac8..e51bc2b180 100644 --- a/src/sql/workbench/contrib/dashboard/browser/contents/dashboardWidgetWrapper.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/contents/dashboardWidgetWrapper.component.ts @@ -165,6 +165,10 @@ export class DashboardWidgetWrapper extends AngularDisposable implements OnInit this._actionbar.pull(this._actionbar.length() - 1); } + public get component(): IDashboardWidget { + return this._component; + } + private loadWidget(): void { if (Object.keys(this._config.widget).length !== 1) { this.logService.error('Exactly 1 widget must be defined per space'); diff --git a/src/sql/workbench/contrib/dashboard/browser/core/dashboardPanelStyles.ts b/src/sql/workbench/contrib/dashboard/browser/core/dashboardPanelStyles.ts index e1748d6746..0873c78f86 100644 --- a/src/sql/workbench/contrib/dashboard/browser/core/dashboardPanelStyles.ts +++ b/src/sql/workbench/contrib/dashboard/browser/core/dashboardPanelStyles.ts @@ -11,7 +11,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = // tab label const tabLabelColor = theme.getColor(TAB_LABEL); if (tabLabelColor) { - collector.addRule(`properties-widget .propertiesValue { + collector.addRule(`properties-widget .propertyValue { color: ${tabLabelColor} }`); } @@ -32,11 +32,11 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = }`); } - // properties name - const propertiesName = theme.getColor(DASHBOARD_PROPERTIES_NAME); - if (propertiesName) { - collector.addRule(`properties-widget .propertiesName { - color: ${propertiesName} + // property name + const propertyName = theme.getColor(DASHBOARD_PROPERTIES_NAME); + if (propertyName) { + collector.addRule(`properties-widget .propertyName { + color: ${propertyName} }`); } }); diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.html b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.html index c61ba9e702..02f9f8185a 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.html +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.html @@ -6,18 +6,12 @@ --> -
-
- - - -
{{item.displayName}}
-
{{item.value}}
-
-
-
-
- - ... - +
+ +
+
{{item.displayName}}
+
:
+
{{item.value}}
+
+
diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.ts b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.ts index a176b694ed..b4c5701576 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./propertiesWidget'; -import { Component, Inject, forwardRef, ChangeDetectorRef, OnInit, ElementRef, ViewChild } from '@angular/core'; +import { Component, Inject, forwardRef, ChangeDetectorRef, OnInit, ElementRef } from '@angular/core'; import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/contrib/dashboard/browser/core/dashboardWidget'; import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service'; @@ -57,6 +57,21 @@ export interface DisplayProperty { value: string; } +enum GridDisplayLayout { + twoColumns = 'twoColumns', + oneColumn = 'oneColumn' +} + +enum PropertyLayoutDirection { + row = 'rowLayout', + column = 'columnLayout' +} + + +const collapseHeight = 25; +const horizontalPropertyHeight = 28; +const verticalPropertyHeight = 46; + @Component({ selector: 'properties-widget', templateUrl: decodeURI(require.toUrl('./propertiesWidget.component.html')) @@ -64,11 +79,10 @@ export interface DisplayProperty { export class PropertiesWidgetComponent extends DashboardWidget implements IDashboardWidget, OnInit { private _connection: ConnectionManagementInfo; private _databaseInfo: DatabaseInfo; - public _clipped: boolean; - private properties: Array; - - @ViewChild('child', { read: ElementRef }) private _child: ElementRef; - @ViewChild('parent', { read: ElementRef }) private _parent: ElementRef; + private _properties: Array; + public gridDisplayLayout: GridDisplayLayout; + public propertyLayout: PropertyLayoutDirection; + public height: number; constructor( @Inject(forwardRef(() => CommonServiceInterface)) private _bootstrap: CommonServiceInterface, @@ -85,7 +99,7 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb ngOnInit() { this._inited = true; - this._register(addDisposableListener(window, EventType.RESIZE, () => this.handleClipping())); + this._register(addDisposableListener(window, EventType.RESIZE, () => this.layoutProperties())); this._changeRef.detectChanges(); } @@ -100,23 +114,36 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb this._databaseInfo = data; this._changeRef.detectChanges(); this.parseProperties(); - if (this._inited) { - this.handleClipping(); - } this.setLoadingStatus(false); + this.layoutProperties(); }, error => { this.setLoadingStatus(false); (this._el.nativeElement).innerText = nls.localize('dashboard.properties.error', "Unable to load dashboard properties"); }))); } - private handleClipping(): void { - if (this._child.nativeElement.offsetWidth > this._parent.nativeElement.offsetWidth) { - this._clipped = true; - } else { - this._clipped = false; + private layoutProperties(): void { + // Reflow: + // 2 columns w/ horizontal alignment : 1366px and above + // 2 columns w/ vertical alignment : 1024 - 1365px + // 1 column w/ vertical alignment : 1024px or less + if (!this._loading) { + if (window.innerWidth >= 1366) { + this.gridDisplayLayout = GridDisplayLayout.twoColumns; + this.propertyLayout = PropertyLayoutDirection.row; + this.height = Math.ceil(this._properties.length / 2) * horizontalPropertyHeight + collapseHeight; + } else if (window.innerWidth < 1366 && window.innerWidth >= 1024) { + this.gridDisplayLayout = GridDisplayLayout.twoColumns; + this.propertyLayout = PropertyLayoutDirection.column; + this.height = Math.ceil(this._properties.length / 2) * verticalPropertyHeight + collapseHeight; + } else if (window.innerWidth < 1024) { + this.gridDisplayLayout = GridDisplayLayout.oneColumn; + this.propertyLayout = PropertyLayoutDirection.column; + this.height = this._properties.length * verticalPropertyHeight + collapseHeight; + } + + this._changeRef.detectChanges(); } - this._changeRef.detectChanges(); } private parseProperties() { @@ -208,11 +235,7 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb infoObject = this._connection.serverInfo; } - // iterate over properties and display them - this.properties = []; - for (let i = 0; i < propertyArray.length; i++) { - const property = propertyArray[i]; - const assignProperty = {}; + this._properties = propertyArray.map(property => { let propertyObject = this.getValueOrDefault(infoObject, property.value, property.default || '--'); // make sure the value we got shouldn't be ignored @@ -225,10 +248,11 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb } } } - assignProperty['displayName'] = property.displayName; - assignProperty['value'] = propertyObject; - this.properties.push(assignProperty); - } + return { + displayName: property.displayName, + value: propertyObject + }; + }); if (this._inited) { this._changeRef.detectChanges(); diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.css b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.css index 9fa11c0a40..c3136b1501 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.css +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.css @@ -3,11 +3,43 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.propertiesName { - opacity: 0.6; +properties-widget .twoColumns.grid-container { + grid-template-columns: 50% 50%; } -.vs-dark .propertiesName, -.hc-black .propertiesName { +properties-widget .oneColumn.grid-container { + grid-template-columns: 100%; +} + +properties-widget .columnLayout.property { + flex-direction: column; +} + +properties-widget .propertyName { + opacity: 0.6; + font-size: 12px; + flex: 0 0 auto +} + +.vs-dark properties-widget .propertyName, +.hc-black properties-widget .propertyName { opacity: 1; } + +properties-widget .propertyValue { + font-size: 12px; + flex: 1 1 auto; + margin-right: 5px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +properties-widget .splitter { + flex: 0 0 15px; + text-align: center; +} + +properties-widget .columnLayout .splitter { + display: none; +} diff --git a/src/sql/workbench/contrib/dashboard/test/electron-browser/propertiesWidget.component.test.ts b/src/sql/workbench/contrib/dashboard/test/electron-browser/propertiesWidget.component.test.ts index 101ecc3f89..6a8a255043 100644 --- a/src/sql/workbench/contrib/dashboard/test/electron-browser/propertiesWidget.component.test.ts +++ b/src/sql/workbench/contrib/dashboard/test/electron-browser/propertiesWidget.component.test.ts @@ -104,9 +104,9 @@ suite('Dashboard Properties Widget Tests', () => { // because config parsing is done async we need to put our asserts on the thread stack setImmediate(() => { // because properties is private we need to do some work arounds to access it. - assert.equal((testComponent).properties.length, 1); - assert.equal((testComponent).properties[0].displayName, 'Test'); - assert.equal((testComponent).properties[0].value, 'Test Property'); + assert.equal((testComponent)._properties.length, 1); + assert.equal((testComponent)._properties[0].displayName, 'Test'); + assert.equal((testComponent)._properties[0].value, 'Test Property'); resolve(); }); });