From 683c43b3273a85545b16b93de80fd077cefd2512 Mon Sep 17 00:00:00 2001 From: Adrian RC Date: Wed, 16 Oct 2024 21:30:28 +0000 Subject: [PATCH 1/2] LSC cl/683332949 - Move initializer into the constructor for instance members that reference identifiers declared in the constructor. --- .../debugger_container.ts | 24 +- .../views/alerts/alerts_container.ts | 40 +- .../webapp/core/effects/core_effects.ts | 364 +++++++++--------- .../views/feature_flag_dialog_container.ts | 57 +-- .../scalar_card_line_chart_container.ts | 84 ++-- .../views/main_view/card_grid_container.ts | 134 ++++--- .../views/main_view/filter_input_container.ts | 45 +-- .../webapp/metrics/views/metrics_container.ts | 6 +- .../right_pane/settings_view_container.ts | 153 ++++---- .../webapp/plugins/plugins_container.ts | 117 +++--- .../webapp/runs/effects/runs_effects.ts | 192 ++++----- .../views/runs_table/runs_table_container.ts | 123 +++--- 12 files changed, 711 insertions(+), 628 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts index e2865d6534..a0d1eb455c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts @@ -38,19 +38,23 @@ import {State} from './store/debugger_types'; ], }) export class DebuggerContainer implements OnInit, OnDestroy { - readonly runs$ = this.store.pipe(select(getDebuggerRunListing)); + readonly runs$; - readonly runsIds$ = this.store.pipe( - select( - createSelector(getDebuggerRunListing, (runs): string[] => - Object.keys(runs) - ) - ) - ); + readonly runsIds$; - readonly activeRunId$ = this.store.pipe(select(getActiveRunId)); + readonly activeRunId$; - constructor(private readonly store: Store) {} + constructor(private readonly store: Store) { + this.runs$ = this.store.pipe(select(getDebuggerRunListing)); + this.runsIds$ = this.store.pipe( + select( + createSelector(getDebuggerRunListing, (runs): string[] => + Object.keys(runs), + ), + ), + ); + this.activeRunId$ = this.store.pipe(select(getActiveRunId)); + } ngOnInit(): void { this.store.dispatch(debuggerLoaded()); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts index 3dd5759089..a40249c075 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts @@ -59,27 +59,31 @@ const ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL: { changeDetection: ChangeDetectionStrategy.OnPush, }) export class AlertsContainer { - readonly numAlerts$ = this.store.pipe(select(getNumAlerts)); + readonly numAlerts$; - readonly alertsBreakdown$ = this.store.pipe( - select( - createSelector(getAlertsBreakdown, (alertsBreakdown) => { - const alertTypes = Object.keys(alertsBreakdown); - alertTypes.sort(); - return alertTypes.map((alertType): AlertTypeDisplay => { - return { - type: alertType as AlertType, - ...ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL[alertType], - count: alertsBreakdown[alertType], - }; - }); - }) - ) - ); + readonly alertsBreakdown$; - readonly focusType$ = this.store.pipe(select(getAlertsFocusType)); + readonly focusType$; - constructor(private readonly store: Store) {} + constructor(private readonly store: Store) { + this.numAlerts$ = this.store.pipe(select(getNumAlerts)); + this.alertsBreakdown$ = this.store.pipe( + select( + createSelector(getAlertsBreakdown, (alertsBreakdown) => { + const alertTypes = Object.keys(alertsBreakdown); + alertTypes.sort(); + return alertTypes.map((alertType): AlertTypeDisplay => { + return { + type: alertType as AlertType, + ...ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL[alertType], + count: alertsBreakdown[alertType], + }; + }); + }), + ), + ); + this.focusType$ = this.store.pipe(select(getAlertsFocusType)); + } onToggleFocusType(alertType: AlertType) { this.store.dispatch(alertTypeFocusToggled({alertType})); diff --git a/tensorboard/webapp/core/effects/core_effects.ts b/tensorboard/webapp/core/effects/core_effects.ts index 4d09d13485..65eadecd01 100644 --- a/tensorboard/webapp/core/effects/core_effects.ts +++ b/tensorboard/webapp/core/effects/core_effects.ts @@ -103,173 +103,14 @@ export class CoreEffects { return from(this.tfBackend.ref.runsStore.refresh()); } - private readonly onDashboardLoad$ = - // Loading dashboard data on `coreLoaded` is temporary; not all TB apps - // use the router. For those router-less applications, we have to support - // the legacy `coreLoaded`. - merge( - this.actions$.pipe( - ofType(coreLoaded, navigated), - withLatestFrom(this.store.select(getActiveRoute)), - distinctUntilChanged(([, beforeRoute], [, afterRoute]) => { - return areSameRouteKindAndExperiments(beforeRoute, afterRoute); - }) - ), - this.actions$.pipe(ofType(reload, manualReload)) - ).pipe( - withLatestFrom(this.store.select(getRouteKind)), - filter(([, routeKind]) => DASHBOARD_ROUTE_KIND.has(routeKind)), - throttleTime(DATA_LOAD_CONDITIONAL_THROTTLE_IN_MS, undefined, { - leading: true, - }) - ); + private readonly onDashboardLoad$; /** * Requires to be exported for JSCompiler. JSCompiler, otherwise, * think it is unused property and deadcode eliminate away. */ /** @export */ - readonly fetchWebAppData$ = createEffect( - () => { - const pluginsListingReload$ = this.onDashboardLoad$.pipe( - withLatestFrom( - this.store.select(getPluginsListLoaded), - this.store.select(getEnabledExperimentalPlugins) - ), - filter(([, {state}]) => state !== DataLoadState.LOADING), - tap(() => this.store.dispatch(pluginsListingRequested())), - mergeMap(([, , enabledExperimentalPlugins]) => { - return zip( - this.webappDataSource.fetchPluginsListing( - enabledExperimentalPlugins - ), - // TODO(tensorboard-team): consider brekaing the environments out of - // the pluginsListingLoaded; currently, plugins listing load state - // is connected to the environments which is not ideal. Have its own - // load state. - this.fetchEnvironment() - ).pipe( - map(([plugins]) => { - this.store.dispatch(pluginsListingLoaded({plugins})); - }), - catchError((e) => { - if (e instanceof TBServerError) { - this.store.dispatch( - pluginsListingFailed({failureCode: e.failureCode}) - ); - } else { - this.store.dispatch( - pluginsListingFailed({ - failureCode: PluginsListFailureCode.UNKNOWN, - }) - ); - } - return EMPTY; - }) - ); - }) - ); - - const runsReload$ = this.onDashboardLoad$.pipe( - map(([, routeKind]) => routeKind), - switchMap((routeKind) => { - if (routeKind !== RouteKind.COMPARE_EXPERIMENT) { - return of([]); - } - - // If alias map changes, we need to refetch the list of runs as - // Polymer's run selector and tags rely on run names including the - // alias. - return this.store.select(getExperimentIdToExperimentAliasMap).pipe( - distinctUntilChanged((beforeAliasDict, afterAliasDict) => { - const entries = Object.entries(beforeAliasDict); - const afterAliasMap = new Map(Object.entries(afterAliasDict)); - if (entries.length !== afterAliasMap.size) { - return false; - } - for (const [experimentId, alias] of entries) { - if (!afterAliasMap.get(experimentId)) { - return false; - } - if ( - afterAliasMap.get(experimentId)!.aliasText !== - alias.aliasText || - afterAliasMap.get(experimentId)!.aliasNumber !== - alias.aliasNumber - ) { - return false; - } - } - return true; - }), - // HACK: arbitrary microtask delay. - // An alias change -> route change -> browser url change -> - // `navigated` action. Because we, especially Polymer code, makes - // requests under a relative path, we must make requests only after - // the URL has been modified to reflect new alias or experiment id. - // - // While we can subscribe to `navigated` without - // `distinctUntilChanged` and `areSameRouteExperiments`, it is hard - // to throttle quick alias Map changes while immediately making a - // request for a real navigation. For example, for route A and - // route B: - // - // 0 100 600 700 - // A -> A' -> A" -> B - // ↑ ↑ ↑ - // req noop req req - // - // Above, we would like to make the request immediately when the set - // of experiments change while debouncing alias changes when the set - // of experiments have not changed. - // - // Instead of more elaborate rxjs techniques, we are - // using `delay(0)` to give the router a chance to modify the URL - // before making the request. - delay(0), - // Prevent changes in the alias map not to over-trigger requests; - // However, we want to use throttle instead of debounce since we - // need to emit on `leading` so it does not cause 500ms delay on - // page load. - throttleTime(ALIAS_CHANGE_RUNS_RELOAD_THROTTLE_IN_MS, undefined, { - leading: true, - trailing: true, - }) - ); - }), - withLatestFrom( - this.store.select(getRouteKind), - this.store.select(getPolymerRunsLoadState) - ), - filter(([, routeKind, loadState]) => { - // While the same check was applied earlier, `delay` + `throttleTime` - // makes it unpredictable and we can sometimes make requests for the - // wrong route. This check prevents making the request in wrong - // hostname in a fool proof way. - return ( - DASHBOARD_ROUTE_KIND.has(routeKind) && - loadState.state !== DataLoadState.LOADING - ); - }), - tap(() => { - this.store.dispatch(polymerRunsFetchRequested()); - }), - switchMap(() => { - return this.refreshPolymerRuns(); - }), - tap(() => { - this.store.dispatch(polymerRunsFetchSucceeded()); - }), - catchError(() => { - this.store.dispatch(polymerRunsFetchFailed()); - return EMPTY; - }) - ); - - return merge(pluginsListingReload$, runsReload$); - }, - {dispatch: false} - ); + readonly fetchWebAppData$; /** * HACK: COMPOSITE ACTION -- Fire `changePlugin` on first truthy value of @@ -283,38 +124,197 @@ export class CoreEffects { * * @export */ - readonly dispatchChangePlugin$ = createEffect( - () => { - return merge( - this.onDashboardLoad$, - this.actions$.pipe(ofType(pluginsListingLoaded)) - ).pipe( - withLatestFrom(this.store.select(getActivePlugin)), - map(([, activePlugin]) => activePlugin), - distinctUntilChanged(), - filter((activePlugin) => activePlugin !== null), - take(1), - tap((plugin) => { - this.store.dispatch(changePlugin({plugin: plugin!})); - }) - ); - }, - {dispatch: false} - ); + readonly dispatchChangePlugin$; private fetchEnvironment() { return this.webappDataSource.fetchEnvironment().pipe( tap((environment) => { this.store.dispatch(environmentLoaded({environment})); - }) + }), ); } constructor( private actions$: Actions, private store: Store, - private webappDataSource: TBServerDataSource - ) {} + private webappDataSource: TBServerDataSource, + ) { + this.onDashboardLoad$ = merge( + this.actions$.pipe( + ofType(coreLoaded, navigated), + withLatestFrom(this.store.select(getActiveRoute)), + distinctUntilChanged(([, beforeRoute], [, afterRoute]) => { + return areSameRouteKindAndExperiments(beforeRoute, afterRoute); + }), + ), + this.actions$.pipe(ofType(reload, manualReload)), + ).pipe( + withLatestFrom(this.store.select(getRouteKind)), + filter(([, routeKind]) => DASHBOARD_ROUTE_KIND.has(routeKind)), + throttleTime(DATA_LOAD_CONDITIONAL_THROTTLE_IN_MS, undefined, { + leading: true, + }), + ); + this.fetchWebAppData$ = createEffect( + () => { + const pluginsListingReload$ = this.onDashboardLoad$.pipe( + withLatestFrom( + this.store.select(getPluginsListLoaded), + this.store.select(getEnabledExperimentalPlugins), + ), + filter(([, {state}]) => state !== DataLoadState.LOADING), + tap(() => this.store.dispatch(pluginsListingRequested())), + mergeMap(([, , enabledExperimentalPlugins]) => { + return zip( + this.webappDataSource.fetchPluginsListing( + enabledExperimentalPlugins, + ), + // TODO(tensorboard-team): consider brekaing the environments out of + // the pluginsListingLoaded; currently, plugins listing load state + // is connected to the environments which is not ideal. Have its own + // load state. + this.fetchEnvironment(), + ).pipe( + map(([plugins]) => { + this.store.dispatch(pluginsListingLoaded({plugins})); + }), + catchError((e) => { + if (e instanceof TBServerError) { + this.store.dispatch( + pluginsListingFailed({failureCode: e.failureCode}), + ); + } else { + this.store.dispatch( + pluginsListingFailed({ + failureCode: PluginsListFailureCode.UNKNOWN, + }), + ); + } + return EMPTY; + }), + ); + }), + ); + + const runsReload$ = this.onDashboardLoad$.pipe( + map(([, routeKind]) => routeKind), + switchMap((routeKind) => { + if (routeKind !== RouteKind.COMPARE_EXPERIMENT) { + return of([]); + } + + // If alias map changes, we need to refetch the list of runs as + // Polymer's run selector and tags rely on run names including the + // alias. + return this.store.select(getExperimentIdToExperimentAliasMap).pipe( + distinctUntilChanged((beforeAliasDict, afterAliasDict) => { + const entries = Object.entries(beforeAliasDict); + const afterAliasMap = new Map(Object.entries(afterAliasDict)); + if (entries.length !== afterAliasMap.size) { + return false; + } + for (const [experimentId, alias] of entries) { + if (!afterAliasMap.get(experimentId)) { + return false; + } + if ( + afterAliasMap.get(experimentId)!.aliasText !== + alias.aliasText || + afterAliasMap.get(experimentId)!.aliasNumber !== + alias.aliasNumber + ) { + return false; + } + } + return true; + }), + // HACK: arbitrary microtask delay. + // An alias change -> route change -> browser url change -> + // `navigated` action. Because we, especially Polymer code, makes + // requests under a relative path, we must make requests only after + // the URL has been modified to reflect new alias or experiment id. + // + // While we can subscribe to `navigated` without + // `distinctUntilChanged` and `areSameRouteExperiments`, it is hard + // to throttle quick alias Map changes while immediately making a + // request for a real navigation. For example, for route A and + // route B: + // + // 0 100 600 700 + // A -> A' -> A" -> B + // ↑ ↑ ↑ + // req noop req req + // + // Above, we would like to make the request immediately when the set + // of experiments change while debouncing alias changes when the set + // of experiments have not changed. + // + // Instead of more elaborate rxjs techniques, we are + // using `delay(0)` to give the router a chance to modify the URL + // before making the request. + delay(0), + // Prevent changes in the alias map not to over-trigger requests; + // However, we want to use throttle instead of debounce since we + // need to emit on `leading` so it does not cause 500ms delay on + // page load. + throttleTime(ALIAS_CHANGE_RUNS_RELOAD_THROTTLE_IN_MS, undefined, { + leading: true, + trailing: true, + }), + ); + }), + withLatestFrom( + this.store.select(getRouteKind), + this.store.select(getPolymerRunsLoadState), + ), + filter(([, routeKind, loadState]) => { + // While the same check was applied earlier, `delay` + `throttleTime` + // makes it unpredictable and we can sometimes make requests for the + // wrong route. This check prevents making the request in wrong + // hostname in a fool proof way. + return ( + DASHBOARD_ROUTE_KIND.has(routeKind) && + loadState.state !== DataLoadState.LOADING + ); + }), + tap(() => { + this.store.dispatch(polymerRunsFetchRequested()); + }), + switchMap(() => { + return this.refreshPolymerRuns(); + }), + tap(() => { + this.store.dispatch(polymerRunsFetchSucceeded()); + }), + catchError(() => { + this.store.dispatch(polymerRunsFetchFailed()); + return EMPTY; + }), + ); + + return merge(pluginsListingReload$, runsReload$); + }, + {dispatch: false}, + ); + this.dispatchChangePlugin$ = createEffect( + () => { + return merge( + this.onDashboardLoad$, + this.actions$.pipe(ofType(pluginsListingLoaded)), + ).pipe( + withLatestFrom(this.store.select(getActivePlugin)), + map(([, activePlugin]) => activePlugin), + distinctUntilChanged(), + filter((activePlugin) => activePlugin !== null), + take(1), + tap((plugin) => { + this.store.dispatch(changePlugin({plugin: plugin!})); + }), + ); + }, + {dispatch: false}, + ); + } } export const TEST_ONLY = { diff --git a/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts b/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts index 2a90abfd76..5b14880118 100644 --- a/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts +++ b/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts @@ -51,31 +51,27 @@ import { >`, }) export class FeatureFlagDialogContainer { - constructor(private readonly store: Store) {} - - readonly showFlagsFilter$ = this.store.select(getOverriddenFeatureFlags).pipe( - map((overriddenFeatureFlags) => { - return overriddenFeatureFlags.showFlags?.toLowerCase(); - }) - ); - - readonly hasFlagsSentToServer$: Observable = this.store - .select(getFeatureFlagsMetadata) - .pipe( - map((flagMetadata) => { - return Object.values(flagMetadata).some((metadata) => { - return (metadata as AdvancedFeatureFlagMetadata) - .sendToServerWhenOverridden; - }); - }) + constructor(private readonly store: Store) { + this.showFlagsFilter$ = this.store.select(getOverriddenFeatureFlags).pipe( + map((overriddenFeatureFlags) => { + return overriddenFeatureFlags.showFlags?.toLowerCase(); + }), ); - - readonly featureFlags$: Observable[]> = - this.store.select(getOverriddenFeatureFlags).pipe( + this.hasFlagsSentToServer$ = this.store + .select(getFeatureFlagsMetadata) + .pipe( + map((flagMetadata) => { + return Object.values(flagMetadata).some((metadata) => { + return (metadata as AdvancedFeatureFlagMetadata) + .sendToServerWhenOverridden; + }); + }), + ); + this.featureFlags$ = this.store.select(getOverriddenFeatureFlags).pipe( withLatestFrom( this.store.select(getDefaultFeatureFlags), this.store.select(getFeatureFlagsMetadata), - this.showFlagsFilter$ + this.showFlagsFilter$, ), map( ([ @@ -94,7 +90,7 @@ export class FeatureFlagDialogContainer { .map(([flagName, defaultValue]) => { const status = getFlagStatus( flagName as keyof FeatureFlags, - overriddenFeatureFlags + overriddenFeatureFlags, ); const metadata = flagMetadata[flagName as keyof FeatureFlags]; return { @@ -106,9 +102,16 @@ export class FeatureFlagDialogContainer { ).sendToServerWhenOverridden, } as FeatureFlagStatus; }); - } - ) + }, + ), ); + } + + readonly showFlagsFilter$; + + readonly hasFlagsSentToServer$: Observable; + + readonly featureFlags$: Observable[]>; onFlagChanged({flag, status}: FeatureFlagStatusEvent) { switch (status) { @@ -117,12 +120,12 @@ export class FeatureFlagDialogContainer { break; case FeatureFlagOverrideStatus.ENABLED: this.store.dispatch( - featureFlagOverrideChanged({flags: {[flag]: true}}) + featureFlagOverrideChanged({flags: {[flag]: true}}), ); break; case FeatureFlagOverrideStatus.DISABLED: this.store.dispatch( - featureFlagOverrideChanged({flags: {[flag]: false}}) + featureFlagOverrideChanged({flags: {[flag]: false}}), ); break; default: @@ -137,7 +140,7 @@ export class FeatureFlagDialogContainer { function getFlagStatus( flagName: keyof FeatureFlags, - overriddenFeatureFlags: Partial + overriddenFeatureFlags: Partial, ): FeatureFlagOverrideStatus { if (overriddenFeatureFlags[flagName] === undefined) { return FeatureFlagOverrideStatus.DEFAULT; diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts index d59869df01..06900b1ef6 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts @@ -38,6 +38,7 @@ import { TimeSelectionWithAffordance, } from '../../../widgets/card_fob/card_fob_types'; import {Extent} from '../../../widgets/line_chart_v2/lib/public_types'; +import {TooltipTemplate} from '../../../widgets/line_chart_v2/line_chart_component'; import {ScaleType} from '../../../widgets/line_chart_v2/types'; import { cardViewBoxChanged, @@ -52,14 +53,13 @@ import { } from '../../store'; import {CardId, XAxisType} from '../../types'; import {CardRenderer} from '../metrics_view_types'; +import {ScalarCardLineChartComponent} from './scalar_card_line_chart_component'; import { MinMaxStep, ScalarCardDataSeries, ScalarCardSeriesMetadataMap, } from './scalar_card_types'; import {TimeSelectionView} from './utils'; -import {TooltipTemplate} from '../../../widgets/line_chart_v2/line_chart_component'; -import {ScalarCardLineChartComponent} from './scalar_card_line_chart_component'; @Component({ standalone: false, @@ -99,7 +99,36 @@ import {ScalarCardLineChartComponent} from './scalar_card_line_chart_component'; export class ScalarCardLineChartContainer implements CardRenderer, OnInit, OnDestroy { - constructor(private readonly store: Store) {} + constructor(private readonly store: Store) { + this.useDarkMode$ = this.store.select(getDarkModeEnabled); + this.tooltipSort$ = this.store.select(getMetricsTooltipSort); + this.forceSvg$ = this.store.select(getForceSvgFeatureFlag); + this.ignoreOutliers$ = this.ignoreOutliers + ? of(this.ignoreOutliers) + : this.store.select(getMetricsIgnoreOutliers); + this.xAxisType$ = this.xAxisType + ? of(this.xAxisType) + : this.store.select(getMetricsXAxisType); + this.xScaleType$ = this.xAxisType + ? ScaleType.LINEAR + : this.store.select(getMetricsXAxisType).pipe( + map((xAxisType) => { + switch (xAxisType) { + case XAxisType.STEP: + case XAxisType.RELATIVE: + return ScaleType.LINEAR; + case XAxisType.WALL_TIME: + return ScaleType.TIME; + default: + const neverType = xAxisType as never; + throw new Error( + `Invalid xAxisType for line chart. ${neverType}`, + ); + } + }), + ); + this.ngUnsubscribe = new Subject(); + } @Input() cardId!: CardId; @Input() seriesMetadataMap!: ScalarCardSeriesMetadataMap; @@ -122,46 +151,27 @@ export class ScalarCardLineChartContainer userViewBox$?: Observable; rangeEnabled$?: Observable; - readonly useDarkMode$ = this.store.select(getDarkModeEnabled); - readonly tooltipSort$ = this.store.select(getMetricsTooltipSort); - readonly forceSvg$ = this.store.select(getForceSvgFeatureFlag); - - readonly ignoreOutliers$ = this.ignoreOutliers - ? of(this.ignoreOutliers) - : this.store.select(getMetricsIgnoreOutliers); - - readonly xAxisType$ = this.xAxisType - ? of(this.xAxisType) - : this.store.select(getMetricsXAxisType); - readonly xScaleType$ = this.xAxisType - ? ScaleType.LINEAR - : this.store.select(getMetricsXAxisType).pipe( - map((xAxisType) => { - switch (xAxisType) { - case XAxisType.STEP: - case XAxisType.RELATIVE: - return ScaleType.LINEAR; - case XAxisType.WALL_TIME: - return ScaleType.TIME; - default: - const neverType = xAxisType as never; - throw new Error(`Invalid xAxisType for line chart. ${neverType}`); - } - }) - ); - - private readonly ngUnsubscribe = new Subject(); + readonly useDarkMode$; + readonly tooltipSort$; + readonly forceSvg$; + + readonly ignoreOutliers$; + + readonly xAxisType$; + readonly xScaleType$; + + private readonly ngUnsubscribe; ngOnInit() { this.userViewBox$ = this.store.select( getMetricsCardUserViewBox, - this.cardId + this.cardId, ); this.loadState$ = this.store.select(getCardLoadState, this.cardId); this.rangeEnabled$ = this.store.select( - getMetricsCardRangeSelectionEnabled(this.cardId) + getMetricsCardRangeSelectionEnabled(this.cardId), ); } @@ -171,13 +181,13 @@ export class ScalarCardLineChartContainer } onTimeSelectionChanged( - newTimeSelectionWithAffordance: TimeSelectionWithAffordance + newTimeSelectionWithAffordance: TimeSelectionWithAffordance, ) { this.store.dispatch( timeSelectionChanged({ ...newTimeSelectionWithAffordance, cardId: this.cardId, - }) + }), ); } @@ -190,7 +200,7 @@ export class ScalarCardLineChartContainer cardViewBoxChanged({ userViewBox: lineChartViewBox, cardId: this.cardId, - }) + }), ); } } diff --git a/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts b/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts index 0d390bd933..9cd327af2b 100644 --- a/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts +++ b/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts @@ -24,6 +24,7 @@ import {Store} from '@ngrx/store'; import {BehaviorSubject, combineLatest, Observable, of, Subject} from 'rxjs'; import {map, shareReplay, switchMap, takeUntil, tap} from 'rxjs/operators'; import {State} from '../../../app_state'; +import * as selectors from '../../../selectors'; import { getMetricsCardMinWidth, getMetricsTagGroupExpansionState, @@ -31,7 +32,6 @@ import { import {selectors as settingsSelectors} from '../../../settings'; import {CardObserver} from '../card_renderer/card_lazy_loader'; import {CardIdWithMetadata} from '../metrics_view_types'; -import * as selectors from '../../../selectors'; @Component({ standalone: false, @@ -62,68 +62,76 @@ export class CardGridContainer implements OnChanges, OnDestroy { readonly pageIndex$ = new BehaviorSubject(0); private readonly items$ = new BehaviorSubject([]); private readonly ngUnsubscribe = new Subject(); - readonly cardStateMap$ = this.store.select(selectors.getCardStateMap); - - readonly numPages$ = combineLatest([ - this.items$, - this.store.select(settingsSelectors.getPageSize), - ]).pipe( - map(([items, pageSize]) => { - return Math.ceil(items.length / pageSize); - }) - ); - - readonly isGroupExpanded$: Observable = this.groupName$.pipe( - switchMap((groupName) => { - return groupName !== null - ? this.store.select(getMetricsTagGroupExpansionState, groupName) - : of(true); - }) - ); - - readonly showPaginationControls$: Observable = this.numPages$.pipe( - map((numPages) => numPages > 1) - ); - - readonly normalizedPageIndex$ = combineLatest([ - this.pageIndex$, - this.numPages$, - ]).pipe( - takeUntil(this.ngUnsubscribe), - tap(([pageIndex, numPages]) => { - // Cycle in the Observable but only loops when pageIndex is not - // valid and does not repeat more than once. - if (numPages === 0) { - return; - } - if (pageIndex >= numPages) { - this.pageIndex$.next(numPages - 1); - } else if (pageIndex < 0) { - this.pageIndex$.next(0); - } - }), - map(([pageIndex, numPages]) => { - return Math.min(Math.max(pageIndex, 0), numPages - 1); - }), - shareReplay(1) - ); - - readonly pagedItems$ = combineLatest([ - this.items$, - this.store.select(settingsSelectors.getPageSize), - this.normalizedPageIndex$, - this.isGroupExpanded$, - ]).pipe( - map(([items, pageSize, pageIndex, expanded]) => { - const startIndex = pageSize * pageIndex; - const endIndex = pageSize * pageIndex + (expanded ? pageSize : 0); - return items.slice(startIndex, endIndex); - }) - ); - - readonly cardMinWidth$ = this.store.select(getMetricsCardMinWidth); - - constructor(private readonly store: Store) {} + readonly cardStateMap$; + + readonly numPages$; + + readonly isGroupExpanded$: Observable; + + readonly showPaginationControls$: Observable; + + readonly normalizedPageIndex$; + + readonly pagedItems$; + + readonly cardMinWidth$; + + constructor(private readonly store: Store) { + this.cardStateMap$ = this.store.select(selectors.getCardStateMap); + this.numPages$ = combineLatest([ + this.items$, + this.store.select(settingsSelectors.getPageSize), + ]).pipe( + map(([items, pageSize]) => { + return Math.ceil(items.length / pageSize); + }), + ); + this.isGroupExpanded$ = this.groupName$.pipe( + switchMap((groupName) => { + return groupName !== null + ? this.store.select(getMetricsTagGroupExpansionState, groupName) + : of(true); + }), + ); + this.showPaginationControls$ = this.numPages$.pipe( + map((numPages) => numPages > 1), + ); + this.normalizedPageIndex$ = combineLatest([ + this.pageIndex$, + this.numPages$, + ]).pipe( + takeUntil(this.ngUnsubscribe), + tap(([pageIndex, numPages]) => { + // Cycle in the Observable but only loops when pageIndex is not + // valid and does not repeat more than once. + if (numPages === 0) { + return; + } + if (pageIndex >= numPages) { + this.pageIndex$.next(numPages - 1); + } else if (pageIndex < 0) { + this.pageIndex$.next(0); + } + }), + map(([pageIndex, numPages]) => { + return Math.min(Math.max(pageIndex, 0), numPages - 1); + }), + shareReplay(1), + ); + this.pagedItems$ = combineLatest([ + this.items$, + this.store.select(settingsSelectors.getPageSize), + this.normalizedPageIndex$, + this.isGroupExpanded$, + ]).pipe( + map(([items, pageSize, pageIndex, expanded]) => { + const startIndex = pageSize * pageIndex; + const endIndex = pageSize * pageIndex + (expanded ? pageSize : 0); + return items.slice(startIndex, endIndex); + }), + ); + this.cardMinWidth$ = this.store.select(getMetricsCardMinWidth); + } ngOnChanges(changes: SimpleChanges) { if (changes['cardIdsWithMetadata']) { diff --git a/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts b/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts index d0b586d8be..e74c369013 100644 --- a/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts +++ b/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts @@ -39,26 +39,20 @@ import {compareTagNames} from '../../utils'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class MetricsFilterInputContainer { - constructor(private readonly store: Store) {} - - readonly tagFilter$: Observable = - this.store.select(getMetricsTagFilter); - - readonly isTagFilterRegexValid$: Observable = this.tagFilter$.pipe( - map((tagFilterString) => { - try { - // tslint:disable-next-line:no-unused-expression Check for validity of filter. - new RegExp(tagFilterString); - return true; - } catch (err) { - return false; - } - }) - ); - - readonly completions$: Observable = this.store - .select(getNonEmptyCardIdsWithMetadata) - .pipe( + constructor(private readonly store: Store) { + this.tagFilter$ = this.store.select(getMetricsTagFilter); + this.isTagFilterRegexValid$ = this.tagFilter$.pipe( + map((tagFilterString) => { + try { + // tslint:disable-next-line:no-unused-expression Check for validity of filter. + new RegExp(tagFilterString); + return true; + } catch (err) { + return false; + } + }), + ); + this.completions$ = this.store.select(getNonEmptyCardIdsWithMetadata).pipe( combineLatestWith(this.store.select(getMetricsFilteredPluginTypes)), map(([cardList, filteredPluginTypes]) => { return cardList @@ -80,13 +74,20 @@ export class MetricsFilterInputContainer { } catch (e) { return [tags, null]; } - } + }, ), filter(([, tagFilterRegex]) => tagFilterRegex !== null), map(([tags, tagFilterRegex]) => { return tags.filter((tag: string) => tagFilterRegex!.test(tag)); - }) + }), ); + } + + readonly tagFilter$: Observable; + + readonly isTagFilterRegexValid$: Observable; + + readonly completions$: Observable; onTagFilterChange(tagFilter: string) { this.store.dispatch(metricsTagFilterChanged({tagFilter})); diff --git a/tensorboard/webapp/metrics/views/metrics_container.ts b/tensorboard/webapp/metrics/views/metrics_container.ts index ed9a27cf04..14faf01b78 100644 --- a/tensorboard/webapp/metrics/views/metrics_container.ts +++ b/tensorboard/webapp/metrics/views/metrics_container.ts @@ -33,7 +33,9 @@ import {getRunsTableFullScreen} from '../../core/store/core_selectors'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class MetricsDashboardContainer { - runsTableFullScreen$ = this.store.select(getRunsTableFullScreen); + runsTableFullScreen$; - constructor(readonly store: Store) {} + constructor(readonly store: Store) { + this.runsTableFullScreen$ = this.store.select(getRunsTableFullScreen); + } } diff --git a/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts b/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts index 8b7a6fb2fb..a413685a62 100644 --- a/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts +++ b/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts @@ -13,8 +13,8 @@ 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 {MatDialog} from '@angular/material/dialog'; +import {Store} from '@ngrx/store'; import {Observable} from 'rxjs'; import {filter, map, take, withLatestFrom} from 'rxjs/operators'; import {State} from '../../../app_state'; @@ -101,71 +101,92 @@ import { export class SettingsViewContainer { constructor( private readonly store: Store, - private readonly dialog: MatDialog - ) {} + private readonly dialog: MatDialog, + ) { + this.isScalarStepSelectorEnabled$ = this.store.select( + selectors.getMetricsStepSelectorEnabled, + ); + this.isScalarStepSelectorRangeEnabled$ = this.store.select( + selectors.getMetricsRangeSelectionEnabled, + ); + this.isLinkedTimeEnabled$ = this.store.select( + selectors.getMetricsLinkedTimeEnabled, + ); + this.isScalarColumnCustomizationEnabled$ = this.store.select( + selectors.getIsScalarColumnCustomizationEnabled, + ); + this.linkedTimeSelection$ = this.store.select( + selectors.getMetricsLinkedTimeSelectionSetting, + ); + this.stepMinMax$ = this.store.select(selectors.getMetricsStepMinMax); + this.isSlideOutMenuOpen$ = this.store.select( + selectors.isMetricsSlideoutMenuOpen, + ); + this.isImageSupportEnabled$ = this.store + .select(selectors.getIsFeatureFlagsLoaded) + .pipe( + filter(Boolean), + take(1), + withLatestFrom( + this.store.select(selectors.getIsMetricsImageSupportEnabled), + ), + map(([, isImagesSupported]) => { + return isImagesSupported; + }), + ); + this.tooltipSort$ = this.store.select(selectors.getMetricsTooltipSort); + this.ignoreOutliers$ = this.store.select( + selectors.getMetricsIgnoreOutliers, + ); + this.xAxisType$ = this.store.select(selectors.getMetricsXAxisType); + this.cardMinWidth$ = this.store.select(selectors.getMetricsCardMinWidth); + this.histogramMode$ = this.store.select(selectors.getMetricsHistogramMode); + this.scalarSmoothing$ = this.store.select( + selectors.getMetricsScalarSmoothing, + ); + this.scalarPartitionX$ = this.store.select( + selectors.getMetricsScalarPartitionNonMonotonicX, + ); + this.imageBrightnessInMilli$ = this.store.select( + selectors.getMetricsImageBrightnessInMilli, + ); + this.imageContrastInMilli$ = this.store.select( + selectors.getMetricsImageContrastInMilli, + ); + this.imageShowActualSize$ = this.store.select( + selectors.getMetricsImageShowActualSize, + ); + this.isSavingPinsEnabled$ = this.store.select( + selectors.getMetricsSavingPinsEnabled, + ); + this.globalPinsFeatureEnabled$ = this.store.select( + selectors.getEnableGlobalPins, + ); + } - readonly isScalarStepSelectorEnabled$: Observable = - this.store.select(selectors.getMetricsStepSelectorEnabled); - readonly isScalarStepSelectorRangeEnabled$: Observable = - this.store.select(selectors.getMetricsRangeSelectionEnabled); - readonly isLinkedTimeEnabled$: Observable = this.store.select( - selectors.getMetricsLinkedTimeEnabled - ); - readonly isScalarColumnCustomizationEnabled$ = this.store.select( - selectors.getIsScalarColumnCustomizationEnabled - ); - readonly linkedTimeSelection$ = this.store.select( - selectors.getMetricsLinkedTimeSelectionSetting - ); - readonly stepMinMax$ = this.store.select(selectors.getMetricsStepMinMax); - readonly isSlideOutMenuOpen$ = this.store.select( - selectors.isMetricsSlideoutMenuOpen - ); + readonly isScalarStepSelectorEnabled$: Observable; + readonly isScalarStepSelectorRangeEnabled$: Observable; + readonly isLinkedTimeEnabled$: Observable; + readonly isScalarColumnCustomizationEnabled$; + readonly linkedTimeSelection$; + readonly stepMinMax$; + readonly isSlideOutMenuOpen$; - readonly isImageSupportEnabled$ = this.store - .select(selectors.getIsFeatureFlagsLoaded) - .pipe( - filter(Boolean), - take(1), - withLatestFrom( - this.store.select(selectors.getIsMetricsImageSupportEnabled) - ), - map(([, isImagesSupported]) => { - return isImagesSupported; - }) - ); + readonly isImageSupportEnabled$; - readonly tooltipSort$ = this.store.select(selectors.getMetricsTooltipSort); - readonly ignoreOutliers$ = this.store.select( - selectors.getMetricsIgnoreOutliers - ); - readonly xAxisType$ = this.store.select(selectors.getMetricsXAxisType); - readonly cardMinWidth$ = this.store.select(selectors.getMetricsCardMinWidth); - readonly histogramMode$ = this.store.select( - selectors.getMetricsHistogramMode - ); - readonly scalarSmoothing$ = this.store.select( - selectors.getMetricsScalarSmoothing - ); - readonly scalarPartitionX$ = this.store.select( - selectors.getMetricsScalarPartitionNonMonotonicX - ); - readonly imageBrightnessInMilli$ = this.store.select( - selectors.getMetricsImageBrightnessInMilli - ); - readonly imageContrastInMilli$ = this.store.select( - selectors.getMetricsImageContrastInMilli - ); - readonly imageShowActualSize$ = this.store.select( - selectors.getMetricsImageShowActualSize - ); - readonly isSavingPinsEnabled$ = this.store.select( - selectors.getMetricsSavingPinsEnabled - ); + readonly tooltipSort$; + readonly ignoreOutliers$; + readonly xAxisType$; + readonly cardMinWidth$; + readonly histogramMode$; + readonly scalarSmoothing$; + readonly scalarPartitionX$; + readonly imageBrightnessInMilli$; + readonly imageContrastInMilli$; + readonly imageShowActualSize$; + readonly isSavingPinsEnabled$; // Feature flag for global pins. - readonly globalPinsFeatureEnabled$ = this.store.select( - selectors.getEnableGlobalPins - ); + readonly globalPinsFeatureEnabled$; onTooltipSortChanged(sort: TooltipSort) { this.store.dispatch(metricsChangeTooltipSort({sort})); @@ -221,13 +242,15 @@ export class SettingsViewContainer { onLinkedTimeToggled() { this.store.dispatch( - linkedTimeToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX}) + linkedTimeToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX}), ); } onStepSelectorToggled() { this.store.dispatch( - stepSelectorToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX}) + stepSelectorToggled({ + affordance: TimeSelectionToggleAffordance.CHECK_BOX, + }), ); } @@ -235,7 +258,7 @@ export class SettingsViewContainer { this.store.dispatch( rangeSelectionToggled({ affordance: TimeSelectionToggleAffordance.CHECK_BOX, - }) + }), ); } diff --git a/tensorboard/webapp/plugins/plugins_container.ts b/tensorboard/webapp/plugins/plugins_container.ts index 6a0b056424..ab241b1185 100644 --- a/tensorboard/webapp/plugins/plugins_container.ts +++ b/tensorboard/webapp/plugins/plugins_container.ts @@ -49,7 +49,7 @@ const activePlugin = createSelector( (plugins, id): UiPluginMetadata | null => { if (!id || !plugins[id]) return null; return Object.assign({id}, plugins[id]); - } + }, ); @Component({ @@ -76,8 +76,8 @@ const activePlugin = createSelector( changeDetection: ChangeDetectionStrategy.OnPush, }) export class PluginsContainer { - readonly activeKnownPlugin$ = this.store.select(activePlugin); - readonly activePluginId$ = this.store.select(getActivePlugin); + readonly activeKnownPlugin$; + readonly activePluginId$; @Input() environmentFailureNotFoundTemplate?: TemplateRef; @@ -88,57 +88,66 @@ export class PluginsContainer { @Input() environmentFailureUnknownTemplate?: TemplateRef; - readonly pluginLoadState$ = combineLatest( - this.activeKnownPlugin$, - this.activePluginId$, - this.store.select(getPluginsListLoaded) - ).pipe( - map(([activePlugin, activePluginId, loadState]) => { - if (loadState.failureCode !== null) { - // Despite its 'Plugins'-specific name, getPluginsListLoaded actually - // encapsulates multiple requests to load different parts of the - // environment. - if (loadState.failureCode === PluginsListFailureCode.NOT_FOUND) { - return PluginLoadState.ENVIRONMENT_FAILURE_NOT_FOUND; - } else if ( - loadState.failureCode === PluginsListFailureCode.PERMISSION_DENIED + readonly pluginLoadState$; + + readonly lastLoadedTimeInMs$; + readonly dataLocation$; + readonly isFeatureFlagsLoaded$; + readonly featureFlags$; + readonly settingsLoadState$; + + constructor(private readonly store: Store) { + this.activeKnownPlugin$ = this.store.select(activePlugin); + this.activePluginId$ = this.store.select(getActivePlugin); + this.pluginLoadState$ = combineLatest( + this.activeKnownPlugin$, + this.activePluginId$, + this.store.select(getPluginsListLoaded), + ).pipe( + map(([activePlugin, activePluginId, loadState]) => { + if (loadState.failureCode !== null) { + // Despite its 'Plugins'-specific name, getPluginsListLoaded actually + // encapsulates multiple requests to load different parts of the + // environment. + if (loadState.failureCode === PluginsListFailureCode.NOT_FOUND) { + return PluginLoadState.ENVIRONMENT_FAILURE_NOT_FOUND; + } else if ( + loadState.failureCode === PluginsListFailureCode.PERMISSION_DENIED + ) { + return PluginLoadState.ENVIRONMENT_FAILURE_PERMISSION_DENIED; + } else { + return PluginLoadState.ENVIRONMENT_FAILURE_UNKNOWN; + } + } + + if (activePlugin !== null) { + return PluginLoadState.LOADED; + } + + if ( + loadState.lastLoadedTimeInMs === null && + loadState.state === DataLoadState.LOADING ) { - return PluginLoadState.ENVIRONMENT_FAILURE_PERMISSION_DENIED; - } else { - return PluginLoadState.ENVIRONMENT_FAILURE_UNKNOWN; + return PluginLoadState.LOADING; } - } - - if (activePlugin !== null) { - return PluginLoadState.LOADED; - } - - if ( - loadState.lastLoadedTimeInMs === null && - loadState.state === DataLoadState.LOADING - ) { - return PluginLoadState.LOADING; - } - - if (activePluginId) { - return PluginLoadState.UNKNOWN_PLUGIN_ID; - } - - return PluginLoadState.NO_ENABLED_PLUGINS; - }) - ); - - readonly lastLoadedTimeInMs$ = this.store.select(getAppLastLoadedTimeInMs); - readonly dataLocation$ = this.store.select(getEnvironment).pipe( - map((env) => { - return env.data_location; - }) - ); - readonly isFeatureFlagsLoaded$ = this.store.select(getIsFeatureFlagsLoaded); - readonly featureFlags$ = this.store.select(getFeatureFlags); - readonly settingsLoadState$ = this.store.select( - settingsSelectors.getSettingsLoadState - ); - - constructor(private readonly store: Store) {} + + if (activePluginId) { + return PluginLoadState.UNKNOWN_PLUGIN_ID; + } + + return PluginLoadState.NO_ENABLED_PLUGINS; + }), + ); + this.lastLoadedTimeInMs$ = this.store.select(getAppLastLoadedTimeInMs); + this.dataLocation$ = this.store.select(getEnvironment).pipe( + map((env) => { + return env.data_location; + }), + ); + this.isFeatureFlagsLoaded$ = this.store.select(getIsFeatureFlagsLoaded); + this.featureFlags$ = this.store.select(getFeatureFlags); + this.settingsLoadState$ = this.store.select( + settingsSelectors.getSettingsLoadState, + ); + } } diff --git a/tensorboard/webapp/runs/effects/runs_effects.ts b/tensorboard/webapp/runs/effects/runs_effects.ts index 3f050a2269..b056f93ea0 100644 --- a/tensorboard/webapp/runs/effects/runs_effects.ts +++ b/tensorboard/webapp/runs/effects/runs_effects.ts @@ -31,19 +31,19 @@ import {navigated} from '../../app_routing/actions'; import {RouteKind} from '../../app_routing/types'; import {State} from '../../app_state'; import * as coreActions from '../../core/actions'; +import * as hparamsActions from '../../hparams/_redux/hparams_actions'; import { getActiveRoute, + getDashboardExperimentNames, getExperimentIdsFromRoute, getRuns, getRunsLoadState, - getDashboardExperimentNames, } from '../../selectors'; import {DataLoadState, LoadState} from '../../types/data'; +import {ColumnHeaderType} from '../../widgets/data_table/types'; import * as actions from '../actions'; -import * as hparamsActions from '../../hparams/_redux/hparams_actions'; import {Run, RunsDataSource} from '../data_source/runs_data_source_types'; import {ExperimentIdToRuns} from '../types'; -import {ColumnHeaderType} from '../../widgets/data_table/types'; /** * Runs effect for fetching data from the backend. @@ -53,8 +53,89 @@ export class RunsEffects { constructor( private readonly actions$: Actions, private readonly store: Store, - private readonly runsDataSource: RunsDataSource - ) {} + private readonly runsDataSource: RunsDataSource, + ) { + this.experimentsWithStaleRunsOnRouteChange$ = this.actions$.pipe( + ofType(navigated), + withLatestFrom(this.store.select(getActiveRoute)), + distinctUntilChanged(([, prevRoute], [, currRoute]) => { + return areSameRouteKindAndExperiments(prevRoute, currRoute); + }), + withLatestFrom(this.store.select(getExperimentIdsFromRoute)), + filter(([, experimentIds]) => !!experimentIds), + map(([, experimentIds]) => experimentIds!), + mergeMap((experimentIds) => { + return this.getExperimentsWithLoadState(experimentIds, (state) => { + return ( + state === DataLoadState.FAILED || state === DataLoadState.NOT_LOADED + ); + }).pipe( + map((experimentIdsToBeFetched) => { + return {experimentIds, experimentIdsToBeFetched}; + }), + ); + }), + ); + this.experimentsWithStaleRunsOnReload$ = this.actions$.pipe( + ofType(coreActions.reload, coreActions.manualReload), + withLatestFrom(this.store.select(getExperimentIdsFromRoute)), + filter(([, experimentIds]) => !!experimentIds), + map(([, experimentIds]) => experimentIds!), + mergeMap((experimentIds) => { + return this.getExperimentsWithLoadState(experimentIds, (state) => { + return state !== DataLoadState.LOADING; + }).pipe( + map((experimentIdsToBeFetched) => { + return {experimentIds, experimentIdsToBeFetched}; + }), + ); + }), + ); + this.loadRunsOnNavigationOrReload$ = createEffect( + () => { + return merge( + this.experimentsWithStaleRunsOnRouteChange$, + this.experimentsWithStaleRunsOnReload$, + ).pipe( + withLatestFrom(this.store.select(getActiveRoute)), + filter( + ([, route]) => route !== null && route.routeKind !== RouteKind.CARD, + ), + mergeMap(([{experimentIds, experimentIdsToBeFetched}]) => { + return this.fetchAllRunsList( + experimentIds, + experimentIdsToBeFetched, + ); + }), + ); + }, + {dispatch: false}, + ); + this.removeHparamFilterWhenColumnIsRemoved$ = createEffect( + () => + this.actions$.pipe( + ofType(actions.runsTableHeaderRemoved), + tap(({header}) => { + if (header.type === ColumnHeaderType.HPARAM) { + this.store.dispatch( + hparamsActions.dashboardHparamFilterRemoved({ + name: header.name, + }), + ); + return; + } + if (header.type === ColumnHeaderType.METRIC) { + this.store.dispatch( + hparamsActions.dashboardMetricFilterRemoved({ + name: header.name, + }), + ); + } + }), + ), + {dispatch: false}, + ); + } private getRunsListLoadState(experimentId: string): Observable { return this.store.select(getRunsLoadState, {experimentId}).pipe(take(1)); @@ -62,111 +143,38 @@ export class RunsEffects { private getExperimentsWithLoadState( experimentIds: string[], - loadStateMatcher: (loadState: DataLoadState) => boolean + loadStateMatcher: (loadState: DataLoadState) => boolean, ) { return forkJoin( experimentIds.map((eid) => { return this.getRunsListLoadState(eid); - }) + }), ).pipe( map((loadStates) => { return experimentIds.filter((unused, index) => { return loadStateMatcher(loadStates[index].state); }); - }) + }), ); } - private readonly experimentsWithStaleRunsOnRouteChange$ = this.actions$.pipe( - ofType(navigated), - withLatestFrom(this.store.select(getActiveRoute)), - distinctUntilChanged(([, prevRoute], [, currRoute]) => { - return areSameRouteKindAndExperiments(prevRoute, currRoute); - }), - withLatestFrom(this.store.select(getExperimentIdsFromRoute)), - filter(([, experimentIds]) => !!experimentIds), - map(([, experimentIds]) => experimentIds!), - mergeMap((experimentIds) => { - return this.getExperimentsWithLoadState(experimentIds, (state) => { - return ( - state === DataLoadState.FAILED || state === DataLoadState.NOT_LOADED - ); - }).pipe( - map((experimentIdsToBeFetched) => { - return {experimentIds, experimentIdsToBeFetched}; - }) - ); - }) - ); + private readonly experimentsWithStaleRunsOnRouteChange$; - private readonly experimentsWithStaleRunsOnReload$ = this.actions$.pipe( - ofType(coreActions.reload, coreActions.manualReload), - withLatestFrom(this.store.select(getExperimentIdsFromRoute)), - filter(([, experimentIds]) => !!experimentIds), - map(([, experimentIds]) => experimentIds!), - mergeMap((experimentIds) => { - return this.getExperimentsWithLoadState(experimentIds, (state) => { - return state !== DataLoadState.LOADING; - }).pipe( - map((experimentIdsToBeFetched) => { - return {experimentIds, experimentIdsToBeFetched}; - }) - ); - }) - ); + private readonly experimentsWithStaleRunsOnReload$; /** * Fetches runs on navigation or in-app reload. * * @export */ - loadRunsOnNavigationOrReload$ = createEffect( - () => { - return merge( - this.experimentsWithStaleRunsOnRouteChange$, - this.experimentsWithStaleRunsOnReload$ - ).pipe( - withLatestFrom(this.store.select(getActiveRoute)), - filter( - ([, route]) => route !== null && route.routeKind !== RouteKind.CARD - ), - mergeMap(([{experimentIds, experimentIdsToBeFetched}]) => { - return this.fetchAllRunsList(experimentIds, experimentIdsToBeFetched); - }) - ); - }, - {dispatch: false} - ); + loadRunsOnNavigationOrReload$; /** * Removes hparam filter when column is removed. * * @export */ - removeHparamFilterWhenColumnIsRemoved$ = createEffect( - () => - this.actions$.pipe( - ofType(actions.runsTableHeaderRemoved), - tap(({header}) => { - if (header.type === ColumnHeaderType.HPARAM) { - this.store.dispatch( - hparamsActions.dashboardHparamFilterRemoved({ - name: header.name, - }) - ); - return; - } - if (header.type === ColumnHeaderType.METRIC) { - this.store.dispatch( - hparamsActions.dashboardMetricFilterRemoved({ - name: header.name, - }) - ); - } - }) - ), - {dispatch: false} - ); + removeHparamFilterWhenColumnIsRemoved$; /** * IMPORTANT: actions are dispatched even when there are no experiments to @@ -182,7 +190,7 @@ export class RunsEffects { */ private fetchAllRunsList( experimentIds: string[], - experimentIdsToBeFetched: string[] + experimentIdsToBeFetched: string[], ): Observable { return of({experimentIds, experimentIdsToBeFetched}).pipe( tap(() => { @@ -190,7 +198,7 @@ export class RunsEffects { actions.fetchRunsRequested({ experimentIds, requestedExperimentIds: experimentIdsToBeFetched, - }) + }), ); }), mergeMap(() => { @@ -227,7 +235,7 @@ export class RunsEffects { newRuns, runsForAllExperiments, expNameByExpId, - }) + }), ); }), catchError((error) => { @@ -235,11 +243,11 @@ export class RunsEffects { actions.fetchRunsFailed({ experimentIds, requestedExperimentIds: experimentIdsToBeFetched, - }) + }), ); return of(null); }), - map(() => null) + map(() => null), ); } @@ -258,7 +266,7 @@ export class RunsEffects { return of(loadState); }), withLatestFrom(this.store.select(getRuns, {experimentId})), - map(([, runs]) => ({fromRemote: false, experimentId, runs})) + map(([, runs]) => ({fromRemote: false, experimentId, runs})), ); } @@ -274,7 +282,7 @@ export class RunsEffects { experimentId, runs: runs as Run[], }; - }) + }), ); } } diff --git a/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts b/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts index 5a0feffa33..1ddf4cc125 100644 --- a/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts +++ b/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts @@ -36,17 +36,22 @@ import { actions as hparamsActions, selectors as hparamsSelectors, } from '../../../hparams'; +import { + getCurrentColumnFilters, + getFilteredRenderableRuns, + getSelectableColumns, +} from '../../../metrics/views/main_view/common_selectors'; import { getActiveRoute, getCurrentRouteRunSelection, getExperiment, getExperimentIdToExperimentAliasMap, + getGroupedRunsTableHeaders, getRunColorMap, getRuns, getRunSelectorRegexFilter, getRunsLoadState, getRunsTableSortingInfo, - getGroupedRunsTableHeaders, } from '../../../selectors'; import {DataLoadState, LoadState} from '../../../types/data'; import { @@ -66,13 +71,8 @@ import { singleRunSelected, } from '../../actions'; import {MAX_NUM_RUNS_TO_ENABLE_BY_DEFAULT} from '../../store/runs_types'; -import {RunsTableColumn, RunTableItem} from './types'; -import { - getCurrentColumnFilters, - getFilteredRenderableRuns, - getSelectableColumns, -} from '../../../metrics/views/main_view/common_selectors'; import {sortTableDataItems} from './sorting_utils'; +import {RunsTableColumn, RunTableItem} from './types'; const getRunsLoading = createSelector< State, @@ -133,51 +133,62 @@ const getRunsLoading = createSelector< export class RunsTableContainer implements OnInit, OnDestroy { sortedRunsTableData$: Observable = of([]); loading$: Observable | null = null; - sortingInfo$ = this.store.select(getRunsTableSortingInfo); + sortingInfo$; // Column to disable in the table. The columns are rendered in the order as // defined by this input. @Input() - columns: RunsTableColumn[] = [RunsTableColumn.RUN_NAME]; + columns: RunsTableColumn[]; @Input() experimentIds!: string[]; - regexFilter$ = this.store.select(getRunSelectorRegexFilter); - runsColumns$ = this.store.select(getGroupedRunsTableHeaders); - selectableColumns$ = this.store.select(getSelectableColumns); - numColumnsLoaded$ = this.store.select( - hparamsSelectors.getNumDashboardHparamsLoaded - ); - numColumnsToLoad$ = this.store.select( - hparamsSelectors.getNumDashboardHparamsToLoad - ); - - columnFilters$ = this.store.select(getCurrentColumnFilters); - - allRunsTableData$ = this.store.select(getFilteredRenderableRuns).pipe( - map((filteredRenderableRuns) => { - return filteredRenderableRuns.map((runTableItem) => { - const tableData: TableData = { - ...Object.fromEntries(runTableItem.hparams.entries()), - id: runTableItem.run.id, - run: runTableItem.run.name, - experimentName: runTableItem.experimentName, - experimentAlias: runTableItem.experimentAlias, - selected: runTableItem.selected, - color: runTableItem.runColor, - }; - return tableData; - }); - }) - ); + regexFilter$; + runsColumns$; + selectableColumns$; + numColumnsLoaded$; + numColumnsToLoad$; - private readonly ngUnsubscribe = new Subject(); + columnFilters$; - constructor(private readonly store: Store) {} + allRunsTableData$; + + private readonly ngUnsubscribe; + + constructor(private readonly store: Store) { + this.sortingInfo$ = this.store.select(getRunsTableSortingInfo); + this.columns = [RunsTableColumn.RUN_NAME]; + this.regexFilter$ = this.store.select(getRunSelectorRegexFilter); + this.runsColumns$ = this.store.select(getGroupedRunsTableHeaders); + this.selectableColumns$ = this.store.select(getSelectableColumns); + this.numColumnsLoaded$ = this.store.select( + hparamsSelectors.getNumDashboardHparamsLoaded, + ); + this.numColumnsToLoad$ = this.store.select( + hparamsSelectors.getNumDashboardHparamsToLoad, + ); + this.columnFilters$ = this.store.select(getCurrentColumnFilters); + this.allRunsTableData$ = this.store.select(getFilteredRenderableRuns).pipe( + map((filteredRenderableRuns) => { + return filteredRenderableRuns.map((runTableItem) => { + const tableData: TableData = { + ...Object.fromEntries(runTableItem.hparams.entries()), + id: runTableItem.run.id, + run: runTableItem.run.name, + experimentName: runTableItem.experimentName, + experimentAlias: runTableItem.experimentAlias, + selected: runTableItem.selected, + color: runTableItem.runColor, + }; + return tableData; + }); + }), + ); + this.ngUnsubscribe = new Subject(); + } ngOnInit() { const getRunTableItemsPerExperiment = this.experimentIds.map((id) => - this.getRunTableItemsForExperiment(id) + this.getRunTableItemsForExperiment(id), ); this.sortedRunsTableData$ = combineLatest([ @@ -186,16 +197,16 @@ export class RunsTableContainer implements OnInit, OnDestroy { ]).pipe( map(([items, sortingInfo]) => { return sortTableDataItems(items, sortingInfo); - }) + }), ); const rawAllUnsortedRunTableItems$ = combineLatest( - getRunTableItemsPerExperiment + getRunTableItemsPerExperiment, ).pipe( map((itemsForExperiments: RunTableItem[][]) => { const items = [] as RunTableItem[]; return items.concat(...itemsForExperiments); - }) + }), ); const getRunsLoadingPerExperiment = this.experimentIds.map((id) => { @@ -204,7 +215,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.loading$ = combineLatest(getRunsLoadingPerExperiment).pipe( map((experimentsLoading) => { return experimentsLoading.some((isLoading) => isLoading); - }) + }), ); /** @@ -233,9 +244,9 @@ export class RunsTableContainer implements OnInit, OnDestroy { filter((runTableItems: RunTableItem[]) => { return runTableItems.length > MAX_NUM_RUNS_TO_ENABLE_BY_DEFAULT; }), - take(1) + take(1), ); - }) + }), ); runsExceedLimitForRoute$.subscribe(() => { const text = @@ -243,7 +254,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { `${MAX_NUM_RUNS_TO_ENABLE_BY_DEFAULT}. New runs are unselected ` + `for performance reasons.`; this.store.dispatch( - alertActions.alertReported({localizedMessage: text}) + alertActions.alertReported({localizedMessage: text}), ); }); } @@ -259,7 +270,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { } private getRunTableItemsForExperiment( - experimentId: string + experimentId: string, ): Observable { return combineLatest([ this.store.select(getRuns, {experimentId}), @@ -288,7 +299,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { metrics: metricMap, }; }); - }) + }), ); } @@ -296,7 +307,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( runSelectionToggled({ runId: id, - }) + }), ); } @@ -304,7 +315,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( singleRunSelected({ runId, - }) + }), ); } @@ -312,7 +323,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( runPageSelectionToggled({ runIds, - }) + }), ); } @@ -330,19 +341,19 @@ export class RunsTableContainer implements OnInit, OnDestroy { column, nextTo, side, - }) + }), ); } removeColumn(header: ColumnHeader) { this.store.dispatch( - hparamsActions.dashboardHparamColumnRemoved({column: header}) + hparamsActions.dashboardHparamColumnRemoved({column: header}), ); } orderColumns(event: ReorderColumnEvent) { this.store.dispatch( - hparamsActions.dashboardHparamColumnOrderChanged(event) + hparamsActions.dashboardHparamColumnOrderChanged(event), ); } @@ -351,7 +362,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { hparamsActions.dashboardHparamFilterAdded({ name: event.name, filter: event.value, - }) + }), ); } From c5a1f50dd29e4964e8e1f1d837c45b05407a1d4c Mon Sep 17 00:00:00 2001 From: Adrian RC Date: Wed, 16 Oct 2024 23:42:45 +0000 Subject: [PATCH 2/2] Fix lint errors. --- .../debugger_container.ts | 6 +-- .../views/alerts/alerts_container.ts | 4 +- .../webapp/core/effects/core_effects.ts | 38 +++++++-------- .../views/feature_flag_dialog_container.ts | 18 +++---- .../scalar_card_line_chart_container.ts | 14 +++--- .../views/main_view/card_grid_container.ts | 10 ++-- .../views/main_view/filter_input_container.ts | 6 +-- .../right_pane/settings_view_container.ts | 40 ++++++++-------- .../webapp/plugins/plugins_container.ts | 10 ++-- .../webapp/runs/effects/runs_effects.ts | 48 +++++++++---------- .../views/runs_table/runs_table_container.ts | 40 ++++++++-------- 11 files changed, 117 insertions(+), 117 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts index a0d1eb455c..6519ca9bc2 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts @@ -49,9 +49,9 @@ export class DebuggerContainer implements OnInit, OnDestroy { this.runsIds$ = this.store.pipe( select( createSelector(getDebuggerRunListing, (runs): string[] => - Object.keys(runs), - ), - ), + Object.keys(runs) + ) + ) ); this.activeRunId$ = this.store.pipe(select(getActiveRunId)); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts index a40249c075..c814ebdd31 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container.ts @@ -79,8 +79,8 @@ export class AlertsContainer { count: alertsBreakdown[alertType], }; }); - }), - ), + }) + ) ); this.focusType$ = this.store.pipe(select(getAlertsFocusType)); } diff --git a/tensorboard/webapp/core/effects/core_effects.ts b/tensorboard/webapp/core/effects/core_effects.ts index 65eadecd01..955576874c 100644 --- a/tensorboard/webapp/core/effects/core_effects.ts +++ b/tensorboard/webapp/core/effects/core_effects.ts @@ -130,14 +130,14 @@ export class CoreEffects { return this.webappDataSource.fetchEnvironment().pipe( tap((environment) => { this.store.dispatch(environmentLoaded({environment})); - }), + }) ); } constructor( private actions$: Actions, private store: Store, - private webappDataSource: TBServerDataSource, + private webappDataSource: TBServerDataSource ) { this.onDashboardLoad$ = merge( this.actions$.pipe( @@ -145,35 +145,35 @@ export class CoreEffects { withLatestFrom(this.store.select(getActiveRoute)), distinctUntilChanged(([, beforeRoute], [, afterRoute]) => { return areSameRouteKindAndExperiments(beforeRoute, afterRoute); - }), + }) ), - this.actions$.pipe(ofType(reload, manualReload)), + this.actions$.pipe(ofType(reload, manualReload)) ).pipe( withLatestFrom(this.store.select(getRouteKind)), filter(([, routeKind]) => DASHBOARD_ROUTE_KIND.has(routeKind)), throttleTime(DATA_LOAD_CONDITIONAL_THROTTLE_IN_MS, undefined, { leading: true, - }), + }) ); this.fetchWebAppData$ = createEffect( () => { const pluginsListingReload$ = this.onDashboardLoad$.pipe( withLatestFrom( this.store.select(getPluginsListLoaded), - this.store.select(getEnabledExperimentalPlugins), + this.store.select(getEnabledExperimentalPlugins) ), filter(([, {state}]) => state !== DataLoadState.LOADING), tap(() => this.store.dispatch(pluginsListingRequested())), mergeMap(([, , enabledExperimentalPlugins]) => { return zip( this.webappDataSource.fetchPluginsListing( - enabledExperimentalPlugins, + enabledExperimentalPlugins ), // TODO(tensorboard-team): consider brekaing the environments out of // the pluginsListingLoaded; currently, plugins listing load state // is connected to the environments which is not ideal. Have its own // load state. - this.fetchEnvironment(), + this.fetchEnvironment() ).pipe( map(([plugins]) => { this.store.dispatch(pluginsListingLoaded({plugins})); @@ -181,19 +181,19 @@ export class CoreEffects { catchError((e) => { if (e instanceof TBServerError) { this.store.dispatch( - pluginsListingFailed({failureCode: e.failureCode}), + pluginsListingFailed({failureCode: e.failureCode}) ); } else { this.store.dispatch( pluginsListingFailed({ failureCode: PluginsListFailureCode.UNKNOWN, - }), + }) ); } return EMPTY; - }), + }) ); - }), + }) ); const runsReload$ = this.onDashboardLoad$.pipe( @@ -260,12 +260,12 @@ export class CoreEffects { throttleTime(ALIAS_CHANGE_RUNS_RELOAD_THROTTLE_IN_MS, undefined, { leading: true, trailing: true, - }), + }) ); }), withLatestFrom( this.store.select(getRouteKind), - this.store.select(getPolymerRunsLoadState), + this.store.select(getPolymerRunsLoadState) ), filter(([, routeKind, loadState]) => { // While the same check was applied earlier, `delay` + `throttleTime` @@ -289,18 +289,18 @@ export class CoreEffects { catchError(() => { this.store.dispatch(polymerRunsFetchFailed()); return EMPTY; - }), + }) ); return merge(pluginsListingReload$, runsReload$); }, - {dispatch: false}, + {dispatch: false} ); this.dispatchChangePlugin$ = createEffect( () => { return merge( this.onDashboardLoad$, - this.actions$.pipe(ofType(pluginsListingLoaded)), + this.actions$.pipe(ofType(pluginsListingLoaded)) ).pipe( withLatestFrom(this.store.select(getActivePlugin)), map(([, activePlugin]) => activePlugin), @@ -309,10 +309,10 @@ export class CoreEffects { take(1), tap((plugin) => { this.store.dispatch(changePlugin({plugin: plugin!})); - }), + }) ); }, - {dispatch: false}, + {dispatch: false} ); } } diff --git a/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts b/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts index 5b14880118..80af1f193f 100644 --- a/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts +++ b/tensorboard/webapp/feature_flag/views/feature_flag_dialog_container.ts @@ -55,7 +55,7 @@ export class FeatureFlagDialogContainer { this.showFlagsFilter$ = this.store.select(getOverriddenFeatureFlags).pipe( map((overriddenFeatureFlags) => { return overriddenFeatureFlags.showFlags?.toLowerCase(); - }), + }) ); this.hasFlagsSentToServer$ = this.store .select(getFeatureFlagsMetadata) @@ -65,13 +65,13 @@ export class FeatureFlagDialogContainer { return (metadata as AdvancedFeatureFlagMetadata) .sendToServerWhenOverridden; }); - }), + }) ); this.featureFlags$ = this.store.select(getOverriddenFeatureFlags).pipe( withLatestFrom( this.store.select(getDefaultFeatureFlags), this.store.select(getFeatureFlagsMetadata), - this.showFlagsFilter$, + this.showFlagsFilter$ ), map( ([ @@ -90,7 +90,7 @@ export class FeatureFlagDialogContainer { .map(([flagName, defaultValue]) => { const status = getFlagStatus( flagName as keyof FeatureFlags, - overriddenFeatureFlags, + overriddenFeatureFlags ); const metadata = flagMetadata[flagName as keyof FeatureFlags]; return { @@ -102,8 +102,8 @@ export class FeatureFlagDialogContainer { ).sendToServerWhenOverridden, } as FeatureFlagStatus; }); - }, - ), + } + ) ); } @@ -120,12 +120,12 @@ export class FeatureFlagDialogContainer { break; case FeatureFlagOverrideStatus.ENABLED: this.store.dispatch( - featureFlagOverrideChanged({flags: {[flag]: true}}), + featureFlagOverrideChanged({flags: {[flag]: true}}) ); break; case FeatureFlagOverrideStatus.DISABLED: this.store.dispatch( - featureFlagOverrideChanged({flags: {[flag]: false}}), + featureFlagOverrideChanged({flags: {[flag]: false}}) ); break; default: @@ -140,7 +140,7 @@ export class FeatureFlagDialogContainer { function getFlagStatus( flagName: keyof FeatureFlags, - overriddenFeatureFlags: Partial, + overriddenFeatureFlags: Partial ): FeatureFlagOverrideStatus { if (overriddenFeatureFlags[flagName] === undefined) { return FeatureFlagOverrideStatus.DEFAULT; diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts index 06900b1ef6..c96008a33b 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_line_chart_container.ts @@ -122,10 +122,10 @@ export class ScalarCardLineChartContainer default: const neverType = xAxisType as never; throw new Error( - `Invalid xAxisType for line chart. ${neverType}`, + `Invalid xAxisType for line chart. ${neverType}` ); } - }), + }) ); this.ngUnsubscribe = new Subject(); } @@ -165,13 +165,13 @@ export class ScalarCardLineChartContainer ngOnInit() { this.userViewBox$ = this.store.select( getMetricsCardUserViewBox, - this.cardId, + this.cardId ); this.loadState$ = this.store.select(getCardLoadState, this.cardId); this.rangeEnabled$ = this.store.select( - getMetricsCardRangeSelectionEnabled(this.cardId), + getMetricsCardRangeSelectionEnabled(this.cardId) ); } @@ -181,13 +181,13 @@ export class ScalarCardLineChartContainer } onTimeSelectionChanged( - newTimeSelectionWithAffordance: TimeSelectionWithAffordance, + newTimeSelectionWithAffordance: TimeSelectionWithAffordance ) { this.store.dispatch( timeSelectionChanged({ ...newTimeSelectionWithAffordance, cardId: this.cardId, - }), + }) ); } @@ -200,7 +200,7 @@ export class ScalarCardLineChartContainer cardViewBoxChanged({ userViewBox: lineChartViewBox, cardId: this.cardId, - }), + }) ); } } diff --git a/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts b/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts index 9cd327af2b..561ecb165d 100644 --- a/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts +++ b/tensorboard/webapp/metrics/views/main_view/card_grid_container.ts @@ -84,17 +84,17 @@ export class CardGridContainer implements OnChanges, OnDestroy { ]).pipe( map(([items, pageSize]) => { return Math.ceil(items.length / pageSize); - }), + }) ); this.isGroupExpanded$ = this.groupName$.pipe( switchMap((groupName) => { return groupName !== null ? this.store.select(getMetricsTagGroupExpansionState, groupName) : of(true); - }), + }) ); this.showPaginationControls$ = this.numPages$.pipe( - map((numPages) => numPages > 1), + map((numPages) => numPages > 1) ); this.normalizedPageIndex$ = combineLatest([ this.pageIndex$, @@ -116,7 +116,7 @@ export class CardGridContainer implements OnChanges, OnDestroy { map(([pageIndex, numPages]) => { return Math.min(Math.max(pageIndex, 0), numPages - 1); }), - shareReplay(1), + shareReplay(1) ); this.pagedItems$ = combineLatest([ this.items$, @@ -128,7 +128,7 @@ export class CardGridContainer implements OnChanges, OnDestroy { const startIndex = pageSize * pageIndex; const endIndex = pageSize * pageIndex + (expanded ? pageSize : 0); return items.slice(startIndex, endIndex); - }), + }) ); this.cardMinWidth$ = this.store.select(getMetricsCardMinWidth); } diff --git a/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts b/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts index e74c369013..4a40c3b653 100644 --- a/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts +++ b/tensorboard/webapp/metrics/views/main_view/filter_input_container.ts @@ -50,7 +50,7 @@ export class MetricsFilterInputContainer { } catch (err) { return false; } - }), + }) ); this.completions$ = this.store.select(getNonEmptyCardIdsWithMetadata).pipe( combineLatestWith(this.store.select(getMetricsFilteredPluginTypes)), @@ -74,12 +74,12 @@ export class MetricsFilterInputContainer { } catch (e) { return [tags, null]; } - }, + } ), filter(([, tagFilterRegex]) => tagFilterRegex !== null), map(([tags, tagFilterRegex]) => { return tags.filter((tag: string) => tagFilterRegex!.test(tag)); - }), + }) ); } diff --git a/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts b/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts index a413685a62..45ae6dcd8c 100644 --- a/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts +++ b/tensorboard/webapp/metrics/views/right_pane/settings_view_container.ts @@ -101,26 +101,26 @@ import { export class SettingsViewContainer { constructor( private readonly store: Store, - private readonly dialog: MatDialog, + private readonly dialog: MatDialog ) { this.isScalarStepSelectorEnabled$ = this.store.select( - selectors.getMetricsStepSelectorEnabled, + selectors.getMetricsStepSelectorEnabled ); this.isScalarStepSelectorRangeEnabled$ = this.store.select( - selectors.getMetricsRangeSelectionEnabled, + selectors.getMetricsRangeSelectionEnabled ); this.isLinkedTimeEnabled$ = this.store.select( - selectors.getMetricsLinkedTimeEnabled, + selectors.getMetricsLinkedTimeEnabled ); this.isScalarColumnCustomizationEnabled$ = this.store.select( - selectors.getIsScalarColumnCustomizationEnabled, + selectors.getIsScalarColumnCustomizationEnabled ); this.linkedTimeSelection$ = this.store.select( - selectors.getMetricsLinkedTimeSelectionSetting, + selectors.getMetricsLinkedTimeSelectionSetting ); this.stepMinMax$ = this.store.select(selectors.getMetricsStepMinMax); this.isSlideOutMenuOpen$ = this.store.select( - selectors.isMetricsSlideoutMenuOpen, + selectors.isMetricsSlideoutMenuOpen ); this.isImageSupportEnabled$ = this.store .select(selectors.getIsFeatureFlagsLoaded) @@ -128,39 +128,39 @@ export class SettingsViewContainer { filter(Boolean), take(1), withLatestFrom( - this.store.select(selectors.getIsMetricsImageSupportEnabled), + this.store.select(selectors.getIsMetricsImageSupportEnabled) ), map(([, isImagesSupported]) => { return isImagesSupported; - }), + }) ); this.tooltipSort$ = this.store.select(selectors.getMetricsTooltipSort); this.ignoreOutliers$ = this.store.select( - selectors.getMetricsIgnoreOutliers, + selectors.getMetricsIgnoreOutliers ); this.xAxisType$ = this.store.select(selectors.getMetricsXAxisType); this.cardMinWidth$ = this.store.select(selectors.getMetricsCardMinWidth); this.histogramMode$ = this.store.select(selectors.getMetricsHistogramMode); this.scalarSmoothing$ = this.store.select( - selectors.getMetricsScalarSmoothing, + selectors.getMetricsScalarSmoothing ); this.scalarPartitionX$ = this.store.select( - selectors.getMetricsScalarPartitionNonMonotonicX, + selectors.getMetricsScalarPartitionNonMonotonicX ); this.imageBrightnessInMilli$ = this.store.select( - selectors.getMetricsImageBrightnessInMilli, + selectors.getMetricsImageBrightnessInMilli ); this.imageContrastInMilli$ = this.store.select( - selectors.getMetricsImageContrastInMilli, + selectors.getMetricsImageContrastInMilli ); this.imageShowActualSize$ = this.store.select( - selectors.getMetricsImageShowActualSize, + selectors.getMetricsImageShowActualSize ); this.isSavingPinsEnabled$ = this.store.select( - selectors.getMetricsSavingPinsEnabled, + selectors.getMetricsSavingPinsEnabled ); this.globalPinsFeatureEnabled$ = this.store.select( - selectors.getEnableGlobalPins, + selectors.getEnableGlobalPins ); } @@ -242,7 +242,7 @@ export class SettingsViewContainer { onLinkedTimeToggled() { this.store.dispatch( - linkedTimeToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX}), + linkedTimeToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX}) ); } @@ -250,7 +250,7 @@ export class SettingsViewContainer { this.store.dispatch( stepSelectorToggled({ affordance: TimeSelectionToggleAffordance.CHECK_BOX, - }), + }) ); } @@ -258,7 +258,7 @@ export class SettingsViewContainer { this.store.dispatch( rangeSelectionToggled({ affordance: TimeSelectionToggleAffordance.CHECK_BOX, - }), + }) ); } diff --git a/tensorboard/webapp/plugins/plugins_container.ts b/tensorboard/webapp/plugins/plugins_container.ts index ab241b1185..774d3a6021 100644 --- a/tensorboard/webapp/plugins/plugins_container.ts +++ b/tensorboard/webapp/plugins/plugins_container.ts @@ -49,7 +49,7 @@ const activePlugin = createSelector( (plugins, id): UiPluginMetadata | null => { if (!id || !plugins[id]) return null; return Object.assign({id}, plugins[id]); - }, + } ); @Component({ @@ -102,7 +102,7 @@ export class PluginsContainer { this.pluginLoadState$ = combineLatest( this.activeKnownPlugin$, this.activePluginId$, - this.store.select(getPluginsListLoaded), + this.store.select(getPluginsListLoaded) ).pipe( map(([activePlugin, activePluginId, loadState]) => { if (loadState.failureCode !== null) { @@ -136,18 +136,18 @@ export class PluginsContainer { } return PluginLoadState.NO_ENABLED_PLUGINS; - }), + }) ); this.lastLoadedTimeInMs$ = this.store.select(getAppLastLoadedTimeInMs); this.dataLocation$ = this.store.select(getEnvironment).pipe( map((env) => { return env.data_location; - }), + }) ); this.isFeatureFlagsLoaded$ = this.store.select(getIsFeatureFlagsLoaded); this.featureFlags$ = this.store.select(getFeatureFlags); this.settingsLoadState$ = this.store.select( - settingsSelectors.getSettingsLoadState, + settingsSelectors.getSettingsLoadState ); } } diff --git a/tensorboard/webapp/runs/effects/runs_effects.ts b/tensorboard/webapp/runs/effects/runs_effects.ts index b056f93ea0..969a07a023 100644 --- a/tensorboard/webapp/runs/effects/runs_effects.ts +++ b/tensorboard/webapp/runs/effects/runs_effects.ts @@ -53,7 +53,7 @@ export class RunsEffects { constructor( private readonly actions$: Actions, private readonly store: Store, - private readonly runsDataSource: RunsDataSource, + private readonly runsDataSource: RunsDataSource ) { this.experimentsWithStaleRunsOnRouteChange$ = this.actions$.pipe( ofType(navigated), @@ -72,9 +72,9 @@ export class RunsEffects { }).pipe( map((experimentIdsToBeFetched) => { return {experimentIds, experimentIdsToBeFetched}; - }), + }) ); - }), + }) ); this.experimentsWithStaleRunsOnReload$ = this.actions$.pipe( ofType(coreActions.reload, coreActions.manualReload), @@ -87,29 +87,29 @@ export class RunsEffects { }).pipe( map((experimentIdsToBeFetched) => { return {experimentIds, experimentIdsToBeFetched}; - }), + }) ); - }), + }) ); this.loadRunsOnNavigationOrReload$ = createEffect( () => { return merge( this.experimentsWithStaleRunsOnRouteChange$, - this.experimentsWithStaleRunsOnReload$, + this.experimentsWithStaleRunsOnReload$ ).pipe( withLatestFrom(this.store.select(getActiveRoute)), filter( - ([, route]) => route !== null && route.routeKind !== RouteKind.CARD, + ([, route]) => route !== null && route.routeKind !== RouteKind.CARD ), mergeMap(([{experimentIds, experimentIdsToBeFetched}]) => { return this.fetchAllRunsList( experimentIds, - experimentIdsToBeFetched, + experimentIdsToBeFetched ); - }), + }) ); }, - {dispatch: false}, + {dispatch: false} ); this.removeHparamFilterWhenColumnIsRemoved$ = createEffect( () => @@ -120,7 +120,7 @@ export class RunsEffects { this.store.dispatch( hparamsActions.dashboardHparamFilterRemoved({ name: header.name, - }), + }) ); return; } @@ -128,12 +128,12 @@ export class RunsEffects { this.store.dispatch( hparamsActions.dashboardMetricFilterRemoved({ name: header.name, - }), + }) ); } - }), + }) ), - {dispatch: false}, + {dispatch: false} ); } @@ -143,18 +143,18 @@ export class RunsEffects { private getExperimentsWithLoadState( experimentIds: string[], - loadStateMatcher: (loadState: DataLoadState) => boolean, + loadStateMatcher: (loadState: DataLoadState) => boolean ) { return forkJoin( experimentIds.map((eid) => { return this.getRunsListLoadState(eid); - }), + }) ).pipe( map((loadStates) => { return experimentIds.filter((unused, index) => { return loadStateMatcher(loadStates[index].state); }); - }), + }) ); } @@ -190,7 +190,7 @@ export class RunsEffects { */ private fetchAllRunsList( experimentIds: string[], - experimentIdsToBeFetched: string[], + experimentIdsToBeFetched: string[] ): Observable { return of({experimentIds, experimentIdsToBeFetched}).pipe( tap(() => { @@ -198,7 +198,7 @@ export class RunsEffects { actions.fetchRunsRequested({ experimentIds, requestedExperimentIds: experimentIdsToBeFetched, - }), + }) ); }), mergeMap(() => { @@ -235,7 +235,7 @@ export class RunsEffects { newRuns, runsForAllExperiments, expNameByExpId, - }), + }) ); }), catchError((error) => { @@ -243,11 +243,11 @@ export class RunsEffects { actions.fetchRunsFailed({ experimentIds, requestedExperimentIds: experimentIdsToBeFetched, - }), + }) ); return of(null); }), - map(() => null), + map(() => null) ); } @@ -266,7 +266,7 @@ export class RunsEffects { return of(loadState); }), withLatestFrom(this.store.select(getRuns, {experimentId})), - map(([, runs]) => ({fromRemote: false, experimentId, runs})), + map(([, runs]) => ({fromRemote: false, experimentId, runs})) ); } @@ -282,7 +282,7 @@ export class RunsEffects { experimentId, runs: runs as Run[], }; - }), + }) ); } } diff --git a/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts b/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts index 1ddf4cc125..018ae6c21b 100644 --- a/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts +++ b/tensorboard/webapp/runs/views/runs_table/runs_table_container.ts @@ -161,10 +161,10 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.runsColumns$ = this.store.select(getGroupedRunsTableHeaders); this.selectableColumns$ = this.store.select(getSelectableColumns); this.numColumnsLoaded$ = this.store.select( - hparamsSelectors.getNumDashboardHparamsLoaded, + hparamsSelectors.getNumDashboardHparamsLoaded ); this.numColumnsToLoad$ = this.store.select( - hparamsSelectors.getNumDashboardHparamsToLoad, + hparamsSelectors.getNumDashboardHparamsToLoad ); this.columnFilters$ = this.store.select(getCurrentColumnFilters); this.allRunsTableData$ = this.store.select(getFilteredRenderableRuns).pipe( @@ -181,14 +181,14 @@ export class RunsTableContainer implements OnInit, OnDestroy { }; return tableData; }); - }), + }) ); this.ngUnsubscribe = new Subject(); } ngOnInit() { const getRunTableItemsPerExperiment = this.experimentIds.map((id) => - this.getRunTableItemsForExperiment(id), + this.getRunTableItemsForExperiment(id) ); this.sortedRunsTableData$ = combineLatest([ @@ -197,16 +197,16 @@ export class RunsTableContainer implements OnInit, OnDestroy { ]).pipe( map(([items, sortingInfo]) => { return sortTableDataItems(items, sortingInfo); - }), + }) ); const rawAllUnsortedRunTableItems$ = combineLatest( - getRunTableItemsPerExperiment, + getRunTableItemsPerExperiment ).pipe( map((itemsForExperiments: RunTableItem[][]) => { const items = [] as RunTableItem[]; return items.concat(...itemsForExperiments); - }), + }) ); const getRunsLoadingPerExperiment = this.experimentIds.map((id) => { @@ -215,7 +215,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.loading$ = combineLatest(getRunsLoadingPerExperiment).pipe( map((experimentsLoading) => { return experimentsLoading.some((isLoading) => isLoading); - }), + }) ); /** @@ -244,9 +244,9 @@ export class RunsTableContainer implements OnInit, OnDestroy { filter((runTableItems: RunTableItem[]) => { return runTableItems.length > MAX_NUM_RUNS_TO_ENABLE_BY_DEFAULT; }), - take(1), + take(1) ); - }), + }) ); runsExceedLimitForRoute$.subscribe(() => { const text = @@ -254,7 +254,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { `${MAX_NUM_RUNS_TO_ENABLE_BY_DEFAULT}. New runs are unselected ` + `for performance reasons.`; this.store.dispatch( - alertActions.alertReported({localizedMessage: text}), + alertActions.alertReported({localizedMessage: text}) ); }); } @@ -270,7 +270,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { } private getRunTableItemsForExperiment( - experimentId: string, + experimentId: string ): Observable { return combineLatest([ this.store.select(getRuns, {experimentId}), @@ -299,7 +299,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { metrics: metricMap, }; }); - }), + }) ); } @@ -307,7 +307,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( runSelectionToggled({ runId: id, - }), + }) ); } @@ -315,7 +315,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( singleRunSelected({ runId, - }), + }) ); } @@ -323,7 +323,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { this.store.dispatch( runPageSelectionToggled({ runIds, - }), + }) ); } @@ -341,19 +341,19 @@ export class RunsTableContainer implements OnInit, OnDestroy { column, nextTo, side, - }), + }) ); } removeColumn(header: ColumnHeader) { this.store.dispatch( - hparamsActions.dashboardHparamColumnRemoved({column: header}), + hparamsActions.dashboardHparamColumnRemoved({column: header}) ); } orderColumns(event: ReorderColumnEvent) { this.store.dispatch( - hparamsActions.dashboardHparamColumnOrderChanged(event), + hparamsActions.dashboardHparamColumnOrderChanged(event) ); } @@ -362,7 +362,7 @@ export class RunsTableContainer implements OnInit, OnDestroy { hparamsActions.dashboardHparamFilterAdded({ name: event.name, filter: event.value, - }), + }) ); }