Skip to content

Commit

Permalink
Add solution date selector
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccollum-woolpert authored May 8, 2023
1 parent b442faf commit 7250135
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,21 @@
<mat-icon svgIcon="navigate_before" [attr.title]="'Previous ' + range?.label"></mat-icon>
</button>
<label>{{ getFormattedRangeOffset() }}</label>
<mat-form-field class="offset-picker" appearance="standard">
<input
matInput
[value]="currentOffsetDate"
[min]="globalStart"
[max]="globalEnd"
[matDatepicker]="offsetPicker"
(dateChange)="onDateChange($event)" />
<mat-datepicker #offsetPicker></mat-datepicker>
</mat-form-field>
<button mat-icon-button type="button" title="Open calendar" (click)="offsetPicker.open()">
<mat-icon svgIcon="calendar"></mat-icon>
</button>
<button
class="next-button"
type="button"
mat-stroked-button
(click)="onNextClick()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,14 @@ app-time-navigation {
margin-left: 8px;
}
}

.offset-picker {
visibility: hidden;
overflow: hidden;
width: 0;
height: 2rem;
}

.next-button {
margin-left: 0 !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ import { MatIconRegistry } from '@angular/material/icon';
import { MaterialModule } from 'src/app/material';
import { FakeMatIconRegistry } from 'src/test/material-fakes';
import { TimeNavigationComponent } from './time-navigation.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatDatepickerModule } from '@angular/material/datepicker';

describe('TimeNavigationComponent', () => {
let component: TimeNavigationComponent;
let fixture: ComponentFixture<TimeNavigationComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MaterialModule],
imports: [MaterialModule, NoopAnimationsModule, MatDatepickerModule],
declarations: [TimeNavigationComponent],
})
.overrideProvider(MatIconRegistry, { useFactory: () => new FakeMatIconRegistry() })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ import {
Inject,
Input,
LOCALE_ID,
OnChanges,
Output,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
import { Range } from 'src/app/shared/models';

@Component({
Expand All @@ -27,17 +30,52 @@ import { Range } from 'src/app/shared/models';
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class TimeNavigationComponent {
export class TimeNavigationComponent implements OnChanges {
@Input() range: Range;
@Input() rangeOffset: number;
@Input() nowRangeOffset: number;
@Input() previousRangeOffset: number;
@Input() nextRangeOffset: number;
@Input() timezoneOffset = 0;
@Input() globalDuration: [Long, Long];
@Output() rangeOffsetChange = new EventEmitter<number>();

currentOffsetDate: Date;
globalStart: Date;
globalEnd: Date;
previousRangeOffset: number;
nextRangeOffset: number;

constructor(@Inject(LOCALE_ID) private locale: string) {}

ngOnChanges(changes: SimpleChanges): void {
if (changes.globalDuration) {
this.globalStart = this.getGlobalStart();
this.globalEnd = this.getGlobalEnd();
}

if (changes.rangeOffset || changes.timezoneOffset) {
this.currentOffsetDate = new Date((this.rangeOffset + this.timezoneOffset) * 1000);
this.currentOffsetDate.setTime(
this.currentOffsetDate.getTime() + this.currentOffsetDate.getTimezoneOffset() * 60 * 1000
);

const previousDate = new Date(this.currentOffsetDate);
previousDate.setDate(previousDate.getDate() - 1);
this.previousRangeOffset =
this.globalStart.getTime() <= previousDate.getTime() ? previousDate.getTime() / 1000 : null;

const nextDate = new Date(this.currentOffsetDate);
nextDate.setDate(nextDate.getDate() + 1);
this.nextRangeOffset = nextDate.getTime() / 1000;
this.nextRangeOffset =
this.globalEnd.getTime() >= nextDate.getTime() ? nextDate.getTime() / 1000 : null;
}
}

onDateChange(event: MatDatepickerInputEvent<Date>): void {
const utcSeconds = (event.value.getTime() + event.value.getTimezoneOffset() * 60 * 1000) / 1000;
this.rangeOffsetChange.emit(utcSeconds + this.timezoneOffset);
}

onNextClick(): void {
this.rangeOffsetChange.emit(this.nextRangeOffset);
}
Expand All @@ -50,6 +88,18 @@ export class TimeNavigationComponent {
this.rangeOffsetChange.emit(this.nowRangeOffset);
}

getGlobalStart(): Date {
const date = new Date((this.globalDuration[0].toNumber() + this.timezoneOffset) * 1000);
date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
return date;
}

getGlobalEnd(): Date {
const date = new Date((this.globalDuration[1].toNumber() + this.timezoneOffset) * 1000);
date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
return date;
}

getFormattedRangeOffset(): string {
return Number.isFinite(this.rangeOffset)
? formatDate((this.rangeOffset + this.timezoneOffset) * 1000, 'longDate', this.locale, 'UTC')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class AppComponent {
'arrow_downward',
'arrow_drop_down',
'arrow_upward',
'calendar',
'clear',
'clock',
'cloud_download',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
[range]="range$ | async"
[rangeOffset]="rangeOffset$ | async"
[nowRangeOffset]="nowRangeOffset$ | async"
[previousRangeOffset]="previousRangeOffset$ | async"
[nextRangeOffset]="nextRangeOffset$ | async"
[timezoneOffset]="timezoneOffset$ | async"
[globalDuration]="globalDuration$ | async"
(rangeOffsetChange)="onRangeOffsetChange($event)">
</app-time-navigation>
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import * as fromConfig from '../../selectors/config.selectors';
import * as fromScenario from '../../selectors/scenario.selectors';
import * as fromUndoRedo from '../../selectors/undo-redo.selectors';
import { PostSolveControlBarComponent } from './post-solve-control-bar.component';
import ShipmentModelSelectors from '../../selectors/shipment-model.selectors';
import Long from 'long';

@Component({
selector: 'app-generate-button',
Expand All @@ -44,11 +46,10 @@ class MockMapToggleButtonComponent {
})
class MockTimeNavigationComponent {
@Input() range: Range;
@Input() rangeOffset: number;
@Input() nowRangeOffset: number;
@Input() previousRangeOffset: number;
@Input() nextRangeOffset: number;
@Input() timezoneOffset: number;
@Input() globalDuration: [Long, Long];
@Output() rangeOffsetChange = new EventEmitter<number>();
}

Expand All @@ -73,8 +74,10 @@ describe('PostSolveControlBarComponent', () => {
{ selector: RoutesChartSelectors.selectSelectedRange, value: [] },
{ selector: RoutesChartSelectors.selectRangeOffset, value: 0 },
{ selector: RoutesChartSelectors.selectNowRangeOffset, value: 0 },
{ selector: RoutesChartSelectors.selectPreviousRangeOffset, value: 0 },
{ selector: RoutesChartSelectors.selectNextRangeOffset, value: 0 },
{
selector: ShipmentModelSelectors.selectGlobalDuration,
value: [Long.ZERO, Long.ZERO],
},
{ selector: fromConfig.selectTimezoneOffset, value: 0 },
{ selector: fromUndoRedo.selectCanUndo, value: false },
{ selector: fromUndoRedo.selectCanRedo, value: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Page } from '../../models';
import * as fromConfig from '../../selectors/config.selectors';
import * as fromScenario from '../../selectors/scenario.selectors';
import * as fromUndoRedo from '../../selectors/undo-redo.selectors';
import ShipmentModelSelectors from '../../selectors/shipment-model.selectors';

@Component({
selector: 'app-post-solve-control-bar',
Expand All @@ -35,11 +36,10 @@ export class PostSolveControlBarComponent implements OnInit {
range$: Observable<Range>;
rangeOffset$: Observable<number>;
nowRangeOffset$: Observable<number>;
previousRangeOffset$: Observable<number>;
nextRangeOffset$: Observable<number>;
timezoneOffset$: Observable<number>;
canUndo$: Observable<boolean>;
canRedo$: Observable<boolean>;
globalDuration$: Observable<[Long, Long]>;

get Page(): typeof Page {
return Page;
Expand All @@ -56,13 +56,10 @@ export class PostSolveControlBarComponent implements OnInit {
this.range$ = this.store.pipe(select(RoutesChartSelectors.selectSelectedRange));
this.rangeOffset$ = this.store.pipe(select(RoutesChartSelectors.selectRangeOffset));
this.nowRangeOffset$ = this.store.pipe(select(RoutesChartSelectors.selectNowRangeOffset));
this.previousRangeOffset$ = this.store.pipe(
select(RoutesChartSelectors.selectPreviousRangeOffset)
);
this.nextRangeOffset$ = this.store.pipe(select(RoutesChartSelectors.selectNextRangeOffset));
this.timezoneOffset$ = this.store.pipe(select(fromConfig.selectTimezoneOffset));
this.canUndo$ = this.store.pipe(select(fromUndoRedo.selectCanUndo));
this.canRedo$ = this.store.pipe(select(fromUndoRedo.selectCanRedo));
this.globalDuration$ = this.store.pipe(select(ShipmentModelSelectors.selectGlobalDuration));
}

onRangeOffsetChange(rangeOffset: number): void {
Expand Down
4 changes: 4 additions & 0 deletions application/frontend/src/assets/images/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7250135

Please sign in to comment.