Skip to content

Commit 0fa03a9

Browse files
authored
linked time: Implement fob deselect logic (#5685)
* implement and test deselect logic * add comment
1 parent a06f39e commit 0fa03a9

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

tensorboard/webapp/widgets/linked_time_fob/linked_time_fob_controller_component.ng.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
[step]="linkedTime.start.step"
3535
(mousedown)="startDrag(FobType().START)"
3636
(stepChange)="stepTyped(FobType().START, $event)"
37+
(removeStep)="deselectFob(FobType().START)"
3738
></linked-time-fob>
3839
</div>
3940
<div
@@ -48,6 +49,7 @@
4849
[step]="linkedTime.end.step"
4950
(mousedown)="startDrag(FobType().END)"
5051
(stepChange)="stepTyped(FobType().END, $event)"
52+
(removeStep)="deselectFob(FobType().END)"
5153
></linked-time-fob>
5254
</div>
5355
</div>

tensorboard/webapp/widgets/linked_time_fob/linked_time_fob_controller_component.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export class LinkedTimeFobControllerComponent {
4343
@Input() axisDirection!: AxisDirection;
4444
@Input() linkedTime!: LinkedTime;
4545
@Input() cardAdapter!: FobCardAdapter;
46+
47+
@Output() onSelectTimeToggle = new EventEmitter();
4648
@Output() onSelectTimeChanged = new EventEmitter<LinkedTime>();
4749

4850
private currentDraggingFob: Fob = Fob.NONE;
@@ -189,4 +191,27 @@ export class LinkedTimeFobControllerComponent {
189191

190192
this.onSelectTimeChanged.emit(newLinkedTime);
191193
}
194+
195+
/**
196+
* When in range selection(which means we have a start and an end
197+
* fob) deselecting a fob will leave the remaining fob in place. This means we
198+
* switch to single selection. If the end fob is deselected we simply remove
199+
* it. However, if the start fob is deselected we must change the end fob to
200+
* the start fob before removing the end fob. This gives the effect that the
201+
* start fob was remove. Lastly when in single selection deselecting the fob
202+
* toggles the feature entirely.
203+
*/
204+
deselectFob(fob: Fob) {
205+
if (fob === Fob.END) {
206+
this.onSelectTimeChanged.emit({...this.linkedTime, end: null});
207+
return;
208+
}
209+
210+
if (this.linkedTime.end !== null) {
211+
this.onSelectTimeChanged.emit({start: this.linkedTime.end, end: null});
212+
return;
213+
}
214+
215+
this.onSelectTimeToggle.emit();
216+
}
192217
}

tensorboard/webapp/widgets/linked_time_fob/linked_time_fob_controller_test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {AxisDirection, FobCardAdapter, LinkedTime} from './linked_time_types';
3333
[linkedTime]="linkedTime"
3434
[cardAdapter]="fobCardAdapter"
3535
(onSelectTimeChanged)="onSelectTimeChanged($event)"
36+
(onSelectTimeToggle)="onSelectTimeToggle()"
3637
></linked-time-fob-controller>
3738
`,
3839
})
@@ -45,10 +46,12 @@ class TestableComponent {
4546
@Input() fobCardAdapter!: FobCardAdapter;
4647

4748
@Input() onSelectTimeChanged!: (newLinkedTime: LinkedTime) => void;
49+
@Input() onSelectTimeToggle!: () => void;
4850
}
4951

5052
describe('linked_time_fob_controller', () => {
5153
let onSelectTimeChanged: jasmine.Spy;
54+
let onSelectTimeToggle: jasmine.Spy;
5255
let getHighestStepSpy: jasmine.Spy;
5356
let getLowestStepSpy: jasmine.Spy;
5457
let getAxisPositionFromStepSpy: jasmine.Spy;
@@ -106,6 +109,9 @@ describe('linked_time_fob_controller', () => {
106109
onSelectTimeChanged = jasmine.createSpy();
107110
fixture.componentInstance.onSelectTimeChanged = onSelectTimeChanged;
108111

112+
onSelectTimeToggle = jasmine.createSpy();
113+
fixture.componentInstance.onSelectTimeToggle = onSelectTimeToggle;
114+
109115
return fixture;
110116
}
111117

@@ -671,4 +677,56 @@ describe('linked_time_fob_controller', () => {
671677
});
672678
});
673679
});
680+
describe('deselecting fob', () => {
681+
it('fires onSelectTimeToggle when in single selection', () => {
682+
const fixture = createComponent({
683+
linkedTime: {start: {step: 1}, end: null},
684+
});
685+
fixture.detectChanges();
686+
687+
const deselectButton = fixture.debugElement.query(
688+
By.css('linked-time-fob.startFob button')
689+
);
690+
deselectButton.triggerEventHandler('click', {});
691+
fixture.detectChanges();
692+
693+
expect(onSelectTimeToggle).toHaveBeenCalledOnceWith();
694+
});
695+
696+
it('fires onSelectTimeChanged to remove end fob when end fob is deselected', () => {
697+
const fixture = createComponent({
698+
linkedTime: {start: {step: 1}, end: {step: 3}},
699+
});
700+
fixture.detectChanges();
701+
702+
const deselectButton = fixture.debugElement.query(
703+
By.css('linked-time-fob.endFob button')
704+
);
705+
deselectButton.triggerEventHandler('click', {});
706+
fixture.detectChanges();
707+
708+
expect(onSelectTimeChanged).toHaveBeenCalledOnceWith({
709+
start: {step: 1},
710+
end: null,
711+
});
712+
});
713+
714+
it('fires onSelectTimeChanged to change the start fob step to the current end fob step and the end fob step to null when start fob is deselected in a range selection', () => {
715+
const fixture = createComponent({
716+
linkedTime: {start: {step: 1}, end: {step: 3}},
717+
});
718+
fixture.detectChanges();
719+
720+
const deselectButton = fixture.debugElement.query(
721+
By.css('linked-time-fob.startFob button')
722+
);
723+
deselectButton.triggerEventHandler('click', {});
724+
fixture.detectChanges();
725+
726+
expect(onSelectTimeChanged).toHaveBeenCalledOnceWith({
727+
start: {step: 3},
728+
end: null,
729+
});
730+
});
731+
});
674732
});

0 commit comments

Comments
 (0)