diff --git a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboardOverviewPage.ts b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboardOverviewPage.ts index 3e56c37cdf..b1e9bbd8fd 100644 --- a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboardOverviewPage.ts +++ b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboardOverviewPage.ts @@ -68,7 +68,7 @@ export class BdcDashboardOverviewPage extends BdcDashboardPage { this.propertiesErrorMessage = view.modelBuilder.text().withProperties({ display: 'none', CSSStyles: { ...cssStyles.errorText } }).component(); rootContainer.addItem(this.propertiesErrorMessage, { flex: '0 0 auto' }); - this.propertiesContainer = view.modelBuilder.divContainer().component(); + this.propertiesContainer = view.modelBuilder.divContainer().withProperties({ clickable: false }).component(); // Row 1 const row1 = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', height: '30px', alignItems: 'center' }).component(); @@ -76,14 +76,20 @@ export class BdcDashboardOverviewPage extends BdcDashboardPage { // Cluster State const clusterStateLabel = view.modelBuilder.text().withProperties({ value: loc.clusterState }).component(); const clusterStateValue = view.modelBuilder.text().component(); - this.clusterStateLoadingComponent = view.modelBuilder.loadingComponent().withItem(clusterStateValue).component(); + this.clusterStateLoadingComponent = view.modelBuilder.loadingComponent() + .withItem(clusterStateValue) + .withProperties({ loadingCompletedText: loc.loadingClusterStateCompleted }) + .component(); row1.addItem(clusterStateLabel, { CSSStyles: { 'width': `${clusterStateLabelColumnWidth}px`, 'min-width': `${clusterStateLabelColumnWidth}px`, 'user-select': 'none', 'font-weight': 'bold' } }); row1.addItem(this.clusterStateLoadingComponent, { CSSStyles: { 'width': `${clusterStateValueColumnWidth}px`, 'min-width': `${clusterStateValueColumnWidth}px` } }); // Health Status const healthStatusLabel = view.modelBuilder.text().withProperties({ value: loc.healthStatusWithColon }).component(); const healthStatusValue = view.modelBuilder.text().component(); - this.clusterHealthStatusLoadingComponent = view.modelBuilder.loadingComponent().withItem(healthStatusValue).component(); + this.clusterHealthStatusLoadingComponent = view.modelBuilder.loadingComponent() + .withItem(healthStatusValue) + .withProperties({ loadingCompletedText: loc.loadingHealthStatusCompleted }) + .component(); row1.addItem(healthStatusLabel, { CSSStyles: { 'width': `${healthStatusColumnWidth}px`, 'min-width': `${healthStatusColumnWidth}px`, 'user-select': 'none', 'font-weight': 'bold' } }); row1.addItem(this.clusterHealthStatusLoadingComponent, { CSSStyles: { 'width': `${healthStatusColumnWidth}px`, 'min-width': `${healthStatusColumnWidth}px` } }); diff --git a/extensions/big-data-cluster/src/bigDataCluster/localizedConstants.ts b/extensions/big-data-cluster/src/bigDataCluster/localizedConstants.ts index eae2cecb54..2d73827565 100644 --- a/extensions/big-data-cluster/src/bigDataCluster/localizedConstants.ts +++ b/extensions/big-data-cluster/src/bigDataCluster/localizedConstants.ts @@ -76,6 +76,8 @@ export const credentials = localize('mount.credentials.title', "Credentials"); export const credentialsInfo = localize('mount.credentials.info', "Mount credentials for authentication to remote data source for reads"); export const refreshMount = localize('refreshmount.dialog.title', "Refresh Mount"); export const deleteMount = localize('deleteMount.dialog.title', "Delete Mount"); +export const loadingClusterStateCompleted = localize('bdc.dashboard.loadingClusterStateCompleted', "Loading cluster state completed"); +export const loadingHealthStatusCompleted = localize('bdc.dashboard.loadingHealthStatusCompleted', "Loading health status completed"); // Errors export const usernameRequired = localize('err.controller.username.required', "Username is required"); diff --git a/src/sql/workbench/browser/modelComponents/divContainer.component.ts b/src/sql/workbench/browser/modelComponents/divContainer.component.ts index 7bfb812a5c..56fdbb4762 100644 --- a/src/sql/workbench/browser/modelComponents/divContainer.component.ts +++ b/src/sql/workbench/browser/modelComponents/divContainer.component.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/divContainer'; import { Component, Input, Inject, ChangeDetectorRef, forwardRef, - ViewChild, ElementRef, OnDestroy, + ViewChild, ElementRef, OnDestroy, Renderer2, AfterViewInit } from '@angular/core'; import * as azdata from 'azdata'; @@ -24,7 +24,7 @@ class DivItem { @Component({ template: ` -
+
@@ -32,22 +32,30 @@ class DivItem {
` }) -export default class DivContainer extends ContainerBase implements IComponent, OnDestroy { +export default class DivContainer extends ContainerBase implements IComponent, OnDestroy, AfterViewInit { @Input() descriptor: IComponentDescriptor; @Input() modelStore: IModelStore; @ViewChild('divContainer', { read: ElementRef }) divContainer; private _height: string; private _width: string; private _overflowY: string; + private viewInitialized: boolean; + private cancelClick: Function; constructor( @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef, - @Inject(forwardRef(() => ElementRef)) el: ElementRef + @Inject(forwardRef(() => ElementRef)) el: ElementRef, + @Inject(forwardRef(() => Renderer2)) private renderer: Renderer2 ) { super(changeRef, el); this._overflowY = ''; // default } + ngAfterViewInit() { + this.viewInitialized = true; + this.updateClickListener(); + } + ngOnInit(): void { this.baseInit(); } @@ -97,6 +105,7 @@ export default class DivContainer extends ContainerBase im element.removeAttribute('tabIndex'); element.style.cursor = 'default'; } + this.updateClickListener(); } private onClick() { @@ -148,4 +157,17 @@ export default class DivContainer extends ContainerBase im public getItemStyles(item: DivItem): { [key: string]: string } { return item.config && item.config.CSSStyles ? item.config.CSSStyles : {}; } + + private updateClickListener(): void { + // We can't hook into the listener until the view is initialized + if (!this.viewInitialized) { + return; + } + if (this.clickable && !this.cancelClick) { + this.cancelClick = this.renderer.listen(this.divContainer.nativeElement, 'click', () => this.onClick()); + } else if (!this.clickable) { + this.cancelClick(); + this.cancelClick = undefined; + } + } } diff --git a/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts b/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts index e2b91e8db6..94930655b6 100644 --- a/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts +++ b/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts @@ -13,13 +13,11 @@ import * as azdata from 'azdata'; import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase'; import { localize } from 'vs/nls'; import { IComponent, IComponentDescriptor, IModelStore } from 'sql/platform/dashboard/browser/interfaces'; +import { status } from 'vs/base/browser/ui/aria/aria'; @Component({ selector: 'modelview-loadingComponent', template: ` -
- {{getStatusText()}} -
{{getStatusText()}}
@@ -66,7 +64,11 @@ export default class LoadingComponent extends ComponentBase implements IComponen } public setProperties(properties: { [key: string]: any; }): void { + const wasLoading = this.loading; super.setProperties(properties); + if (wasLoading && !this.loading) { + status(this.getStatusText()); + } } public get loading(): boolean { diff --git a/src/sql/workbench/browser/modelComponents/media/loadingComponent.css b/src/sql/workbench/browser/modelComponents/media/loadingComponent.css index f5fa7d9033..9e74fb2cef 100644 --- a/src/sql/workbench/browser/modelComponents/media/loadingComponent.css +++ b/src/sql/workbench/browser/modelComponents/media/loadingComponent.css @@ -32,14 +32,3 @@ .modelview-loadingComponent-content-loading { display: none; } - -/* We want to make this on DOM but not visible so that screen reader can read the status message */ - -.modelview-loading-component-status-message { - top: -1; - left: -1px; - width: 1px; - height: 1px; - position: absolute; - overflow: hidden; -}