diff --git a/functions-python/tasks_executor/src/tasks/pmtiles_builder/build_pmtiles.py b/functions-python/tasks_executor/src/tasks/pmtiles_builder/build_pmtiles.py index d899b628d..6c0b5136a 100644 --- a/functions-python/tasks_executor/src/tasks/pmtiles_builder/build_pmtiles.py +++ b/functions-python/tasks_executor/src/tasks/pmtiles_builder/build_pmtiles.py @@ -256,6 +256,21 @@ def _upload_files_to_gcs(self, file_to_upload): self.bucket_name, blob_path, ) + + try: + blob.make_public() + self.logger.debug( + "Made object public: https://storage.googleapis.com/%s/%s", + self.bucket_name, + blob_path, + ) + except Exception as e: + # Likely due to Uniform bucket-level access; log and continue + self.logger.warning( + "Could not make %s public (uniform bucket-level access enabled?): %s", + blob_path, + e, + ) except Exception as e: raise Exception(f"Failed to upload files to GCS: {e}") from e diff --git a/web-app/package.json b/web-app/package.json index 154bfb146..2b6558acb 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -13,6 +13,7 @@ "@turf/center": "^6.5.0", "@types/i18next": "^13.0.0", "@types/leaflet": "^1.9.12", + "@types/react-map-gl": "^6.1.7", "axios": "^1.7.2", "countries-list": "^3.1.1", "date-fns": "^2.30.0", @@ -24,10 +25,12 @@ "i18next-browser-languagedetector": "^8.0.0", "i18next-http-backend": "^2.5.2", "leaflet": "^1.9.4", + "maplibre-gl": "^4.7.1", "material-react-table": "^2.13.0", "mui-datatables": "^4.3.0", "mui-nested-menu": "^3.4.0", "openapi-fetch": "^0.9.3", + "pmtiles": "^4.2.1", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0", "react-ga4": "^2.1.0", @@ -36,6 +39,7 @@ "react-hook-form": "^7.52.1", "react-i18next": "^14.1.2", "react-leaflet": "^4.2.1", + "react-map-gl": "^7.1.7", "react-redux": "^8.1.3", "react-router-dom": "^6.16.0", "react-scripts": "5.0.1", diff --git a/web-app/src/app/Theme.ts b/web-app/src/app/Theme.ts index debe32a49..2b095587a 100644 --- a/web-app/src/app/Theme.ts +++ b/web-app/src/app/Theme.ts @@ -12,6 +12,17 @@ declare module '@mui/material/styles' { interface PaletteOptions { boxShadow?: string; } + interface Theme { + map: { + basemapTileUrl: string; + }; + } + + interface ThemeOptions { + map?: { + basemapTileUrl?: string; + }; + } } declare module '@mui/material/Typography' { @@ -96,6 +107,11 @@ export const getTheme = (mode: ThemeModeEnum): Theme => { const chosenPalette = !isLightMode ? darkPalette : palette; return createTheme({ palette: { ...chosenPalette, mode }, + map: { + basemapTileUrl: isLightMode + ? 'https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png' + : 'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', + }, mixins: { code: { contrastText: '#f1fa8c', diff --git a/web-app/src/app/components/ContentBox.tsx b/web-app/src/app/components/ContentBox.tsx index d389ecc11..9ca888ed4 100644 --- a/web-app/src/app/components/ContentBox.tsx +++ b/web-app/src/app/components/ContentBox.tsx @@ -42,7 +42,7 @@ export const ContentBox = ( mb: 1, }} > - {props.title} + {props.title.trim() !== '' && {props.title}} {props.action != null && props.action} )} diff --git a/web-app/src/app/components/CoveredAreaMap.tsx b/web-app/src/app/components/CoveredAreaMap.tsx index 343a489d2..d94db19aa 100644 --- a/web-app/src/app/components/CoveredAreaMap.tsx +++ b/web-app/src/app/components/CoveredAreaMap.tsx @@ -7,7 +7,9 @@ import { Skeleton, Button, Typography, + Fab, } from '@mui/material'; +import { Link } from 'react-router-dom'; import MapIcon from '@mui/icons-material/Map'; import TravelExploreIcon from '@mui/icons-material/TravelExplore'; import { ContentBox } from './ContentBox'; @@ -28,6 +30,9 @@ import { computeBoundingBox } from '../screens/Feed/Feed.functions'; import { displayFormattedDate } from '../utils/date'; import { useSelector } from 'react-redux'; import { selectAutodiscoveryGbfsVersion } from '../store/feed-selectors'; +import ModeOfTravelIcon from '@mui/icons-material/ModeOfTravel'; +import { GtfsVisualizationMap } from './GtfsVisualizationMap'; +import ZoomOutMapIcon from '@mui/icons-material/ZoomOutMap'; interface CoveredAreaMapProps { boundingBox?: LatLngExpression[]; @@ -50,6 +55,11 @@ export const fetchGeoJson = async ( return await response.json(); }; +type MapViews = + | 'boundingBoxView' + | 'detailedCoveredAreaView' + | 'gtfsVisualizationView'; + const CoveredAreaMap: React.FC = ({ boundingBox, latestDataset, @@ -63,9 +73,7 @@ const CoveredAreaMap: React.FC = ({ >(null); const [geoJsonError, setGeoJsonError] = useState(false); const [geoJsonLoading, setGeoJsonLoading] = useState(false); - const [view, setView] = useState< - 'boundingBoxView' | 'detailedCoveredAreaView' - >('detailedCoveredAreaView'); + const [view, setView] = useState('detailedCoveredAreaView'); const latestGbfsVersion = useSelector(selectAutodiscoveryGbfsVersion); const getAndSetGeoJsonData = (urlToExtract: string): void => { @@ -74,7 +82,7 @@ const CoveredAreaMap: React.FC = ({ .then((data) => { setGeoJsonData(data); setGeoJsonError(false); - setView('detailedCoveredAreaView'); + setView('gtfsVisualizationView'); }) .catch(() => { setGeoJsonError(true); @@ -112,7 +120,7 @@ const CoveredAreaMap: React.FC = ({ const handleViewChange = ( _: React.MouseEvent, - newView: 'boundingBoxView' | 'detailedCoveredAreaView' | null, + newView: MapViews | null, ): void => { if (newView !== null) setView(newView); }; @@ -132,6 +140,9 @@ const CoveredAreaMap: React.FC = ({ const renderMap = (): JSX.Element => { const displayBoundingBoxMap = view === 'boundingBoxView' && feed?.data_type === 'gtfs'; + + const displayGtfsVisualizationView = + view === 'gtfsVisualizationView' && feed?.data_type === 'gtfs'; let gbfsBoundingBox: LatLngExpression[] = []; if (feed?.data_type === 'gbfs') { gbfsBoundingBox = computeBoundingBox(geoJsonData) ?? []; @@ -139,18 +150,36 @@ const CoveredAreaMap: React.FC = ({ setGeoJsonError(true); } } - return ( - <> - {displayBoundingBoxMap ? ( - - ) : ( - ; + } + + if (displayGtfsVisualizationView) { + return ( + <> + + + + - )} - + + ); + } + + return ( + ); }; @@ -166,73 +195,91 @@ const CoveredAreaMap: React.FC = ({ flexDirection: 'column', maxHeight: { xs: '100%', - md: '70vh', + md: '70vh', // TODO: optimize this }, minHeight: '50vh', }} - title={mapDisplayError ? '' : t('coveredAreaTitle') + ' - ' + t(view)} + title={''} width={{ xs: '100%' }} outlineColor={theme.palette.primary.dark} padding={2} - action={ - <> - {feed?.data_type === 'gbfs' ? ( - - {latestAutodiscoveryUrl != undefined && ( - - )} - {(geoJsonData as GeoJSONDataGBFS)?.extracted_at != undefined && ( - - {t('common:updated')}:{' '} - {displayFormattedDate( - (geoJsonData as GeoJSONDataGBFS).extracted_at, - )} - - )} - - ) : ( - - - - - - - - - - - - - )} - - } > + + {view === 'gtfsVisualizationView' && ( + + )} + {feed?.data_type === 'gbfs' ? ( + + {latestAutodiscoveryUrl != undefined && ( + + )} + {(geoJsonData as GeoJSONDataGBFS)?.extracted_at != undefined && ( + + {t('common:updated')}:{' '} + {displayFormattedDate( + (geoJsonData as GeoJSONDataGBFS).extracted_at, + )} + + )} + + ) : ( + + + + + + + + + + + + + + + + + + )} + {feed?.data_type === 'gtfs' && boundingBox === undefined && view === 'boundingBoxView' && ( diff --git a/web-app/src/app/components/GtfsVisualizationMap.tsx b/web-app/src/app/components/GtfsVisualizationMap.tsx new file mode 100644 index 000000000..c45054f07 --- /dev/null +++ b/web-app/src/app/components/GtfsVisualizationMap.tsx @@ -0,0 +1,614 @@ +/* eslint-disable */ + +import { useEffect, useRef, useState, useMemo } from 'react'; +import Map, { + type MapRef, + MapProvider, + NavigationControl, + ScaleControl, +} from 'react-map-gl/maplibre'; +import maplibregl, { + type ExpressionSpecification, + type LngLatBoundsLike, +} from 'maplibre-gl'; +import 'maplibre-gl/dist/maplibre-gl.css'; +import { Protocol } from 'pmtiles'; +import { type LatLngExpression } from 'leaflet'; +import type { FeatureCollection } from 'geojson'; +import { Box, useTheme } from '@mui/material'; +import { MapElement, MapRouteElement, MapStopElement } from './MapElement'; +import { + reversedRouteTypesMapping, +} from '../constants/RouteTypes'; +import { MapDataPopup } from './Map/MapDataPopup'; +import { useTheme as themeProvider } from '../context/ThemeProvider'; + +interface LatestDatasetLite { + hosted_url?: string; + id?: string; + stable_id?: string; +} + +export interface GtfsVisualizationMapProps { + polygon: LatLngExpression[]; + latestDataset?: LatestDatasetLite; + filteredRoutes?: string[]; + filteredRouteTypes?: string[]; + hideStops?: boolean; +} + +export const GtfsVisualizationMap = ({ + polygon, + latestDataset, + filteredRoutes = [], + filteredRouteTypes = [], + hideStops = false, +}: GtfsVisualizationMapProps): JSX.Element => { + + console.log('[GtfsVisualizationMap] mount', { + latestDatasetId: latestDataset?.id, + latestDatasetHostedUrl: latestDataset?.hosted_url, + }); + + const { stopsPmtilesUrl, routesPmtilesUrl } = useMemo(() => { + const baseUrl = latestDataset?.hosted_url ? latestDataset.hosted_url.replace(/[^/]+$/, '') : undefined; + console.log('[GtfsVisualizationMap] latestDataset URLs', { + hostedUrl: latestDataset?.hosted_url, + baseUrl, + }); + + const stops = `${baseUrl}/pmtiles/stops.pmtiles`; + const routes = `${baseUrl}/pmtiles/routes.pmtiles`; + + return { stopsPmtilesUrl: stops, routesPmtilesUrl: routes }; + }, [latestDataset?.id, latestDataset?.stable_id]); + + + useEffect(() => { + console.log('[GtfsVisualizationMap] PMTiles URLs', { + stopsPmtilesUrl, + routesPmtilesUrl, + }); + }, [stopsPmtilesUrl, routesPmtilesUrl]); + + // Log whenever the identifiers change + useEffect(() => { + console.log('[GtfsVisualizationMap] props update', { + latestDatasetId: latestDataset?.id, + }); + }, [latestDataset?.id]); + + const theme = useTheme(); + const [hoverInfo, setHoverInfo] = useState([]); + const [hoverData, setHoverData] = useState(''); + const [mapElement, setMapElement] = useState([]); + const [mapClickRouteData, setMapClickRouteData] = useState | null>(null); + const [mapClickStopData, setMapClickStopData] = useState | null>(null); + const mapRef = useRef(null); + + const filteredRouteTypesIds = filteredRouteTypes.map( + (d) => reversedRouteTypesMapping[d], + ); + + // Create a map to store routeId to routeColor mapping + const routeIdToColorMap: Record = {}; + mapElement.forEach((el) => { + if (!el.isStop) { + const routeElement: MapRouteElement = el as MapRouteElement; + if (routeElement.routeId && routeElement.routeColor) { + routeIdToColorMap[routeElement.routeId] = routeElement.routeColor; + } + } + }); + + function generateStopColorExpression( + routeIdToColor: Record, + fallback = '#888', + ): ExpressionSpecification { + const expression: any[] = ['case']; + + Object.entries(routeIdToColor).forEach(([routeId, color]) => { + expression.push( + ['in', `"${routeId}"`, ['get', 'route_ids']], + `#${color}`, + ); + }); + + // If no conditions added, just return a fallback color directly + if (expression.length === 1) { + return fallback as unknown as ExpressionSpecification; + } + + expression.push(fallback); // Add fallback color + return expression as ExpressionSpecification; + } + + const routeTypeFilter: ExpressionSpecification | boolean = + filteredRouteTypes.length > 0 + ? ['in', ['get', 'route_type'], ['literal', filteredRouteTypesIds]] + : true; // if no filter applied, show all + + const handleMouseClick = (event: maplibregl.MapLayerMouseEvent): void => { + const map = mapRef.current?.getMap(); + if (map != undefined) { + // Get the features under the mouse pointer + const features = map.queryRenderedFeatures(event.point, { + layers: ['stops-highlight', 'routes-highlight'], // Change this to your actual layer ID + }); + + const selectedStop = features.find( + (feature) => feature.layer.id === 'stops-highlight', + ); + if (selectedStop != undefined) { + setMapClickStopData({ + ...selectedStop.properties, + longitude: String(event.lngLat.lng), + latitude: String(event.lngLat.lat), + }); // Example properties, adjust as needed + console.log('Mouse selectedStop', selectedStop); + setMapClickRouteData(null); + return; + } + + const selectedRoute = features.find( + (feature) => feature.layer.id === 'routes-highlight', + ); + if (selectedRoute != undefined) { + setMapClickRouteData({ + ...selectedRoute.properties, + longitude: String(event.lngLat.lng), + latitude: String(event.lngLat.lat), + }); // Example properties, adjust as needed + console.log('Mouse clicked on map:', features); + setMapClickStopData(null); + } + } + }; + + const handlePopupClose = () => { + setMapClickRouteData(null); + setMapClickStopData(null); + }; + + const handleMouseMove = (event: maplibregl.MapLayerMouseEvent): void => { + // Ensure that the mapRef is not null before trying to access the map + const map = mapRef.current?.getMap(); + const mapElements: MapElement[] = []; + + if (map != undefined) { + // Get the features under the mouse pointer + const features = map.queryRenderedFeatures(event.point, { + layers: ['stops', 'routes', 'routes-white', 'stops-highlight'], // Change this to your actual layer ID + }); + + if ( + features.length > 0 || + mapClickRouteData != null || + mapClickStopData != null + ) { + if (mapClickRouteData != null) { + const mapElement: MapRouteElement = { + isStop: false, + name: mapClickRouteData.route_long_name, + routeType: Number(mapClickRouteData.route_type), + routeColor: mapClickRouteData.route_color, + routeTextColor: mapClickRouteData.route_text_color, + routeId: mapClickRouteData.route_id, + }; + mapElements.push(mapElement); + } + if (mapClickStopData != null) { + const mapElement: MapStopElement = { + isStop: true, + name: mapClickStopData.stop_name, + locationType: Number(mapClickStopData.location_type), + stopId: mapClickStopData.stop_id, + }; + mapElements.push(mapElement); + } + features.forEach((feature) => { + if ( + feature.layer.id === 'stops' || + feature.layer.id === 'stops-highlight' + ) { + const mapElement: MapStopElement = { + isStop: true, + name: feature.properties.stop_name, + locationType: Number(feature.properties.location_type), + stopId: feature.properties.stop_id, + }; + mapElements.push(mapElement); + } else { + const mapElement: MapElement = { + isStop: false, + name: feature.properties.route_long_name, + routeType: feature.properties.route_type, + routeColor: feature.properties.route_color, + routeTextColor: feature.properties.route_text_color, + routeId: feature.properties.route_id, + }; + mapElements.push(mapElement); + } + }); + + setMapElement(mapElements); + + const elementIds: string[] = []; + features.forEach((feature) => { + if (feature.properties.route_id != undefined) { + elementIds.push(feature.properties.route_id); + } else { + elementIds.push(feature.properties.stop_id); + } + }); + setHoverInfo(elementIds); + } else { + setHoverInfo([]); + setHoverData(''); + setMapElement([]); + } + } + }; + + useEffect(() => { + // Will be called on add statup only once + const protocol = new Protocol(); + maplibregl.addProtocol('pmtiles', protocol.tile); + return () => { + maplibregl.removeProtocol('pmtiles'); + }; + }, []); + + const getBoundsFromCoordinates = ( + coordinates: Array<[number, number]>, + ): LngLatBoundsLike => { + let minLng = Number.POSITIVE_INFINITY; + let minLat = Number.POSITIVE_INFINITY; + let maxLng = Number.NEGATIVE_INFINITY; + let maxLat = Number.NEGATIVE_INFINITY; + + coordinates.forEach(([lat, lng]) => { + minLat = Math.min(minLat, lat); + maxLat = Math.max(maxLat, lat); + minLng = Math.min(minLng, lng); + maxLng = Math.max(maxLng, lng); + }); + + return [minLng, minLat, maxLng, maxLat]; // Matches LngLatBoundsLike format + }; + + const bounds: LngLatBoundsLike = getBoundsFromCoordinates( + polygon as Array<[number, number]>, + ); + + // in polygon: IMPORTANT - the coordinates are in the format [lat, lng] (not [lng, lat]) + const boundingBoxFormmated = polygon.map((point: any) => [ + point[1], + point[0], + ]); + + // TODO: example of how to use geojson in maplibre (stop density) + const geojson: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [boundingBoxFormmated], + }, + }, + ], + }; + + return ( + + + + + { + handleMouseClick(event); + }} + ref={mapRef} + onMouseMove={(event) => { + handleMouseMove(event); + }} + style={{ width: '100%', height: '100%' }} + initialViewState={{ bounds }} + interactiveLayerIds={[ + 'stops', + 'routes', + 'routes-white', + 'routes-highlight', + 'stops-highlight', + ]} + scrollZoom={true} + dragPan={true} + // https://pmtiles.io/ Good tool for debugging PMTiles + mapStyle={{ + version: 8, + sources: { + 'raster-tiles': { + type: 'raster', + tiles: [theme.map.basemapTileUrl], + tileSize: 256, + attribution: + '© OpenStreetMap contributors', + }, + sample: { + type: 'vector', + url: `pmtiles://${stopsPmtilesUrl}`, // dynamic stops + //url: 'pmtiles://https://storage.googleapis.com/map-details-bucket-test/stops-bordeaux.pmtiles', // bordeaux + }, + routes: { + type: 'vector', + url: `pmtiles://${routesPmtilesUrl}`, // dynamic routes + //url: 'pmtiles://https://storage.googleapis.com/map-details-bucket-test/routes-bordeaux.pmtiles', // bordeaux + }, + // boundingBox: { + // type: 'geojson', + // data: geojson, // displays the bounding box + // }, + }, + // Order matters: the last layer will be on top + // Layers control all the logic in the map -> lots of duplicated for the sake of effects + layers: [ + { + id: 'simple-tiles', + type: 'raster', + source: 'raster-tiles', + minzoom: 0, + maxzoom: 22, + }, + { + id: 'routes-white', // white padding on the route lines + source: 'routes', + filter: routeTypeFilter, + 'source-layer': 'routesoutput', // Name of the geojson file when converting to pmtile. route-output.geojson -> routesoutput + type: 'line', + paint: { + // style and color of the stops + 'line-color': theme.palette.background.paper, + 'line-width': [ + 'match', + ['get', 'route_type'], // Property from the vector tile + '3', + 4, // 3 = bus + '1', + 15, // 1 = metro + 3, // Default width + ], + }, + }, + { + id: 'routes', + filter: routeTypeFilter, + source: 'routes', + 'source-layer': 'routesoutput', // Name of the geojson file when converting to pmtile. route-output.geojson -> routesoutput + type: 'line', + paint: { + // style and color of the stops + 'line-color': ['concat', '#', ['get', 'route_color']], + 'line-width': [ + // line with thickness based on route type (thicker for metro, thinner for bus) + 'match', + ['get', 'route_type'], // Property from the vector tile + '3', + 1, // 3 = bus + '1', + 4, // 1 = metro + 3, // Default width + ], + 'line-opacity': [ + // Opacity based on whether the route is selected or not + 'case', + [ + 'any', + ['==', filteredRoutes.length, 0], + [ + 'in', + ['get', 'route_id'], + ['literal', filteredRoutes], + ], + ], + 0.4, // default opacity if selected or no filter + 0.1, // faded if NOT in filteredRoutes + ], + }, + // If routeTypesFilter includes a value -> show that + // If routeTypesFilter is empty -> show all + layout: { + 'line-sort-key': [ + 'match', + ['get', 'route_type'], + '1', + 3, // metro on top + '3', + 2, // bus second + 0, // Default priority + ], + }, + }, + + // { + // id: 'boundingBox', + // type: 'fill', + // source: 'boundingBox', + // paint: { + // 'fill-color': '#088', + // 'fill-opacity': 0.8, + // }, + // }, + { + id: 'stops', + filter: !hideStops, // Hide stops if hideStops is true + source: 'sample', + 'source-layer': 'stopsoutput', // Name of the geojson file when converting to pmtile. stops-output.geojson -> stopssoutput + type: 'circle', + paint: { + // style and color of the stops + 'circle-radius': 3, + 'circle-color': '#000000', + 'circle-opacity': 0.4, + }, + minzoom: 12, + maxzoom: 22, + }, + { + id: 'routes-highlight', + source: 'routes', + 'source-layer': 'routesoutput', // Name of the geojson file when converting to pmtile. stops-output.geojson -> stopssoutput + type: 'line', + paint: { + // style and color of the stops + 'line-color': ['concat', '#', ['get', 'route_color']], + 'line-opacity': 1, + 'line-width': [ + 'match', + ['get', 'route_type'], // Property from the vector tile + '3', + 5, // 3 = bus + '1', + 6, // 1 = metro + 3, // Default width + ], + }, + + filter: [ + 'any', + ['in', ['get', 'route_id'], ['literal', hoverInfo]], + ['in', ['get', 'route_id'], ['literal', filteredRoutes]], + [ + 'in', + ['get', 'route_id'], + ['literal', mapClickRouteData?.route_id ?? ''], + ], + ], + }, + { + id: 'stops-highlight', + source: 'sample', + 'source-layer': 'stopsoutput', // Name of the geojson file when converting to pmtile. stops-output.geojson -> stopssoutput + type: 'circle', + paint: { + 'circle-radius': 7, + 'circle-color': generateStopColorExpression( + routeIdToColorMap, + ) as ExpressionSpecification, // VERY IMPORTANT: during the conversion to PMTiles, the route_colors are stored as strings with quotes NOT arrays. [1,2,3] -> "["1","2","3"]" + 'circle-opacity': 1, + }, + minzoom: 10, + maxzoom: 22, + filter: hideStops + ? !hideStops + : [ + 'any', + ['in', ['get', 'stop_id'], ['literal', hoverInfo]], + [ + 'in', + ['get', 'stop_id'], + ['literal', mapClickStopData?.stop_id ?? ''], + ], + [ + 'any', + ...filteredRoutes.map((id) => { + return [ + 'in', + `\"${id}\"`, + ['get', 'route_ids'], + ] as any; // VERY IMPORTANT: during the conversion to PMTiles, the route_ids are stored as strings with quotes NOT arrays. [1,2,3] -> "["1","2","3"]" + }), + ], + [ + 'any', + ...hoverInfo.map((id) => { + return [ + 'in', + `\"${id}\"`, + ['get', 'route_ids'], + ] as any; + }), + ], + ], + }, + { + id: 'stops-highlight-outer', + source: 'sample', + 'source-layer': 'stopsoutput', + type: 'circle', + paint: { + 'circle-radius': 3, + 'circle-color': theme.palette.background.paper, + 'circle-opacity': 1, + }, + filter: hideStops + ? !hideStops + : [ + 'any', + ['in', ['get', 'stop_id'], ['literal', hoverInfo]], + [ + 'any', + ...filteredRoutes.map((id) => { + return [ + 'in', + `\"${id}\"`, + ['get', 'route_ids'], + ] as any; // VERY IMPORTANT: during the conversion to PMTiles, the route_ids are stored as strings with quotes NOT arrays. [1,2,3] -> "["1","2","3"]" + }), + ], + [ + 'any', + ...hoverInfo.map((id) => { + return [ + 'in', + `\"${id}\"`, + ['get', 'route_ids'], + ] as any; + }), + ], + ], + }, + ], + }} + > + {/* TODO: Idea only display the compass and scale on advanced map view */} + + + + + + + + ); +}; diff --git a/web-app/src/app/components/Map/MapDataPopup.tsx b/web-app/src/app/components/Map/MapDataPopup.tsx new file mode 100644 index 000000000..f732815ce --- /dev/null +++ b/web-app/src/app/components/Map/MapDataPopup.tsx @@ -0,0 +1,183 @@ +import { Popup } from 'react-map-gl/maplibre'; +import { + locationTypesMapping, + type RouteTypeMetadata, + routeTypesMapping, +} from '../../constants/RouteTypes'; +import { Box, Link, Typography, useTheme } from '@mui/material'; +import AccessibleIcon from '@mui/icons-material/Accessible'; + +interface MapDataPopupProps { + mapClickRouteData: Record | null; + mapClickStopData: Record | null; + onPopupClose: () => void; +} + +export const MapDataPopup = ( + props: React.PropsWithChildren, +): JSX.Element => { + const { mapClickRouteData, mapClickStopData, onPopupClose } = props; + const theme = useTheme(); + + const renderRouteTypeIcon = ( + routeTypeMetadata: RouteTypeMetadata, + routeColorText: string, + ): JSX.Element => { + const { icon: Icon } = routeTypeMetadata; + return ; + }; + + function getGradientBorder(colorString: string): string { + try { + const colors: string[] = JSON.parse(colorString); + + if (!Array.isArray(colors) || colors.length === 0) { + return 'none'; + } + + const gradient = `linear-gradient(to right, ${colors + .map((c) => `#${c}`) + .join(', ')})`; + + // Using border-image for gradient border + return `6px solid transparent; border-image: ${gradient} 1;`; + } catch { + return 'none'; + } + } + + return ( + <> + {mapClickRouteData != null && ( + + + + {renderRouteTypeIcon( + routeTypesMapping[mapClickRouteData.route_type], + mapClickRouteData.route_text_color, + )} + + {routeTypesMapping[mapClickRouteData.route_type].name}{' '} + + {mapClickRouteData.route_id} + + + + + + {mapClickRouteData.route_long_name} + + +

{mapClickRouteData.agency_name}

+
+
+ )} + {mapClickStopData != null && ( + + + + + {renderRouteTypeIcon( + locationTypesMapping[mapClickStopData.location_type], + theme.palette.text.primary, + )} + + {locationTypesMapping[mapClickStopData.location_type].name}{' '} + + {mapClickStopData.stop_id} + + + + {mapClickStopData.wheelchair_boarding === '1' && ( + + )} + + + + {mapClickStopData.stop_name} + + + {mapClickStopData.route_ids != null && + mapClickStopData.route_ids.replace(/[\[\]"\\]/g, ',').length > + 0 && ( + + Route Ids + + {mapClickStopData.route_ids.replace(/[\[\]"\\]/g, ' ')} + + + )} + + {mapClickStopData.stop_code != null && ( + + Stop Code + {mapClickStopData.stop_code} + + )} + {mapClickStopData.stop_url != null && ( + + View Stop Info + + )} + + + + )} + + ); +}; diff --git a/web-app/src/app/components/MapElement.tsx b/web-app/src/app/components/MapElement.tsx new file mode 100644 index 000000000..4ddbe1185 --- /dev/null +++ b/web-app/src/app/components/MapElement.tsx @@ -0,0 +1,147 @@ +import * as React from 'react'; +import 'leaflet/dist/leaflet.css'; +import { Box, Typography, useTheme } from '@mui/material'; +import { + locationTypesMapping, + type RouteTypeMetadata, + routeTypesMapping, +} from '../constants/RouteTypes'; + +export interface BaseMapElement { + isStop: boolean; + name: string; +} + +export interface MapRouteElement extends BaseMapElement { + routeType: number; + routeColor: string; + routeTextColor: string; + routeId: string; +} + +export interface MapStopElement extends BaseMapElement { + locationType: number; + stopId: string; +} + +export type MapElement = MapRouteElement | MapStopElement; + +export interface MapElementProps { + mapElements: MapElement[]; +} + +export const MapElement = ( + props: React.PropsWithChildren, +): JSX.Element => { + const theme = useTheme(); + const formatSet = new Set(); + const formattedElements: MapElement[] = []; + + props.mapElements.forEach((element) => { + if (!formatSet.has(element.name)) { + formattedElements.push(element); + } + formatSet.add(element.name); + }); + + // TODO: duplicate + const renderRouteTypeIcon = ( + routeTypeMetadata: RouteTypeMetadata, + routeColorText: string, + ): JSX.Element | null => { + // The route type could be out of specs (e.g. google route types), so we may not have an icon. + if (!routeTypeMetadata || !routeTypeMetadata.icon) { + // Optionally render a default icon or return null + return null; + } + const { icon: Icon } = routeTypeMetadata; + return ; + }; + + const renderRouteMapElement = (element: MapRouteElement): JSX.Element => { + return ( + + {renderRouteTypeIcon( + routeTypesMapping[element.routeType?.toString() || '0'], + element.routeTextColor ? '#' + element.routeTextColor : '#000000', + )} + + + {element.routeId} - {element.name} + + + ); + }; + + const renderStopMapElement = (element: MapStopElement, iconColor: string): JSX.Element => { + return ( + + {renderRouteTypeIcon( + locationTypesMapping[element.locationType?.toString() || '0'], + iconColor, + )} + + + {element.stopId} - {element.name} + + + ); + }; + + return ( + + {formattedElements.map((element, index) => { + return ( + + + {element.isStop ? 'Stop' : 'Route'} + + {element.isStop ? ( + <>{renderStopMapElement(element as MapStopElement, theme.palette.text.primary)} + ) : ( + <>{renderRouteMapElement(element as MapRouteElement)} + )} + + ); + })} + + ); +}; diff --git a/web-app/src/app/components/NestedCheckboxList.tsx b/web-app/src/app/components/NestedCheckboxList.tsx index ebb5fcb7a..2a9ef75e1 100644 --- a/web-app/src/app/components/NestedCheckboxList.tsx +++ b/web-app/src/app/components/NestedCheckboxList.tsx @@ -28,6 +28,7 @@ export interface CheckboxStructure { seeChildren?: boolean; children?: CheckboxStructure[]; disabled?: boolean; + props?: Record; } function useDebouncedCallback(callback: () => void, delay: number): () => void { diff --git a/web-app/src/app/components/RouteSelector.tsx b/web-app/src/app/components/RouteSelector.tsx new file mode 100644 index 000000000..12a63e35a --- /dev/null +++ b/web-app/src/app/components/RouteSelector.tsx @@ -0,0 +1,117 @@ +import React, { useState, useMemo, useEffect } from 'react'; +import { + TextField, + List, + Checkbox, + ListItemText, + ListItemIcon, + Typography, + Box, + ListItemButton, +} from '@mui/material'; + +interface RouteSelectorProps { + routes: any[]; // Replace 'any' with a more specific type if available + selectedRouteIds?: string[]; + onSelectionChange?: (selectedRoutes: string[]) => void; +} + +export default function RouteSelector({ + routes, + selectedRouteIds = [], + onSelectionChange, +}: RouteSelectorProps) { + const [search, setSearch] = useState(''); + const [selectedRoutes, setSelectedRoutes] = + useState(selectedRouteIds); + + const filteredRoutes = useMemo(() => { + const searchLower = search.toLowerCase(); + return routes.filter( + (route) => + route.routeName.toLowerCase().includes(searchLower) || + route.routeId.includes(searchLower), + ); + }, [search, routes]); + + useEffect(() => { + setSelectedRoutes([...selectedRouteIds]); + }, [selectedRouteIds]); + + const handleToggle = (routeId: string) => { + setSelectedRoutes((prev) => { + const newSelection = prev.includes(routeId) + ? prev.filter((id) => id !== routeId) + : [...prev, routeId]; + + onSelectionChange?.(newSelection); + return newSelection; + }); + }; + + return ( + + + {filteredRoutes.length} route{filteredRoutes.length !== 1 ? 's' : ''} + + setSearch(e.target.value)} + /> + + + {filteredRoutes + .sort((a, b) => a.routeId - b.routeId) + .map((route) => ( + handleToggle(route.routeId)} + dense={true} + > + + + + + + + {route.routeId} - {route.routeName} + + + } + /> + + ))} + + + ); +} diff --git a/web-app/src/app/components/sample-route-output.json b/web-app/src/app/components/sample-route-output.json new file mode 100644 index 000000000..cbe3d6de9 --- /dev/null +++ b/web-app/src/app/components/sample-route-output.json @@ -0,0 +1,3410 @@ +[ + { + "routeId": "1", + "routeName": "Ligne 1 - Verte", + "color": "#00B300", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "2", + "routeName": "Ligne 2 - Orange", + "color": "#D95700", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "4", + "routeName": "Ligne 4 - Jaune", + "color": "#FFD900", + "textColor": "#000000", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "5", + "routeName": "Ligne 5 - Bleue", + "color": "#0095E6", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "93", + "routeName": "Jean-Talon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "16", + "routeName": "Graham", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "160", + "routeName": "Barclay", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "100", + "routeName": "Cr\u00e9mazie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "80", + "routeName": "Avenue du Parc", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "380", + "routeName": "Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "105", + "routeName": "Sherbrooke", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "171", + "routeName": "Henri-Bourassa", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "371", + "routeName": "D\u00e9carie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "103", + "routeName": "Monkland", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "162", + "routeName": "Westminster", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "369", + "routeName": "C\u00f4te-des-Neiges", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "166", + "routeName": "Queen-Mary", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "119", + "routeName": "Rockland", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "124", + "routeName": "Victoria", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "128", + "routeName": "Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "363", + "routeName": "Boulevard Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "165", + "routeName": "C\u00f4te-des-Neiges", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "470", + "routeName": "Express Pierrefonds", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "711", + "routeName": "Parc-du-Mont-Royal / Oratoire", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "747", + "routeName": "YUL A\u00e9roport / Centre-Ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "460", + "routeName": "Express M\u00e9tropolitaine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "164", + "routeName": "Dudemaine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "51", + "routeName": "\u00c9douard-Montpetit", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "92", + "routeName": "Jean-Talon Ouest", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "54", + "routeName": "Charland / Chabanel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "465", + "routeName": "Express C\u00f4te-des-Neiges", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "480", + "routeName": "Express du Parc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "115", + "routeName": "Par\u00e9", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "95", + "routeName": "B\u00e9langer", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "47", + "routeName": "Masson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "25", + "routeName": "Angus", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "97", + "routeName": "Avenue-du-Mont-Royal", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "192", + "routeName": "Robert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "213", + "routeName": "Parc-Industriel-Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "170", + "routeName": "Keller", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "175", + "routeName": "Griffith / Saint-Fran\u00e7ois", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "135", + "routeName": "De l'Esplanade", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "202", + "routeName": "Dawson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "129", + "routeName": "C\u00f4te-Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "24", + "routeName": "Sherbrooke", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "55", + "routeName": "Boulevard Saint-Laurent", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "18", + "routeName": "Beaubien", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "409", + "routeName": "Express Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "485", + "routeName": "Express Antoine-Faucon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "26", + "routeName": "Mercier-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "186", + "routeName": "Sherbrooke-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "44", + "routeName": "Armand-Bombardier", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "33", + "routeName": "Langelier", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "32", + "routeName": "Lacordaire", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "28", + "routeName": "Honor\u00e9-Beaugrand", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "187", + "routeName": "Ren\u00e9-L\u00e9vesque", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "189", + "routeName": "Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "86", + "routeName": "Pointe-aux-Trembles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "362", + "routeName": "Hochelaga / Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "49", + "routeName": "Maurice-Duplessis", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "43", + "routeName": "Monselet", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "372", + "routeName": "Jean-Talon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "141", + "routeName": "Jean-Talon Est", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "364", + "routeName": "Sherbrooke / Joseph-Renaud", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "355", + "routeName": "Pie-IX", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "353", + "routeName": "Lacordaire / Maurice-Duplessis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "81", + "routeName": "Saint-Jean-Baptiste", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "183", + "routeName": "Gouin Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "40", + "routeName": "Henri-Bourassa-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "188", + "routeName": "Couture", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "487", + "routeName": "Express Bout-de-l'\u00cele", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "448", + "routeName": "Express Maurice-Duplessis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "486", + "routeName": "Express Sherbrooke", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "449", + "routeName": "Express Rivi\u00e8re-des-Prairies", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "428", + "routeName": "Express Parcs industriels de l'Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "432", + "routeName": "Express Lacordaire", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "39", + "routeName": "Des Grandes-Prairies", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "48", + "routeName": "Perras", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "197", + "routeName": "Rosemont", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "469", + "routeName": "Express Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "45", + "routeName": "Papineau", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "193", + "routeName": "Jarry", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "444", + "routeName": "Express C\u00e9gep Marie-Victorin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "822", + "routeName": "Navette Longue-Pointe", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "179", + "routeName": "De l'Acadie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "161", + "routeName": "Van Horne", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "361", + "routeName": "Saint-Denis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "144", + "routeName": "Avenue des Pins", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "30", + "routeName": "Saint-Denis / Saint-Hubert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "31", + "routeName": "Saint-Denis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "66", + "routeName": "The Boulevard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "370", + "routeName": "Rosemont", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "99", + "routeName": "Villeray", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "13", + "routeName": "Christophe-Colomb", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "445", + "routeName": "Express Papineau", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "46", + "routeName": "Casgrain", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "52", + "routeName": "de Li\u00e8ge", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "427", + "routeName": "Express Saint-Joseph", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "41", + "routeName": "Quartier Saint-Michel / Ahuntsic", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "108", + "routeName": "Bannantyne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "12", + "routeName": "\u00cele-des-Soeurs", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "57", + "routeName": "Charlevoix", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "90", + "routeName": "Saint-Jacques", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "71", + "routeName": "Pointe-Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "113", + "routeName": "Lapierre", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "496", + "routeName": "Express Victoria", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "35", + "routeName": "Griffintown", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "112", + "routeName": "Airlie", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "114", + "routeName": "Angrignon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "106", + "routeName": "Newman", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "110", + "routeName": "Centrale", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "350", + "routeName": "Verdun / LaSalle", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "198", + "routeName": "Broadway", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "36", + "routeName": "Monk", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "37", + "routeName": "Jolicoeur", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "195", + "routeName": "Dorval / Angrignon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "38", + "routeName": "De l'\u00c9glise", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "356", + "routeName": "Lachine / YUL A\u00e9roport / Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "102", + "routeName": "Somerled", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "107", + "routeName": "Verdun", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "61", + "routeName": "Wellington", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "360", + "routeName": "Avenue des Pins", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "104", + "routeName": "Cavendish", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "63", + "routeName": "Girouard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "211", + "routeName": "Bord-du-Lac", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "354", + "routeName": "Sainte-Anne-de-Bellevue / Centre-ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "123", + "routeName": "Dollard / Shevchenko", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "138", + "routeName": "Notre-Dame-de-Gr\u00e2ce", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "190", + "routeName": "Norman", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "425", + "routeName": "Express Anse-\u00e0-l'Orme", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "405", + "routeName": "Express Bord-du-Lac", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "411", + "routeName": "Express Lionel-Groulx", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "101", + "routeName": "Saint-Patrick", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "491", + "routeName": "Express Provost", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "420", + "routeName": "Express Notre-Dame-de-Gr\u00e2ce", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "11", + "routeName": "Parc-du-Mont-Royal / Ridgewood", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "27", + "routeName": "Boulevard Saint-Joseph", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "368", + "routeName": "Avenue-du-Mont-Royal", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "14", + "routeName": "Atateken", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "359", + "routeName": "Papineau", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "410", + "routeName": "Express Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "430", + "routeName": "Express Pointe-aux-Trembles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "19", + "routeName": "Chabanel / March\u00e9 Central", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "139", + "routeName": "Pie-IX", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "365", + "routeName": "Avenue du Parc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "140", + "routeName": "Fleury", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "146", + "routeName": "Christophe-Colomb / Meilleur", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "180", + "routeName": "De Salaberry", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "67", + "routeName": "Saint-Michel", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "69", + "routeName": "Gouin", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "121", + "routeName": "Sauv\u00e9 / C\u00f4te-Vertu", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "439", + "routeName": "Express Pie-IX", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "440", + "routeName": "Express Charleroi", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "131", + "routeName": "De l'Assomption", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "136", + "routeName": "Viau", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "56", + "routeName": "Saint-Hubert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "177", + "routeName": "Thimens", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "174", + "routeName": "C\u00f4te-Vertu-Ouest", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "64", + "routeName": "Grenet", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "467", + "routeName": "Express Saint-Michel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "10", + "routeName": "De Lorimier", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "150", + "routeName": "Ren\u00e9-L\u00e9vesque", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "358", + "routeName": "Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "22", + "routeName": "Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "29", + "routeName": "Rachel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "125", + "routeName": "Ontario", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "168", + "routeName": "Cit\u00e9-du-Havre", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "357", + "routeName": "Saint-Michel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "34", + "routeName": "Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "50", + "routeName": "Vieux-Montr\u00e9al / Vieux-Port", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "74", + "routeName": "Bridge", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "85", + "routeName": "Hochelaga", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "94", + "routeName": "D'Iberville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "185", + "routeName": "Sherbrooke", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "176", + "routeName": "Berlioz", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "777", + "routeName": "Jean-Drapeau / Casino / Bonaventure", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "172", + "routeName": "Du Golf", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "811", + "routeName": "Navette Services sant\u00e9", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "872", + "routeName": "\u00cele-des-Soeurs", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "17", + "routeName": "D\u00e9carie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "207", + "routeName": "Jacques-Bizard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "215", + "routeName": "Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "205", + "routeName": "Gouin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "204", + "routeName": "Cardinal", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "68", + "routeName": "Pierrefonds", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "70", + "routeName": "Bois-Franc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "201", + "routeName": "Saint-Charles / Saint-Jean", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "208", + "routeName": "Brunswick", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "206", + "routeName": "Roger-Pilon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "382", + "routeName": "Pierrefonds / Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "209", + "routeName": "Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "378", + "routeName": "Sauv\u00e9 / YUL A\u00e9roport", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "217", + "routeName": "Anse-\u00e0-l'Orme", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "200", + "routeName": "Sainte-Anne-de-Bellevue", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "203", + "routeName": "Carson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "376", + "routeName": "Pierrefonds / Centre-ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "117", + "routeName": "O'Brien", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "968", + "routeName": "Trainbus Roxboro / C\u00f4te-Vertu", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "216", + "routeName": "Transcanadienne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "225", + "routeName": "Hymus", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "72", + "routeName": "Alfred-Nobel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "219", + "routeName": "Chemin Sainte-Marie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "401", + "routeName": "Express Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "218", + "routeName": "Antoine-Faucon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "73", + "routeName": "Dalton", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "196", + "routeName": "Parc-Industriel-Lachine", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "468", + "routeName": "Express Pierrefonds / Gouin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "126", + "routeName": "Thimens / Grenet", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "220", + "routeName": "Kieran", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "475", + "routeName": "Express Dollard-des-Ormeaux", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "407", + "routeName": "Express \u00cele-Bizard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "419", + "routeName": "Express John Abbott", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "212", + "routeName": "Sainte-Anne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + } +] \ No newline at end of file diff --git a/web-app/src/app/constants/RouteTypes.tsx b/web-app/src/app/constants/RouteTypes.tsx new file mode 100644 index 000000000..d6afbb0da --- /dev/null +++ b/web-app/src/app/constants/RouteTypes.tsx @@ -0,0 +1,48 @@ +import TramIcon from '@mui/icons-material/Tram'; +import SubwayIcon from '@mui/icons-material/Subway'; +import TrainIcon from '@mui/icons-material/Train'; +import DirectionsBusIcon from '@mui/icons-material/DirectionsBus'; +import DirectionsBoatIcon from '@mui/icons-material/DirectionsBoat'; +import CableIcon from '@mui/icons-material/Cable'; +import EmojiTransportationIcon from '@mui/icons-material/EmojiTransportation'; // for Gondola +import TerrainIcon from '@mui/icons-material/Terrain'; // for Funicular +import DepartureBoardIcon from '@mui/icons-material/DepartureBoard'; // for Monorail +import SpeedIcon from '@mui/icons-material/Speed'; // for High Speed Train +import FlightIcon from '@mui/icons-material/Flight'; +import MeetingRoomIcon from '@mui/icons-material/MeetingRoom'; +import PlaceIcon from '@mui/icons-material/Place'; +import DirectionsSubwayIcon from '@mui/icons-material/DirectionsSubway'; +import type { SvgIconComponent } from '@mui/icons-material'; + +export interface RouteTypeMetadata { + name: string; + icon: SvgIconComponent; +} + +export type LocationTypeMetadata = RouteTypeMetadata; + +export const routeTypesMapping: Record = { + '0': { name: 'Tram', icon: TramIcon }, + '1': { name: 'Subway', icon: SubwayIcon }, + '2': { name: 'Rail', icon: TrainIcon }, + '3': { name: 'Bus', icon: DirectionsBusIcon }, + '4': { name: 'Ferry', icon: DirectionsBoatIcon }, + '5': { name: 'Cable Car', icon: CableIcon }, + '6': { name: 'Gondola', icon: EmojiTransportationIcon }, + '7': { name: 'Funicular', icon: TerrainIcon }, + '11': { name: 'Monorail', icon: DepartureBoardIcon }, + '12': { name: 'High Speed Train', icon: SpeedIcon }, + '13': { name: 'Airplane', icon: FlightIcon }, +}; + +// TODO: find better icons for these +export const locationTypesMapping: Record = { + '0': { name: 'Stop', icon: DirectionsBusIcon }, + '1': { name: 'Station', icon: TrainIcon }, + '2': { name: 'Entrance/Exit', icon: MeetingRoomIcon }, + '3': { name: 'Generic Node', icon: PlaceIcon }, + '4': { name: 'Boarding Area', icon: DirectionsSubwayIcon }, +}; +export const reversedRouteTypesMapping = Object.fromEntries( + Object.entries(routeTypesMapping).map(([k, v]) => [v.name, k]), +); diff --git a/web-app/src/app/router/Router.tsx b/web-app/src/app/router/Router.tsx index 4a021ecf5..48ad4caeb 100644 --- a/web-app/src/app/router/Router.tsx +++ b/web-app/src/app/router/Router.tsx @@ -34,6 +34,7 @@ import GBFSFeedAnalytics from '../screens/Analytics/GBFSFeedAnalytics'; import GBFSNoticeAnalytics from '../screens/Analytics/GBFSNoticeAnalytics'; import GBFSVersionAnalytics from '../screens/Analytics/GBFSVersionAnalytics'; import ContactUs from '../screens/ContactUs'; +import FullMapView from '../screens/Feed/components/FullMapView'; export const AppRouter: React.FC = () => { const navigateTo = useNavigate(); @@ -101,6 +102,8 @@ export const AppRouter: React.FC = () => { /> } /> } /> + } /> + } /> } /> } /> } /> diff --git a/web-app/src/app/screens/Feed/Feed.styles.ts b/web-app/src/app/screens/Feed/Feed.styles.ts index 1c842a352..1fedd1833 100644 --- a/web-app/src/app/screens/Feed/Feed.styles.ts +++ b/web-app/src/app/screens/Feed/Feed.styles.ts @@ -37,6 +37,7 @@ export const featureChipsStyle: SxProps = (theme) => ({ }); export const mapBoxPositionStyle = { + position: 'relative', width: 'calc(100% + 32px)', flexGrow: 1, mb: '-16px', @@ -68,11 +69,14 @@ export const StyledTitleContainer = styled(Box)(({ theme }) => ({ alignItems: 'center', })); -export const ResponsiveListItem = styled('li')(({ theme }) => ({ +export const StyledListItem = styled('li')(({ theme }) => ({ width: '100%', margin: '5px 0', fontWeight: 'normal', fontSize: '16px', +})); + +export const ResponsiveListItem = styled(StyledListItem)(({ theme }) => ({ [theme.breakpoints.up('lg')]: { width: 'calc(50% - 15px)', }, diff --git a/web-app/src/app/screens/Feed/Map.styles.ts b/web-app/src/app/screens/Feed/Map.styles.ts new file mode 100644 index 000000000..8e14570de --- /dev/null +++ b/web-app/src/app/screens/Feed/Map.styles.ts @@ -0,0 +1,48 @@ +import { Box, styled } from '@mui/material'; + +interface StyledMapControlPanelProps { + showMapControlMobile: boolean; +} + +export const StyledMapControlPanel = styled(Box, { + shouldForwardProp: (prop) => prop !== 'showMapControlMobile', +})(({ theme, showMapControlMobile }) => ({ + padding: theme.spacing(2), + paddingTop: '100px', // to account for the fixed header on mobile + flexDirection: 'column', + flexWrap: 'nowrap', + backgroundColor: theme.palette.background.paper, + zIndex: 10000, + display: showMapControlMobile ? 'flex' : 'none', + width: '100%', + position: 'fixed', + top: 0, + height: '100%', + overflowY: 'auto', + margin: 0, + borderRadius: theme.shape.borderRadius, + + [theme.breakpoints.up('md')]: { + display: 'flex', + width: '300px', + position: 'relative', + top: 'unset', + paddingTop: 0, + margin: theme.spacing(2), + }, +})); + +export const StyledChipFilterContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing(1), + padding: theme.spacing(1), + minHeight: '50px', + flexWrap: 'nowrap', + overflowX: 'auto', + + [theme.breakpoints.up('md')]: { + flexWrap: 'wrap', + overflowX: 'hidden', + }, +})); diff --git a/web-app/src/app/screens/Feed/components/FeedSummary.tsx b/web-app/src/app/screens/Feed/components/FeedSummary.tsx index 81f13773e..71a329a4d 100644 --- a/web-app/src/app/screens/Feed/components/FeedSummary.tsx +++ b/web-app/src/app/screens/Feed/components/FeedSummary.tsx @@ -40,8 +40,12 @@ import { ResponsiveListItem, boxElementStyleProducerURL, featureChipsStyle, + StyledListItem, } from '../Feed.styles'; import FeedAuthenticationSummaryInfo from './FeedAuthenticationSummaryInfo'; +import CommuteIcon from '@mui/icons-material/Commute'; +import { Link as RouterLink } from 'react-router-dom'; +import TravelExploreIcon from '@mui/icons-material/TravelExplore'; export interface FeedSummaryProps { feed: GTFSFeedType | GTFSRTFeedType | undefined; @@ -104,9 +108,15 @@ export default function FeedSummary({ listStyle: providersToDisplay.length <= 1 ? 'none' : undefined, }} > - {providersToDisplay.map((provider) => ( - {provider} - ))} + {providersToDisplay.map((provider) => + providersToDisplay.length <= 1 ? ( + {provider} + ) : ( + + {provider} + + ), + )} {!showAllProviders && sortedProviders.length > 4 && ( @@ -132,6 +142,58 @@ export default function FeedSummary({ )} + {feed?.data_type === 'gtfs' && ( + + + {/* TODO: get back to this */} + + + Number of Routes + + + + 130 + + + + + + + + )} + {feed?.data_type === 'gtfs' && ( + + + {/* TODO: get back to this */} + + + Type of Routes + + + + Bus, Ferry, Tram + + + + + + + + )} {latestDataset?.agency_timezone != undefined && ( diff --git a/web-app/src/app/screens/Feed/components/FullMapView.tsx b/web-app/src/app/screens/Feed/components/FullMapView.tsx new file mode 100644 index 000000000..88d2d2c2b --- /dev/null +++ b/web-app/src/app/screens/Feed/components/FullMapView.tsx @@ -0,0 +1,320 @@ +import { Box, Fab, Button, Chip, useTheme } from '@mui/material'; +import RouteSelector from '../../../components/RouteSelector'; +import sampleRoutes from './sample-route-output.json'; // STM +// import sampleRoutes from './routes_TBM-2622_sample.json'; // BOrdaux +import React, { useState } from 'react'; +import { GtfsVisualizationMap } from '../../../components/GtfsVisualizationMap'; +import CloseIcon from '@mui/icons-material/Close'; +import NestedCheckboxList, { + type CheckboxStructure, +} from '../../../components/NestedCheckboxList'; +import { routeTypesMapping } from '../../../constants/RouteTypes'; +import { ChevronLeft } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import { SearchHeader } from '../../../styles/Filters.styles'; +import FilterAltIcon from '@mui/icons-material/FilterAlt'; +import { + StyledChipFilterContainer, + StyledMapControlPanel, +} from '../Map.styles'; +import { + selectBoundingBoxFromLatestDataset, + selectDatasetsLoadingStatus, + selectLatestDatasetsData, +} from '../../../store/selectors'; +import { useSelector } from 'react-redux'; +import { useParams } from 'react-router-dom'; +import { loadingDataset } from '../../../store/dataset-reducer'; +import { useAppDispatch } from '../../../hooks'; + +export default function FullMapView(): React.ReactElement { + const { t } = useTranslation('feeds'); + const { feedId, feedDataType } = useParams(); + const theme = useTheme(); + const [filteredRoutes, setFilteredRoutes] = useState([]); + const [filteredRouteTypes, setFilteredRouteTypes] = useState([]); + const [hideStops, setHideStops] = useState(false); + const [showMapControlMobile, setShowMapControlMobile] = + useState(false); + const latestDataset = useSelector(selectLatestDatasetsData); + const boundingBox = useSelector(selectBoundingBoxFromLatestDataset); + const datasetLoadingStatus = useSelector(selectDatasetsLoadingStatus); + const dispatch = useAppDispatch(); + + const clearAllFilters = (): void => { + setFilteredRoutes([]); + setFilteredRouteTypes([]); + setHideStops(false); + }; + + const getRouteDisplayName = (routeId: string): string => { + const route = sampleRoutes.find((r) => r.routeId === routeId); + return route != null ? `${route.routeId} - ${route.routeName}` : routeId; + }; + + const getUniqueRouteTypesCheckboxData = ( + routes: Array<{ routeType: string }>, + ): CheckboxStructure[] => { + const uniqueTypes = new Set(); + routes.forEach((route) => { + if (route?.routeType !== '') { + uniqueTypes.add(route.routeType); + } + }); + return Array.from(uniqueTypes).map((type) => ({ + title: routeTypesMapping[type].name, + checked: filteredRouteTypes.includes(routeTypesMapping[type].name), + props: { + routeTypeId: type, + }, + type: 'checkbox', + })) as CheckboxStructure[]; + }; + + // since this is a page on it's own, we can check if the bounding box is set in state, if not we have no choice but to fetch it + // console.log( + // 'boundingBox from state', + // boundingBox, + // latestDataset, + // datasetLoadingStatus, + // feedId, + // ); + if (boundingBox == undefined && latestDataset == undefined) { + if (feedId != undefined) { + dispatch( + loadingDataset({ + feedId, + limit: 1, + }), + ); + } + } + + const renderFilterChips = (): React.ReactElement => { + return ( + + {(filteredRoutes.length > 0 || + filteredRouteTypes.length > 0 || + hideStops) && ( + + )} + {hideStops && ( + { + setHideStops(false); + }} + sx={{ cursor: 'pointer' }} + > + )} + {filteredRouteTypes.map((routeType) => ( + { + setFilteredRouteTypes((prev) => + prev.filter((type) => type !== routeType), + ); + }} + sx={{ cursor: 'pointer' }} + > + ))} + {filteredRoutes.map((routeId) => ( + { + setFilteredRoutes((prev) => prev.filter((id) => id !== routeId)); + }} + sx={{ cursor: 'pointer' }} + > + ))} + + ); + }; + + return ( + + + + + + + {renderFilterChips()} + + + + + Route Types + + { + setFilteredRouteTypes( + checkboxData + .map((item) => { + return item.checked ? item?.title ?? '' : ''; + }) + .filter((item) => item !== ''), + ); + }} + /> + + Visibility + + { + setHideStops(checkboxData[0].checked); + }} + /> + + + Routes + + { + setFilteredRoutes(val); + }} + > + + + + + + {renderFilterChips()} + + { + window.history.back(); + }} + > + + + setShowMapControlMobile(!showMapControlMobile)} + > + + + {boundingBox != undefined && ( + + )} + + + + ); +} diff --git a/web-app/src/app/screens/Feed/components/routes_TBM-2622_sample.json b/web-app/src/app/screens/Feed/components/routes_TBM-2622_sample.json new file mode 100644 index 000000000..93de5ebe8 --- /dev/null +++ b/web-app/src/app/screens/Feed/components/routes_TBM-2622_sample.json @@ -0,0 +1,1172 @@ +[ + { + "routeId": "01", + "routeName": "Lianes 1", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "02", + "routeName": "Lianes 2", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "05", + "routeName": "Lianes 5", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "06", + "routeName": "Lianes 6", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "07", + "routeName": "Lianes 7", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "08", + "routeName": "Lianes 8", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "09", + "routeName": "Lianes 9", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "15", + "routeName": "Lianes 15", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "16", + "routeName": "Lianes 16", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "20", + "routeName": "Principale 20", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "22", + "routeName": "Principale 22", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "23", + "routeName": "Principale 23", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "24", + "routeName": "Principale 24", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "25", + "routeName": "Principale 25", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "26", + "routeName": "Principale 26", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "27", + "routeName": "Principale 27", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "28", + "routeName": "Principale 28", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "29", + "routeName": "Principale 29", + "color": "#00A98B", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "30", + "routeName": "Locale 30", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "31", + "routeName": "Lianes 31", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "32", + "routeName": "Locale 32", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "33", + "routeName": "Locale 33", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "34", + "routeName": "Locale 34", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "35", + "routeName": "Lianes 35", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "37", + "routeName": "Locale 37", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "38", + "routeName": "Locale 38", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "39", + "routeName": "Lianes 39", + "color": "#00B1EB", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "51", + "routeName": "Directe 51", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "52", + "routeName": "Directe 52", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "53", + "routeName": "Directe 53", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "454", + "routeName": "Directe 54", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "55", + "routeName": "Directe 55", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "57", + "routeName": "Directe 57", + "color": "#4A4A49", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "460", + "routeName": "Locale 60", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "461", + "routeName": "Locale 61", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "64", + "routeName": "Locale 64", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "65", + "routeName": "Locale 65", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "66", + "routeName": "Locale 66", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "67", + "routeName": "Locale 67", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "469", + "routeName": "Locale 69", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "70", + "routeName": "Locale 70", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "71", + "routeName": "Locale 71", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "72", + "routeName": "Locale 72", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "73", + "routeName": "Locale 73", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "74", + "routeName": "Locale 74", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "75", + "routeName": "Locale 75", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "76", + "routeName": "Locale 76", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "77", + "routeName": "Locale 77", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "78", + "routeName": "Locale 78", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "79", + "routeName": "Locale 79", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "80", + "routeName": "Locale 80", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "81", + "routeName": "Locale 81", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "82", + "routeName": "Locale 82", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "83", + "routeName": "Locale 83", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "84", + "routeName": "Locale 84", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "85", + "routeName": "Locale 85", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "86", + "routeName": "Locale 86", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "87", + "routeName": "Locale 87", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "89", + "routeName": "Locale 89", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "90", + "routeName": "Locale 90", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "951", + "routeName": "LE BATO 1", + "color": "#006BB5", + "textColor": "#FFFFFF", + "routeType": "4", + "startDate": "", + "endDate": "" + }, + { + "routeId": "952", + "routeName": "LE BATO 2", + "color": "#006BB5", + "textColor": "#FFFFFF", + "routeType": "4", + "startDate": "", + "endDate": "" + }, + { + "routeId": "953", + "routeName": "LE BATO 3", + "color": "#006BB5", + "textColor": "#FFFFFF", + "routeType": "4", + "startDate": "", + "endDate": "" + }, + { + "routeId": "19", + "routeName": "Navette Arena", + "color": "#CD117E", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "568", + "routeName": "Flex' Artigues", + "color": "#76B82A", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "59", + "routeName": "Ligne A", + "color": "#831F82", + "textColor": "#FFFFFF", + "routeType": "0", + "startDate": "", + "endDate": "" + }, + { + "routeId": "159", + "routeName": "Bus Relais A", + "color": "#8CBF44", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "161", + "routeName": "Bus Relais C", + "color": "#8CBF44", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "60", + "routeName": "Ligne B", + "color": "#E50040", + "textColor": "#FFFFFF", + "routeType": "0", + "startDate": "", + "endDate": "" + }, + { + "routeId": "61", + "routeName": "Ligne C", + "color": "#D35098", + "textColor": "#FFFFFF", + "routeType": "0", + "startDate": "", + "endDate": "" + }, + { + "routeId": "62", + "routeName": "Ligne D", + "color": "#9262A3", + "textColor": "#FFFFFF", + "routeType": "0", + "startDate": "", + "endDate": "" + }, + { + "routeId": "901", + "routeName": "BUS EXPRESS G", + "color": "#006685", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "501", + "routeName": "Flex'Night 1", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "502", + "routeName": "Flex'Night 2", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "503", + "routeName": "Flex'Night 3", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "504", + "routeName": "Flex'Night 4", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "505", + "routeName": "Flex'Night 5", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "506", + "routeName": "Flex'Night 6", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "507", + "routeName": "Flex'Night 7", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "810", + "routeName": "SCODI S10", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "811", + "routeName": "SCODI S11", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "813", + "routeName": "SCODI S13", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "814", + "routeName": "SCODI S14", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "815", + "routeName": "SCODI S15", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "816", + "routeName": "SCODI S16", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "817", + "routeName": "SCODI S17", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "801", + "routeName": "SCODI S01", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "820", + "routeName": "SCODI S20", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "821", + "routeName": "SCODI S21", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "822", + "routeName": "SCODI S22", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "824", + "routeName": "SCODI S24", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "825", + "routeName": "SCODI S25", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "826", + "routeName": "SCODI S26", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "827", + "routeName": "SCODI S27", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "828", + "routeName": "SCODI S28", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "829", + "routeName": "SCODI S29", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "802", + "routeName": "SCODI S02", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "830", + "routeName": "SCODI S30", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "832", + "routeName": "SCODI S32", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "833", + "routeName": "SCODI S33", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "834", + "routeName": "SCODI S34", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "835", + "routeName": "SCODI S35", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "836", + "routeName": "SCODI S36", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "837", + "routeName": "SCODI S37", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "838", + "routeName": "SCODI S38", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "839", + "routeName": "SCODI S39", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "803", + "routeName": "SCODI S03", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "840", + "routeName": "SCODI S40", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "842", + "routeName": "SCODI S42", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "843", + "routeName": "SCODI S43", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "844", + "routeName": "SCODI S44", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "845", + "routeName": "SCODI S45", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "846", + "routeName": "SCODI S46", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "847", + "routeName": "SCODI S47", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "848", + "routeName": "SCODI S48", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "849", + "routeName": "SCODI S49", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "804", + "routeName": "SCODI S04", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "853", + "routeName": "SCODI S53", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "855", + "routeName": "SCODI S55", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "856", + "routeName": "SCODI S56", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "857", + "routeName": "SCODI S57", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "858", + "routeName": "SCODI S58", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "859", + "routeName": "SCODI S59", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "805", + "routeName": "SCODI S05", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "860", + "routeName": "SCODI S60", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "864", + "routeName": "SCODI S64", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "807", + "routeName": "SCODI S07", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "808", + "routeName": "SCODI S08", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "809", + "routeName": "SCODI S09", + "color": "#164194", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + }, + { + "routeId": "58", + "routeName": "TBNight", + "color": "#0C324C", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "", + "endDate": "" + } +] \ No newline at end of file diff --git a/web-app/src/app/screens/Feed/components/sample-route-output.json b/web-app/src/app/screens/Feed/components/sample-route-output.json new file mode 100644 index 000000000..cbe3d6de9 --- /dev/null +++ b/web-app/src/app/screens/Feed/components/sample-route-output.json @@ -0,0 +1,3410 @@ +[ + { + "routeId": "1", + "routeName": "Ligne 1 - Verte", + "color": "#00B300", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "2", + "routeName": "Ligne 2 - Orange", + "color": "#D95700", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "4", + "routeName": "Ligne 4 - Jaune", + "color": "#FFD900", + "textColor": "#000000", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "5", + "routeName": "Ligne 5 - Bleue", + "color": "#0095E6", + "textColor": "#FFFFFF", + "routeType": "1", + "startDate": "20241028", + "endDate": "20250103", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "93", + "routeName": "Jean-Talon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "16", + "routeName": "Graham", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "160", + "routeName": "Barclay", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "100", + "routeName": "Cr\u00e9mazie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "80", + "routeName": "Avenue du Parc", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "380", + "routeName": "Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "105", + "routeName": "Sherbrooke", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "171", + "routeName": "Henri-Bourassa", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "371", + "routeName": "D\u00e9carie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "103", + "routeName": "Monkland", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "162", + "routeName": "Westminster", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "369", + "routeName": "C\u00f4te-des-Neiges", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "166", + "routeName": "Queen-Mary", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "119", + "routeName": "Rockland", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "124", + "routeName": "Victoria", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "128", + "routeName": "Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "363", + "routeName": "Boulevard Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "165", + "routeName": "C\u00f4te-des-Neiges", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "470", + "routeName": "Express Pierrefonds", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "711", + "routeName": "Parc-du-Mont-Royal / Oratoire", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "747", + "routeName": "YUL A\u00e9roport / Centre-Ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "460", + "routeName": "Express M\u00e9tropolitaine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "164", + "routeName": "Dudemaine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "51", + "routeName": "\u00c9douard-Montpetit", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "92", + "routeName": "Jean-Talon Ouest", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "54", + "routeName": "Charland / Chabanel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "465", + "routeName": "Express C\u00f4te-des-Neiges", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "480", + "routeName": "Express du Parc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "115", + "routeName": "Par\u00e9", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "95", + "routeName": "B\u00e9langer", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "47", + "routeName": "Masson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "25", + "routeName": "Angus", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "97", + "routeName": "Avenue-du-Mont-Royal", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "192", + "routeName": "Robert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "213", + "routeName": "Parc-Industriel-Saint-Laurent", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "170", + "routeName": "Keller", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "175", + "routeName": "Griffith / Saint-Fran\u00e7ois", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "135", + "routeName": "De l'Esplanade", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "202", + "routeName": "Dawson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "129", + "routeName": "C\u00f4te-Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "24", + "routeName": "Sherbrooke", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "55", + "routeName": "Boulevard Saint-Laurent", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "18", + "routeName": "Beaubien", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "409", + "routeName": "Express Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "485", + "routeName": "Express Antoine-Faucon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "26", + "routeName": "Mercier-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "186", + "routeName": "Sherbrooke-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "44", + "routeName": "Armand-Bombardier", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "33", + "routeName": "Langelier", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "32", + "routeName": "Lacordaire", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "28", + "routeName": "Honor\u00e9-Beaugrand", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "187", + "routeName": "Ren\u00e9-L\u00e9vesque", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "189", + "routeName": "Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "86", + "routeName": "Pointe-aux-Trembles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "362", + "routeName": "Hochelaga / Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "49", + "routeName": "Maurice-Duplessis", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "43", + "routeName": "Monselet", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "372", + "routeName": "Jean-Talon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "141", + "routeName": "Jean-Talon Est", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "364", + "routeName": "Sherbrooke / Joseph-Renaud", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "355", + "routeName": "Pie-IX", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "353", + "routeName": "Lacordaire / Maurice-Duplessis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "81", + "routeName": "Saint-Jean-Baptiste", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "183", + "routeName": "Gouin Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "40", + "routeName": "Henri-Bourassa-Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "188", + "routeName": "Couture", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "487", + "routeName": "Express Bout-de-l'\u00cele", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "448", + "routeName": "Express Maurice-Duplessis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "486", + "routeName": "Express Sherbrooke", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "449", + "routeName": "Express Rivi\u00e8re-des-Prairies", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "428", + "routeName": "Express Parcs industriels de l'Est", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "432", + "routeName": "Express Lacordaire", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "39", + "routeName": "Des Grandes-Prairies", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "48", + "routeName": "Perras", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "197", + "routeName": "Rosemont", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "469", + "routeName": "Express Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "45", + "routeName": "Papineau", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "193", + "routeName": "Jarry", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "444", + "routeName": "Express C\u00e9gep Marie-Victorin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "822", + "routeName": "Navette Longue-Pointe", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "179", + "routeName": "De l'Acadie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "161", + "routeName": "Van Horne", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "361", + "routeName": "Saint-Denis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "144", + "routeName": "Avenue des Pins", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "30", + "routeName": "Saint-Denis / Saint-Hubert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "31", + "routeName": "Saint-Denis", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "66", + "routeName": "The Boulevard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "370", + "routeName": "Rosemont", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "99", + "routeName": "Villeray", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "13", + "routeName": "Christophe-Colomb", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "445", + "routeName": "Express Papineau", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "46", + "routeName": "Casgrain", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "52", + "routeName": "de Li\u00e8ge", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "427", + "routeName": "Express Saint-Joseph", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "41", + "routeName": "Quartier Saint-Michel / Ahuntsic", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "108", + "routeName": "Bannantyne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "12", + "routeName": "\u00cele-des-Soeurs", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "57", + "routeName": "Charlevoix", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "90", + "routeName": "Saint-Jacques", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "71", + "routeName": "Pointe-Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "113", + "routeName": "Lapierre", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "496", + "routeName": "Express Victoria", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "35", + "routeName": "Griffintown", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "112", + "routeName": "Airlie", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "114", + "routeName": "Angrignon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "106", + "routeName": "Newman", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "110", + "routeName": "Centrale", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "350", + "routeName": "Verdun / LaSalle", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "198", + "routeName": "Broadway", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "36", + "routeName": "Monk", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "37", + "routeName": "Jolicoeur", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "195", + "routeName": "Dorval / Angrignon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "38", + "routeName": "De l'\u00c9glise", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "356", + "routeName": "Lachine / YUL A\u00e9roport / Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "102", + "routeName": "Somerled", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "107", + "routeName": "Verdun", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "61", + "routeName": "Wellington", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "360", + "routeName": "Avenue des Pins", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "104", + "routeName": "Cavendish", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "63", + "routeName": "Girouard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "211", + "routeName": "Bord-du-Lac", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "354", + "routeName": "Sainte-Anne-de-Bellevue / Centre-ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "123", + "routeName": "Dollard / Shevchenko", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "138", + "routeName": "Notre-Dame-de-Gr\u00e2ce", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "190", + "routeName": "Norman", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "425", + "routeName": "Express Anse-\u00e0-l'Orme", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "405", + "routeName": "Express Bord-du-Lac", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "411", + "routeName": "Express Lionel-Groulx", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "101", + "routeName": "Saint-Patrick", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "491", + "routeName": "Express Provost", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "420", + "routeName": "Express Notre-Dame-de-Gr\u00e2ce", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "11", + "routeName": "Parc-du-Mont-Royal / Ridgewood", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "27", + "routeName": "Boulevard Saint-Joseph", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "368", + "routeName": "Avenue-du-Mont-Royal", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "14", + "routeName": "Atateken", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "359", + "routeName": "Papineau", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "410", + "routeName": "Express Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "430", + "routeName": "Express Pointe-aux-Trembles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "19", + "routeName": "Chabanel / March\u00e9 Central", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "139", + "routeName": "Pie-IX", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "365", + "routeName": "Avenue du Parc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "140", + "routeName": "Fleury", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "146", + "routeName": "Christophe-Colomb / Meilleur", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "180", + "routeName": "De Salaberry", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "67", + "routeName": "Saint-Michel", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "69", + "routeName": "Gouin", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "121", + "routeName": "Sauv\u00e9 / C\u00f4te-Vertu", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "439", + "routeName": "Express Pie-IX", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "440", + "routeName": "Express Charleroi", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "131", + "routeName": "De l'Assomption", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "136", + "routeName": "Viau", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "56", + "routeName": "Saint-Hubert", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "177", + "routeName": "Thimens", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "174", + "routeName": "C\u00f4te-Vertu-Ouest", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "64", + "routeName": "Grenet", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "467", + "routeName": "Express Saint-Michel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "10", + "routeName": "De Lorimier", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "150", + "routeName": "Ren\u00e9-L\u00e9vesque", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "358", + "routeName": "Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "22", + "routeName": "Notre-Dame", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "29", + "routeName": "Rachel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "125", + "routeName": "Ontario", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "168", + "routeName": "Cit\u00e9-du-Havre", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "357", + "routeName": "Saint-Michel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "34", + "routeName": "Sainte-Catherine", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "50", + "routeName": "Vieux-Montr\u00e9al / Vieux-Port", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "74", + "routeName": "Bridge", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "85", + "routeName": "Hochelaga", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "94", + "routeName": "D'Iberville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "185", + "routeName": "Sherbrooke", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "176", + "routeName": "Berlioz", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "777", + "routeName": "Jean-Drapeau / Casino / Bonaventure", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "172", + "routeName": "Du Golf", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "811", + "routeName": "Navette Services sant\u00e9", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "872", + "routeName": "\u00cele-des-Soeurs", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "17", + "routeName": "D\u00e9carie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "207", + "routeName": "Jacques-Bizard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "215", + "routeName": "Henri-Bourassa", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "205", + "routeName": "Gouin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "204", + "routeName": "Cardinal", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "68", + "routeName": "Pierrefonds", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "70", + "routeName": "Bois-Franc", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "201", + "routeName": "Saint-Charles / Saint-Jean", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "208", + "routeName": "Brunswick", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "206", + "routeName": "Roger-Pilon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "382", + "routeName": "Pierrefonds / Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "209", + "routeName": "Des Sources", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "378", + "routeName": "Sauv\u00e9 / YUL A\u00e9roport", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "217", + "routeName": "Anse-\u00e0-l'Orme", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "200", + "routeName": "Sainte-Anne-de-Bellevue", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "203", + "routeName": "Carson", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "376", + "routeName": "Pierrefonds / Centre-ville", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "117", + "routeName": "O'Brien", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "968", + "routeName": "Trainbus Roxboro / C\u00f4te-Vertu", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + }, + { + "routeId": "216", + "routeName": "Transcanadienne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "225", + "routeName": "Hymus", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "72", + "routeName": "Alfred-Nobel", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "219", + "routeName": "Chemin Sainte-Marie", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "401", + "routeName": "Express Saint-Charles", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "218", + "routeName": "Antoine-Faucon", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "73", + "routeName": "Dalton", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "196", + "routeName": "Parc-Industriel-Lachine", + "color": "#781B7D", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "468", + "routeName": "Express Pierrefonds / Gouin", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "126", + "routeName": "Thimens / Grenet", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "220", + "routeName": "Kieran", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "475", + "routeName": "Express Dollard-des-Ormeaux", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "407", + "routeName": "Express \u00cele-Bizard", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "419", + "routeName": "Express John Abbott", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241028", + "endDate": "20241220", + "monday": true, + "tuesday": true, + "wednesday": true, + "thursday": true, + "friday": true, + "saturday": false, + "sunday": false + }, + { + "routeId": "212", + "routeName": "Sainte-Anne", + "color": "#009EE0", + "textColor": "#FFFFFF", + "routeType": "3", + "startDate": "20241102", + "endDate": "20241221", + "monday": false, + "tuesday": false, + "wednesday": false, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false + } +] \ No newline at end of file diff --git a/web-app/src/app/screens/Feed/index.tsx b/web-app/src/app/screens/Feed/index.tsx index 97db57b03..85fe228b8 100644 --- a/web-app/src/app/screens/Feed/index.tsx +++ b/web-app/src/app/screens/Feed/index.tsx @@ -340,12 +340,12 @@ export default function Feed(): React.ReactElement { feedId, structuredData, - - + + ({ - '&.no-collapse': { - margin: '12px 0', - }, - '&:not(:first-of-type)': { - marginTop: theme.spacing(1), - }, - '&:after': { - content: '""', - display: 'block', - height: '3px', - width: '104px', - background: theme.palette.text.primary, - }, -})); +import { type SxProps, type Theme } from '@mui/material'; export const chipHolderStyles: SxProps = (theme) => ({ display: 'flex', diff --git a/web-app/src/app/screens/Feeds/SearchFilters.tsx b/web-app/src/app/screens/Feeds/SearchFilters.tsx index 3e0cd5f0c..c1e4f2c7e 100644 --- a/web-app/src/app/screens/Feeds/SearchFilters.tsx +++ b/web-app/src/app/screens/Feeds/SearchFilters.tsx @@ -2,13 +2,13 @@ import { Accordion, AccordionSummary, AccordionDetails } from '@mui/material'; import NestedCheckboxList, { type CheckboxStructure, } from '../../components/NestedCheckboxList'; -import { SearchHeader } from './Feeds.styles'; import { useTranslation } from 'react-i18next'; import { useRemoteConfig } from '../../context/RemoteConfigProvider'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { useEffect, useState } from 'react'; import { DATASET_FEATURES, groupFeaturesByComponent } from '../../utils/consts'; import { type GbfsVersionConfig } from '../../interface/RemoteConfig'; +import { SearchHeader } from '../../styles/Filters.styles'; function setInitialExpandGroup(): Record { const expandGroup: Record = {}; diff --git a/web-app/src/app/styles/Filters.styles.ts b/web-app/src/app/styles/Filters.styles.ts new file mode 100644 index 000000000..c0f180cdc --- /dev/null +++ b/web-app/src/app/styles/Filters.styles.ts @@ -0,0 +1,17 @@ +import { styled, Typography } from '@mui/material'; + +export const SearchHeader = styled(Typography)(({ theme }) => ({ + '&.no-collapse': { + margin: '12px 0', + }, + '&:not(:first-of-type)': { + marginTop: theme.spacing(1), + }, + '&:after': { + content: '""', + display: 'block', + height: '3px', + width: '104px', + background: theme.palette.text.primary, + }, +})); diff --git a/web-app/yarn.lock b/web-app/yarn.lock index ef73f9a02..6011cde5b 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -2416,6 +2416,71 @@ resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== +"@mapbox/geojson-rewind@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz#591a5d71a9cd1da1a0bf3420b3bea31b0fc7946a" + integrity sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA== + dependencies: + get-stream "^6.0.1" + minimist "^1.2.6" + +"@mapbox/jsonlint-lines-primitives@^2.0.2", "@mapbox/jsonlint-lines-primitives@~2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234" + integrity sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ== + +"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2" + integrity sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ== + +"@mapbox/tiny-sdf@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz#9a1d33e5018093e88f6a4df2343e886056287282" + integrity sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA== + +"@mapbox/unitbezier@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01" + integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw== + +"@mapbox/vector-tile@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666" + integrity sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw== + dependencies: + "@mapbox/point-geometry" "~0.1.0" + +"@mapbox/whoots-js@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" + integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== + +"@maplibre/maplibre-gl-style-spec@^19.2.1": + version "19.3.3" + resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz#a106248bd2e25e77c963a362aeaf630e00f924e9" + integrity sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw== + dependencies: + "@mapbox/jsonlint-lines-primitives" "~2.0.2" + "@mapbox/unitbezier" "^0.0.1" + json-stringify-pretty-compact "^3.0.0" + minimist "^1.2.8" + rw "^1.3.3" + sort-object "^3.0.3" + +"@maplibre/maplibre-gl-style-spec@^20.3.1": + version "20.4.0" + resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.4.0.tgz#408339e051fb51e022b40af2235e0beb037937ea" + integrity sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw== + dependencies: + "@mapbox/jsonlint-lines-primitives" "~2.0.2" + "@mapbox/unitbezier" "^0.0.1" + json-stringify-pretty-compact "^4.0.0" + minimist "^1.2.8" + quickselect "^2.0.0" + rw "^1.3.3" + tinyqueue "^3.0.0" + "@mui/base@^5.0.0-beta.20": version "5.0.0-beta.30" resolved "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.30.tgz" @@ -3326,11 +3391,23 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson-vt@3.2.5": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/geojson-vt/-/geojson-vt-3.2.5.tgz#b6c356874991d9ab4207533476dfbcdb21e38408" + integrity sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g== + dependencies: + "@types/geojson" "*" + "@types/geojson@*": version "7946.0.14" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== +"@types/geojson@^7946.0.14": + version "7946.0.16" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" + integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== + "@types/glob@*": version "8.1.0" resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz" @@ -3445,6 +3522,27 @@ resolved "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== +"@types/mapbox-gl@*", "@types/mapbox-gl@>=1.0.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-3.4.1.tgz#b6a1b81b802e62fb7e1d1d13a97ccece63b232a3" + integrity sha512-NsGKKtgW93B+UaLPti6B7NwlxYlES5DpV5Gzj9F75rK5ALKsqSk15CiEHbOnTr09RGbr6ZYiCdI+59NNNcAImg== + dependencies: + "@types/geojson" "*" + +"@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz#0ef017b75eedce02ff6243b4189210e2e6d5e56d" + integrity sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA== + +"@types/mapbox__vector-tile@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz#ad757441ef1d34628d9e098afd9c91423c1f8734" + integrity sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg== + dependencies: + "@types/geojson" "*" + "@types/mapbox__point-geometry" "*" + "@types/pbf" "*" + "@types/markdown-it@^12.2.3": version "12.2.3" resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz" @@ -3525,6 +3623,11 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== +"@types/pbf@*", "@types/pbf@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.5.tgz#a9495a58d8c75be4ffe9a0bd749a307715c07404" + integrity sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA== + "@types/prettier@^2.1.5": version "2.7.3" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz" @@ -3576,6 +3679,16 @@ dependencies: "@types/react" "*" +"@types/react-map-gl@^6.1.7": + version "6.1.7" + resolved "https://registry.yarnpkg.com/@types/react-map-gl/-/react-map-gl-6.1.7.tgz#c3e81ccd21c31cee8fe1576eab894cf6d4be9f0a" + integrity sha512-szkfkWd3FbySDkxyn0MDj9yzD8XYk+RIi4od6sGb3lVHNBGcW20G2v2vcq2N5k18UYAdqAoKGSYuHkGV4JOCrA== + dependencies: + "@types/geojson" "*" + "@types/mapbox-gl" "*" + "@types/react" "*" + "@types/viewport-mercator-project" "*" + "@types/react-redux@^7.1.27": version "7.1.31" resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.31.tgz" @@ -3709,6 +3822,13 @@ resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/supercluster@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/supercluster/-/supercluster-7.1.3.tgz#1a1bc2401b09174d9c9e44124931ec7874a72b27" + integrity sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA== + dependencies: + "@types/geojson" "*" + "@types/testing-library__jest-dom@^5.9.1": version "5.14.9" resolved "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz" @@ -3731,6 +3851,13 @@ resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz" integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== +"@types/viewport-mercator-project@*": + version "6.1.6" + resolved "https://registry.yarnpkg.com/@types/viewport-mercator-project/-/viewport-mercator-project-6.1.6.tgz#74874286099e9506943c3f868c9cbeaf2a6d1559" + integrity sha512-uWrbqhRXFeiT6CAvRjf0BkQKRkKED+ofrPhglKpUktQML3463dEPiA4iwe7cZQs6m49Zo/g03rL7ChMLiE5Z8w== + dependencies: + gl-matrix "^3.2.0" + "@types/ws@^8.5.5": version "8.5.10" resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz" @@ -4372,6 +4499,11 @@ aria-query@^5.0.0, aria-query@^5.3.0: dependencies: dequal "^2.0.3" +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + array-buffer-byte-length@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" @@ -4504,6 +4636,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + ast-types-flow@^0.0.8: version "0.0.8" resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz" @@ -5018,6 +5155,21 @@ bytes@3.1.2: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + cacache@^18.0.0: version "18.0.0" resolved "https://registry.npmjs.org/cacache/-/cacache-18.0.0.tgz" @@ -6438,6 +6590,11 @@ duplexify@^4.0.0: readable-stream "^3.1.1" stream-shift "^1.0.0" +earcut@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.1.tgz#f60b3f671c5657cca9d3e131c5527c5dde00ef38" + integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" @@ -7272,6 +7429,21 @@ express@^4.16.4, express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" @@ -7388,6 +7560,11 @@ fecha@^4.2.0: resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" @@ -7838,6 +8015,11 @@ gensync@^1.0.0-beta.2: resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +geojson-vt@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-4.0.2.tgz#1162f6c7d61a0ba305b1030621e6e111f847828a" + integrity sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" @@ -7900,6 +8082,11 @@ get-uri@^6.0.1: debug "^4.3.4" fs-extra "^8.1.0" +get-value@^2.0.2, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + getos@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz" @@ -7914,6 +8101,11 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +gl-matrix@^3.2.0, gl-matrix@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9" + integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" @@ -8016,6 +8208,15 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" +global-prefix@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-4.0.0.tgz#e9cc79aab9be1d03287e156a3f912dd0895463ed" + integrity sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA== + dependencies: + ini "^4.1.3" + kind-of "^6.0.3" + which "^4.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" @@ -8507,9 +8708,9 @@ identity-obj-proxy@^3.0.0: dependencies: harmony-reflect "^1.4.6" -ieee754@^1.1.13: +ieee754@^1.1.12, ieee754@^1.1.13: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^5.2.0, ignore@^5.2.4: @@ -8581,6 +8782,11 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +ini@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.3.tgz#4c359675a6071a46985eb39b14e4a2c0ec98a795" + integrity sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg== + inquirer@^8.2.0: version "8.2.6" resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz" @@ -8759,6 +8965,18 @@ is-docker@^3.0.0: resolved "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz" integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" @@ -8872,6 +9090,13 @@ is-plain-obj@^3.0.0: resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" @@ -9029,6 +9254,11 @@ isexe@^3.1.1: resolved "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz" integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + isomorphic-fetch@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz" @@ -9857,6 +10087,16 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-pretty-compact@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz#f71ef9d82ef16483a407869556588e91b681d9ab" + integrity sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA== + +json-stringify-pretty-compact@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz#cf4844770bddee3cb89a6170fe4b00eee5dbf1d4" + integrity sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q== + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" @@ -9984,6 +10224,11 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" @@ -9991,9 +10236,9 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -kind-of@^6.0.2: +kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== klaw@^3.0.0: @@ -10435,6 +10680,38 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +maplibre-gl@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-4.7.1.tgz#06a524438ee2aafbe8bcd91002a4e01468ea5486" + integrity sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA== + dependencies: + "@mapbox/geojson-rewind" "^0.5.2" + "@mapbox/jsonlint-lines-primitives" "^2.0.2" + "@mapbox/point-geometry" "^0.1.0" + "@mapbox/tiny-sdf" "^2.0.6" + "@mapbox/unitbezier" "^0.0.1" + "@mapbox/vector-tile" "^1.3.1" + "@mapbox/whoots-js" "^3.1.0" + "@maplibre/maplibre-gl-style-spec" "^20.3.1" + "@types/geojson" "^7946.0.14" + "@types/geojson-vt" "3.2.5" + "@types/mapbox__point-geometry" "^0.1.4" + "@types/mapbox__vector-tile" "^1.3.4" + "@types/pbf" "^3.0.5" + "@types/supercluster" "^7.1.3" + earcut "^3.0.0" + geojson-vt "^4.0.2" + gl-matrix "^3.4.3" + global-prefix "^4.0.0" + kdbush "^4.0.2" + murmurhash-js "^1.0.0" + pbf "^3.3.0" + potpack "^2.0.0" + quickselect "^3.0.0" + supercluster "^8.0.1" + tinyqueue "^3.0.0" + vt-pbf "^3.1.3" + markdown-it-anchor@^8.4.1: version "8.6.7" resolved "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz" @@ -10754,6 +11031,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +murmurhash-js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51" + integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw== + mute-stream@0.0.8: version "0.0.8" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" @@ -11366,6 +11648,14 @@ path-type@^4.0.0: resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pbf@^3.2.1, pbf@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.3.0.tgz#1790f3d99118333cc7f498de816028a346ef367f" + integrity sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q== + dependencies: + ieee754 "^1.1.12" + resolve-protobuf-schema "^2.1.0" + pend@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" @@ -11415,6 +11705,13 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +pmtiles@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/pmtiles/-/pmtiles-4.3.0.tgz#65066296103ee199e8a09d399377a322ab376a14" + integrity sha512-wnzQeSiYT/MyO63o7AVxwt7+uKqU0QUy2lHrivM7GvecNy0m1A4voVyGey7bujnEW5Hn+ZzLdvHPoFaqrOzbPA== + dependencies: + fflate "^0.8.2" + portfinder@^1.0.32: version "1.0.32" resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz" @@ -11976,6 +12273,11 @@ postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.4: picocolors "^1.0.0" source-map-js "^1.0.2" +potpack@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" + integrity sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -12165,6 +12467,11 @@ protobufjs@^7.0.0, protobufjs@^7.2.4: "@types/node" ">=13.7.0" long "^5.0.0" +protocol-buffers-schema@^3.3.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" + integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" @@ -12268,6 +12575,16 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quickselect@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018" + integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw== + +quickselect@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-3.0.0.tgz#a37fc953867d56f095a20ac71c6d27063d2de603" + integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== + raf@^3.2.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz" @@ -12498,6 +12815,14 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-map-gl@^7.1.7: + version "7.1.9" + resolved "https://registry.yarnpkg.com/react-map-gl/-/react-map-gl-7.1.9.tgz#d41093ce266c342f89a2c49dec3739e980835fa7" + integrity sha512-KsCc8Gyn05wVGlHZoopaiiCr0RCAQ6LDISo5sEy1/pV/d7RlozkF946tiX7IgyijJQMRujHol5QdwUPESjh73w== + dependencies: + "@maplibre/maplibre-gl-style-spec" "^19.2.1" + "@types/mapbox-gl" ">=1.0.0" + react-redux@^8.1.3: version "8.1.3" resolved "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz" @@ -12957,6 +13282,13 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve-protobuf-schema@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" + integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== + dependencies: + protocol-buffers-schema "^3.3.1" + resolve-url-loader@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz" @@ -13083,6 +13415,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@^7.5.1, rxjs@^7.5.5, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz" @@ -13318,6 +13655,16 @@ set-function-name@^2.0.0, set-function-name@^2.0.1: functions-have-names "^1.2.3" has-property-descriptors "^1.0.0" +set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" @@ -13452,6 +13799,28 @@ socks@^2.7.1: ip "^2.0.0" smart-buffer "^4.2.0" +sort-asc@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sort-asc/-/sort-asc-0.2.0.tgz#00a49e947bc25d510bfde2cbb8dffda9f50eb2fc" + integrity sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA== + +sort-desc@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sort-desc/-/sort-desc-0.2.0.tgz#280c1bdafc6577887cedbad1ed2e41c037976646" + integrity sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w== + +sort-object@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sort-object/-/sort-object-3.0.3.tgz#945727165f244af9dc596ad4c7605a8dee80c269" + integrity sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ== + dependencies: + bytewise "^1.1.0" + get-value "^2.0.2" + is-extendable "^0.1.1" + sort-asc "^0.2.0" + sort-desc "^0.2.0" + union-value "^1.0.1" + source-list-map@^2.0.0, source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" @@ -13529,6 +13898,13 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +split-string@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" @@ -13826,6 +14202,13 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + superstatic@^9.0.3: version "9.0.3" resolved "https://registry.npmjs.org/superstatic/-/superstatic-9.0.3.tgz" @@ -14122,6 +14505,11 @@ tiny-warning@^1.0.2: resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tinyqueue@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-3.0.0.tgz#101ea761ccc81f979e29200929e78f1556e3661e" + integrity sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g== + titleize@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz" @@ -14413,6 +14801,18 @@ typescript@^5.2.2: resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz" integrity sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ== +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" @@ -14483,6 +14883,16 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== +union-value@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz" @@ -14690,6 +15100,15 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== +vt-pbf@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac" + integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA== + dependencies: + "@mapbox/point-geometry" "0.1.0" + "@mapbox/vector-tile" "^1.3.1" + pbf "^3.2.1" + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz"