Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map tooltip bus #114

Merged
merged 30 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f07cf35
fix in menu.scss for
Oct 5, 2023
277c88a
fix in menu.scss for
Oct 6, 2023
661ab12
fix in menu.scss for
Oct 6, 2023
8135950
Merge branch 'main' into fix-menu-mobile
giladfuchs Oct 7, 2023
88062d5
change rem to px
Oct 7, 2023
c6a9667
Merge remote-tracking branch 'origin/fix-menu-mobile' into fix-menu-m…
Oct 7, 2023
d856647
begin to design card
Oct 10, 2023
b7a347c
tool tip begin to get body
Oct 11, 2023
55c8204
add api add hebrew text in file
Oct 11, 2023
a402f86
after merge from main and resolve conflict
Oct 11, 2023
c095fa2
add bus tool tip for SingleLineMapPage and find bug there
Oct 11, 2023
8bc43b0
add bus tool tip for SingleLineMapPage and find bug there
Oct 11, 2023
8f5e2c9
Merge remote-tracking branch 'origin/map-tooltip-bus' into map-toolti…
Oct 11, 2023
d577f49
Merge branch 'hasadna:main' into main
giladfuchs Oct 11, 2023
ddd3633
fix: single line map page
NoamGaash Oct 11, 2023
622ea0b
fix: route times
NoamGaash Oct 12, 2023
6200576
change after comment
Oct 12, 2023
88d6902
Merge branch 'fix/single-line-map-page' into map-tooltip-bus
Oct 15, 2023
89af229
change from mui element like Card and Typography to div and h4/span.
Oct 15, 2023
482c3b8
change from mui element like Card and Typography to div and h4/span.
Oct 15, 2023
3e5e473
Merge remote-tracking branch 'origin/main'
Oct 15, 2023
681d5a3
change from mui element like Card and Typography to div and h4/span.
Oct 15, 2023
ae963df
change from mui element like Card and Typography to div and h4/span.
Oct 15, 2023
6532aaf
Merge remote-tracking branch 'origin/map-tooltip-bus' into map-toolti…
Oct 15, 2023
cccfe1a
Merge branch 'main' into map-tooltip-bus
NoamGaash Oct 15, 2023
ef620c6
add scss file and remove all using of sx
Oct 15, 2023
a15392c
Merge remote-tracking branch 'origin/map-tooltip-bus' into map-toolti…
Oct 15, 2023
d50eb28
style: clean html & css
NoamGaash Oct 16, 2023
79a9e07
fix for linter
Oct 16, 2023
f033397
Merge branch 'main' into map-tooltip-bus
giladfuchs Oct 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
flex-direction: row;
font-family: Heebo;

.header {
> .header {
height: 100vh;
background-color: white;
padding: 30px;
Expand Down
16 changes: 16 additions & 0 deletions src/api/siriService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { geoLocationBoundary, nearestLocation } from 'src/api/geoService'
import { Coordinates } from 'src/model/location'
import { log } from 'src/log'
import { BusRoute } from 'src/model/busRoute'
import { SiriRideWithRelatedPydanticModel } from 'open-bus-stride-client/openapi/models/SiriRideWithRelatedPydanticModel'

const SIRI_API = new SiriApi(API_CONFIG)
const LOCATION_DELTA_METERS = 500
Expand All @@ -26,6 +27,21 @@ async function getRidesAsync(route: BusRoute, stop: BusStop, timestamp: moment.M
})
}

export async function getSiriRideWithRelated(
siriRouteId: string,
vehicleRefs: string,
siriRouteLineRefs: string,
) {
const gtfs_route_promise: SiriRideWithRelatedPydanticModel[] = await SIRI_API.siriRidesListGet({
limit: 1,
siriRouteIds: siriRouteId.toString(),
siriRouteLineRefs,
vehicleRefs,
})

return gtfs_route_promise[0]
}

export async function getSiriStopHitTimesAsync(route: BusRoute, stop: BusStop, timestamp: Moment) {
log('looking for rides arriving at stop around time', {
route,
Expand Down
31 changes: 16 additions & 15 deletions src/pages/RealtimeMapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { Label } from './components/Label'
import { getColorByHashString } from './dashboard/OperatorHbarChart/utils'
import createClusterCustomIcon from './components/utils/customCluster/customCluster'
import { TimeSelector } from './components/TimeSelector'
import { busIcon } from './components/utils/BusIcon'
import { busIcon, busIconPath } from './components/utils/BusIcon'
import { BusToolTip } from 'src/pages/components/MapLayers/BusToolTip'

export interface Point {
loc: [number, number]
Expand Down Expand Up @@ -152,7 +153,7 @@ export default function RealtimeMapPage() {
</Grid>
{/* Buttons */}
{/*TODO (another PR another issue)
3) use text `TEXTS`.
3) use text `TEXTS`.
*/}
{/* loaded info */}
<Grid xs={11}>
Expand Down Expand Up @@ -205,19 +206,19 @@ export function Markers({ positions }: { positions: Point[] }) {
return (
<>
<MarkerClusterGroup chunkedLoading iconCreateFunction={createClusterCustomIcon}>
{positions.map((pos) => (
<Marker
position={pos.loc}
icon={busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)?.agency_name,
})}
key={pos.point?.id}>
<Popup>
<pre>{JSON.stringify(pos, null, 2)}</pre>
</Popup>
</Marker>
))}
{positions.map((pos) => {
const icon = busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)?.agency_name,
})
return (
<Marker position={pos.loc} icon={icon} key={pos.point?.id}>
<Popup minWidth={300} maxWidth={700}>
<BusToolTip position={pos} icon={busIconPath(String(pos.operator))} />
</Popup>
</Marker>
)
})}
</MarkerClusterGroup>
</>
)
Expand Down
31 changes: 16 additions & 15 deletions src/pages/SingleLineMapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { TEXTS } from 'src/resources/texts'
import { SearchContext } from '../model/pageState'
import { NotFound } from './components/NotFound'
import { Point } from './RealtimeMapPage'

import Grid from '@mui/material/Unstable_Grid2' // Grid version 2
import './Map.scss'
import getAgencyList, { Agency } from 'src/api/agencyList'
Expand All @@ -21,7 +22,8 @@ import { DateSelector } from './components/DateSelector'
import { CircularProgress } from '@mui/material'
import { FilterPositionsByStartTimeSelector } from './components/FilterPositionsByStartTimeSelector'
import { PageContainer } from './components/PageContainer'
import { busIcon } from './components/utils/BusIcon'
import { busIcon, busIconPath } from './components/utils/BusIcon'
import { BusToolTip } from 'src/pages/components/MapLayers/BusToolTip'

interface Path {
locations: VehicleLocation[]
Expand Down Expand Up @@ -165,20 +167,19 @@ const SingleLineMapPage = () => {
url="https://tile-a.openstreetmap.fr/hot/{z}/{x}/{y}.png"
/>

{filteredPositions.map((pos, i) => (
<Marker
position={pos.loc}
icon={busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)
?.agency_name,
})}
key={i}>
<Popup>
<pre>{JSON.stringify(pos, null, 2)}</pre>
</Popup>
</Marker>
))}
{filteredPositions.map((pos, i) => {
const icon = busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)?.agency_name,
})
return (
<Marker position={pos.loc} icon={icon} key={i}>
<Popup minWidth={300} maxWidth={700}>
<BusToolTip position={pos} icon={busIconPath(operatorId!)} />
</Popup>
</Marker>
)
})}

{paths.map((path) => (
<Polyline
Expand Down
2 changes: 1 addition & 1 deletion src/pages/components/MapLayers/BusLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function BusLayer({ positions }: { positions: VehicleLocationMapPoint[] }
name: agencyList.find((agency) => agency.operator_ref === pos.operator)?.agency_name,
})}
key={i}>
<Popup>
<Popup minWidth={300} maxWidth={700}>
<pre>{JSON.stringify(pos, null, 2)}</pre>
</Popup>
</Marker>
Expand Down
33 changes: 33 additions & 0 deletions src/pages/components/MapLayers/BusToolTip.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.leaflet-popup-content:has(.bus-tooltip) {
width: 350px;
direction: rtl;
text-align: right;

.bus-tooltip {
> ul {
list-style: none;
padding: 0;
margin: 0;

> li {
font-weight: bold;

> span {
font-weight: normal;
}
}
}

> .header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;

img {
width: 50px;
height: 50px;
}
}
}
}
96 changes: 96 additions & 0 deletions src/pages/components/MapLayers/BusToolTip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useEffect, useState } from 'react'
import { Point } from 'src/pages/RealtimeMapPage'
import { Button } from '@mui/material'
import moment from 'moment-timezone'
import './BusToolTip.scss'

import { getSiriRideWithRelated } from 'src/api/siriService'
import { SiriRideWithRelatedPydanticModel } from 'open-bus-stride-client/openapi/models/SiriRideWithRelatedPydanticModel'
import { TEXTS } from 'src/resources/texts'
import { Spin } from 'antd'
import cn from 'classnames'

export function BusToolTip({ position, icon }: { position: Point; icon: string }) {
const [siriRide, setSiriRide] = useState<SiriRideWithRelatedPydanticModel | undefined>()
const [isLoading, setIsLoading] = useState(false)
const [showJson, setShowJson] = useState(false)

useEffect(() => {
setIsLoading(true)
getSiriRideWithRelated(
position.point!.siri_route__id.toString(),
position.point!.siri_ride__vehicle_ref.toString(),
position.point!.siri_route__line_ref.toString(),
)
.then((siriRideRes: SiriRideWithRelatedPydanticModel) => setSiriRide(siriRideRes))
.finally(() => setIsLoading(false))
}, [position])
return (
<div className={cn({ 'extend-for-json': showJson }, 'bus-tooltip')}>
{isLoading ? (
<>
{TEXTS.loading_routes}
<Spin />
</>
) : (
<>
<header className="header">
<h1 className="title">
{TEXTS.line} :<span>{siriRide && siriRide!.gtfsRouteRouteShortName}</span>
</h1>
<img src={icon} alt="bus icon" className="bus-icon" />
</header>
<ul>
<li>
{TEXTS.from} :
<span>{siriRide && siriRide!.gtfsRouteRouteLongName?.split('<->')[0]}</span>
</li>
<li>
{TEXTS.destination} :
<span>{siriRide && siriRide!.gtfsRouteRouteLongName?.split('<->')[1]}</span>
</li>
<li>
{TEXTS.velocity} :<span>{`${position.point?.velocity} ${TEXTS.kmh}`}</span>
</li>

<li>
{TEXTS.sample_time} :
<span>
{moment(position.point!.recorded_at_time as string, moment.ISO_8601)
.tz('Israel')
.format('DD/MM/yyyy בשעה HH:mm')}
</span>
</li>
<li>
{TEXTS.vehicle_ref} :<span>{position.point?.siri_ride__vehicle_ref}</span>
</li>
</ul>
{/*maybe option to add info like this in extend card for now I put this condition */}
{window.screen.height > 1100 && (
<>
<h4>
{TEXTS.drive_direction} :
<span>
( {position.point?.bearing} {TEXTS.bearing})
</span>
</h4>
<h4>
{TEXTS.coords} :<span>{position.loc.join(' , ')}</span>
</h4>
</>
)}
</>
)}
<Button onClick={() => setShowJson((showJson) => !showJson)}>
{showJson ? TEXTS.hide_document : TEXTS.show_document}
</Button>
{showJson && (
<pre>
{JSON.stringify(position, null, 2)}
<br />
{siriRide && JSON.stringify(siriRide, null, 2)}
</pre>
)}
</div>
)
}
4 changes: 2 additions & 2 deletions src/pages/components/header/menu/menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

@media screen and (max-width: $mobile-max-width) {

.main .header {
.main > .header {
max-width: 0;
padding: 0;
transition: all 0.2s ease-in-out;
Expand All @@ -56,7 +56,7 @@
}
}

.main .header.open{
.main > .header.open{
display: block;
position: absolute;
z-index: 500;
Expand Down
4 changes: 3 additions & 1 deletion src/pages/components/utils/BusIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { DivIcon } from 'leaflet'

export const busIconPath = (operator_id: string) => `/bus-logos/${operator_id}.svg`

export const busIcon = ({ operator_id, name }: { operator_id: string; name?: string }) => {
const path = `/bus-logos/${operator_id}.svg`
const path = busIconPath(operator_id)
return new DivIcon({
className: 'my-div-icon',
html: `
Expand Down
12 changes: 12 additions & 0 deletions src/resources/texts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ export const TEXTS = {
missing_rides: 'מהנסיעות חסרות',
order_by_hour: 'לפי שעה',
order_by_severity: 'לפי חומרה',
line: 'קו',
from: 'מוצא',
destination: 'יעד',
sample_time: 'זמן דגימה',
velocity: 'מהירות',
drive_direction: 'כיוון נסיעה:',
coords: 'נ.צ:',
vehicle_ref: 'לוחית רישוי',
hide_document: 'הסתר מידע לחנונים',
show_document: 'הצג מידע לחנונים',
bearing: 'מעלות',
kmh: 'קמ״ש',
}

export const formatted = (text: string, value: string) => text.replace(PLACEHOLDER, value)
Loading