diff --git a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts index 279d8ebab6..2757c0e3e6 100644 --- a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts +++ b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts @@ -29,7 +29,6 @@ export class BdcDashboard { private dashboard: azdata.workspace.ModelViewEditor; private initialized: boolean = false; - private serviceTabsCreated: boolean = false; private modelView: azdata.ModelView; private mainAreaContainer: azdata.FlexContainer; @@ -38,7 +37,7 @@ export class BdcDashboard { private currentTab: NavTab; private currentPage: azdata.FlexContainer; - private serviceTabPageMapping: { [key: string]: { navTab: NavTab, servicePage: azdata.FlexContainer } } = {}; + private serviceTabPageMapping = new Map(); constructor(private title: string, private model: BdcDashboardModel) { this.model.onDidUpdateBdcStatus(bdcStatus => this.handleBdcStatusUpdate(bdcStatus)); @@ -161,7 +160,7 @@ export class BdcDashboard { return; } - this.createServiceNavTabs(bdcStatus.services); + this.updateServiceNavTabs(bdcStatus.services); } /** @@ -184,21 +183,27 @@ export class BdcDashboard { } /** - * Helper to create the navigation tabs for the services once the status has been loaded + * Helper to update the navigation tabs for the services when we get a status update */ - private createServiceNavTabs(services: ServiceStatusModel[]): void { - if (this.initialized && !this.serviceTabsCreated && services) { + private updateServiceNavTabs(services?: ServiceStatusModel[]): void { + if (this.initialized && services) { // Add a nav item for each service services.forEach(s => { - const navItem = createServiceNavTab(this.modelView.modelBuilder, s); - const serviceStatusPage = new BdcServiceStatusPage(s.serviceName, this.model, this.modelView).container; - this.serviceTabPageMapping[s.serviceName] = { navTab: navItem, servicePage: serviceStatusPage }; - navItem.div.onDidClick(() => { - this.switchToServiceTab(s.serviceName); - }); - this.navContainer.addItem(navItem.div, { flex: '0 0 auto' }); + const existingTabPage = this.serviceTabPageMapping[s.serviceName]; + if (existingTabPage) { + // We've already created the tab and page for this service, just update the tab health status dot + existingTabPage.navTab.dot.value = getHealthStatusDot(s.healthStatus); + } else { + // New service - create the page and tab + const navItem = createServiceNavTab(this.modelView.modelBuilder, s); + const serviceStatusPage = new BdcServiceStatusPage(s.serviceName, this.model, this.modelView).container; + this.serviceTabPageMapping[s.serviceName] = { navTab: navItem, servicePage: serviceStatusPage }; + navItem.div.onDidClick(() => { + this.switchToServiceTab(s.serviceName); + }); + this.navContainer.addItem(navItem.div, { flex: '0 0 auto' }); + } }); - this.serviceTabsCreated = true; } } } diff --git a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcServiceStatusPage.ts b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcServiceStatusPage.ts index cd38d8277c..501423341e 100644 --- a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcServiceStatusPage.ts +++ b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcServiceStatusPage.ts @@ -11,16 +11,19 @@ import { BdcDashboardModel } from './bdcDashboardModel'; import { getHealthStatusDot } from '../utils'; import { cssStyles } from '../constants'; +type ServiceTab = { div: azdata.DivContainer, dot: azdata.TextComponent, text: azdata.TextComponent }; + export class BdcServiceStatusPage { private initialized: boolean = false; - private resourceTabsCreated: boolean = false; - private currentTab: { div: azdata.DivContainer, text: azdata.TextComponent, index: number }; + private currentTab: { tab: ServiceTab, index: number }; private currentTabPage: azdata.FlexContainer; private rootContainer: azdata.FlexContainer; private resourceHeader: azdata.FlexContainer; + private createdTabs: Map = new Map(); + constructor(private serviceName: string, private model: BdcDashboardModel, private modelView: azdata.ModelView) { this.model.onDidUpdateBdcStatus(bdcStatus => this.handleBdcStatusUpdate(bdcStatus)); this.createPage(); @@ -76,42 +79,48 @@ export class BdcServiceStatusPage { * Helper to create the navigation tabs for the resources */ private createResourceNavTabs(resources: ResourceStatusModel[]) { - if (this.initialized && !this.resourceTabsCreated) { - let tabIndex = 0; + if (this.initialized) { + let tabIndex = this.createdTabs.size; resources.forEach(resource => { - const currentIndex = tabIndex++; - const resourceHeaderTab = createResourceHeaderTab(this.modelView.modelBuilder, resource); - const resourceStatusPage: azdata.FlexContainer = new BdcDashboardResourceStatusPage(this.model, this.modelView, this.serviceName, resource.resourceName).container; - resourceHeaderTab.div.onDidClick(() => { - // Don't need to do anything if this is already the currently selected tab - if (this.currentTab.index === currentIndex) { - return; + const existingTab: ServiceTab = this.createdTabs[resource.resourceName]; + if (existingTab) { + // We already created this tab so just update the status + existingTab.dot.value = getHealthStatusDot(resource.healthStatus); + } else { + // New tab - create and add to the end of the container + const currentIndex = tabIndex++; + const resourceHeaderTab = createResourceHeaderTab(this.modelView.modelBuilder, resource); + this.createdTabs[resource.resourceName] = resourceHeaderTab; + const resourceStatusPage: azdata.FlexContainer = new BdcDashboardResourceStatusPage(this.model, this.modelView, this.serviceName, resource.resourceName).container; + resourceHeaderTab.div.onDidClick(() => { + // Don't need to do anything if this is already the currently selected tab + if (this.currentTab.index === currentIndex) { + return; + } + if (this.currentTab) { + this.currentTab.tab.text.updateCssStyles(cssStyles.unselectedResourceHeaderTab); + this.resourceHeader.removeItem(this.currentTab.tab.div); + this.resourceHeader.insertItem(this.currentTab.tab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.unselectedTabDiv }); + } + this.changeSelectedTabPage(resourceStatusPage); + this.currentTab = { tab: resourceHeaderTab, index: currentIndex }; + this.currentTab.tab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab); + this.resourceHeader.removeItem(this.currentTab.tab.div); + this.resourceHeader.insertItem(this.currentTab.tab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv }); + }); + // Set initial page + if (!this.currentTabPage) { + this.changeSelectedTabPage(resourceStatusPage); + this.currentTab = { tab: resourceHeaderTab, index: currentIndex }; + this.currentTab.tab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab); + this.resourceHeader.addItem(resourceHeaderTab.div, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv }); } - if (this.currentTab) { - this.currentTab.text.updateCssStyles(cssStyles.unselectedResourceHeaderTab); - this.resourceHeader.removeItem(this.currentTab.div); - this.resourceHeader.insertItem(this.currentTab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.unselectedTabDiv }); + else { + resourceHeaderTab.text.updateCssStyles(cssStyles.unselectedResourceHeaderTab); + this.resourceHeader.addItem(resourceHeaderTab.div, { flex: '0 0 auto', CSSStyles: cssStyles.unselectedTabDiv }); } - this.changeSelectedTabPage(resourceStatusPage); - this.currentTab = { ...resourceHeaderTab, index: currentIndex }; - this.currentTab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab); - this.resourceHeader.removeItem(this.currentTab.div); - this.resourceHeader.insertItem(this.currentTab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv }); - }); - // Set initial page - if (!this.currentTabPage) { - this.changeSelectedTabPage(resourceStatusPage); - this.currentTab = { ...resourceHeaderTab, index: currentIndex }; - this.currentTab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab); - this.resourceHeader.addItem(resourceHeaderTab.div, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv }); } - else { - resourceHeaderTab.text.updateCssStyles(cssStyles.unselectedResourceHeaderTab); - this.resourceHeader.addItem(resourceHeaderTab.div, { flex: '0 0 auto', CSSStyles: cssStyles.unselectedTabDiv }); - } - }); - this.resourceTabsCreated = true; } } } @@ -119,14 +128,15 @@ export class BdcServiceStatusPage { /** * Creates a single resource header tab * @param modelBuilder The ModelBuilder used to construct the object - * @param title The text to display in the tab + * @param resourceStatus The status of the resource we're creating */ -function createResourceHeaderTab(modelBuilder: azdata.ModelBuilder, resourceStatus: ResourceStatusModel): { div: azdata.DivContainer, text: azdata.TextComponent } { +function createResourceHeaderTab(modelBuilder: azdata.ModelBuilder, resourceStatus: ResourceStatusModel): ServiceTab { const resourceHeaderTab = modelBuilder.divContainer().withLayout({ width: '100px', height: '25px' }).withProperties({ CSSStyles: { 'cursor': 'pointer' } }).component(); const innerContainer = modelBuilder.flexContainer().withLayout({ width: '100px', height: '25px', flexFlow: 'row' }).component(); - innerContainer.addItem(modelBuilder.text().withProperties({ value: getHealthStatusDot(resourceStatus.healthStatus), CSSStyles: { 'color': 'red', 'font-size': '40px', 'width': '20px', 'text-align': 'right', ...cssStyles.nonSelectableText } }).component(), { flex: '0 0 auto' }); + const statusDot = modelBuilder.text().withProperties({ value: getHealthStatusDot(resourceStatus.healthStatus), CSSStyles: { 'color': 'red', 'font-size': '40px', 'width': '20px', 'text-align': 'right', ...cssStyles.nonSelectableText } }).component(); + innerContainer.addItem(statusDot, { flex: '0 0 auto' }); const resourceHeaderLabel = modelBuilder.text().withProperties({ value: resourceStatus.resourceName, CSSStyles: { 'text-align': 'left', ...cssStyles.text } }).component(); innerContainer.addItem(resourceHeaderLabel); resourceHeaderTab.addItem(innerContainer); - return { div: resourceHeaderTab, text: resourceHeaderLabel }; + return { div: resourceHeaderTab, text: resourceHeaderLabel, dot: statusDot }; }