* #708 apply strictier linting rules and fix simple eslint bugs * #708 fix eslint errors relate to promise * #708 fix eslint import/no-extraneous-dependencies * #708 fix eslint errors of react-hook * #708 enable eslint check for typescript --------- Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
This commit is contained in:
@@ -1,43 +1,43 @@
|
||||
import { useAppDispatch, useAppSelector } from "@/app/hooks";
|
||||
import { useAppDispatch, useAppSelector } from '@/app/hooks'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Fade,
|
||||
Paper,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@linagora/twake-mui";
|
||||
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
|
||||
import ReplayIcon from "@mui/icons-material/Replay";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { push } from "redux-first-history";
|
||||
import { useI18n } from "twake-i18n";
|
||||
Typography
|
||||
} from '@linagora/twake-mui'
|
||||
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'
|
||||
import ReplayIcon from '@mui/icons-material/Replay'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { push } from 'redux-first-history'
|
||||
import { useI18n } from 'twake-i18n'
|
||||
|
||||
export function Error() {
|
||||
const { t } = useI18n();
|
||||
const dispatch = useAppDispatch();
|
||||
const userError = useAppSelector((state) => state.user.error);
|
||||
const calendarError = useAppSelector((state) => state.calendars.error);
|
||||
const initialUserError = useRef(userError);
|
||||
const { t } = useI18n()
|
||||
const dispatch = useAppDispatch()
|
||||
const userError = useAppSelector(state => state.user.error)
|
||||
const calendarError = useAppSelector(state => state.calendars.error)
|
||||
const initialUserError = useRef(userError)
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialUserError.current) {
|
||||
dispatch(push("/"));
|
||||
dispatch(push('/'))
|
||||
}
|
||||
}, [dispatch]);
|
||||
}, [dispatch])
|
||||
|
||||
const errorMessage = userError || calendarError || t("error.unknown");
|
||||
const errorMessage = userError || calendarError || t('error.unknown')
|
||||
|
||||
return (
|
||||
<Fade in timeout={500}>
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
bgcolor: "background.default",
|
||||
p: 3,
|
||||
minHeight: '100vh',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
bgcolor: 'background.default',
|
||||
p: 3
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
@@ -45,28 +45,28 @@ export function Error() {
|
||||
sx={{
|
||||
borderRadius: 4,
|
||||
p: 6,
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
maxWidth: 420,
|
||||
width: "100%",
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2} alignItems="center">
|
||||
<Box
|
||||
sx={{
|
||||
color: "error.main",
|
||||
borderRadius: "50%",
|
||||
color: 'error.main',
|
||||
borderRadius: '50%',
|
||||
width: 72,
|
||||
height: 72,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<ErrorOutlineIcon sx={{ fontSize: 40 }} />
|
||||
</Box>
|
||||
|
||||
<Typography variant="h5" fontWeight={600}>
|
||||
{t("error.title")}
|
||||
{t('error.title')}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body1" color="text.secondary" sx={{ mb: 2 }}>
|
||||
@@ -79,19 +79,19 @@ export function Error() {
|
||||
startIcon={<ReplayIcon />}
|
||||
onClick={() => window.location.reload()}
|
||||
sx={{
|
||||
textTransform: "none",
|
||||
textTransform: 'none',
|
||||
fontWeight: 600,
|
||||
borderRadius: 2,
|
||||
px: 3,
|
||||
py: 1,
|
||||
boxShadow: "none",
|
||||
boxShadow: 'none'
|
||||
}}
|
||||
>
|
||||
{t("error.retry")}
|
||||
{t('error.retry')}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Fade>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,109 +1,109 @@
|
||||
import { useAppDispatch } from "@/app/hooks";
|
||||
import { clearError as calendarClearError } from "@/features/Calendars/CalendarSlice";
|
||||
import { clearError as userClearError } from "@/features/User/userSlice";
|
||||
import { Alert, Button, Snackbar } from "@linagora/twake-mui";
|
||||
import { useI18n } from "twake-i18n";
|
||||
import { useAppDispatch } from '@/app/hooks'
|
||||
import { clearError as calendarClearError } from '@/features/Calendars/CalendarSlice'
|
||||
import { clearError as userClearError } from '@/features/User/userSlice'
|
||||
import { Alert, Button, Snackbar } from '@linagora/twake-mui'
|
||||
import { useI18n } from 'twake-i18n'
|
||||
|
||||
export function ErrorSnackbar({
|
||||
error,
|
||||
type,
|
||||
type
|
||||
}: {
|
||||
error: string | null;
|
||||
type: "user" | "calendar";
|
||||
error: string | null
|
||||
type: 'user' | 'calendar'
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useI18n()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const handleCloseSnackbar = () => {
|
||||
dispatch(type === "calendar" ? calendarClearError() : userClearError());
|
||||
};
|
||||
dispatch(type === 'calendar' ? calendarClearError() : userClearError())
|
||||
}
|
||||
|
||||
const getErrorMessage = () => {
|
||||
if (!error) return t("error.unknown");
|
||||
if (!error) return t('error.unknown')
|
||||
|
||||
// Check if error message is a translation key with params
|
||||
// Format: TRANSLATION:key|param1=value1|param2=value2
|
||||
if (error.startsWith("TRANSLATION:")) {
|
||||
const parts = error.substring(12).split("|");
|
||||
const translationKey = parts[0];
|
||||
const params: Record<string, string> = {};
|
||||
if (error.startsWith('TRANSLATION:')) {
|
||||
const parts = error.substring(12).split('|')
|
||||
const translationKey = parts[0]
|
||||
const params: Record<string, string> = {}
|
||||
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
const equalIndex = parts[i].indexOf("=");
|
||||
if (equalIndex === -1) continue;
|
||||
const key = parts[i].substring(0, equalIndex);
|
||||
const value = parts[i].substring(equalIndex + 1);
|
||||
const equalIndex = parts[i].indexOf('=')
|
||||
if (equalIndex === -1) continue
|
||||
const key = parts[i].substring(0, equalIndex)
|
||||
const value = parts[i].substring(equalIndex + 1)
|
||||
if (key && value) {
|
||||
try {
|
||||
params[key] = decodeURIComponent(value);
|
||||
params[key] = decodeURIComponent(value)
|
||||
} catch {
|
||||
params[key] = value;
|
||||
params[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return t(translationKey, params);
|
||||
return t(translationKey, params)
|
||||
}
|
||||
|
||||
return error;
|
||||
};
|
||||
return error
|
||||
}
|
||||
|
||||
return (
|
||||
<Snackbar
|
||||
open={!!error}
|
||||
onClose={handleCloseSnackbar}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
>
|
||||
<Alert
|
||||
severity="error"
|
||||
onClose={handleCloseSnackbar}
|
||||
sx={{ width: "100%" }}
|
||||
sx={{ width: '100%' }}
|
||||
action={
|
||||
<Button color="inherit" size="small" onClick={handleCloseSnackbar}>
|
||||
{t("common.ok")}
|
||||
{t('common.ok')}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{getErrorMessage()}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export function EventErrorSnackbar({
|
||||
messages,
|
||||
onClose,
|
||||
onClose
|
||||
}: {
|
||||
messages: string[];
|
||||
onClose: () => void;
|
||||
messages: string[]
|
||||
onClose: () => void
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const open = messages.length > 0;
|
||||
const { t } = useI18n()
|
||||
const open = messages.length > 0
|
||||
|
||||
const summary =
|
||||
messages.length === 1
|
||||
? messages[0]
|
||||
: t("error.multipleEvents", { count: messages.length });
|
||||
: t('error.multipleEvents', { count: messages.length })
|
||||
|
||||
return (
|
||||
<Snackbar
|
||||
open={open}
|
||||
autoHideDuration={6000}
|
||||
onClose={onClose}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
>
|
||||
<Alert
|
||||
severity="error"
|
||||
onClose={onClose}
|
||||
sx={{ width: "100%" }}
|
||||
sx={{ width: '100%' }}
|
||||
action={
|
||||
<Button color="inherit" size="small" onClick={onClose}>
|
||||
{t("common.ok")}
|
||||
{t('common.ok')}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{summary}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
export class EventErrorHandler {
|
||||
private errors = new Map<string, string>();
|
||||
private reportedEvents = new Set<string>();
|
||||
private onErrorCallback?: (messages: string[]) => void;
|
||||
private errors = new Map<string, string>()
|
||||
private reportedEvents = new Set<string>()
|
||||
private onErrorCallback?: (messages: string[]) => void
|
||||
|
||||
setErrorCallback(callback: (messages: string[]) => void) {
|
||||
this.onErrorCallback = callback;
|
||||
this.onErrorCallback = callback
|
||||
}
|
||||
|
||||
reportError(eventId: string, message: string) {
|
||||
if (!this.reportedEvents.has(eventId)) {
|
||||
this.reportedEvents.add(eventId);
|
||||
this.errors.set(eventId, message);
|
||||
console.warn(`[EventErrorHandler] ${eventId}: ${message}`);
|
||||
this.emit();
|
||||
this.reportedEvents.add(eventId)
|
||||
this.errors.set(eventId, message)
|
||||
console.warn(`[EventErrorHandler] ${eventId}: ${message}`)
|
||||
this.emit()
|
||||
}
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
this.errors.clear();
|
||||
this.emit();
|
||||
this.errors.clear()
|
||||
this.emit()
|
||||
}
|
||||
|
||||
private emit() {
|
||||
this.onErrorCallback?.(Array.from(this.errors.values()));
|
||||
this.onErrorCallback?.(Array.from(this.errors.values()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user