Skip to content

Commit a48d619

Browse files
authored
linked time: set up feature flag and fob rendering (#5995)
Introduce feature flag in the card fob and used to render a fob component.
1 parent 1e7c972 commit a48d619

File tree

8 files changed

+81
-0
lines changed

8 files changed

+81
-0
lines changed

tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ng.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@
234234
[minMaxHorizontalViewExtend]="viewExtent.x"
235235
[minMaxStep]="minMaxStep"
236236
[axisSize]="domDim.width"
237+
[isProspectiveFobFeatureEnabled]="isProspectiveFobFeatureEnabled"
237238
(onTimeSelectionChanged)="onTimeSelectionChanged.emit($event)"
238239
(onTimeSelectionToggled)="onFobRemoved()"
239240
></scalar-card-fob-controller>

tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class ScalarCardComponent<Downloader> {
9292
@Input() forceSvg!: boolean;
9393
@Input() linkedTimeSelection!: TimeSelectionView | null;
9494
@Input() stepOrLinkedTimeSelection!: TimeSelection | null;
95+
@Input() isProspectiveFobFeatureEnabled: Boolean = false;
9596
@Input() minMaxStep!: MinMaxStep;
9697
@Input() dataHeaders!: ColumnHeaders[];
9798

tensorboard/webapp/metrics/views/card_renderer/scalar_card_container.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {
5151
getDarkModeEnabled,
5252
getExperimentIdForRunId,
5353
getExperimentIdToExperimentAliasMap,
54+
getIsLinkedTimeProspectiveFobEnabled,
5455
getMetricsLinkedTimeEnabled,
5556
getMetricsLinkedTimeSelection,
5657
getMetricsStepSelectorEnabled,
@@ -156,6 +157,7 @@ function areSeriesEqual(
156157
[useDarkMode]="useDarkMode$ | async"
157158
[linkedTimeSelection]="linkedTimeSelection$ | async"
158159
[stepOrLinkedTimeSelection]="stepOrLinkedTimeSelection$ | async"
160+
[isProspectiveFobFeatureEnabled]="isProspectiveFobFeatureEnabled$ | async"
159161
[forceSvg]="forceSvg$ | async"
160162
[minMaxStep]="minMaxSteps$ | async"
161163
[dataHeaders]="columnHeaders$ | async"
@@ -204,6 +206,9 @@ export class ScalarCardContainer implements CardRenderer, OnInit, OnDestroy {
204206
columnHeaders$?: Observable<ColumnHeaders[]>;
205207
stepOrLinkedTimeSelection$?: Observable<TimeSelection | null>;
206208

209+
readonly isProspectiveFobFeatureEnabled$: Observable<boolean> =
210+
this.store.select(getIsLinkedTimeProspectiveFobEnabled);
211+
207212
onVisibilityChange({visible}: {visible: boolean}) {
208213
this.isVisible = visible;
209214
}

tensorboard/webapp/metrics/views/card_renderer/scalar_card_fob_controller.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import {MinMaxStep} from './scalar_card_types';
3636
[endStepAxisPosition]="getAxisPositionFromEndStep()"
3737
[highestStep]="getHighestStep()"
3838
[lowestStep]="getLowestStep()"
39+
[prospectiveStep]="prospectiveStep"
40+
[isProspectiveFobFeatureEnabled]="isProspectiveFobFeatureEnabled"
3941
[cardFobHelper]="cardFobHelper"
4042
[showExtendedLine]="true"
4143
(onTimeSelectionChanged)="onTimeSelectionChanged.emit($event)"
@@ -51,6 +53,7 @@ export class ScalarCardFobController {
5153
@Input() minMaxHorizontalViewExtend!: [number, number];
5254
@Input() minMaxStep!: MinMaxStep;
5355
@Input() axisSize!: number;
56+
@Input() isProspectiveFobFeatureEnabled: Boolean = false;
5457

5558
@Output() onTimeSelectionChanged = new EventEmitter<{
5659
timeSelection: TimeSelection;
@@ -64,6 +67,7 @@ export class ScalarCardFobController {
6467
this.getStepHigherThanAxisPosition.bind(this),
6568
getStepLowerThanAxisPosition: this.getStepLowerThanAxisPosition.bind(this),
6669
};
70+
prospectiveStep: number | null = null;
6771

6872
getAxisPositionFromStartStep() {
6973
return this.scale.forward(

tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ describe('scalar card', () => {
335335
store.overrideSelector(selectors.getDarkModeEnabled, false);
336336
store.overrideSelector(selectors.getForceSvgFeatureFlag, false);
337337
store.overrideSelector(selectors.getMetricsStepSelectorEnabled, false);
338+
store.overrideSelector(
339+
selectors.getIsLinkedTimeProspectiveFobEnabled,
340+
false
341+
);
338342
});
339343

340344
describe('basic renders', () => {

tensorboard/webapp/widgets/card_fob/card_fob_controller_component.ng.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
-->
1717

1818
<div>
19+
<div
20+
#prospectiveFobWrapper
21+
class="time-fob-wrapper"
22+
*ngIf="prospectiveStep !== null && isProspectiveFobFeatureEnabled"
23+
>
24+
<div *ngIf="showExtendedLine" class="extended-line"></div>
25+
<card-fob
26+
[ngClass]="isVertical() ? 'vertical-fob' : 'horizontal-fob'"
27+
></card-fob>
28+
</div>
1929
<div
2030
#startFobWrapper
2131
class="time-fob-wrapper"

tensorboard/webapp/widgets/card_fob/card_fob_controller_component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ const TIME_SELECTION_TO_FOB: Record<keyof TimeSelection, Fob> = {
5050
export class CardFobControllerComponent {
5151
@ViewChild('startFobWrapper') readonly startFobWrapper!: ElementRef;
5252
@ViewChild('endFobWrapper') readonly endFobWrapper!: ElementRef;
53+
@ViewChild('prospectiveFobWrapper')
54+
readonly prospectiveFobWrapper!: ElementRef;
5355
@Input() axisDirection!: AxisDirection;
5456
@Input() timeSelection!: TimeSelection;
5557
@Input() cardFobHelper!: CardFobGetStepFromPositionHelper;
@@ -58,6 +60,8 @@ export class CardFobControllerComponent {
5860
@Input() highestStep!: number;
5961
@Input() lowestStep!: number;
6062
@Input() showExtendedLine?: Boolean = false;
63+
@Input() isProspectiveFobFeatureEnabled?: Boolean = false;
64+
@Input() prospectiveStep?: number | null = null;
6165

6266
@Output() onTimeSelectionChanged =
6367
new EventEmitter<TimeSelectionWithAffordance>();

tensorboard/webapp/widgets/card_fob/card_fob_controller_test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import {
3939
[lowestStep]="lowestStep"
4040
[cardFobHelper]="cardFobHelper"
4141
[showExtendedLine]="showExtendedLine"
42+
[isProspectiveFobFeatureEnabled]="isProspectiveFobFeatureEnabled"
43+
[prospectiveStep]="prospectiveStep"
4244
(onTimeSelectionChanged)="onTimeSelectionChanged($event)"
4345
(onTimeSelectionToggled)="onTimeSelectionToggled()"
4446
></card-fob-controller>
@@ -56,6 +58,8 @@ class TestableComponent {
5658
@Input() lowestStep!: number;
5759
@Input() getAxisPositionFromStartStep!: () => number;
5860
@Input() getAxisPositionFromEndStep!: () => number;
61+
@Input() isProspectiveFobFeatureEnabled!: Boolean;
62+
@Input() prospectiveStep!: number | null;
5963

6064
@Input() onTimeSelectionChanged!: (newTimeSelection: TimeSelection) => void;
6165
@Input() onTimeSelectionToggled!: () => void;
@@ -85,6 +89,8 @@ describe('card_fob_controller', () => {
8589
timeSelection: TimeSelection;
8690
showExtendedLine?: Boolean;
8791
steps?: number[];
92+
isProspectiveFobFeatureEnabled?: Boolean;
93+
prospectiveStep?: number | null;
8894
}): ComponentFixture<TestableComponent> {
8995
const fixture = TestBed.createComponent(TestableComponent);
9096

@@ -133,6 +139,10 @@ describe('card_fob_controller', () => {
133139
fixture.componentInstance.showExtendedLine =
134140
input.showExtendedLine ?? false;
135141

142+
fixture.componentInstance.isProspectiveFobFeatureEnabled =
143+
input.isProspectiveFobFeatureEnabled ?? false;
144+
fixture.componentInstance.prospectiveStep = input.prospectiveStep ?? null;
145+
136146
onTimeSelectionChanged = jasmine.createSpy();
137147
fixture.componentInstance.onTimeSelectionChanged = onTimeSelectionChanged;
138148
onTimeSelectionChanged.and.callFake(
@@ -1269,4 +1279,46 @@ describe('card_fob_controller', () => {
12691279
});
12701280
});
12711281
});
1282+
1283+
describe('prospective fob', () => {
1284+
it('renders when feature flag is enabled and the step is not null', () => {
1285+
const fixture = createComponent({
1286+
timeSelection: {start: {step: 4}, end: null},
1287+
isProspectiveFobFeatureEnabled: true,
1288+
prospectiveStep: 2,
1289+
});
1290+
fixture.detectChanges();
1291+
1292+
const fobController = fixture.componentInstance.fobController;
1293+
const prospectiveFob = fobController.prospectiveFobWrapper.nativeElement;
1294+
1295+
expect(prospectiveFob).toBeTruthy();
1296+
});
1297+
1298+
it('does not render when feature flag is disenabled', () => {
1299+
const fixture = createComponent({
1300+
timeSelection: {start: {step: 4}, end: null},
1301+
isProspectiveFobFeatureEnabled: false,
1302+
prospectiveStep: 2,
1303+
});
1304+
fixture.detectChanges();
1305+
1306+
expect(
1307+
fixture.componentInstance.fobController.prospectiveFobWrapper
1308+
).toBeUndefined();
1309+
});
1310+
1311+
it('does not render when step is null', () => {
1312+
const fixture = createComponent({
1313+
timeSelection: {start: {step: 4}, end: null},
1314+
isProspectiveFobFeatureEnabled: true,
1315+
prospectiveStep: null,
1316+
});
1317+
fixture.detectChanges();
1318+
1319+
expect(
1320+
fixture.componentInstance.fobController.prospectiveFobWrapper
1321+
).toBeUndefined();
1322+
});
1323+
});
12721324
});

0 commit comments

Comments
 (0)