diff --git a/tensorboard/webapp/metrics/store/metrics_reducers.ts b/tensorboard/webapp/metrics/store/metrics_reducers.ts index 17d4b2a67e..5c320d19e0 100644 --- a/tensorboard/webapp/metrics/store/metrics_reducers.ts +++ b/tensorboard/webapp/metrics/store/metrics_reducers.ts @@ -1141,8 +1141,8 @@ const reducer = createReducer( // Updates cardStepIndex only when toggle to enable linked time. if (nextLinkedTimeEnabled) { - const {min} = state.stepMinMax; - const startStep = min === Infinity ? 0 : min; + const {max} = state.stepMinMax; + const startStep = max === -Infinity ? 0 : max; nextLinkedTimeSelection = state.linkedTimeSelection ?? { start: {step: startStep}, end: null, @@ -1202,15 +1202,19 @@ const reducer = createReducer( }; } if (!linkedTimeSelection.end) { + // Enabling range selection from single selection selects the first + // step as the start of the range. The previous start step from single + // selection is now the end step. linkedTimeSelection = { - ...linkedTimeSelection, - end: {step: state.stepMinMax.max}, + start: {step: state.stepMinMax.min}, + end: linkedTimeSelection.start, }; } } else { if (linkedTimeSelection) { + // Disabling range selection keeps the largest step from the range. linkedTimeSelection = { - ...linkedTimeSelection, + start: linkedTimeSelection.end ?? linkedTimeSelection.start, end: null, }; } diff --git a/tensorboard/webapp/metrics/store/metrics_reducers_test.ts b/tensorboard/webapp/metrics/store/metrics_reducers_test.ts index da4c8a63ae..8f9d0575ae 100644 --- a/tensorboard/webapp/metrics/store/metrics_reducers_test.ts +++ b/tensorboard/webapp/metrics/store/metrics_reducers_test.ts @@ -4057,8 +4057,8 @@ describe('metrics reducers', () => { const state2 = reducers(state1, actions.rangeSelectionToggled({})); expect(state2.linkedTimeSelection).toEqual({ - start: {step: 100}, - end: {step: -Infinity}, + start: {step: Infinity}, + end: {step: 100}, }); }); @@ -4073,7 +4073,7 @@ describe('metrics reducers', () => { const state2 = reducers(state1, actions.rangeSelectionToggled({})); expect(state2.linkedTimeSelection).toEqual({ - start: {step: 100}, + start: {step: 1000}, end: null, }); }); @@ -4358,7 +4358,7 @@ describe('metrics reducers', () => { }); }); - it('sets linkedTimeSelection to min step when linkedTimeSelection is null before toggling', () => { + it('sets linkedTimeSelection to max step when linkedTimeSelection is null before toggling', () => { const state1 = buildMetricsState({ stepMinMax: {min: 10, max: 100}, }); @@ -4366,7 +4366,7 @@ describe('metrics reducers', () => { const state2 = reducers(state1, actions.linkedTimeToggled({})); expect(state2.linkedTimeSelection).toEqual({ - start: {step: 10}, + start: {step: 100}, end: null, }); }); diff --git a/tensorboard/webapp/metrics/store/metrics_selectors.ts b/tensorboard/webapp/metrics/store/metrics_selectors.ts index 35dc62a2bb..448f9e8d61 100644 --- a/tensorboard/webapp/metrics/store/metrics_selectors.ts +++ b/tensorboard/webapp/metrics/store/metrics_selectors.ts @@ -439,7 +439,7 @@ export const getMetricsLinkedTimeSelectionSetting = createSelector( if (!state.linkedTimeSelection) { return { start: { - step: stepMinMax.min, + step: stepMinMax.max, }, end: null, }; @@ -588,15 +588,33 @@ export const getMetricsCardTimeSelection = createSelector( globalRangeSelectionEnabled ); - const startStep = cardState.timeSelection?.start.step ?? minMaxStep.minStep; - const endStep = cardState.timeSelection?.end?.step ?? minMaxStep.maxStep; + let timeSelection = cardState.timeSelection; + if (!timeSelection) { + timeSelection = { + start: {step: minMaxStep.minStep}, + end: {step: minMaxStep.maxStep}, + }; + } + if (rangeSelectionEnabled) { + if (!timeSelection.end) { + // Enabling range selection from single selection selects the first + // step as the start of the range. The previous start step from single + // selection is now the end step. + timeSelection = { + start: {step: minMaxStep.minStep}, + end: timeSelection.start, + }; + } + } else { + // Disabling range selection keeps the largest step from the range. + timeSelection = { + start: timeSelection.end ?? timeSelection.start, + end: null, + }; + } - // The default time selection return formatTimeSelection( - { - start: {step: startStep}, - end: {step: endStep}, - }, + timeSelection, minMaxStep, rangeSelectionEnabled ); diff --git a/tensorboard/webapp/metrics/store/metrics_selectors_test.ts b/tensorboard/webapp/metrics/store/metrics_selectors_test.ts index a6cba2e60c..99fb2da79d 100644 --- a/tensorboard/webapp/metrics/store/metrics_selectors_test.ts +++ b/tensorboard/webapp/metrics/store/metrics_selectors_test.ts @@ -549,7 +549,7 @@ describe('metrics selectors', () => { ).toBeUndefined(); }); - it('uses max step as end value if none exists', () => { + it('uses min step as start value if end value does not exists', () => { const state = appStateFromMetricsState( buildMetricsState({ ...partialState, @@ -562,7 +562,7 @@ describe('metrics selectors', () => { maxStep: 10, }, timeSelection: { - start: {step: 0}, + start: {step: 5}, end: null, }, }, @@ -572,7 +572,7 @@ describe('metrics selectors', () => { expect(selectors.getMetricsCardTimeSelection(state, 'card1')).toEqual({ start: {step: 0}, - end: {step: 10}, + end: {step: 5}, }); }); @@ -619,7 +619,7 @@ describe('metrics selectors', () => { ); expect(selectors.getMetricsCardTimeSelection(state, 'card1')).toEqual({ - start: {step: 0}, + start: {step: 5}, end: null, }); }); @@ -642,7 +642,7 @@ describe('metrics selectors', () => { ); expect(selectors.getMetricsCardTimeSelection(state, 'card1')).toEqual({ - start: {step: 0}, + start: {step: 5}, end: null, }); }); @@ -1392,7 +1392,7 @@ describe('metrics selectors', () => { }) ); expect(selectors.getMetricsLinkedTimeSelectionSetting(state)).toEqual({ - start: {step: 0}, + start: {step: 1000}, end: null, }); }); diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts index 26407cf6ce..c42fc859b9 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts @@ -3963,7 +3963,7 @@ describe('scalar card', () => { ); const fakeEvent = new MouseEvent('mousemove', { clientX: 25 + controllerStartPosition, - movementX: 1, + movementX: -1, }); testController.mouseMove(fakeEvent);