Skip to content

Commit 8c1b193

Browse files
Feat: gbfs validator loading error state + multi language handling (#1471)
* gbfs validator error loading state and language handle * Language Icon accessibility Co-authored-by: Copilot <[email protected]> * Sackbar accessibility Co-authored-by: Copilot <[email protected]> * copilot pr comments * better language detection in gbfs validator * long loading state + big feed accomodation --------- Co-authored-by: Copilot <[email protected]>
1 parent 4820180 commit 8c1b193

File tree

7 files changed

+750
-294
lines changed

7 files changed

+750
-294
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { Refresh, ContentCopy } from '@mui/icons-material';
2+
import {
3+
Alert,
4+
AlertTitle,
5+
Box,
6+
Button,
7+
Snackbar,
8+
Typography,
9+
useTheme,
10+
} from '@mui/material';
11+
import React, { useState } from 'react';
12+
import { AlertErrorBoxStyles } from './ValidationReport.styles';
13+
14+
interface ValidationErrorAlertProps {
15+
validationError: string | null;
16+
triggerDataFetch: () => void;
17+
}
18+
19+
export function ValidationErrorAlert({
20+
validationError,
21+
triggerDataFetch,
22+
}: ValidationErrorAlertProps): React.ReactElement {
23+
const theme = useTheme();
24+
const [snackbarOpen, setSnackbarOpen] = useState(false);
25+
const [showDetails, setShowDetails] = useState(false);
26+
const errorText = validationError ?? '';
27+
return (
28+
<>
29+
<Alert
30+
severity='error'
31+
sx={{ mb: 2, '.MuiAlert-message ': { width: '100%' } }}
32+
>
33+
<AlertTitle
34+
sx={{
35+
display: 'flex',
36+
alignItems: 'flex-start',
37+
justifyContent: 'space-between',
38+
gap: 1,
39+
}}
40+
>
41+
<Box component='span'>GBFS validation failed</Box>
42+
<Box sx={{ display: 'flex', gap: 2 }}>
43+
<Button
44+
size='small'
45+
variant='text'
46+
startIcon={<Refresh />}
47+
onClick={triggerDataFetch}
48+
color='secondary'
49+
>
50+
Retry
51+
</Button>
52+
<Button
53+
size='small'
54+
variant='text'
55+
startIcon={<ContentCopy />}
56+
color='secondary'
57+
onClick={() => {
58+
setSnackbarOpen(true);
59+
void navigator.clipboard.writeText(errorText);
60+
}}
61+
>
62+
Copy details
63+
</Button>
64+
</Box>
65+
</AlertTitle>
66+
<Typography variant='body2' sx={{ mb: 1 }}>
67+
We couldn&apos;t validate the feed at the URL above. Details:
68+
</Typography>
69+
<Box component='pre' sx={AlertErrorBoxStyles(theme, showDetails)}>
70+
{errorText}
71+
</Box>
72+
{errorText.length > 300 && (
73+
<Button
74+
size='small'
75+
sx={{ mt: 1 }}
76+
onClick={() => {
77+
setShowDetails(!showDetails);
78+
}}
79+
>
80+
{showDetails ? 'Show less' : 'Show more'}
81+
</Button>
82+
)}
83+
</Alert>
84+
<Snackbar
85+
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
86+
open={snackbarOpen}
87+
autoHideDuration={5000}
88+
onClose={() => {
89+
setSnackbarOpen(false);
90+
}}
91+
message={'Error text copied to clipboard'}
92+
action={
93+
<Button
94+
color='inherit'
95+
size='small'
96+
onClick={() => {
97+
setSnackbarOpen(false);
98+
}}
99+
aria-label='Close'
100+
>
101+
Close
102+
</Button>
103+
}
104+
/>
105+
</>
106+
);
107+
}

web-app/src/app/screens/GbfsValidator/ValidationReport.styles.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,22 @@ export const ValidationElementCardStyles = (
7272
},
7373
});
7474

75+
export const AlertErrorBoxStyles = (
76+
theme: Theme,
77+
showDetails: boolean,
78+
): SxProps<Theme> => ({
79+
whiteSpace: 'pre-wrap',
80+
fontFamily:
81+
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
82+
bgcolor: theme.palette.action.hover,
83+
p: 1.5,
84+
borderRadius: 1,
85+
maxHeight: showDetails ? 400 : 140,
86+
overflow: 'auto',
87+
border: '1px solid',
88+
borderColor: 'divider',
89+
});
90+
7591
export const ValidationErrorPathStyles = (theme: Theme): CSSProperties => ({
7692
padding: theme.spacing(0.5),
7793
background: theme.palette.background.paper,

0 commit comments

Comments
 (0)