From 410b044210dc2f95798b2279f1d788b8eeef7126 Mon Sep 17 00:00:00 2001 From: Alessandro Kreslin Date: Fri, 20 Mar 2026 09:11:41 -0400 Subject: [PATCH 1/3] update types --- external_types/DatabaseCatalogAPI.yaml | 56 ++++++++++++++++++++------ src/app/services/feeds/types.ts | 32 +++++++++++++-- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/external_types/DatabaseCatalogAPI.yaml b/external_types/DatabaseCatalogAPI.yaml index abc315cd..0054dd48 100644 --- a/external_types/DatabaseCatalogAPI.yaml +++ b/external_types/DatabaseCatalogAPI.yaml @@ -145,7 +145,6 @@ paths: description: Get GBFS feeds from the Mobility Database. tags: - "feeds" - - "beta" operationId: getGbfsFeeds parameters: - $ref: "#/components/parameters/limit_query_param_gbfs_feeds_endpoint" @@ -175,7 +174,6 @@ paths: description: Get the specified GTFS feed from the Mobility Database. Once a week, we check if the latest dataset has been updated and, if so, we update it in our system accordingly. tags: - "feeds" - - "beta" operationId: getGtfsFeed security: @@ -338,7 +336,9 @@ paths: - $ref: "#/components/parameters/version_query_param" - $ref: "#/components/parameters/search_text_query_param" - $ref: "#/components/parameters/feature" - - $ref: "#/components/parameters/license_ids_query_param" + - $ref: "#/components/parameters/license_ids" + - $ref: "#/components/parameters/license_is_spdx" + - $ref: "#/components/parameters/license_tags" security: - Authentication: [] responses: @@ -1087,6 +1087,14 @@ components: description: Notes concerning the relation between the feed and the license. type: string example: Detected locale/jurisdiction port 'nl'. SPDX does not list ported CC licenses; using canonical ID. + license_tags: + description: List of taxonomy tags associated with the feed's license. + type: array + items: + type: string + example: + - "family:ODC" + - "license:open-data-commons" Locations: type: array @@ -1344,6 +1352,14 @@ components: type: string example: 2023-07-10T22:06:00Z format: date-time + license_tags: + description: List of taxonomy tags associated with the license. + type: array + items: + type: string + example: + - "family:ODC" + - "license:open-data-commons" LicenseWithRules: allOf: @@ -1486,6 +1502,29 @@ components: type: array items: type: string + license_ids: + name: license_ids + in: query + description: Comma separated list of license IDs to filter feeds by their license. + required: false + schema: + type: string + example: CC-BY-4.0,ODbL-1.0 + license_is_spdx: + name: license_is_spdx + in: query + description: Filter feeds by whether their license is an SPDX license. + required: false + schema: + type: boolean + license_tags: + name: license_tags + in: query + description: Comma separated list of tags to filter feeds by their license tags. + required: false + schema: + type: string + example: family:ODC,license:open-data-commons provider: name: provider in: query @@ -1794,18 +1833,9 @@ components: type: string example: 2.3 - license_ids_query_param: - name: license_ids - in: query - description: Comma separated list of license IDs to filter by. - required: False - schema: - type: string - example: CC-BY-4.0,CC0-1.0 - securitySchemes: Authentication: $ref: "./BearerTokenSchema.yaml#/components/securitySchemes/Authentication" security: - - Authentication: [] + - Authentication: [] \ No newline at end of file diff --git a/src/app/services/feeds/types.ts b/src/app/services/feeds/types.ts index b8846372..aa230c46 100644 --- a/src/app/services/feeds/types.ts +++ b/src/app/services/feeds/types.ts @@ -795,6 +795,14 @@ export interface components { * @example Detected locale/jurisdiction port 'nl'. SPDX does not list ported CC licenses; using canonical ID. */ license_notes?: string; + /** + * @description List of taxonomy tags associated with the feed's license. + * @example [ + * "family:ODC", + * "license:open-data-commons" + * ] + */ + license_tags?: string[]; }; Locations: Array; Location: { @@ -1017,6 +1025,14 @@ export interface components { * @example 2023-07-10T22:06:00Z */ updated_at?: string; + /** + * @description List of taxonomy tags associated with the license. + * @example [ + * "family:ODC", + * "license:open-data-commons" + * ] + */ + license_tags?: string[]; }; LicenseWithRules: components['schemas']['LicenseBase'] & { license_rules?: Array; @@ -1119,6 +1135,12 @@ export interface components { >; /** @description Filter feeds by their GTFS features. [GTFS features definitions defined here](https://gtfs.org/getting-started/features/overview) */ feature: string[]; + /** @description Comma separated list of license IDs to filter feeds by their license. */ + license_ids: string; + /** @description Filter feeds by whether their license is an SPDX license. */ + license_is_spdx: boolean; + /** @description Comma separated list of tags to filter feeds by their license tags. */ + license_tags: string; /** @description List only feeds with the specified value. Can be a partial match. Case insensitive. */ provider: string; /** @description List only feeds with the specified value. Can be a partial match. Case insensitive. */ @@ -1194,8 +1216,6 @@ export interface components { system_id_param: string; /** @description Filter feeds by their supported GBFS version. This is a string that follows the semantic versioning format. */ version_param: string; - /** @description Comma separated list of license IDs to filter by. */ - license_ids_query_param: string; }; requestBodies: never; headers: never; @@ -1556,8 +1576,12 @@ export interface operations { search_query?: components['parameters']['search_text_query_param']; /** @description Filter feeds by their GTFS features. [GTFS features definitions defined here](https://gtfs.org/getting-started/features/overview) */ feature?: components['parameters']['feature']; - /** @description Comma separated list of license IDs to filter by. */ - license_ids?: components['parameters']['license_ids_query_param']; + /** @description Comma separated list of license IDs to filter feeds by their license. */ + license_ids?: components['parameters']['license_ids']; + /** @description Filter feeds by whether their license is an SPDX license. */ + license_is_spdx?: components['parameters']['license_is_spdx']; + /** @description Comma separated list of tags to filter feeds by their license tags. */ + license_tags?: components['parameters']['license_tags']; }; header?: never; path?: never; From ce194bb0b5b9640b11309e7b993186709ac50f6d Mon Sep 17 00:00:00 2001 From: Alessandro Kreslin Date: Fri, 20 Mar 2026 09:12:45 -0400 Subject: [PATCH 2/3] license tags in feed details page --- src/app/screens/Feed/FeedSummary.styles.ts | 4 - .../Feed/components/CopyLinkElement.tsx | 6 +- .../screens/Feed/components/FeedSummary.tsx | 87 ++++++++++++++++--- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/app/screens/Feed/FeedSummary.styles.ts b/src/app/screens/Feed/FeedSummary.styles.ts index b30bbc1f..0348eb09 100644 --- a/src/app/screens/Feed/FeedSummary.styles.ts +++ b/src/app/screens/Feed/FeedSummary.styles.ts @@ -24,8 +24,4 @@ export const GroupHeader = styled(Typography)<{ component?: ElementType }>( export const FeedLinkElement = styled(Box)(({ theme }) => ({ width: 'calc(100% - 16px)', marginLeft: '16px', - marginBottom: '16px', - '&:last-of-type': { - marginBottom: 0, - }, })); diff --git a/src/app/screens/Feed/components/CopyLinkElement.tsx b/src/app/screens/Feed/components/CopyLinkElement.tsx index 7e072481..31d1a5ab 100644 --- a/src/app/screens/Feed/components/CopyLinkElement.tsx +++ b/src/app/screens/Feed/components/CopyLinkElement.tsx @@ -9,6 +9,8 @@ import { Snackbar, Tooltip, Typography, + type SxProps, + type Theme, } from '@mui/material'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; import DownloadIcon from '@mui/icons-material/Download'; @@ -22,6 +24,7 @@ export interface CopyLinkElementProps { linkType?: 'download' | 'external' | 'email' | 'internal' | 'label'; titleInfo?: string; internalClickAction?: () => void; + sx?: SxProps; } export default function CopyLinkElement({ @@ -30,6 +33,7 @@ export default function CopyLinkElement({ linkType, titleInfo, internalClickAction, + sx, }: CopyLinkElementProps): ReactElement { const [snackbarOpen, setSnackbarOpen] = useState(false); @@ -52,7 +56,7 @@ export default function CopyLinkElement({ const formattedUrl = linkType === 'email' ? `mailto:${url}` : url; return ( - + {title != null && ( {linkType === 'label' ? ( diff --git a/src/app/screens/Feed/components/FeedSummary.tsx b/src/app/screens/Feed/components/FeedSummary.tsx index 253f3b96..3355861a 100644 --- a/src/app/screens/Feed/components/FeedSummary.tsx +++ b/src/app/screens/Feed/components/FeedSummary.tsx @@ -82,6 +82,7 @@ export default function FeedSummary({ const [openProvidersDetails, setOpenProvidersDetails] = useState(false); const [openLicenseDetails, setOpenLicenseDetails] = useState(false); const [showAllFeatures, setShowAllFeatures] = useState(false); + const [showAllLicenseTags, setShowAllLicenseTags] = useState(false); const fullScreen = useMediaQuery(theme.breakpoints.down('md')); @@ -107,6 +108,8 @@ export default function FeedSummary({ return hasOtherLinks; }; + console.log('FeedSummary render', feed); + return ( <> @@ -220,8 +223,7 @@ export default function FeedSummary({ feed?.locations?.length === 1 && ( {getLocationName(feed?.locations)} @@ -638,7 +640,7 @@ export default function FeedSummary({ : allFeatures.slice(0, 6); return ( <> - + {visible.map((feature, index) => { const featureDecorators = getFeatureComponentDecorators(feature); @@ -678,7 +680,6 @@ export default function FeedSummary({ onClick={() => { setShowAllFeatures((v) => !v); }} - sx={{ ml: 1 }} > {showAllFeatures ? tCommon('showLess') @@ -756,6 +757,63 @@ export default function FeedSummary({ {feed?.source_info?.license_url} )} + {feed.source_info.license_tags != undefined && + feed.source_info.license_tags.length > 0 && ( + <> + + Tags + + + {(showAllLicenseTags + ? feed.source_info.license_tags + : feed.source_info.license_tags.slice(0, 3) + ).map((tag, index) => ( + + ))} + {feed.source_info.license_tags.length > 3 && ( + + )} + + + )} )} @@ -766,15 +824,18 @@ export default function FeedSummary({ {t('relatedLinks')} - {(feed as GTFSFeedType)?.related_links?.map((link, index) => ( - - ))} + {(feed as GTFSFeedType)?.related_links?.map( + (link, index, allLinks) => ( + + ), + )} )} From 0d928b2b583d5331865f4691a95e7a07bc0acdc1 Mon Sep 17 00:00:00 2001 From: Alessandro Kreslin Date: Fri, 20 Mar 2026 10:13:40 -0400 Subject: [PATCH 3/3] translation --- messages/en.json | 3 ++- messages/fr.json | 3 ++- src/app/screens/Feed/components/FeedSummary.tsx | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/messages/en.json b/messages/en.json index 54989ee1..bb01951b 100644 --- a/messages/en.json +++ b/messages/en.json @@ -103,7 +103,8 @@ "showLess": "Show less", "showMore": "Show {count} more", "moreInfo": "More Info", - "license": "License" + "license": "License", + "tags": "Tags" }, "feeds": { "feeds": "Feeds", diff --git a/messages/fr.json b/messages/fr.json index 4c5ce805..64bcf3f6 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -103,7 +103,8 @@ "showLess": "Show less", "showMore": "Show {count} more", "moreInfo": "More Info", - "license": "License" + "license": "License", + "tags": "Tags" }, "feeds": { "feeds": "Feeds", diff --git a/src/app/screens/Feed/components/FeedSummary.tsx b/src/app/screens/Feed/components/FeedSummary.tsx index 3355861a..93e66f1a 100644 --- a/src/app/screens/Feed/components/FeedSummary.tsx +++ b/src/app/screens/Feed/components/FeedSummary.tsx @@ -108,8 +108,6 @@ export default function FeedSummary({ return hasOtherLinks; }; - console.log('FeedSummary render', feed); - return ( <> @@ -770,7 +768,7 @@ export default function FeedSummary({ mt: 1, }} > - Tags + {tCommon('tags')}