diff options
Diffstat (limited to 'src/reports/components/ReportFilter.jsx')
-rw-r--r-- | src/reports/components/ReportFilter.jsx | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/reports/components/ReportFilter.jsx b/src/reports/components/ReportFilter.jsx new file mode 100644 index 00000000..e6e08f16 --- /dev/null +++ b/src/reports/components/ReportFilter.jsx @@ -0,0 +1,215 @@ +import React, { useState } from 'react'; +import { + FormControl, InputLabel, Select, MenuItem, Button, TextField, Typography, +} from '@mui/material'; +import { useDispatch, useSelector } from 'react-redux'; +import dayjs from 'dayjs'; +import { useTranslation } from '../../common/components/LocalizationProvider'; +import useReportStyles from '../common/useReportStyles'; +import { devicesActions, reportsActions } from '../../store'; +import SplitButton from '../../common/components/SplitButton'; +import SelectField from '../../common/components/SelectField'; +import { useRestriction } from '../../common/util/permissions'; + +const ReportFilter = ({ children, handleSubmit, handleSchedule, showOnly, ignoreDevice, multiDevice, includeGroups }) => { + const classes = useReportStyles(); + const dispatch = useDispatch(); + const t = useTranslation(); + + const readonly = useRestriction('readonly'); + + const devices = useSelector((state) => state.devices.items); + const groups = useSelector((state) => state.groups.items); + + const deviceId = useSelector((state) => state.devices.selectedId); + const deviceIds = useSelector((state) => state.devices.selectedIds); + const groupIds = useSelector((state) => state.reports.groupIds); + const period = useSelector((state) => state.reports.period); + const from = useSelector((state) => state.reports.from); + const to = useSelector((state) => state.reports.to); + const [button, setButton] = useState('json'); + + const [description, setDescription] = useState(); + const [calendarId, setCalendarId] = useState(); + + const scheduleDisabled = button === 'schedule' && (!description || !calendarId); + const disabled = (!ignoreDevice && !deviceId && !deviceIds.length && !groupIds.length) || scheduleDisabled; + + const handleClick = (type) => { + if (type === 'schedule') { + handleSchedule(deviceIds, groupIds, { + description, + calendarId, + attributes: {}, + }); + } else { + let selectedFrom; + let selectedTo; + switch (period) { + case 'today': + selectedFrom = dayjs().startOf('day'); + selectedTo = dayjs().endOf('day'); + break; + case 'yesterday': + selectedFrom = dayjs().subtract(1, 'day').startOf('day'); + selectedTo = dayjs().subtract(1, 'day').endOf('day'); + break; + case 'thisWeek': + selectedFrom = dayjs().startOf('week'); + selectedTo = dayjs().endOf('week'); + break; + case 'previousWeek': + selectedFrom = dayjs().subtract(1, 'week').startOf('week'); + selectedTo = dayjs().subtract(1, 'week').endOf('week'); + break; + case 'thisMonth': + selectedFrom = dayjs().startOf('month'); + selectedTo = dayjs().endOf('month'); + break; + case 'previousMonth': + selectedFrom = dayjs().subtract(1, 'month').startOf('month'); + selectedTo = dayjs().subtract(1, 'month').endOf('month'); + break; + default: + selectedFrom = dayjs(from, 'YYYY-MM-DDTHH:mm'); + selectedTo = dayjs(to, 'YYYY-MM-DDTHH:mm'); + break; + } + + handleSubmit({ + deviceId, + deviceIds, + groupIds, + from: selectedFrom.toISOString(), + to: selectedTo.toISOString(), + calendarId, + type, + }); + } + }; + + return ( + <div className={classes.filter}> + {!ignoreDevice && ( + <div className={classes.filterItem}> + <SelectField + label={t(multiDevice ? 'deviceTitle' : 'reportDevice')} + data={Object.values(devices).sort((a, b) => a.name.localeCompare(b.name))} + value={multiDevice ? deviceIds : deviceId} + onChange={(e) => dispatch(multiDevice ? devicesActions.selectIds(e.target.value) : devicesActions.selectId(e.target.value))} + multiple={multiDevice} + fullWidth + /> + </div> + )} + {includeGroups && ( + <div className={classes.filterItem}> + <SelectField + label={t('settingsGroups')} + data={Object.values(groups).sort((a, b) => a.name.localeCompare(b.name))} + value={groupIds} + onChange={(e) => dispatch(reportsActions.updateGroupIds(e.target.value))} + multiple + fullWidth + /> + </div> + )} + {button !== 'schedule' ? ( + <> + <div className={classes.filterItem}> + <FormControl fullWidth> + <InputLabel>{t('reportPeriod')}</InputLabel> + <Select label={t('reportPeriod')} value={period} onChange={(e) => dispatch(reportsActions.updatePeriod(e.target.value))}> + <MenuItem value="today">{t('reportToday')}</MenuItem> + <MenuItem value="yesterday">{t('reportYesterday')}</MenuItem> + <MenuItem value="thisWeek">{t('reportThisWeek')}</MenuItem> + <MenuItem value="previousWeek">{t('reportPreviousWeek')}</MenuItem> + <MenuItem value="thisMonth">{t('reportThisMonth')}</MenuItem> + <MenuItem value="previousMonth">{t('reportPreviousMonth')}</MenuItem> + <MenuItem value="custom">{t('reportCustom')}</MenuItem> + </Select> + </FormControl> + </div> + {period === 'custom' && ( + <div className={classes.filterItem}> + <TextField + label={t('reportFrom')} + type="datetime-local" + value={from} + onChange={(e) => dispatch(reportsActions.updateFrom(e.target.value))} + fullWidth + /> + </div> + )} + {period === 'custom' && ( + <div className={classes.filterItem}> + <TextField + label={t('reportTo')} + type="datetime-local" + value={to} + onChange={(e) => dispatch(reportsActions.updateTo(e.target.value))} + fullWidth + /> + </div> + )} + </> + ) : ( + <> + <div className={classes.filterItem}> + <TextField + value={description || ''} + onChange={(event) => setDescription(event.target.value)} + label={t('sharedDescription')} + fullWidth + /> + </div> + <div className={classes.filterItem}> + <SelectField + value={calendarId} + onChange={(event) => setCalendarId(Number(event.target.value))} + endpoint="/api/calendars" + label={t('sharedCalendar')} + fullWidth + /> + </div> + </> + )} + {children} + <div className={classes.filterItem}> + {showOnly ? ( + <Button + fullWidth + variant="outlined" + color="secondary" + disabled={disabled} + onClick={() => handleClick('json')} + > + <Typography variant="button" noWrap>{t('reportShow')}</Typography> + </Button> + ) : ( + <SplitButton + fullWidth + variant="outlined" + color="secondary" + disabled={disabled} + onClick={handleClick} + selected={button} + setSelected={(value) => setButton(value)} + options={readonly ? { + json: t('reportShow'), + export: t('reportExport'), + mail: t('reportEmail'), + } : { + json: t('reportShow'), + export: t('reportExport'), + mail: t('reportEmail'), + schedule: t('reportSchedule'), + }} + /> + )} + </div> + </div> + ); +}; + +export default ReportFilter; |