Skip to content

Commit

Permalink
DBC22-1265: commented unused tooltips
Browse files Browse the repository at this point in the history
DBC22-1265: disable road conditions in events list page

DBC22-904: refactoring, events filters now use context

DBC22-1429: fixed zoom button references

DBC22-1266: updated map icons

DBC22-1266: fixed click and hover handlers

DBC22-1266: layers panel styling fix

DBC22-1266: layer toggling and zindex fixes

DBC22-1266: reworked event layers

DBC22-1265: replaced event_type with display_category for display logic
  • Loading branch information
ray-oxd authored and fatbird committed Dec 21, 2023
1 parent 00957f6 commit b6d3e5c
Show file tree
Hide file tree
Showing 14 changed files with 448 additions and 350 deletions.
28 changes: 28 additions & 0 deletions src/backend/apps/event/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ class EVENT_TYPE:
INCIDENT = "INCIDENT"
SPECIAL_EVENT = "SPECIAL_EVENT"
WEATHER_CONDITION = "WEATHER_CONDITION"
ROAD_CONDITION = "ROAD_CONDITION"


EVENT_TYPE_CHOICES = (
(EVENT_TYPE.CONSTRUCTION, "Construction"),
(EVENT_TYPE.INCIDENT, "Incident"),
(EVENT_TYPE.SPECIAL_EVENT, "Special event"),
(EVENT_TYPE.WEATHER_CONDITION, "Weather condition"),
(EVENT_TYPE.ROAD_CONDITION, "Road condition"),
)


Expand All @@ -20,6 +22,10 @@ class EVENT_SUB_TYPE:
ROAD_CONSTRUCTION = "ROAD_CONSTRUCTION"
ROAD_MAINTENANCE = "ROAD_MAINTENANCE"
PARTLY_ICY = "PARTLY_ICY"
ICE_COVERED = "ICE_COVERED"
SNOW_PACKED = "SNOW_PACKED"
PARTLY_SNOW_PACKED = "PARTLY_SNOW_PACKED"
MUD = "MUD"
PLANNED_EVENT = "PLANNED_EVENT"
POOR_VISIBILITY = "POOR_VISIBILITY"

Expand All @@ -31,6 +37,10 @@ class EVENT_SUB_TYPE:
(EVENT_SUB_TYPE.ROAD_CONSTRUCTION, "Road construction"),
(EVENT_SUB_TYPE.ROAD_MAINTENANCE, "Road maintenance"),
(EVENT_SUB_TYPE.PARTLY_ICY, "Partly Icy"),
(EVENT_SUB_TYPE.ICE_COVERED, "Ice Covered"),
(EVENT_SUB_TYPE.SNOW_PACKED, "Snow Packed"),
(EVENT_SUB_TYPE.PARTLY_SNOW_PACKED, "Partly Snow Packed"),
(EVENT_SUB_TYPE.MUD, "Mud"),
(EVENT_SUB_TYPE.PLANNED_EVENT, "Planned event"),
(EVENT_SUB_TYPE.POOR_VISIBILITY, "Poor visibility"),
)
Expand Down Expand Up @@ -86,3 +96,21 @@ class EVENT_DIRECTION:
EVENT_DIFF_FIELDS = [
'last_updated'
]


class EVENT_DISPLAY_CATEGORY:
MAJOR_DELAYS = 'majorEvents'
MINOR_DELAYS = 'minorEvents'
FUTURE_DELAYS = 'futureEvents'
ROAD_CONDITION = 'roadConditions'
HIGHWAY_CAMERAS = 'highwayCams'


EVENT_DISPLAY_CATEGORY_MAP = {
# Only road conditions are directly mapped currently
EVENT_SUB_TYPE.POOR_VISIBILITY: EVENT_DISPLAY_CATEGORY.ROAD_CONDITION,
EVENT_SUB_TYPE.PARTLY_ICY: EVENT_DISPLAY_CATEGORY.ROAD_CONDITION,
EVENT_SUB_TYPE.ICE_COVERED: EVENT_DISPLAY_CATEGORY.ROAD_CONDITION,
EVENT_SUB_TYPE.SNOW_PACKED: EVENT_DISPLAY_CATEGORY.ROAD_CONDITION,
EVENT_SUB_TYPE.PARTLY_SNOW_PACKED: EVENT_DISPLAY_CATEGORY.ROAD_CONDITION,
}
22 changes: 21 additions & 1 deletion src/backend/apps/event/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
from apps.event.enums import EVENT_DIRECTION_DISPLAY
import datetime

import pytz
from apps.event.enums import (
EVENT_DIRECTION_DISPLAY,
EVENT_DISPLAY_CATEGORY,
EVENT_DISPLAY_CATEGORY_MAP,
EVENT_SEVERITY,
)
from apps.event.models import Event
from rest_framework import serializers

Expand All @@ -11,6 +19,7 @@ class ScheduleSerializer(serializers.Serializer):


class EventSerializer(serializers.ModelSerializer):
display_category = serializers.SerializerMethodField()
direction_display = serializers.SerializerMethodField()
route_display = serializers.SerializerMethodField()
schedule = ScheduleSerializer()
Expand Down Expand Up @@ -41,3 +50,14 @@ def get_route_display(self, obj):
res += " to " + obj.route_to

return res

def get_display_category(self, obj):
if obj.event_sub_type in EVENT_DISPLAY_CATEGORY_MAP:
return EVENT_DISPLAY_CATEGORY_MAP[obj.event_sub_type]

if obj.start and datetime.datetime.now(pytz.utc) < obj.start:
return EVENT_DISPLAY_CATEGORY.FUTURE_DELAYS

return EVENT_DISPLAY_CATEGORY.MAJOR_DELAYS \
if obj.severity == EVENT_SEVERITY.MAJOR \
else EVENT_DISPLAY_CATEGORY.MINOR_DELAYS
3 changes: 2 additions & 1 deletion src/frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module.exports = {
'FunctionExpression': false,
},
}],
"react/prop-types": "off"
"react/prop-types": "off",
'camelcase': 'off',
},
};
8 changes: 6 additions & 2 deletions src/frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ function App() {
? JSON.parse(context)
: {
visible_layers: {
eventsLayer: true,
webcamsLayer: true,
majorEvents: true,
minorEvents: true,
futureEvents: true,
roadConditions: true,
highwayCams: true,
inlandFerries: true,
},
};
}
Expand Down
25 changes: 13 additions & 12 deletions src/frontend/src/Components/EventTypeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ import React from 'react';
// Third Party packages
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faTriangleExclamation,
faExclamationTriangle,
faExclamationCircle,
faPersonDigging,
faCalendarDays,
faSnowflake,
} from "@fortawesome/free-solid-svg-icons";

export default function EventTypeIcon({eventType}) {
switch(eventType) {
case "incident":
return <FontAwesomeIcon icon={faTriangleExclamation} alt="incident" />;
case "construction":
return <FontAwesomeIcon icon={faPersonDigging} alt="construction" />;
case "special_event":
return <FontAwesomeIcon icon={faCalendarDays} alt="special event" />;
case "weather_condition":
return <FontAwesomeIcon icon={faSnowflake} alt="weather condition" />;
export default function EventTypeIcon({ displayCategory }) {
switch (displayCategory) {
case "majorEvents":
return <FontAwesomeIcon icon={faExclamationTriangle} alt="major delays" />;
case "minorEvents":
return <FontAwesomeIcon icon={faExclamationCircle} alt="minor delays" />;
case "futureEvents":
return <FontAwesomeIcon icon={faCalendarDays} alt="future delays" />;
case "roadConditions":
return <FontAwesomeIcon icon={faSnowflake} alt="road conditions" />;
default:
return <FontAwesomeIcon icon={faTriangleExclamation} alt="incident" />;
return <FontAwesomeIcon icon={faPersonDigging} alt="minor delays" />;
}
}
102 changes: 59 additions & 43 deletions src/frontend/src/Components/Layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {
faVideo,
faSnowflake,
faFerry,
faRestroom,
faCloudSun } from '@fortawesome/free-solid-svg-icons';
// faRestroom,
// faCloudSun
} from '@fortawesome/free-solid-svg-icons';
import Button from 'react-bootstrap/Button';
import Tooltip from 'react-bootstrap/Tooltip';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
Expand All @@ -26,7 +27,7 @@ import './Layers.scss';

export default function Layers({ open, setLayersOpen, toggleLayer }) {
const { mapContext } = useContext(MapContext);

const tooltipMajor = (
<Tooltip id="tooltip" className="tooltip-content">
<p>Indicates a significant delay of more than 20 minutes to travel in at least one direction on this road. A Major Delay may be a traffic incident or a road event (such as road work, construction, or restoration).</p>
Expand Down Expand Up @@ -63,36 +64,25 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
</Tooltip>
);

const tooltipReststops = (
<Tooltip id="tooltip" className="tooltip-content">
<p>Shows the location of Provincial Rest Stops on highways throughout the province.</p>
</Tooltip>
);
// const tooltipReststops = (
// <Tooltip id="tooltip" className="tooltip-content">
// <p>Shows the location of Provincial Rest Stops on highways throughout the province.</p>
// </Tooltip>
// );

const tooltipWeather = (
<Tooltip id="tooltip" className="tooltip-content">
<p>Regional current and forecasted weather from Environment Canada for this area.</p>
</Tooltip>
);


// States for events
const [filterChecked, setFilterChecked] = useState(false);
const toggleChecked = () => {
setFilterChecked(!filterChecked);
};
// const tooltipWeather = (
// <Tooltip id="tooltip" className="tooltip-content">
// <p>Regional current and forecasted weather from Environment Canada for this area.</p>
// </Tooltip>
// );

// States for cameras
const [filterCheckedCams, setFilterCheckedCams] = useState(false);
const toggleCheckedCams = () => {
setFilterCheckedCams(!filterCheckedCams);
};

// States for ferries
const [filterCheckedFerries, setFilterCheckedFerries] = useState(false);
const toggleCheckedFerries = () => {
setFilterCheckedFerries(!filterCheckedFerries);
};
// States for toggles
const [majorEvents, setMajorEvents] = useState(mapContext.visible_layers.majorEvents);
const [minorEvents, setMinorEvents] = useState(mapContext.visible_layers.minorEvents);
const [futureEvents, setFutureEvents] = useState(mapContext.visible_layers.futureEvents);
const [roadConditions, setRoadConditions] = useState(mapContext.visible_layers.roadConditions);
const [highwayCams, setHighwayCams] = useState(mapContext.visible_layers.highwayCams);
const [inlandFerries, setInlandFerries] = useState(mapContext.visible_layers.inlandFerries);

const largeScreen = useMediaQuery('only screen and (min-width : 768px)');

Expand All @@ -108,8 +98,8 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
<FontAwesomeIcon icon={faFilter} />
Filters
</Button>
{ open &&

{ open &&
<div className="layers">
{ !largeScreen &&
<div>
Expand All @@ -128,7 +118,7 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
<p className="filter-group__title">Delays</p>
<div className="filter-items-group">
<div className="filter-items filter-items--delays">
<div className={'filter-item filter-item--major'}>
<div className={'filter-item filter-item--major' + (majorEvents ? ' checked' : '')}>
<div className="filter-item__icon">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path className="customIcon-bg" d="M7.87872 1.12135C9.05029 -0.0502183 10.9498 -0.0502166 12.1214 1.12136L18.8787 7.87868C20.0503 9.05026 20.0503 10.9498 18.8787 12.1213L12.1213 18.8787C10.9497 20.0503 9.05026 20.0503 7.87868 18.8787L1.12136 12.1214C-0.0502174 10.9498 -0.0502174 9.05029 1.12136 7.87872L7.87872 1.12135Z" fill="#1A5A96"/>
Expand All @@ -139,14 +129,20 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
type="checkbox"
name="major"
id="filter--major"
onChange={e => {
toggleLayer('majorEvents', e.target.checked);
toggleLayer('majorEventsLines', e.target.checked);
setMajorEvents(!majorEvents)
}}
defaultChecked={mapContext.visible_layers.majorEvents}
/>
<label htmlFor="filter--major">Major</label>
<OverlayTrigger placement="top" overlay={tooltipMajor}>
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

<div className={'filter-item filter-item--minor'}>
<div className={'filter-item filter-item--minor' + (minorEvents ? ' checked' : '')}>
<div className="filter-item__icon">
<svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path className="customIcon-bg" d="M11.2552 15.2763C10.3487 16.9079 7.65127 16.9079 6.74483 15.2763L0.247828 3.5816C-0.54594 2.1528 0.663609 0.5 2.50299 0.5L15.497 0.500001C17.3364 0.500001 18.5459 2.1528 17.7522 3.5816L11.2552 15.2763Z" fill="#1A5A96"/>
Expand All @@ -157,22 +153,33 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
type="checkbox"
name="minor"
id="filter--minor"
onChange={e => {
toggleLayer('minorEvents', e.target.checked);
toggleLayer('minorEventsLines', e.target.checked);
setMinorEvents(!minorEvents);
}}
defaultChecked={mapContext.visible_layers.minorEvents}
/>
<label htmlFor="filter--minor">Minor</label>
<OverlayTrigger placement="top" overlay={tooltipMinor}>
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

<div className={'filter-item filter-item--future-events' + (filterChecked ? ' checked' : '')}>
<div className={'filter-item filter-item--future-events' + (futureEvents ? ' checked' : '')}>
<div className="filter-item__icon">
<FontAwesomeIcon icon={faCalendarDays} alt="future events" />
</div>
<input
type="checkbox"
name="future events"
id="filter--future-events"
onChange={e => {toggleLayer('eventsLayer', e.target.checked); toggleChecked()}}
onChange={e => {
toggleLayer('futureEvents', e.target.checked);
toggleLayer('futureEventsLines', e.target.checked);
setFutureEvents(!futureEvents);
}}
defaultChecked={mapContext.visible_layers.futureEvents}
/>
<label htmlFor="filter--future-events">Future Events</label>
<OverlayTrigger placement="top" overlay={tooltipFutureevents}>
Expand All @@ -187,54 +194,62 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
<p className="filter-group__title">Conditions and features</p>
<div className="filter-items-group">
<div className="filter-items filter-items--conditions">
<div className={'filter-item filter-item--highway-cameras' + (filterCheckedCams ? ' checked' : '')}>
<div className={'filter-item filter-item--highway-cameras' + (highwayCams ? ' checked' : '')}>
<div className="filter-item__icon">
<FontAwesomeIcon icon={faVideo} alt="highway cameras" />
</div>
<input
type="checkbox"
name="highway cameras"
id="filter--highway-cameras"
onChange={e => {toggleLayer('webcamsLayer', e.target.checked); toggleCheckedCams()}}
defaultChecked={mapContext.visible_layers.webcamsLayer}
onChange={e => {toggleLayer('highwayCams', e.target.checked); setHighwayCams(!highwayCams)}}
defaultChecked={mapContext.visible_layers.highwayCams}
/>
<label htmlFor="filter--highway-cameras">Highway cameras</label>
<OverlayTrigger placement="top" overlay={tooltipHighwaycameras}>
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

<div className={'filter-item filter-item--road-conditions'}>
<div className={'filter-item filter-item--road-conditions' + (roadConditions ? ' checked' : '')}>
<div className="filter-item__icon">
<FontAwesomeIcon icon={faSnowflake} alt="road conditions" />
</div>
<input
type="checkbox"
name="road conditions"
id="filter--road-conditions"
onChange={e => {
toggleLayer('roadConditions', e.target.checked);
toggleLayer('roadConditionsLines', e.target.checked);
setRoadConditions(!roadConditions);
}}
defaultChecked={mapContext.visible_layers.roadConditions}
/>
<label htmlFor="filter--road-conditions">Road conditions</label>
<OverlayTrigger placement="top" overlay={tooltipRoadconditions}>
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

<div className={'filter-item filter-item--inland-ferries' + (filterCheckedFerries ? ' checked' : '')}>
<div className={'filter-item filter-item--inland-ferries' + (inlandFerries ? ' checked' : '')}>
<div className="filter-item__icon">
<FontAwesomeIcon icon={faFerry} alt="inland ferries" />
</div>
<input
type="checkbox"
name="inland ferries"
id="filter--inland-ferries"
onChange={e => {toggleLayer('ferriesLayer', e.target.checked); toggleCheckedFerries()}}
onChange={e => {toggleLayer('inlandFerries', e.target.checked); setInlandFerries(!inlandFerries)}}
defaultChecked={mapContext.visible_layers.inlandFerries}
/>
<label htmlFor="filter--inland-ferries">Inland ferries</label>
<OverlayTrigger placement="top" overlay={tooltipInlandferries}>
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

{/*
<div className={'filter-item filter-item--rest-stops'}>
<div className="filter-item__icon">
<FontAwesomeIcon icon={faRestroom} alt="provincial rest stops" />
Expand Down Expand Up @@ -264,6 +279,7 @@ export default function Layers({ open, setLayersOpen, toggleLayer }) {
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>
*/}
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit b6d3e5c

Please sign in to comment.