Skip to content

Commit 45307cf

Browse files
committed
Feed status added to search
1 parent 57525b1 commit 45307cf

File tree

5 files changed

+285
-9
lines changed

5 files changed

+285
-9
lines changed

web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,12 @@ export default function AdvancedSearchTable({
194194
{feed.official === true && (
195195
<OfficialChip isLongDisplay={false}></OfficialChip>
196196
)}
197-
{feed.data_type !== 'gbfs' && (
198-
<FeedStatusIndicator
199-
status={feed.status}
200-
></FeedStatusIndicator>
201-
)}
197+
{feed.data_type !== 'gbfs' &&
198+
feed.data_type !== 'gtfs_rt' && (
199+
<FeedStatusIndicator
200+
status={feed.status}
201+
></FeedStatusIndicator>
202+
)}
202203
</Box>
203204

204205
<Box

web-app/src/app/screens/Feeds/SearchFilters.tsx

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useEffect, useState } from 'react';
99
import { DATASET_FEATURES, groupFeaturesByComponent } from '../../utils/consts';
1010
import { type GbfsVersionConfig } from '../../interface/RemoteConfig';
1111
import { SearchHeader } from '../../styles/Filters.styles';
12+
import { type AllowedFeedSearchStatus } from './utility';
1213

1314
function setInitialExpandGroup(): Record<string, boolean> {
1415
const expandGroup: Record<string, boolean> = {};
@@ -24,27 +25,33 @@ interface SearchFiltersProps {
2425
selectedFeedTypes: Record<string, boolean>;
2526
isOfficialFeedSearch: boolean;
2627
selectedFeatures: string[];
28+
selectedStatuses: AllowedFeedSearchStatus[];
2729
selectedGbfsVersions: string[];
2830
setSelectedFeedTypes: (selectedFeedTypes: Record<string, boolean>) => void;
2931
setIsOfficialFeedSearch: (isOfficialFeedSearch: boolean) => void;
3032
setSelectedFeatures: (selectedFeatures: string[]) => void;
33+
setSelectedStatuses: (selectedStatuses: AllowedFeedSearchStatus[]) => void;
3134
setSelectedGbfsVerions: (selectedVersions: string[]) => void;
3235
isOfficialTagFilterEnabled: boolean;
3336
areFeatureFiltersEnabled: boolean;
37+
areStatusFiltersEnabled: boolean;
3438
areGBFSFiltersEnabled: boolean;
3539
}
3640

3741
export function SearchFilters({
3842
selectedFeedTypes,
3943
isOfficialFeedSearch,
4044
selectedFeatures,
45+
selectedStatuses,
4146
selectedGbfsVersions,
4247
setSelectedFeedTypes,
4348
setIsOfficialFeedSearch,
4449
setSelectedFeatures,
50+
setSelectedStatuses,
4551
setSelectedGbfsVerions,
4652
isOfficialTagFilterEnabled,
4753
areFeatureFiltersEnabled,
54+
areStatusFiltersEnabled,
4855
areGBFSFiltersEnabled,
4956
}: SearchFiltersProps): React.ReactElement {
5057
const { t } = useTranslation('feeds');
@@ -57,6 +64,7 @@ export function SearchFilters({
5764
>({
5865
features: areFeatureFiltersEnabled,
5966
tags: isOfficialTagFilterEnabled,
67+
status: areStatusFiltersEnabled,
6068
gbfsVersions: true,
6169
});
6270
const [featureCheckboxData, setFeatureCheckboxData] = useState<
@@ -164,10 +172,94 @@ export function SearchFilters({
164172
</>
165173
)}
166174

175+
<Accordion
176+
disableGutters
177+
sx={{
178+
border: 0,
179+
'&::before': {
180+
display: 'none',
181+
},
182+
}}
183+
variant={'outlined'}
184+
expanded={expandedCategories.status && areStatusFiltersEnabled}
185+
onChange={() => {
186+
setExpandedCategories({
187+
...expandedCategories,
188+
status: !expandedCategories.status,
189+
});
190+
}}
191+
>
192+
<AccordionSummary
193+
expandIcon={<ExpandMoreIcon />}
194+
aria-controls='panel-status-content'
195+
sx={{ px: 0 }}
196+
>
197+
<SearchHeader
198+
variant='h6'
199+
sx={areStatusFiltersEnabled ? {} : { opacity: 0.5 }}
200+
>
201+
Status
202+
</SearchHeader>
203+
</AccordionSummary>
204+
<AccordionDetails
205+
sx={{
206+
p: 0,
207+
m: 0,
208+
border: 0,
209+
'&.Mui-expanded': { m: 0, minHeight: 'initial' },
210+
}}
211+
>
212+
<NestedCheckboxList
213+
disableAll={!areStatusFiltersEnabled}
214+
debounceTime={300}
215+
checkboxData={[
216+
{
217+
title: t('feedStatus.active.label'),
218+
checked: selectedStatuses.includes('active'),
219+
type: 'checkbox',
220+
props: { key: 'active' },
221+
},
222+
{
223+
title: t('feedStatus.inactive.label'),
224+
checked: selectedStatuses.includes('inactive'),
225+
type: 'checkbox',
226+
props: { key: 'inactive' },
227+
},
228+
{
229+
title: t('feedStatus.future.label'),
230+
checked: selectedStatuses.includes('future'),
231+
type: 'checkbox',
232+
props: { key: 'future' },
233+
},
234+
]}
235+
onCheckboxChange={(checkboxData) => {
236+
const statuses: AllowedFeedSearchStatus[] = [];
237+
checkboxData.forEach((cb) => {
238+
if (cb.checked) {
239+
if (
240+
cb.props?.key === 'active' ||
241+
cb.props?.key === 'inactive' ||
242+
cb.props?.key === 'future'
243+
) {
244+
statuses.push(cb.props.key);
245+
}
246+
}
247+
});
248+
setSelectedStatuses(statuses);
249+
}}
250+
/>
251+
</AccordionDetails>
252+
</Accordion>
253+
167254
{config.enableFeatureFilterSearch && (
168255
<Accordion
169256
disableGutters
170-
sx={{ border: 0 }}
257+
sx={{
258+
border: 0,
259+
'&::before': {
260+
display: 'none',
261+
},
262+
}}
171263
variant={'outlined'}
172264
expanded={expandedCategories.features && areFeatureFiltersEnabled}
173265
onChange={() => {

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ import { useSearchParams } from 'react-router-dom';
3030
import SearchTable from './SearchTable';
3131
import { Trans, useTranslation } from 'react-i18next';
3232
import {
33+
type AllowedFeedSearchStatus,
3334
getDataTypeParamFromSelectedFeedTypes,
3435
getInitialSelectedFeedTypes,
36+
parseQueryParamStatus,
3537
} from './utility';
3638
import {
3739
chipHolderStyles,
@@ -65,6 +67,9 @@ export default function Feed(): React.ReactElement {
6567
const [selectedFeatures, setSelectedFeatures] = useState<string[]>(
6668
searchParams.get('features')?.split(',') ?? [],
6769
);
70+
const [selectedStatuses, setSelectedStatuses] = useState<
71+
AllowedFeedSearchStatus[]
72+
>(parseQueryParamStatus(searchParams.get('status')?.split(',')));
6873
const [selectGbfsVersions, setSelectGbfsVersions] = useState<string[]>(
6974
searchParams.get('gbfs_versions')?.split(',') ?? [],
7075
);
@@ -91,6 +96,9 @@ export default function Feed(): React.ReactElement {
9196
const areFeatureFiltersEnabled =
9297
(!selectedFeedTypes.gtfs_rt && !selectedFeedTypes.gbfs) ||
9398
selectedFeedTypes.gtfs;
99+
const areStatusFiltersEnabled =
100+
(!selectedFeedTypes.gtfs_rt && !selectedFeedTypes.gbfs) ||
101+
selectedFeedTypes.gtfs;
94102
const areGBFSFiltersEnabled =
95103
selectedFeedTypes.gbfs &&
96104
!selectedFeedTypes.gtfs_rt &&
@@ -122,9 +130,10 @@ export default function Feed(): React.ReactElement {
122130
is_official: isOfficialTagFilterEnabled
123131
? isOfficialFeedSearch || undefined
124132
: undefined,
125-
// Fixed status values for now, until a status filter is implemented
126-
// Filtering out deprecated feeds
127-
status: ['active', 'inactive', 'development', 'future'],
133+
status:
134+
areStatusFiltersEnabled && selectedStatuses.length > 0
135+
? selectedStatuses
136+
: ['active', 'inactive', 'development', 'future'],
128137
feature: areFeatureFiltersEnabled ? selectedFeatures : undefined,
129138
version: areGBFSFiltersEnabled
130139
? selectGbfsVersions.join(',').replaceAll('v', '')
@@ -141,6 +150,7 @@ export default function Feed(): React.ReactElement {
141150
searchLimit,
142151
isOfficialFeedSearch,
143152
selectedFeatures,
153+
selectedStatuses,
144154
selectGbfsVersions,
145155
]);
146156

@@ -165,6 +175,9 @@ export default function Feed(): React.ReactElement {
165175
if (selectedFeatures.length > 0) {
166176
newSearchParams.set('features', selectedFeatures.join(','));
167177
}
178+
if (selectedStatuses.length > 0) {
179+
newSearchParams.set('status', selectedStatuses.join(','));
180+
}
168181
if (selectGbfsVersions.length > 0) {
169182
newSearchParams.set('gbfs_versions', selectGbfsVersions.join(','));
170183
}
@@ -179,6 +192,7 @@ export default function Feed(): React.ReactElement {
179192
activePagination,
180193
selectedFeedTypes,
181194
selectedFeatures,
195+
selectedStatuses,
182196
selectGbfsVersions,
183197
isOfficialFeedSearch,
184198
]);
@@ -202,6 +216,12 @@ export default function Feed(): React.ReactElement {
202216
setSelectedFeatures([...newFeatures]);
203217
}
204218

219+
const newStatusesRaw = searchParams.get('status')?.split(',') ?? [];
220+
const newStatuses = parseQueryParamStatus(newStatusesRaw);
221+
if (newStatuses.join(',') !== selectedStatuses.join(',')) {
222+
setSelectedStatuses([...newStatuses]);
223+
}
224+
205225
const newGbfsVersions = searchParams.get('gbfs_versions')?.split(',') ?? [];
206226
if (newGbfsVersions.join(',') !== selectGbfsVersions.join(',')) {
207227
setSelectGbfsVersions([...newGbfsVersions]);
@@ -257,6 +277,7 @@ export default function Feed(): React.ReactElement {
257277
gbfs: false,
258278
});
259279
setSelectedFeatures([]);
280+
setSelectedStatuses([]);
260281
setSelectGbfsVersions([]);
261282
setIsOfficialFeedSearch(false);
262283
}
@@ -388,6 +409,7 @@ export default function Feed(): React.ReactElement {
388409
selectedFeedTypes={selectedFeedTypes}
389410
isOfficialFeedSearch={isOfficialFeedSearch}
390411
selectedFeatures={selectedFeatures}
412+
selectedStatuses={selectedStatuses}
391413
selectedGbfsVersions={selectGbfsVersions}
392414
setSelectedFeedTypes={(feedTypes) => {
393415
setActivePagination(1);
@@ -401,12 +423,17 @@ export default function Feed(): React.ReactElement {
401423
setActivePagination(1);
402424
setSelectedFeatures(features);
403425
}}
426+
setSelectedStatuses={(statuses) => {
427+
setActivePagination(1);
428+
setSelectedStatuses(statuses);
429+
}}
404430
setSelectedGbfsVerions={(versions) => {
405431
setSelectGbfsVersions(versions);
406432
setActivePagination(1);
407433
}}
408434
isOfficialTagFilterEnabled={isOfficialTagFilterEnabled}
409435
areFeatureFiltersEnabled={areFeatureFiltersEnabled}
436+
areStatusFiltersEnabled={areStatusFiltersEnabled}
410437
areGBFSFiltersEnabled={areGBFSFiltersEnabled}
411438
></SearchFilters>
412439
</Grid>
@@ -486,6 +513,22 @@ export default function Feed(): React.ReactElement {
486513
/>
487514
))}
488515

516+
{areStatusFiltersEnabled &&
517+
selectedStatuses.map((status) => (
518+
<Chip
519+
color='primary'
520+
variant='outlined'
521+
size='small'
522+
label={t('feedStatus.' + status + '.label')}
523+
key={status}
524+
onDelete={() => {
525+
setSelectedStatuses([
526+
...selectedStatuses.filter((s) => s !== status),
527+
]);
528+
}}
529+
/>
530+
))}
531+
489532
{areGBFSFiltersEnabled &&
490533
selectGbfsVersions.map((gbfsVersion) => (
491534
<Chip
@@ -505,6 +548,7 @@ export default function Feed(): React.ReactElement {
505548
))}
506549

507550
{(selectedFeatures.length > 0 ||
551+
selectedStatuses.length > 0 ||
508552
selectGbfsVersions.length > 0 ||
509553
isOfficialFeedSearch ||
510554
selectedFeedTypes.gtfs_rt ||

0 commit comments

Comments
 (0)