Skip to content

Commit

Permalink
linked time: add affordance for toggling action (tensorflow#5822)
Browse files Browse the repository at this point in the history
We are interested in learning how often deselect is trigged. However, when deselecting fob in single selection, we triggered toggle action instead of time selection change. We do not know if the toggle action is trigged by deselecting fob or check/uncheck box in settings pane. This PR adds an affordance to the action.
  • Loading branch information
japie1235813 authored Jul 27, 2022
1 parent cf342b0 commit 0f4d6e9
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 36 deletions.
21 changes: 17 additions & 4 deletions tensorboard/webapp/metrics/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ limitations under the License.
==============================================================================*/
import {createAction, props} from '@ngrx/store';
import {ElementId} from '../../util/dom';
import {TimeSelectionAffordance} from '../../widgets/card_fob/card_fob_types';
import {
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../widgets/card_fob/card_fob_types';
import {
TagMetadata,
TimeSeriesRequest,
Expand Down Expand Up @@ -177,7 +180,7 @@ export const linkedTimeSelectionChanged = createAction(
startStep: number;
endStep: number | undefined;
};
// Affordance for analytics purpose. When no affordance is specified or is
// Affordance for internal analytics purpose. When no affordance is specified or is
// undefined we do not want to log an analytics event.
affordance?: TimeSelectionAffordance | undefined;
}>()
Expand All @@ -188,11 +191,21 @@ export const timeSelectionCleared = createAction(
);

export const linkedTimeToggled = createAction(
'[Metrics] Linked Time Enable Toggle'
'[Metrics] Linked Time Enable Toggle',
props<{
// Affordance for internal analytics purpose. When no affordance is specified or is
// undefined we do not want to log an analytics event.
affordance?: TimeSelectionToggleAffordance;
}>()
);

export const stepSelectorToggled = createAction(
'[Metrics] Time Selector Enable Toggle'
'[Metrics] Time Selector Enable Toggle',
props<{
// Affordance for internal analytics purpose. When no affordance is specified or is
// undefined we do not want to log an analytics event.
affordance?: TimeSelectionToggleAffordance;
}>()
);

/**
Expand Down
20 changes: 10 additions & 10 deletions tensorboard/webapp/metrics/store/metrics_reducers_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2737,10 +2737,10 @@ describe('metrics reducers', () => {
linkedTimeEnabled: false,
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));
expect(state2.linkedTimeEnabled).toBe(true);

const state3 = reducers(state2, actions.linkedTimeToggled());
const state3 = reducers(state2, actions.linkedTimeToggled({}));
expect(state3.linkedTimeEnabled).toBe(false);
});

Expand Down Expand Up @@ -2770,7 +2770,7 @@ describe('metrics reducers', () => {
cardStepIndex: {[imageCardId]: buildStepIndexMetadata({index: 2})},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));

expect(state2.cardStepIndex).toEqual({
[imageCardId]: buildStepIndexMetadata({index: 0}),
Expand Down Expand Up @@ -2802,7 +2802,7 @@ describe('metrics reducers', () => {
cardStepIndex: {[imageCardId]: buildStepIndexMetadata({index: 2})},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));
expect(state2.cardStepIndex).toEqual({
[imageCardId]: buildStepIndexMetadata({index: 1}),
});
Expand Down Expand Up @@ -2840,7 +2840,7 @@ describe('metrics reducers', () => {
cardStepIndex: {[imageCardId]: buildStepIndexMetadata({index: 2})},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));
expect(state2.cardStepIndex).toEqual({
[imageCardId]: buildStepIndexMetadata({index: 2}),
});
Expand All @@ -2851,7 +2851,7 @@ describe('metrics reducers', () => {
stepMinMax: {min: Infinity, max: -Infinity},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));

expect(state2.linkedTimeSelection).toEqual({
start: {step: 0},
Expand All @@ -2864,7 +2864,7 @@ describe('metrics reducers', () => {
stepMinMax: {min: 10, max: 100},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));

expect(state2.linkedTimeSelection).toEqual({
start: {step: 10},
Expand All @@ -2877,7 +2877,7 @@ describe('metrics reducers', () => {
linkedTimeSelection: {start: {step: 20}, end: null},
});

const state2 = reducers(state1, actions.linkedTimeToggled());
const state2 = reducers(state1, actions.linkedTimeToggled({}));
expect(state2.linkedTimeSelection).toEqual({
start: {step: 20},
end: null,
Expand All @@ -2892,10 +2892,10 @@ describe('metrics reducers', () => {
stepSelectorEnabled: false,
});

const state2 = reducers(state1, actions.stepSelectorToggled());
const state2 = reducers(state1, actions.stepSelectorToggled({}));
expect(state2.stepSelectorEnabled).toBe(true);

const state3 = reducers(state2, actions.stepSelectorToggled());
const state3 = reducers(state2, actions.stepSelectorToggled({}));
expect(state3.stepSelectorEnabled).toBe(false);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import {filter, map} from 'rxjs/operators';
import {State} from '../../../app_state';
import {DataLoadState} from '../../../types/data';
import {RunColorScale} from '../../../types/ui';
import {TimeSelectionAffordance} from '../../../widgets/card_fob/card_fob_types';
import {
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../../widgets/card_fob/card_fob_types';
import {HistogramDatum} from '../../../widgets/histogram/histogram_types';
import {buildNormalizedHistograms} from '../../../widgets/histogram/histogram_util';
import {linkedTimeSelectionChanged, linkedTimeToggled} from '../../actions';
Expand Down Expand Up @@ -241,6 +244,10 @@ export class HistogramCardContainer implements CardRenderer, OnInit {
}

onLinkedTimeToggled() {
this.store.dispatch(linkedTimeToggled());
this.store.dispatch(
linkedTimeToggled({
affordance: TimeSelectionToggleAffordance.FOB_DESELECT,
})
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import {
} from '../../../selectors';
import {MatIconTestingModule} from '../../../testing/mat_icon_module';
import {DataLoadState} from '../../../types/data';
import {TimeSelectionAffordance} from '../../../widgets/card_fob/card_fob_types';
import {
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../../widgets/card_fob/card_fob_types';
import {
HistogramData,
HistogramMode,
Expand Down Expand Up @@ -554,7 +557,11 @@ describe('histogram card', () => {
).componentInstance;
histogramWidget.onLinkedTimeToggled.emit();

expect(dispatchedActions).toEqual([linkedTimeToggled()]);
expect(dispatchedActions).toEqual([
linkedTimeToggled({
affordance: TimeSelectionToggleAffordance.FOB_DESELECT,
}),
]);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {DataLoadState} from '../../../types/data';
import {
TimeSelection,
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../../widgets/card_fob/card_fob_types';
import {
Formatter,
Expand Down Expand Up @@ -94,12 +95,14 @@ export class ScalarCardComponent<Downloader> {

@Output() onFullSizeToggle = new EventEmitter<void>();
@Output() onPinClicked = new EventEmitter<boolean>();
@Output() onLinkedTimeToggled = new EventEmitter();
@Output() onLinkedTimeToggled =
new EventEmitter<TimeSelectionToggleAffordance>();
@Output() onLinkedTimeSelectionChanged = new EventEmitter<{
timeSelection: TimeSelection;
affordance: TimeSelectionAffordance;
}>();
@Output() onStepSelectorToggled = new EventEmitter();
@Output() onStepSelectorToggled =
new EventEmitter<TimeSelectionToggleAffordance>();
@Output() onStepSelectorTimeSelectionChanged = new EventEmitter<{
timeSelection: TimeSelection;
affordance: TimeSelectionAffordance;
Expand Down Expand Up @@ -308,9 +311,11 @@ export class ScalarCardComponent<Downloader> {

onFobRemoved() {
if (this.linkedTimeSelection !== null) {
this.onLinkedTimeToggled.emit();
this.onLinkedTimeToggled.emit(TimeSelectionToggleAffordance.FOB_DESELECT);
} else {
this.onStepSelectorToggled.emit();
this.onStepSelectorToggled.emit(
TimeSelectionToggleAffordance.FOB_DESELECT
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {DataLoadState} from '../../../types/data';
import {
TimeSelection,
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../../widgets/card_fob/card_fob_types';
import {classicSmoothing} from '../../../widgets/line_chart_v2/data_transformer';
import {ScaleType} from '../../../widgets/line_chart_v2/types';
Expand Down Expand Up @@ -152,8 +153,8 @@ function areSeriesEqual(
(onStepSelectorTimeSelectionChanged)="
onStepSelectorTimeSelectionChanged($event)
"
(onLinkedTimeToggled)="onLinkedTimeToggled()"
(onStepSelectorToggled)="onStepSelectorToggled()"
(onLinkedTimeToggled)="onLinkedTimeToggled($event)"
(onStepSelectorToggled)="onStepSelectorToggled($event)"
></scalar-card-component>
`,
styles: [
Expand Down Expand Up @@ -602,11 +603,11 @@ export class ScalarCardContainer implements CardRenderer, OnInit, OnDestroy {
);
}

onLinkedTimeToggled() {
this.store.dispatch(linkedTimeToggled());
onLinkedTimeToggled(affordance: TimeSelectionToggleAffordance) {
this.store.dispatch(linkedTimeToggled({affordance}));
}

onStepSelectorToggled() {
this.store.dispatch(stepSelectorToggled());
onStepSelectorToggled(affordance: TimeSelectionToggleAffordance) {
this.store.dispatch(stepSelectorToggled({affordance}));
}
}
17 changes: 14 additions & 3 deletions tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ import {
Fob,
} from '../../../widgets/card_fob/card_fob_controller_component';
import {CardFobModule} from '../../../widgets/card_fob/card_fob_module';
import {TimeSelectionAffordance} from '../../../widgets/card_fob/card_fob_types';
import {
TimeSelectionAffordance,
TimeSelectionToggleAffordance,
} from '../../../widgets/card_fob/card_fob_types';
import {DataTableComponent} from '../../../widgets/data_table/data_table_component';
import {DataTableModule} from '../../../widgets/data_table/data_table_module';
import {ExperimentAliasModule} from '../../../widgets/experiment_alias/experiment_alias_module';
Expand Down Expand Up @@ -2296,7 +2299,11 @@ describe('scalar card', () => {
).componentInstance;
fobComponent.fobRemoved.emit();

expect(dispatchedActions).toEqual([linkedTimeToggled()]);
expect(dispatchedActions).toEqual([
linkedTimeToggled({
affordance: TimeSelectionToggleAffordance.FOB_DESELECT,
}),
]);
}));
});

Expand Down Expand Up @@ -2786,7 +2793,11 @@ describe('scalar card', () => {
).componentInstance;
fobComponent.fobRemoved.emit();

expect(dispatchedActions).toEqual([stepSelectorToggled()]);
expect(dispatchedActions).toEqual([
stepSelectorToggled({
affordance: TimeSelectionToggleAffordance.FOB_DESELECT,
}),
]);
}));
});

Expand Down
2 changes: 2 additions & 0 deletions tensorboard/webapp/metrics/views/right_pane/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tf_ng_module(
"//tensorboard/webapp/feature_flag",
"//tensorboard/webapp/metrics:types",
"//tensorboard/webapp/metrics/actions",
"//tensorboard/webapp/widgets/card_fob:types",
"//tensorboard/webapp/widgets/dropdown",
"//tensorboard/webapp/widgets/range_input",
"@npm//@angular/common",
Expand Down Expand Up @@ -61,6 +62,7 @@ tf_ts_library(
"//tensorboard/webapp/metrics:types",
"//tensorboard/webapp/metrics/actions",
"//tensorboard/webapp/metrics/store",
"//tensorboard/webapp/widgets/card_fob:types",
"//tensorboard/webapp/widgets/dropdown",
"@npm//@angular/core",
"@npm//@angular/platform-browser",
Expand Down
11 changes: 9 additions & 2 deletions tensorboard/webapp/metrics/views/right_pane/right_pane_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {Store} from '@ngrx/store';
import {MockStore, provideMockStore} from '@ngrx/store/testing';
import {State} from '../../../app_state';
import * as selectors from '../../../selectors';
import {TimeSelectionToggleAffordance} from '../../../widgets/card_fob/card_fob_types';
import {DropdownModule} from '../../../widgets/dropdown/dropdown_module';
import * as actions from '../../actions';
import {HistogramMode, TooltipSort, XAxisType} from '../../types';
Expand Down Expand Up @@ -432,7 +433,9 @@ describe('metrics right_pane', () => {
enabled.nativeElement.click();

expect(dispatchSpy).toHaveBeenCalledOnceWith(
actions.linkedTimeToggled()
actions.linkedTimeToggled({
affordance: TimeSelectionToggleAffordance.CHECK_BOX,
})
);

store.overrideSelector(selectors.getMetricsLinkedTimeEnabled, true);
Expand Down Expand Up @@ -598,7 +601,11 @@ describe('metrics right_pane', () => {

select(fixture, '.scalars-step-selector input').nativeElement.click();

expect(dispatchSpy).toHaveBeenCalledWith(actions.stepSelectorToggled());
expect(dispatchSpy).toHaveBeenCalledWith(
actions.stepSelectorToggled({
affordance: TimeSelectionToggleAffordance.CHECK_BOX,
})
);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {Observable} from 'rxjs';
import {filter, map, take, withLatestFrom} from 'rxjs/operators';
import {State} from '../../../app_state';
import * as selectors from '../../../selectors';
import {TimeSelectionToggleAffordance} from '../../../widgets/card_fob/card_fob_types';
import {
linkedTimeSelectionChanged,
linkedTimeToggled,
Expand Down Expand Up @@ -200,11 +201,15 @@ export class SettingsViewContainer {
}

onLinkedTimeToggled() {
this.store.dispatch(linkedTimeToggled());
this.store.dispatch(
linkedTimeToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX})
);
}

onStepSelectorToggled() {
this.store.dispatch(stepSelectorToggled());
this.store.dispatch(
stepSelectorToggled({affordance: TimeSelectionToggleAffordance.CHECK_BOX})
);
}

onLinkedTimeSelectionChanged(newValue: TimeSelection) {
Expand Down
15 changes: 14 additions & 1 deletion tensorboard/webapp/widgets/card_fob/card_fob_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export interface TimeSelection {
}

/**
* The affordance supported to update the time selection.
* The affordance supported to update the time selection in step selector and linked time.
* Only used for internal analytics.
*/
export enum TimeSelectionAffordance {
NONE,
Expand All @@ -39,6 +40,18 @@ export enum TimeSelectionAffordance {
SETTINGS_SLIDER,
}

/**
* The affordance supported to toggle step selector and linked time.
* Only used for internal analytics.
*/
export enum TimeSelectionToggleAffordance {
NONE,
// Clicking cross sign in fob.
FOB_DESELECT,
// Clicking check box in settings pane.
CHECK_BOX,
}

/**
* The direction of the axis used to control the fob movements.
*/
Expand Down

0 comments on commit 0f4d6e9

Please sign in to comment.