diff --git a/tensorboard/webapp/feature_flag/store/feature_flag_selectors.ts b/tensorboard/webapp/feature_flag/store/feature_flag_selectors.ts index b0d6d5c3f4..b5a13a7586 100644 --- a/tensorboard/webapp/feature_flag/store/feature_flag_selectors.ts +++ b/tensorboard/webapp/feature_flag/store/feature_flag_selectors.ts @@ -174,3 +174,10 @@ export const getIsScalarColumnCustomizationEnabled = createSelector( return flags.enableScalarColumnCustomization; } ); + +export const getEnableHparamsInTimeSeries = createSelector( + getFeatureFlags, + (flags: FeatureFlags): boolean => { + return flags.enableHparamsInTimeSeries; + } +); diff --git a/tensorboard/webapp/feature_flag/store/feature_flag_selectors_test.ts b/tensorboard/webapp/feature_flag/store/feature_flag_selectors_test.ts index 5e033e7ae6..076ddffbeb 100644 --- a/tensorboard/webapp/feature_flag/store/feature_flag_selectors_test.ts +++ b/tensorboard/webapp/feature_flag/store/feature_flag_selectors_test.ts @@ -444,4 +444,28 @@ describe('feature_flag_selectors', () => { ); }); }); + + describe('#getEnableHparamsInTimeSeries', () => { + it('returns true when enableHparamsInTimeSeries is true', () => { + let state = buildState( + buildFeatureFlagState({ + defaultFlags: buildFeatureFlag({ + enableHparamsInTimeSeries: true, + }), + }) + ); + expect(selectors.getEnableHparamsInTimeSeries(state)).toBeTrue(); + }); + + it('returns false when enableHparamsInTimeSeries is false', () => { + let state = buildState( + buildFeatureFlagState({ + defaultFlags: buildFeatureFlag({ + enableHparamsInTimeSeries: false, + }), + }) + ); + expect(selectors.getEnableHparamsInTimeSeries(state)).toBeFalse(); + }); + }); }); diff --git a/tensorboard/webapp/metrics/views/BUILD b/tensorboard/webapp/metrics/views/BUILD index 5eeec4d6a2..0aa162840e 100644 --- a/tensorboard/webapp/metrics/views/BUILD +++ b/tensorboard/webapp/metrics/views/BUILD @@ -34,12 +34,15 @@ tf_ng_module( "//tensorboard/webapp/angular:expect_angular_material_icon", "//tensorboard/webapp/core", "//tensorboard/webapp/customization", + "//tensorboard/webapp/feature_flag/store", + "//tensorboard/webapp/feature_flag/store:types", "//tensorboard/webapp/metrics/actions", "//tensorboard/webapp/metrics/views/main_view", "//tensorboard/webapp/metrics/views/right_pane", "//tensorboard/webapp/runs/views/runs_selector", "@npm//@angular/common", "@npm//@angular/core", + "@npm//@ngrx/store", ], ) @@ -73,11 +76,15 @@ tf_ts_library( ":types", ":utils", ":views", + "//tensorboard/webapp:app_state", "//tensorboard/webapp/angular:expect_angular_core_testing", "//tensorboard/webapp/angular:expect_angular_platform_browser_animations", "//tensorboard/webapp/angular:expect_ngrx_store_testing", + "//tensorboard/webapp/feature_flag/store", "//tensorboard/webapp/metrics/actions", "//tensorboard/webapp/metrics/data_source", + "//tensorboard/webapp/runs/views/runs_selector", + "//tensorboard/webapp/testing:utils", "@npm//@angular/core", "@npm//@angular/platform-browser", "@npm//@types/jasmine", diff --git a/tensorboard/webapp/metrics/views/metrics_container.ts b/tensorboard/webapp/metrics/views/metrics_container.ts index 86b246e1b3..7328ab47c8 100644 --- a/tensorboard/webapp/metrics/views/metrics_container.ts +++ b/tensorboard/webapp/metrics/views/metrics_container.ts @@ -13,16 +13,26 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {Store} from '@ngrx/store'; +import {getEnableHparamsInTimeSeries} from '../../feature_flag/store/feature_flag_selectors'; +import {State} from '../../feature_flag/store/feature_flag_types'; @Component({ selector: 'metrics-dashboard', template: ` - + `, styleUrls: ['metrics_container.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MetricsDashboardContainer {} +export class MetricsDashboardContainer { + showHparamsAndMetrics$ = this.store.select(getEnableHparamsInTimeSeries); + + constructor(readonly store: Store) {} +} diff --git a/tensorboard/webapp/metrics/views/metrics_container_test.ts b/tensorboard/webapp/metrics/views/metrics_container_test.ts index 704f86b450..5814d45bfc 100644 --- a/tensorboard/webapp/metrics/views/metrics_container_test.ts +++ b/tensorboard/webapp/metrics/views/metrics_container_test.ts @@ -15,22 +15,53 @@ limitations under the License. import {NO_ERRORS_SCHEMA} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; +import {Store} from '@ngrx/store'; +import {MockStore} from '@ngrx/store/testing'; +import {State} from '../../app_state'; +import {getEnableHparamsInTimeSeries} from '../../feature_flag/store/feature_flag_selectors'; +import {RunsSelectorContainer} from '../../runs/views/runs_selector/runs_selector_container'; +import {provideMockTbStore} from '../../testing/utils'; import {MetricsDashboardContainer} from './metrics_container'; describe('metrics view', () => { + let store: MockStore; + beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [MetricsDashboardContainer], - providers: [], + declarations: [MetricsDashboardContainer, RunsSelectorContainer], + providers: [provideMockTbStore()], // Ignore errors from components that are out-of-scope for this test: // 'runs-selector'. schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); + + store = TestBed.inject>(Store) as MockStore; }); it('renders', () => { + store.overrideSelector(getEnableHparamsInTimeSeries, false); const fixture = TestBed.createComponent(MetricsDashboardContainer); fixture.detectChanges(); expect(fixture.debugElement.query(By.css('runs-selector'))).not.toBeNull(); }); + + it('enables hparamsAndMetrics when enableHparamsInTimeSeries is true', () => { + store.overrideSelector(getEnableHparamsInTimeSeries, true); + const fixture = TestBed.createComponent(MetricsDashboardContainer); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('runs-selector')).componentInstance + .showHparamsAndMetrics + ).toBeTrue(); + }); + + it('disables hparamsAndMetrics when enableHparamsInTimeSeries is false', () => { + store.overrideSelector(getEnableHparamsInTimeSeries, false); + const fixture = TestBed.createComponent(MetricsDashboardContainer); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('runs-selector')).componentInstance + .showHparamsAndMetrics + ).toBeFalse(); + }); });