diff --git a/web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx b/web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx index 6abc38143..9f4f9b0fa 100644 --- a/web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx +++ b/web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx @@ -31,6 +31,43 @@ export interface AdvancedSearchTableProps { selectedGbfsVersions: string[] | undefined; } +interface DetailsContainerProps { + children: React.ReactNode; + feedSearchItem: SearchFeedItem; +} + +const DetailsContainer = ({ + children, + feedSearchItem, +}: DetailsContainerProps): React.ReactElement => { + return ( + + {children} + + + {feedSearchItem.source_info?.license_id} + + + + ); +}; + const renderGTFSDetails = ( gtfsFeed: SearchFeedItem, selectedFeatures: string[], @@ -39,7 +76,7 @@ const renderGTFSDetails = ( const feedFeatures = gtfsFeed?.latest_dataset?.validation_report?.features ?? []; return ( - <> + {gtfsFeed?.feed_name != null && ( - + ); }; @@ -83,10 +120,12 @@ const renderGTFSRTDetails = ( gtfsRtFeed: SearchFeedItem, ): React.ReactElement => { return ( - + + + ); }; @@ -96,7 +135,7 @@ const renderGBFSDetails = ( ): JSX.Element => { const theme = useTheme(); return ( - + {gbfsFeedSearchElement.versions?.map((version: string, index: number) => ( ))} - + ); }; diff --git a/web-app/src/app/screens/Feeds/SearchFilters.tsx b/web-app/src/app/screens/Feeds/SearchFilters.tsx index c70f39e31..c701093f1 100644 --- a/web-app/src/app/screens/Feeds/SearchFilters.tsx +++ b/web-app/src/app/screens/Feeds/SearchFilters.tsx @@ -25,10 +25,12 @@ interface SearchFiltersProps { isOfficialFeedSearch: boolean; selectedFeatures: string[]; selectedGbfsVersions: string[]; + selectedLicenses: string[]; setSelectedFeedTypes: (selectedFeedTypes: Record) => void; setIsOfficialFeedSearch: (isOfficialFeedSearch: boolean) => void; setSelectedFeatures: (selectedFeatures: string[]) => void; setSelectedGbfsVerions: (selectedVersions: string[]) => void; + setSelectedLicenses: (selectedLicenses: string[]) => void; isOfficialTagFilterEnabled: boolean; areFeatureFiltersEnabled: boolean; areGBFSFiltersEnabled: boolean; @@ -39,10 +41,12 @@ export function SearchFilters({ isOfficialFeedSearch, selectedFeatures, selectedGbfsVersions, + selectedLicenses, setSelectedFeedTypes, setIsOfficialFeedSearch, setSelectedFeatures, setSelectedGbfsVerions, + setSelectedLicenses, isOfficialTagFilterEnabled, areFeatureFiltersEnabled, areGBFSFiltersEnabled, @@ -58,6 +62,7 @@ export function SearchFilters({ features: areFeatureFiltersEnabled, tags: isOfficialTagFilterEnabled, gbfsVersions: true, + licenses: true, }); const [featureCheckboxData, setFeatureCheckboxData] = useState< CheckboxStructure[] @@ -276,6 +281,75 @@ export function SearchFilters({ > + + { + setExpandedCategories({ + ...expandedCategories, + licenses: !expandedCategories.licenses, + }); + }} + > + } + aria-controls='panel-licenses-content' + sx={{ + px: 0, + }} + > + Licenses + + + { + const selectedLicenseIds: string[] = []; + checkboxData.forEach((checkbox) => { + if (checkbox.checked) { + selectedLicenseIds.push(checkbox.title); + } + }); + setSelectedLicenses([...selectedLicenseIds]); + }} + > + + ); } diff --git a/web-app/src/app/screens/Feeds/index.tsx b/web-app/src/app/screens/Feeds/index.tsx index e140bbe7a..e6c15b99f 100644 --- a/web-app/src/app/screens/Feeds/index.tsx +++ b/web-app/src/app/screens/Feeds/index.tsx @@ -66,6 +66,9 @@ export default function Feed(): React.ReactElement { const [selectGbfsVersions, setSelectGbfsVersions] = useState( searchParams.get('gbfs_versions')?.split(',') ?? [], ); + const [selectedLicenses, setSelectedLicenses] = useState( + searchParams.get('licenses')?.split(',') ?? [], + ); const [activePagination, setActivePagination] = useState( searchParams.get('o') !== null ? Number(searchParams.get('o')) : 1, ); @@ -127,6 +130,10 @@ export default function Feed(): React.ReactElement { version: areGBFSFiltersEnabled ? selectGbfsVersions.join(',').replaceAll('v', '') : undefined, + license_ids: + selectedLicenses.length > 0 + ? selectedLicenses.join(',') + : undefined, }, }, }), @@ -140,6 +147,7 @@ export default function Feed(): React.ReactElement { isOfficialFeedSearch, selectedFeatures, selectGbfsVersions, + selectedLicenses, ]); useEffect(() => { @@ -166,6 +174,9 @@ export default function Feed(): React.ReactElement { if (selectGbfsVersions.length > 0) { newSearchParams.set('gbfs_versions', selectGbfsVersions.join(',')); } + if (selectedLicenses.length > 0) { + newSearchParams.set('licenses', selectedLicenses.join(',')); + } if (isOfficialFeedSearch) { newSearchParams.set('official', 'true'); } @@ -181,6 +192,7 @@ export default function Feed(): React.ReactElement { selectedFeedTypes, selectedFeatures, selectGbfsVersions, + selectedLicenses, isOfficialFeedSearch, ]); @@ -208,6 +220,11 @@ export default function Feed(): React.ReactElement { setSelectGbfsVersions([...newGbfsVersions]); } + const newLicenses = searchParams.get('licenses')?.split(',') ?? []; + if (newLicenses.join(',') !== selectedLicenses.join(',')) { + setSelectedLicenses([...newLicenses]); + } + const newSearchOfficial = Boolean(searchParams.get('official')) ?? false; if (newSearchOfficial !== isOfficialFeedSearch) { setIsOfficialFeedSearch(newSearchOfficial); @@ -259,6 +276,7 @@ export default function Feed(): React.ReactElement { }); setSelectedFeatures([]); setSelectGbfsVersions([]); + setSelectedLicenses([]); setIsOfficialFeedSearch(false); } @@ -396,6 +414,7 @@ export default function Feed(): React.ReactElement { isOfficialFeedSearch={isOfficialFeedSearch} selectedFeatures={selectedFeatures} selectedGbfsVersions={selectGbfsVersions} + selectedLicenses={selectedLicenses} setSelectedFeedTypes={(feedTypes) => { setActivePagination(1); setSelectedFeedTypes(feedTypes); @@ -412,6 +431,10 @@ export default function Feed(): React.ReactElement { setSelectGbfsVersions(versions); setActivePagination(1); }} + setSelectedLicenses={(licenses) => { + setActivePagination(1); + setSelectedLicenses(licenses); + }} isOfficialTagFilterEnabled={isOfficialTagFilterEnabled} areFeatureFiltersEnabled={areFeatureFiltersEnabled} areGBFSFiltersEnabled={areGBFSFiltersEnabled} @@ -511,8 +534,24 @@ export default function Feed(): React.ReactElement { /> ))} + {selectedLicenses.map((license) => ( + { + setSelectedLicenses([ + ...selectedLicenses.filter((sl) => sl !== license), + ]); + }} + /> + ))} + {(selectedFeatures.length > 0 || selectGbfsVersions.length > 0 || + selectedLicenses.length > 0 || isOfficialFeedSearch || selectedFeedTypes.gtfs_rt || selectedFeedTypes.gtfs ||