Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"resultsFor": "{startResult}-{endResult} of {totalResults} results",
"deprecated": "Deprecated",
"searchPlaceholder": "Transit provider, feed name, or location",
"noResults": "We're sorry, we found no search results for '{activeSearch}'.",
"noResults": "We're sorry, we found no search results for ''{activeSearch}''.",
"searchSuggestions": "Search suggestions: ",
"searchTips": {
"twoDigit": "Use the full English name of a location e.g \"France\" or \"New York City\"",
Expand Down
2 changes: 1 addition & 1 deletion messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"resultsFor": "{startResult}-{endResult} of {totalResults} results",
"deprecated": "Deprecated",
"searchPlaceholder": "Transit provider, feed name, or location",
"noResults": "We're sorry, we found no search results for '{activeSearch}'.",
"noResults": "We're sorry, we found no search results for ''{activeSearch}''.",
"searchSuggestions": "Search suggestions: ",
"searchTips": {
"twoDigit": "Use the full English name of a location e.g \"France\" or \"New York City\"",
Expand Down
45 changes: 45 additions & 0 deletions src/app/api/revalidate/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,51 @@ const defaultRevalidateOptions: RevalidateBody = {
feedIds: [],
};

/**
* GET handler for the Vercel cron job that revalidates all feed pages once a day.
* Vercel automatically passes Authorization: Bearer <CRON_SECRET> with each invocation.
* Configured in vercel.json under "crons" (schedule: 0 9 * * * = 4am EST / 9am UTC).
*/
export async function GET(req: Request): Promise<NextResponse> {
const authHeader = req.headers.get('authorization');
const cronSecret = process.env.CRON_SECRET;

if (cronSecret == null) {
return NextResponse.json(
{ ok: false, error: 'Server misconfigured: CRON_SECRET missing' },
{ status: 500 },
);
}

if (authHeader !== `Bearer ${cronSecret}`) {
return NextResponse.json(
{ ok: false, error: 'Unauthorized' },
{ status: 401 },
);
}

try {
revalidateTag('guest-feeds', 'max');
revalidatePath('/[locale]/feeds/[feedDataType]/[feedId]', 'layout');
console.log(
'[cron] revalidate /api/revalidate: all-feeds revalidation triggered',
);
return NextResponse.json({
ok: true,
message: 'All feeds revalidated successfully',
});
} catch (error) {
console.error(
'[cron] revalidate /api/revalidate: revalidation failed:',
error,
);
return NextResponse.json(
{ ok: false, error: 'Revalidation failed' },
{ status: 500 },
);
}
}

export async function POST(req: Request): Promise<NextResponse> {
const expectedSecret = nonEmpty(process.env.REVALIDATE_SECRET);
if (expectedSecret == null) {
Expand Down
1 change: 1 addition & 0 deletions src/app/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ export default function DrawerAppBar(): React.ReactElement {
<Button
sx={{ fontFamily: fontFamily.secondary }}
href={SIGN_IN_TARGET}
component={Link}
>
Login
</Button>
Expand Down
32 changes: 16 additions & 16 deletions src/app/screens/Feed/Feed.functions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, Typography } from '@mui/material';
import {
type GTFSFeedType,
type GBFSVersionType,
type GBFSFeedType,
} from '../../services/feeds/utils';
import { type LatLngTuple } from 'leaflet';
import { type GeoJSONData, type GeoJSONDataGBFS } from '../../types';
Expand Down Expand Up @@ -192,36 +193,35 @@ export function computeBoundingBox(
}

export const getBoundingBox = (
feed: GTFSFeedType,
feed: GTFSFeedType | GBFSFeedType ,
): LatLngTuple[] | undefined => {
if (feed == undefined || feed.data_type !== 'gtfs') {
if (feed == undefined || feed.data_type === 'gtfs_rt') {
return undefined;
}
const gtfsFeed: GTFSFeedType = feed;
};
if (
gtfsFeed.bounding_box?.maximum_latitude == undefined ||
gtfsFeed.bounding_box?.maximum_longitude == undefined ||
gtfsFeed.bounding_box?.minimum_latitude == undefined ||
gtfsFeed.bounding_box?.minimum_longitude == undefined
feed.bounding_box?.maximum_latitude == undefined ||
feed.bounding_box?.maximum_longitude == undefined ||
feed.bounding_box?.minimum_latitude == undefined ||
feed.bounding_box?.minimum_longitude == undefined
) {
return undefined;
}
return [
[
gtfsFeed.bounding_box.minimum_latitude,
gtfsFeed.bounding_box.minimum_longitude,
feed.bounding_box.minimum_latitude,
feed.bounding_box.minimum_longitude,
],
[
gtfsFeed.bounding_box.minimum_latitude,
gtfsFeed.bounding_box.maximum_longitude,
feed.bounding_box.minimum_latitude,
feed.bounding_box.maximum_longitude,
],
[
gtfsFeed.bounding_box.maximum_latitude,
gtfsFeed.bounding_box.maximum_longitude,
feed.bounding_box.maximum_latitude,
feed.bounding_box.maximum_longitude,
],
[
gtfsFeed.bounding_box.maximum_latitude,
gtfsFeed.bounding_box.minimum_longitude,
feed.bounding_box.maximum_latitude,
feed.bounding_box.minimum_longitude,
],
];
};
2 changes: 1 addition & 1 deletion src/app/screens/Feed/FeedView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export default async function FeedView({
? (feed as GBFSFeedType)?.source_info?.producer_url
: undefined; // Simplified

const boundingBox = getBoundingBox(feed as GTFSFeedType);
const boundingBox = getBoundingBox(feed);

let latestDataset: LatestDatasetFull;
if (feed.data_type === 'gtfs') {
Expand Down
10 changes: 8 additions & 2 deletions src/app/screens/Feed/components/FeedNavigationControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Button, Grid, Typography } from '@mui/material';
import { ChevronLeft } from '@mui/icons-material';
import { useTranslations } from 'next-intl';
import { useRouter } from '../../../../i18n/navigation';
import { Link, useRouter } from '../../../../i18n/navigation';

interface Props {
feedDataType: string;
Expand Down Expand Up @@ -43,12 +43,18 @@ export default function FeedNavigationControls({
},
}}
>
<Button variant='text' href='/feeds' className='inline'>
<Button
variant='text'
component={Link}
href='/feeds'
className='inline'
>
{t('feeds')}
</Button>
/
<Button
variant='text'
component={Link}
href={`/feeds?${feedDataType}=true`}
className='inline'
>
Expand Down
Loading