Skip to content

Commit

Permalink
official_updated_at added
Browse files Browse the repository at this point in the history
Co-authored-by: Jingsi Lu <jingsi@mobilitydata.org>
  • Loading branch information
Alessandro100 and qcdyx committed Jan 13, 2025
1 parent 2a715c0 commit 0de4b02
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 112 deletions.
6 changes: 2 additions & 4 deletions api/src/feeds/impl/models/basic_feed_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ class Config:
def from_orm(cls, feed: Feed | None, _=None) -> BasicFeed | None:
if not feed:
return None
latest_official_status = None
if len(feed.officialstatushistories) > 0:
latest_official_status = max(feed.officialstatushistories, key=lambda x: x.timestamp).is_official
return cls(
id=feed.stable_id,
data_type=feed.data_type,
status=feed.status,
official=latest_official_status,
official=feed.official,
official_updated_at=feed.official_updated_at,
created_at=feed.created_at,
external_ids=sorted(
[ExternalIdImpl.from_orm(item) for item in feed.externalids], key=lambda x: x.external_id
Expand Down
6 changes: 6 additions & 0 deletions docs/DatabaseCatalogAPI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@ components:
Official feeds are provided by the transit agency or a trusted source.
type: boolean
example: true
official_updated_at:
description: >
The date and time the official status was last updated, in ISO 8601 date-time format.
type: string
example: 2023-07-10T22:06:00Z
format: date-time
external_ids:
$ref: "#/components/schemas/ExternalIds"
provider:
Expand Down
1 change: 1 addition & 0 deletions liquibase/changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@
<include file="changes/feat_741.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_794.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_794_2.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_871.sql" relativeToChangelogFile="true"/>
</databaseChangeLog>
1 change: 1 addition & 0 deletions liquibase/changes/feat_871.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE Feed ADD COLUMN official_updated_at TIMESTAMP DEFAULT NULL;
4 changes: 3 additions & 1 deletion liquibase/changes/official_tag_update.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
-- Query to update official tag for feeds with contact email in the feed table where the source is mdb

UPDATE public.feed f
SET official = TRUE
SET
official = TRUE
official_updated_at = NOW()
FROM public.externalid e
WHERE f.id = e.feed_id
AND f.feed_contact_email LIKE '%@%'
Expand Down
3 changes: 2 additions & 1 deletion web-app/public/locales/en/feeds.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,6 @@
"officialFeedTooltipShort": "Verified feed: Confirmed by the transit provider or the Mobility Database team for rider use.",
"seeDetailPageProviders": "See detail page to view {providersCount} others",
"openFullQualityReport": "Open Full Quality Report",
"qualityReportUpdated": "Quality report updated"
"qualityReportUpdated": "Quality report updated",
"officialFeedUpdated": "Official verification updated"
}
190 changes: 97 additions & 93 deletions web-app/src/app/screens/Feed/DataQualitySummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,102 +24,106 @@ export default function DataQualitySummary({
latestDataset.validation_report === null) && (
<WarningContentBox>{t('errorLoadingQualityReport')}</WarningContentBox>
)}
{latestDataset?.validation_report !== undefined &&
latestDataset.validation_report !== null && (
<Box sx={{ display: 'flex', gap: 1 }}>
{isOfficialFeed && (
<Tooltip title={t('officialFeedTooltip')} placement='top'>
<Chip
sx={verificationBadgeStyle}
icon={<VerifiedIcon sx={{ fill: 'white' }}></VerifiedIcon>}
label={t('officialFeed')}
></Chip>
</Tooltip>
)}
<Box sx={{ display: 'flex', gap: 1 }}>
{isOfficialFeed && (
<Tooltip title={t('officialFeedTooltip')} placement='top'>
<Chip
data-testid='error-count'
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
icon={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0 ? (
<ReportOutlined />
) : (
<CheckCircle />
)
}
label={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0
? `${latestDataset?.validation_report
?.unique_error_count} ${t('common:feedback.errors')}`
: t('common:feedback.noErrors')
}
color={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0
? 'error'
: 'success'
}
variant='outlined'
/>
sx={verificationBadgeStyle}
icon={<VerifiedIcon sx={{ fill: 'white' }}></VerifiedIcon>}
label={t('officialFeed')}
></Chip>
</Tooltip>
)}
{latestDataset?.validation_report !== undefined &&
latestDataset.validation_report !== null && (
<>
<Chip
data-testid='error-count'
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
icon={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0 ? (
<ReportOutlined />
) : (
<CheckCircle />
)
}
label={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0
? `${latestDataset?.validation_report
?.unique_error_count} ${t('common:feedback.errors')}`
: t('common:feedback.noErrors')
}
color={
latestDataset?.validation_report?.unique_error_count !==
undefined &&
latestDataset?.validation_report?.unique_error_count > 0
? 'error'
: 'success'
}
variant='outlined'
/>

<Chip
data-testid='warning-count'
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
icon={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0 ? (
<ReportOutlined />
) : (
<CheckCircle />
)
}
label={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0
? `${latestDataset?.validation_report
?.unique_warning_count} ${t('common:feedback.warnings')}`
: t('common:feedback.no_warnings')
}
color={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0
? 'warning'
: 'success'
}
variant='outlined'
/>
<Chip
data-testid='warning-count'
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
icon={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0 ? (
<ReportOutlined />
) : (
<CheckCircle />
)
}
label={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0
? `${latestDataset?.validation_report
?.unique_warning_count} ${t(
'common:feedback.warnings',
)}`
: t('common:feedback.no_warnings')
}
color={
latestDataset?.validation_report?.unique_warning_count !==
undefined &&
latestDataset?.validation_report?.unique_warning_count > 0
? 'warning'
: 'success'
}
variant='outlined'
/>

<Chip
data-testid='info-count'
icon={<InfoOutlinedIcon />}
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
label={`${
latestDataset?.validation_report?.unique_info_count ?? '0'
} ${t('common:feedback.infoNotices')}`}
color='primary'
variant='outlined'
/>
</Box>
)}
<Chip
data-testid='info-count'
icon={<InfoOutlinedIcon />}
clickable
component='a'
href={latestDataset?.validation_report?.url_html}
target='_blank'
rel='noopener noreferrer'
label={`${
latestDataset?.validation_report?.unique_info_count ?? '0'
} ${t('common:feedback.infoNotices')}`}
color='primary'
variant='outlined'
/>
</>
)}
</Box>
</Box>
);
}
35 changes: 22 additions & 13 deletions web-app/src/app/screens/Feed/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,19 +423,28 @@ export default function Feed(): React.ReactElement {
)}
<Box>
{latestDataset?.validation_report?.validated_at != undefined && (
<>
<Typography
data-testid='last-updated'
variant={'caption'}
width={'100%'}
component={'div'}
>
{`${t('qualityReportUpdated')}: ${new Date(
latestDataset.validation_report.validated_at,
).toDateString()}`}
</Typography>
{/* TODO: add timestamp for badge verify */}
</>
<Typography
data-testid='last-updated'
variant={'caption'}
width={'100%'}
component={'div'}
>
{`${t('qualityReportUpdated')}: ${new Date(
latestDataset.validation_report.validated_at,
).toDateString()}`}
</Typography>
)}
{feed?.official_updated_at != undefined && (
<Typography
data-testid='last-updated'
variant={'caption'}
width={'100%'}
component={'div'}
>
{`${t('officialFeedUpdated')}: ${new Date(
feed?.official_updated_at,
).toDateString()}`}
</Typography>
)}
</Box>

Expand Down
7 changes: 7 additions & 0 deletions web-app/src/app/services/feeds/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ export interface components {
* @example true
*/
official?: boolean;
/**
* Format: date-time
* @description The date and time the official status was last updated, in ISO 8601 date-time format.
*
* @example "2023-07-10T22:06:00.000Z"
*/
official_updated_at?: string;
external_ids?: components['schemas']['ExternalIds'];
/**
* @description A commonly used name for the transit provider included in the feed.
Expand Down

0 comments on commit 0de4b02

Please sign in to comment.