Skip to content

Commit 406c0c9

Browse files
feed status in feed detail page (#885)
1 parent 181c30f commit 406c0c9

File tree

5 files changed

+180
-4
lines changed

5 files changed

+180
-4
lines changed

web-app/public/locales/en/feeds.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,29 @@
9494
"seeDetailPageProviders": "See detail page to view {providersCount} others",
9595
"openFullQualityReport": "Open Full Quality Report",
9696
"qualityReportUpdated": "Quality report updated",
97-
"officialFeedUpdated": "Official verification updated"
97+
"officialFeedUpdated": "Official verification updated",
98+
"serviceDateRange": "Service Date Range",
99+
"serviceDateRangeTooltip": "Dates are relative to local timezone",
100+
"feedStatus": {
101+
"active": {
102+
"label": "Active",
103+
"toolTip": "Active Feed",
104+
"toolTipLong": "This feed is currently active and being used."
105+
},
106+
"inactive": {
107+
"label": "Inactive",
108+
"toolTip": "Inactive Feed",
109+
"toolTipLong": "This feed is currently inactive and not being used."
110+
},
111+
"deprecated": {
112+
"label": "Deprecated",
113+
"toolTip": "Deprecated Feed",
114+
"toolTipLong": "This feed is deprecated and should not be used."
115+
},
116+
"future": {
117+
"label": "Future",
118+
"toolTip": "Future Feed",
119+
"toolTipLong": "This feed is not yet active but will be used in the future."
120+
}
121+
}
98122
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { Box, Chip, Tooltip } from '@mui/material';
2+
import { theme } from '../Theme';
3+
import { useTranslation } from 'react-i18next';
4+
import { type TFunction } from 'i18next';
5+
6+
export interface FeedStatusProps {
7+
status: string;
8+
}
9+
10+
interface FeedStatusData {
11+
toolTip: string;
12+
label: string;
13+
themeColor: 'success' | 'info' | 'warning' | 'error';
14+
toolTipLong: string;
15+
}
16+
17+
function getFeedStatusData(
18+
status: string,
19+
t: TFunction,
20+
): FeedStatusData | undefined {
21+
const data: Record<string, FeedStatusData> = {
22+
active: {
23+
toolTip: t('feedStatus.active.toolTip'),
24+
label: t('feedStatus.active.label'),
25+
themeColor: 'success',
26+
toolTipLong: t('feedStatus.active.toolTipLong'),
27+
},
28+
future: {
29+
toolTip: t('feedStatus.future.toolTip'),
30+
label: t('feedStatus.future.label'),
31+
themeColor: 'info',
32+
toolTipLong: t('feedStatus.future.toolTipLong'),
33+
},
34+
inactive: {
35+
toolTip: t('feedStatus.inactive.toolTip'),
36+
label: t('feedStatus.inactive.label'),
37+
themeColor: 'warning',
38+
toolTipLong: t('feedStatus.inactive.toolTipLong'),
39+
},
40+
deprecated: {
41+
toolTip: t('feedStatus.deprecated.toolTip'),
42+
label: t('feedStatus.deprecated.label'),
43+
themeColor: 'error',
44+
toolTipLong: t('feedStatus.deprecated.toolTipLong'),
45+
},
46+
};
47+
48+
return data[status];
49+
}
50+
51+
export const FeedStatusIndicator = (
52+
props: React.PropsWithChildren<FeedStatusProps>,
53+
): JSX.Element => {
54+
const { t } = useTranslation('feeds');
55+
const statusData = getFeedStatusData(props.status, t);
56+
return (
57+
<>
58+
{statusData != undefined && (
59+
<Tooltip title={statusData.toolTip} placement='top'>
60+
<Box
61+
sx={{
62+
background: theme.palette[statusData.themeColor].main,
63+
width: '12px',
64+
height: '12px',
65+
borderRadius: '50%',
66+
}}
67+
></Box>
68+
</Tooltip>
69+
)}
70+
</>
71+
);
72+
};
73+
74+
export const FeedStatusChip = (
75+
props: React.PropsWithChildren<FeedStatusProps>,
76+
): JSX.Element => {
77+
const { t } = useTranslation('feeds');
78+
const statusData = getFeedStatusData(props.status, t);
79+
return (
80+
<>
81+
{statusData != undefined && (
82+
<Tooltip title={statusData.toolTipLong} placement='top'>
83+
<Chip label={statusData.label} color={statusData.themeColor}></Chip>
84+
</Tooltip>
85+
)}
86+
</>
87+
);
88+
};

web-app/src/app/screens/Feed/DataQualitySummary.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import { WarningContentBox } from '../../components/WarningContentBox';
77
import VerifiedIcon from '@mui/icons-material/Verified';
88
import { useTranslation } from 'react-i18next';
99
import { verificationBadgeStyle } from '../../styles/VerificationBadge.styles';
10+
import { FeedStatusChip } from '../../components/FeedStatus';
1011

1112
export interface DataQualitySummaryProps {
13+
feedStatus: components['schemas']['BasicFeed']['status'];
1214
isOfficialFeed: boolean;
1315
latestDataset: components['schemas']['GtfsDataset'] | undefined;
1416
}
1517

1618
export default function DataQualitySummary({
19+
feedStatus,
1720
isOfficialFeed,
1821
latestDataset,
1922
}: DataQualitySummaryProps): React.ReactElement {
@@ -24,7 +27,8 @@ export default function DataQualitySummary({
2427
latestDataset.validation_report === null) && (
2528
<WarningContentBox>{t('errorLoadingQualityReport')}</WarningContentBox>
2629
)}
27-
<Box sx={{ display: 'flex', gap: 1 }}>
30+
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
31+
<FeedStatusChip status={feedStatus ?? ''}></FeedStatusChip>
2832
{isOfficialFeed && (
2933
<Tooltip title={t('officialFeedTooltip')} placement='top'>
3034
<Chip

web-app/src/app/screens/Feed/FeedSummary.tsx

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import DatasetIcon from '@mui/icons-material/Dataset';
3030
import LayersIcon from '@mui/icons-material/Layers';
3131
import EmailIcon from '@mui/icons-material/Email';
3232
import LockIcon from '@mui/icons-material/Lock';
33+
import DateRangeIcon from '@mui/icons-material/DateRange';
34+
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
35+
import { FeedStatusIndicator } from '../../components/FeedStatus';
3336

3437
export interface FeedSummaryProps {
3538
feed: GTFSFeedType | GTFSRTFeedType | undefined;
@@ -58,7 +61,7 @@ const boxElementStyleProducerURL: SxProps = {
5861
const StyledTitleContainer = styled(Box)(({ theme }) => ({
5962
display: 'flex',
6063
gap: theme.spacing(1),
61-
marginBottom: theme.spacing(1),
64+
marginBottom: '4px',
6265
marginTop: theme.spacing(3),
6366
alignItems: 'center',
6467
}));
@@ -73,6 +76,35 @@ const ResponsiveListItem = styled('li')(({ theme }) => ({
7376
},
7477
}));
7578

79+
const formatServiceDateRange = (
80+
dateStart: string,
81+
dateEnd: string,
82+
): JSX.Element => {
83+
const startDate = new Date(dateStart);
84+
const endDate = new Date(dateEnd);
85+
const formattedDateStart = new Intl.DateTimeFormat('en-US', {
86+
month: 'short',
87+
day: 'numeric',
88+
year: 'numeric',
89+
}).format(startDate);
90+
const formattedDateEnd = new Intl.DateTimeFormat('en-US', {
91+
month: 'short',
92+
day: 'numeric',
93+
year: 'numeric',
94+
}).format(endDate);
95+
return (
96+
<Box>
97+
<Typography variant='body1'>
98+
{formattedDateStart}{' '}
99+
<Typography component={'span'} sx={{ mx: 2, fontSize: '14px' }}>
100+
-
101+
</Typography>{' '}
102+
{formattedDateEnd}
103+
</Typography>
104+
</Box>
105+
);
106+
};
107+
76108
export default function FeedSummary({
77109
feed,
78110
sortedProviders,
@@ -89,7 +121,6 @@ export default function FeedSummary({
89121
const hasAuthenticationInfo =
90122
feed?.source_info?.authentication_info_url !== undefined &&
91123
feed?.source_info.authentication_info_url.trim() !== '';
92-
93124
return (
94125
<ContentBox
95126
width={width}
@@ -158,6 +189,34 @@ export default function FeedSummary({
158189
)}
159190
</Box>
160191
</Box>
192+
{latestDataset?.service_date_range_start != undefined &&
193+
latestDataset.service_date_range_end != undefined && (
194+
<Box sx={boxElementStyle}>
195+
<StyledTitleContainer>
196+
<DateRangeIcon></DateRangeIcon>
197+
<Typography variant='subtitle1' sx={{ fontWeight: 'bold' }}>
198+
{t('serviceDateRange')}
199+
<Tooltip title={t('serviceDateRangeTooltip')} placement='top'>
200+
<IconButton>
201+
<InfoOutlinedIcon />
202+
</IconButton>
203+
</Tooltip>
204+
</Typography>
205+
</StyledTitleContainer>
206+
<Typography
207+
variant='body1'
208+
sx={{ display: 'flex', alignItems: 'center', gap: 3 }}
209+
>
210+
{formatServiceDateRange(
211+
latestDataset?.service_date_range_start,
212+
latestDataset?.service_date_range_end,
213+
)}
214+
<FeedStatusIndicator
215+
status={feed?.status ?? ''}
216+
></FeedStatusIndicator>
217+
</Typography>
218+
</Box>
219+
)}
161220
<Box sx={boxElementStyleProducerURL}>
162221
<StyledTitleContainer>
163222
<LinkIcon></LinkIcon>

web-app/src/app/screens/Feed/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ export default function Feed(): React.ReactElement {
417417

418418
{feed?.data_type === 'gtfs' && (
419419
<DataQualitySummary
420+
feedStatus={feed?.status}
420421
isOfficialFeed={feed.official === true}
421422
latestDataset={latestDataset}
422423
/>

0 commit comments

Comments
 (0)