* #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,113 +1,113 @@
|
||||
import { useAppDispatch, useAppSelector } from "@/app/hooks";
|
||||
import { AppDispatch } from "@/app/store";
|
||||
import { defaultColors } from "@/utils/defaultColors";
|
||||
import { browserDefaultTimeZone } from "@/utils/timezone";
|
||||
import { useAppDispatch, useAppSelector } from '@/app/hooks'
|
||||
import { AppDispatch } from '@/app/store'
|
||||
import { defaultColors } from '@/utils/defaultColors'
|
||||
import { browserDefaultTimeZone } from '@/utils/timezone'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
IconButton,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@linagora/twake-mui";
|
||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import RepeatIcon from "@mui/icons-material/Repeat";
|
||||
import SquareRoundedIcon from "@mui/icons-material/SquareRounded";
|
||||
import VideocamIcon from "@mui/icons-material/Videocam";
|
||||
import { useState } from "react";
|
||||
import { useI18n } from "twake-i18n";
|
||||
import logo from "../../static/noResult-logo.svg";
|
||||
import { getEventAsync } from "../Calendars/services";
|
||||
import EventPreviewModal from "@/features/Events/EventPreview";
|
||||
import { CalendarEvent } from "../Events/EventsTypes";
|
||||
import { setView } from "../Settings/SettingsSlice";
|
||||
import "./searchResult.styl";
|
||||
import { SearchEventResult } from "./types/SearchEventResult";
|
||||
Typography
|
||||
} from '@linagora/twake-mui'
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
|
||||
import RepeatIcon from '@mui/icons-material/Repeat'
|
||||
import SquareRoundedIcon from '@mui/icons-material/SquareRounded'
|
||||
import VideocamIcon from '@mui/icons-material/Videocam'
|
||||
import { useState } from 'react'
|
||||
import { useI18n } from 'twake-i18n'
|
||||
import logo from '../../static/noResult-logo.svg'
|
||||
import { getEventAsync } from '../Calendars/services'
|
||||
import EventPreviewModal from '@/features/Events/EventPreview'
|
||||
import { CalendarEvent } from '../Events/EventsTypes'
|
||||
import { setView } from '../Settings/SettingsSlice'
|
||||
import './searchResult.styl'
|
||||
import { SearchEventResult } from './types/SearchEventResult'
|
||||
|
||||
const styles = {
|
||||
M3BodyLarge: {
|
||||
fontFamily: "Roboto",
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: 400,
|
||||
fontStyle: "normal",
|
||||
fontSize: "22px",
|
||||
lineHeight: "28px",
|
||||
letterSpacing: "0%",
|
||||
color: "#243B55",
|
||||
fontStyle: 'normal',
|
||||
fontSize: '22px',
|
||||
lineHeight: '28px',
|
||||
letterSpacing: '0%',
|
||||
color: '#243B55'
|
||||
},
|
||||
M3BodyMedium1: {
|
||||
fontFamily: "Inter",
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: 400,
|
||||
fontStyle: "normal",
|
||||
fontSize: "16px",
|
||||
lineHeight: "24px",
|
||||
letterSpacing: "-0.15px",
|
||||
color: "#243B55",
|
||||
fontStyle: 'normal',
|
||||
fontSize: '16px',
|
||||
lineHeight: '24px',
|
||||
letterSpacing: '-0.15px',
|
||||
color: '#243B55'
|
||||
},
|
||||
M3BodyMedium: {
|
||||
fontFamily: "Roboto",
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: 400,
|
||||
fontStyle: "normal",
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
letterSpacing: "0.25px",
|
||||
verticalAlign: "middle",
|
||||
color: "#8C9CAF",
|
||||
fontStyle: 'normal',
|
||||
fontSize: '14px',
|
||||
lineHeight: '20px',
|
||||
letterSpacing: '0.25px',
|
||||
verticalAlign: 'middle',
|
||||
color: '#8C9CAF'
|
||||
},
|
||||
M3BodyMedium3: {
|
||||
fontFamily: "Inter",
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: 400,
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
letterSpacing: "0.25px",
|
||||
verticalAlign: "middle",
|
||||
color: "#8C9CAF",
|
||||
fontSize: '14px',
|
||||
lineHeight: '20px',
|
||||
letterSpacing: '0.25px',
|
||||
verticalAlign: 'middle',
|
||||
color: '#8C9CAF'
|
||||
},
|
||||
M3TitleMedium: {
|
||||
fontFamily: "Roboto",
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: 500,
|
||||
fontStyle: "medium",
|
||||
fontSize: "16px",
|
||||
lineHeight: "24px",
|
||||
letterSpacing: "0.15px",
|
||||
textAlign: "center",
|
||||
verticalAlign: "middle",
|
||||
color: "#243B55",
|
||||
},
|
||||
};
|
||||
fontStyle: 'medium',
|
||||
fontSize: '16px',
|
||||
lineHeight: '24px',
|
||||
letterSpacing: '0.15px',
|
||||
textAlign: 'center',
|
||||
verticalAlign: 'middle',
|
||||
color: '#243B55'
|
||||
}
|
||||
}
|
||||
|
||||
export default function SearchResultsPage() {
|
||||
const { t } = useI18n();
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useI18n()
|
||||
const dispatch = useAppDispatch()
|
||||
const { error, loading, hits, results } = useAppSelector(
|
||||
(state) => state.searchResult
|
||||
);
|
||||
state => state.searchResult
|
||||
)
|
||||
|
||||
let layout;
|
||||
let layout
|
||||
|
||||
if (loading) {
|
||||
layout = (
|
||||
<Box className="loading">
|
||||
<CircularProgress size={32} />
|
||||
</Box>
|
||||
);
|
||||
)
|
||||
} else if (error) {
|
||||
layout = (
|
||||
<Box className="error">
|
||||
<Typography className="error-text">{error}</Typography>
|
||||
</Box>
|
||||
);
|
||||
)
|
||||
} else if (!hits) {
|
||||
layout = (
|
||||
<Box className="noResults">
|
||||
<img className="logo" src={logo} alt={t("search.noResults")} />
|
||||
<img className="logo" src={logo} alt={t('search.noResults')} />
|
||||
<Typography sx={styles.M3TitleMedium}>
|
||||
{t("search.noResults")}
|
||||
{t('search.noResults')}
|
||||
</Typography>
|
||||
<Typography sx={styles.M3BodyMedium}>
|
||||
{t("search.noResultsSubtitle")}
|
||||
{t('search.noResultsSubtitle')}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
)
|
||||
} else {
|
||||
layout = (
|
||||
<Box className="search-result-content-body">
|
||||
@@ -121,49 +121,48 @@ export default function SearchResultsPage() {
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className={`search-layout`}>
|
||||
<Box className="search-layout">
|
||||
<Box className="search-result-content-header">
|
||||
<Box className="back-button">
|
||||
<IconButton
|
||||
onClick={() => dispatch(setView("calendar"))}
|
||||
aria-label={t("settings.back")}
|
||||
onClick={() => dispatch(setView('calendar'))}
|
||||
aria-label={t('settings.back')}
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h5">{t("search.resultsTitle")}</Typography>
|
||||
<Typography variant="h5">{t('search.resultsTitle')}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
{layout}
|
||||
</Box>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function ResultItem({
|
||||
eventData,
|
||||
dispatch,
|
||||
dispatch
|
||||
}: {
|
||||
eventData: SearchEventResult;
|
||||
dispatch: AppDispatch;
|
||||
eventData: SearchEventResult
|
||||
dispatch: AppDispatch
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const startDate = new Date(eventData.data.start);
|
||||
const endDate = eventData.data.end ? new Date(eventData.data.end) : startDate;
|
||||
const { t } = useI18n()
|
||||
const startDate = new Date(eventData.data.start)
|
||||
const endDate = eventData.data.end ? new Date(eventData.data.end) : startDate
|
||||
const timeZone =
|
||||
useAppSelector((state) => state.settings.timeZone) ??
|
||||
browserDefaultTimeZone;
|
||||
useAppSelector(state => state.settings.timeZone) ?? browserDefaultTimeZone
|
||||
const calendar = useAppSelector(
|
||||
(state) =>
|
||||
state =>
|
||||
state.calendars.list[
|
||||
`${eventData.data.userId}/${eventData.data.calendarId}`
|
||||
]
|
||||
);
|
||||
const calendarColor = calendar?.color?.light;
|
||||
)
|
||||
const calendarColor = calendar?.color?.light
|
||||
|
||||
const [openPreview, setOpenPreview] = useState(false);
|
||||
const [openPreview, setOpenPreview] = useState(false)
|
||||
|
||||
const handleOpenResult = async (eventData: SearchEventResult) => {
|
||||
if (calendar) {
|
||||
@@ -181,59 +180,59 @@ function ResultItem({
|
||||
location: eventData.data.location,
|
||||
organizer: eventData.data.organizer,
|
||||
title: eventData.data.summary,
|
||||
timezone: timeZone,
|
||||
} as CalendarEvent;
|
||||
await dispatch(getEventAsync(event));
|
||||
setOpenPreview(true);
|
||||
timezone: timeZone
|
||||
} as CalendarEvent
|
||||
await dispatch(getEventAsync(event))
|
||||
setOpenPreview(true)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
gap: 2,
|
||||
p: 3,
|
||||
borderTop: "1px solid #F3F6F9",
|
||||
cursor: "pointer",
|
||||
"&:hover": { backgroundColor: "#e7e7e7ff" },
|
||||
alignItems: "center",
|
||||
textAlign: "left",
|
||||
maxWidth: "80vw",
|
||||
borderTop: '1px solid #F3F6F9',
|
||||
cursor: 'pointer',
|
||||
'&:hover': { backgroundColor: '#e7e7e7ff' },
|
||||
alignItems: 'center',
|
||||
textAlign: 'left',
|
||||
maxWidth: '80vw'
|
||||
}}
|
||||
onClick={() => handleOpenResult(eventData)}
|
||||
>
|
||||
<Typography sx={{ ...styles.M3BodyLarge, minWidth: "90px" }}>
|
||||
{startDate.toLocaleDateString(t("locale"), {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
timeZone,
|
||||
<Typography sx={{ ...styles.M3BodyLarge, minWidth: '90px' }}>
|
||||
{startDate.toLocaleDateString(t('locale'), {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
timeZone
|
||||
})}
|
||||
{startDate.toDateString() !== endDate.toDateString() && (
|
||||
<>
|
||||
{" - "}
|
||||
{endDate.toLocaleDateString(t("locale"), {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
timeZone,
|
||||
{' - '}
|
||||
{endDate.toLocaleDateString(t('locale'), {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
timeZone
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</Typography>
|
||||
{!eventData.data.allDay && (
|
||||
<Typography sx={{ ...styles.M3BodyMedium1, minWidth: "120px" }}>
|
||||
{startDate.toLocaleTimeString(t("locale"), {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
timeZone,
|
||||
<Typography sx={{ ...styles.M3BodyMedium1, minWidth: '120px' }}>
|
||||
{startDate.toLocaleTimeString(t('locale'), {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZone
|
||||
})}
|
||||
-
|
||||
{endDate.toLocaleTimeString(t("locale"), {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
timeZone,
|
||||
{endDate.toLocaleTimeString(t('locale'), {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZone
|
||||
})}
|
||||
</Typography>
|
||||
)}
|
||||
@@ -243,12 +242,12 @@ function ResultItem({
|
||||
color: calendarColor ?? defaultColors[0].light,
|
||||
width: 24,
|
||||
height: 24,
|
||||
flexShrink: 0,
|
||||
flexShrink: 0
|
||||
}}
|
||||
/>
|
||||
<Box display="flex" flexDirection="row" gap={1} sx={{ minWidth: 0 }}>
|
||||
<Typography sx={styles.M3BodyLarge}>
|
||||
{eventData.data.summary || t("event.untitled")}
|
||||
{eventData.data.summary || t('event.untitled')}
|
||||
</Typography>
|
||||
{eventData.data.isRecurrentMaster && <RepeatIcon />}
|
||||
</Box>
|
||||
@@ -256,11 +255,11 @@ function ResultItem({
|
||||
<Typography
|
||||
sx={{
|
||||
...styles.M3BodyMedium1,
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
minWidth: "150px",
|
||||
maxWidth: "150px",
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
minWidth: '150px',
|
||||
maxWidth: '150px'
|
||||
}}
|
||||
>
|
||||
{eventData.data.organizer.cn || eventData.data.organizer.email}
|
||||
@@ -270,11 +269,11 @@ function ResultItem({
|
||||
<Typography
|
||||
sx={{
|
||||
...styles.M3BodyMedium,
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
minWidth: "150px",
|
||||
maxWidth: "250px",
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
minWidth: '150px',
|
||||
maxWidth: '250px'
|
||||
}}
|
||||
>
|
||||
{eventData.data.location}
|
||||
@@ -284,30 +283,30 @@ function ResultItem({
|
||||
<Typography
|
||||
sx={{
|
||||
...styles.M3BodyMedium3,
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
minWidth: 0
|
||||
}}
|
||||
>
|
||||
{eventData.data.description.replace(/\n/g, " ")}
|
||||
{eventData.data.description.replace(/\n/g, ' ')}
|
||||
</Typography>
|
||||
)}
|
||||
{eventData.data["x-openpaas-videoconference"] && (
|
||||
{eventData.data['x-openpaas-videoconference'] && (
|
||||
<Button
|
||||
startIcon={<VideocamIcon />}
|
||||
sx={{ flexShrink: 0, ml: "auto" }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
sx={{ flexShrink: 0, ml: 'auto' }}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
window.open(
|
||||
eventData.data["x-openpaas-videoconference"],
|
||||
"_blank",
|
||||
"noopener,noreferrer"
|
||||
);
|
||||
eventData.data['x-openpaas-videoconference'],
|
||||
'_blank',
|
||||
'noopener,noreferrer'
|
||||
)
|
||||
}}
|
||||
>
|
||||
{t("eventPreview.joinVideoShort")}
|
||||
{t('eventPreview.joinVideoShort')}
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
@@ -320,5 +319,5 @@ function ResultItem({
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user