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 ||