aboutsummaryrefslogtreecommitdiff
path: root/src/reports/components/ReportFilter.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/reports/components/ReportFilter.jsx')
-rw-r--r--src/reports/components/ReportFilter.jsx215
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;