Skip to content

Commit

Permalink
Re-implement mouse hover map highlights in post-solve view
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccollum-woolpert committed Jul 25, 2024
1 parent c125c7e commit a012759
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ export const mouseEnterVisitRequest = createAction(

export const mouseExitVisitRequest = createAction('[RoutesChart] Mouse Exit Visit Request');

export const mouseEnterVisits = createAction(
'[RoutesChart] Mouse Enter Visits',
props<{ ids: number[] }>()
);

export const mouseExitVisits = createAction('[RoutesChart] Mouse Exit Visits');

export const resetView = createAction('[RoutesChart] Reset View');

export const setView = createAction(
Expand Down
12 changes: 12 additions & 0 deletions application/frontend/src/app/core/reducers/routes-chart.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface State {
filters: ActiveFilter[];
selectedRoutes: number[];
selectedRoutesColors: [id: number, colorIdx: number][];
hoveredVisits: number[];
}

export const initialState: State = {
Expand All @@ -50,6 +51,7 @@ export const initialState: State = {
filters: [],
selectedRoutes: [],
selectedRoutesColors: [],
hoveredVisits: [],
};

export const reducer = createReducer(
Expand Down Expand Up @@ -152,6 +154,14 @@ export const reducer = createReducer(
addedRange: 0,
rangeIndex: chartConfig.day.defaultRangeIndex,
rangeOffset: props.rangeOffset,
})),
on(RoutesChartActions.mouseEnterVisits, (state, props) => ({
...state,
hoveredVisits: props.ids,
})),
on(RoutesChartActions.mouseExitVisits, (state) => ({
...state,
hoveredVisits: [],
}))
);

Expand All @@ -173,3 +183,5 @@ export const selectRangeOffset = (state: State): number => state.rangeOffset;
export const selectFilters = (state: State): ActiveFilter[] => state.filters;

export const selectAddedRange = (state: State): number => state.addedRange;

export const selectHoveredVisitIds = (state: State): number[] => state.hoveredVisits;
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import * as fromVisit from './visit.selectors';
import PreSolveShipmentSelectors from './pre-solve-shipment.selectors';
import { fromDispatcherToTurfPoint } from 'src/app/util';
import { Feature, Point } from '@turf/helpers';
import { selectMouseOverId } from './ui.selectors';
import RoutesMetadataSelectors from './routes-metadata.selectors';
import * as fromUI from './ui.selectors';
import ShipmentRouteSelectors from './shipment-route.selectors';
Expand Down Expand Up @@ -166,15 +165,15 @@ export const selectFilteredVisitRequestsTurfPoints = createSelector(
}
);

export const selectMouseOverVisitRequest = createSelector(
export const selectMouseOverVisitRequests = createSelector(
selectFilteredRouteVisitRequests,
RoutesChartSelectors.selectSelectedRoutesVisitIds,
fromVisit.selectEntities,
RoutesChartSelectors.selectSelectedRoutesColors,
selectMouseOverId,
(filtered, selected, visits, colors, mouseOverId) => {
RoutesChartSelectors.selectHoveredVisitIds,
(filtered, selected, visits, colors, visitIds) => {
return filtered
.filter((visitRequest) => visitRequest.id === mouseOverId)
.filter((visitRequest) => visitIds.includes(visitRequest.id))
.map((visitRequest) => {
const made = !!visits[visitRequest.id];
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ export const selectFilteredRoutesSelected = createSelector(
vehicles,
mapLayers
) => {
const lookup =
page === Page.RoutesChart ? chartSelectedRoutesLookup : tableSelectedRouteLookup;
const lookup = page === Page.RoutesChart ? chartSelectedRoutesLookup : tableSelectedRouteLookup;
const lookupSet = new Set(Object.keys(lookup).map(Number));
const selectedRoutes = paths.filter(
(p) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('RoutesChart Selectors', () => {
addedRange: 1000,
selectedRoutes: [6],
selectedRoutesColors,
hoveredVisits: [],
},
});

Expand All @@ -46,6 +47,7 @@ describe('RoutesChart Selectors', () => {
addedRange: 1000,
selectedRoutes: [6],
selectedRoutesColors,
hoveredVisits: [],
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ const selectViewHasChanged = createSelector(
routes.length !== selectedRoutes.length
);

const selectHoveredVisitIds = createSelector(
selectRoutesChartState,
fromRoutesChart.selectHoveredVisitIds
);

export const RoutesChartSelectors = {
selectView,
selectRangeIndex,
Expand Down Expand Up @@ -413,6 +418,7 @@ export const RoutesChartSelectors = {
selectNextRangeOffset,
selectDuration,
selectViewHasChanged,
selectHoveredVisitIds,
};

export default RoutesChartSelectors;
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { State } from 'src/app/reducers';
import {
selectFilteredVisitRequests,
selectFilteredVisitRequestsSelected,
selectMouseOverVisitRequest,
selectMouseOverVisitRequests,
} from '../selectors/post-solve-visit-request-layer.selectors';
import { BaseVisitRequestLayer } from './base-visit-request-layer.service';
import { MapService } from './map.service';
Expand All @@ -39,7 +39,7 @@ export class PostSolveVisitRequestLayer extends BaseVisitRequestLayer {
this.onDataSelected(visitRequests);
});

this.store.pipe(select(selectMouseOverVisitRequest)).subscribe((visitRequests) => {
this.store.pipe(select(selectMouseOverVisitRequests)).subscribe((visitRequests) => {
this.onDataMouseOver(visitRequests);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
[pendingNewPois]="pendingNewPois"
[pendingOldVisitIds]="pendingOldVisitIds"
[color]="color"
(clickVisitIds)="clickVisitIds.emit($event)">
(clickVisitIds)="clickVisitIds.emit($event)"
(mouseEnterVisits)="mouseEnterVisits.emit($event)"
(mouseExitVisits)="mouseExitVisits.emit()">
</app-points-of-interest>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export class BaseRoutesRowComponent implements OnInit {
@Output() editVehicle = new EventEmitter<number>();
@Output() viewMetadata = new EventEmitter<number>();
@Output() clickVisitIds = new EventEmitter<number[]>();
@Output() mouseEnterVisits = new EventEmitter<number[]>();
@Output() mouseExitVisits = new EventEmitter();
@HostBinding('class') className = 'item item-container';
allowExperimentalFeatures: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
[color]="color$ | async"
(editVehicle)="onEditVehicle($event)"
(viewMetadata)="onViewMetadata($event)"
(clickVisitIds)="onClickVisitIds($event)">
(clickVisitIds)="onClickVisitIds($event)"
(mouseEnterVisits)="onMouseEnterVisitIds($event)"
(mouseExitVisits)="onMouseExitVisits()">
</app-base-routes-row>
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class MockBaseRoutesRowComponent {
@Input() route: ShipmentRoute;
@Input() vehicle: Vehicle;
@Input() shipmentCount: number;
@Input() selected = false;
@Input() timeline: Timeline;
@Input() duration: [Long, Long];
@Input() availability: [Long, Long];
Expand All @@ -64,9 +63,11 @@ class MockBaseRoutesRowComponent {
@Input() changedVisits: ChangedVisits;
@Input() color = '#1a73e8';
@Output() selectedChange = new EventEmitter<boolean>();
@Output() pointOfInterestClick = new EventEmitter<PointOfInterestClick>();
@Output() editVehicle = new EventEmitter<number>();
@Output() viewMetadata = new EventEmitter<number>();
@Output() clickVisitIds = new EventEmitter<number[]>();
@Output() mouseEnterVisits = new EventEmitter<number[]>();
@Output() mouseExitVisits = new EventEmitter();
}

describe('RoutesRowComponent', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ export class RoutesRowComponent implements OnChanges, OnInit, OnDestroy {
this.router.navigateByUrl('/' + Page.RoutesMetadata, { skipLocationChange: true });
}

onMouseEnterVisitIds(ids: number[]): void {
this.store.dispatch(RoutesChartActions.mouseEnterVisits({ ids }));
}

onMouseExitVisits(): void {
this.store.dispatch(RoutesChartActions.mouseExitVisits());
}

onClickVisitIds(ids: number[]): void {
this.store.dispatch(
RoutesChartActions.setFilters({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
[attr.width]="attr.width"
[attr.height]="attr.height"
(mousedown)="onMouseDown($event, p)"
(mouseover)="onMouseOver(p)"
(mouseleave)="mouseExitVisits.emit()"
[ngClass]="{
'poi-validation-error': changedVisits[p[0]],
'pending-poi-old': isPendingOldPoi(p)
Expand Down Expand Up @@ -49,6 +51,8 @@
[attr.width]="attr.width"
[attr.height]="attr.height"
(mousedown)="onMouseDown($event, p)"
(mouseover)="onMouseOver(p)"
(mouseleave)="mouseExitVisits.emit()"
[ngClass]="{
'poi-validation-error': changedVisits[p[0]],
'pending-poi-old': isPendingOldPoi(p)
Expand Down Expand Up @@ -98,6 +102,8 @@
[attr.height]="attr.height"
title="{{ attr.title + ' ' + p[3] + ' (pending)' }}"
(mousedown)="onMouseDown($event, p)"
(mouseover)="onMouseOver(p)"
(mouseleave)="mouseExitVisits.emit()"
[ngClass]="{
'poi-validation-error': changedVisits[p[0]],
'pending-poi-old': isPendingOldPoi(p)
Expand All @@ -112,6 +118,8 @@
[attr.height]="attr.height"
title="{{ attr.title + ' ' + p[3] + ' (pending)' }}"
(mousedown)="onMouseDown($event, p)"
(mouseover)="onMouseOver(p)"
(mouseleave)="mouseExitVisits.emit()"
[ngClass]="{
'poi-validation-error': changedVisits[p[0]],
'pending-poi-old': isPendingOldPoi(p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export class PointsOfInterestComponent implements OnChanges {
@Input() changedVisits: ChangedVisits;
@Input() color: string;
@Output() clickVisitIds = new EventEmitter<number[]>();
@Output() mouseEnterVisits = new EventEmitter<number[]>();
@Output() mouseExitVisits = new EventEmitter();

get imageAttributeLookup(): { [key: string]: PointsOfInterestImageAttribute } {
return PointsOfInterestComponent.imageAttributeLookup;
Expand Down Expand Up @@ -110,6 +112,22 @@ export class PointsOfInterestComponent implements OnChanges {
}
}

onMouseOver(point: PoiPoint): void {
const visitIds = [point[0]];
const cluster = this.clusters.find(
(cluster) => cluster.start <= point[2] && cluster.end >= point[2]
);
if (cluster) {
this.points.forEach((p) => {
if (cluster.start <= p[2] && cluster.end >= p[2]) {
visitIds.push(p[0]);
}
});
}

this.mouseEnterVisits.emit(visitIds);
}

onMouseDown(event: MouseEvent, point: PoiPoint): void {
if (event.button !== 0) {
// Not the primary button
Expand Down

0 comments on commit a012759

Please sign in to comment.