@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
318 lines (316 loc) • 11.6 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import useStyles from './styles';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import React, { useCallback, useMemo, useState } from 'react';
import ClearRoundedIcon from '@mui/icons-material/ClearRounded';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
import { AdapterMoment as DateAdapter } from '@mui/x-date-pickers/AdapterMoment';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import MenuItem from '@mui/material/MenuItem';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
import moment from 'moment-timezone';
import { useDebouncedInput } from '../../hooks/useDebouncedInput';
const translations = defineMessages({
siteId: {
id: 'auditGridFilterPopover.filterBySite',
defaultMessage: 'Filter by Project'
},
user: {
id: 'auditGridFilterPopover.filterByUser',
defaultMessage: 'Filter by User'
},
origin: {
id: 'auditGridFilterPopover.filterByOrigin',
defaultMessage: 'Filter by Origin'
},
operations: {
id: 'auditGridFilterPopover.filterByOperations',
defaultMessage: 'Filter by Operations'
},
target: {
id: 'auditGridFilterPopover.filterByTarget',
defaultMessage: 'Filter by Target Value'
},
allOperations: {
id: 'auditGridFilterPopover.allOperations',
defaultMessage: 'All Operations'
}
});
export function AuditGridFilterPopoverBody(props) {
var _a, _b;
const { filterId, value, onFilterChange, timezone, onTimezoneSelected, onResetFilter, onClose } = props;
const { classes } = useStyles();
const { sites, users, operations, origins, timezones } = props.options;
const { formatMessage } = useIntl();
const [keyword, setKeyword] = useState((_a = props.value) !== null && _a !== void 0 ? _a : '');
const [fromDate, setFromDate] = useState(props.dateFrom ? moment(props.dateFrom) : null);
const [toDate, setToDate] = useState(props.dateTo ? moment(props.dateTo) : null);
const onSearch = useCallback((keywords) => onFilterChange(filterId, keywords), [onFilterChange, filterId]);
const onSearch$ = useDebouncedInput(onSearch, 400);
const options = useMemo(() => {
switch (filterId) {
case 'siteId': {
return [
{
id: 'all',
value: 'all',
name: React.createElement(FormattedMessage, { id: 'auditGrid.allSites', defaultMessage: 'All Projects' })
},
{
id: 'studio_root',
value: 'studio_root',
name: React.createElement(FormattedMessage, { id: 'words.system', defaultMessage: 'System' })
},
...sites.map((site) => ({ id: site.id, name: site.name, value: site.id }))
];
}
case 'user': {
return [
{
id: 'all',
value: 'all',
name: React.createElement(FormattedMessage, { id: 'auditGrid.allUsers', defaultMessage: 'All Users' })
},
...users.map((user) => ({ id: user.id.toString(), name: user.username, value: user.username }))
];
}
case 'origin': {
return [
{
id: 'all',
value: 'all',
name: React.createElement(FormattedMessage, { id: 'auditGrid.allOrigins', defaultMessage: 'All Origins' })
},
...origins
];
}
case 'operations': {
return [
{
id: 'all',
value: 'all',
name: formatMessage(translations.allOperations)
},
...operations
];
}
}
}, [filterId, formatMessage, operations, origins, sites, users]);
const onTextFieldChanges = (e) => {
onSearch$.next(e.target.value);
setKeyword(e.target.value);
};
const onMultipleSelectChanges = (e) => {
const lastString = e.target.value[e.target.value.length - 1];
if (lastString === 'all' || e.target.value.length === 0) {
onFilterChange(filterId, 'all');
} else {
const values = e.target.value.filter((value) => value !== 'all');
onFilterChange(filterId, values.join());
}
};
const onFromDateSelected = (date) => {
if (date.isValid()) {
onFilterChange('dateFrom', (date === null || date === void 0 ? void 0 : date.format()) || 'all');
}
setFromDate(date);
};
const onToDateSelected = (date) => {
if (date.isValid()) {
onFilterChange('dateTo', (date === null || date === void 0 ? void 0 : date.format()) || 'all');
}
setToDate(date);
};
const onClearDates = () => {
setToDate(null);
setFromDate(null);
onResetFilter(['dateFrom', 'dateTo']);
};
const onClearTextField = () => {
onResetFilter(filterId);
setKeyword('');
};
return React.createElement(
React.Fragment,
null,
React.createElement(
Box,
{ display: 'flex', justifyContent: 'end', marginBottom: '10px' },
React.createElement(
IconButton,
{ onClick: onClose },
React.createElement(ClearRoundedIcon, { fontSize: 'small' })
)
),
filterId === 'operationTimestamp' &&
React.createElement(
LocalizationProvider,
{ dateAdapter: DateAdapter },
React.createElement(
'form',
{ noValidate: true, autoComplete: 'off' },
React.createElement(
Box,
{ className: classes.timestampFiltersContainer },
React.createElement(DateTimePicker, {
label: React.createElement(FormattedMessage, { id: 'words.from', defaultMessage: 'From' }),
value: fromDate,
onChange: onFromDateSelected,
renderInput: (props) => React.createElement(TextField, Object.assign({}, props))
}),
React.createElement(DateTimePicker, {
label: React.createElement(FormattedMessage, { id: 'words.to', defaultMessage: 'To' }),
value: toDate,
onChange: onToDateSelected,
renderInput: (props) => React.createElement(TextField, Object.assign({}, props))
}),
React.createElement(
Button,
{
className: classes.clearButton,
disabled: !toDate && !fromDate,
variant: 'text',
color: 'primary',
onClick: () => onClearDates()
},
React.createElement(FormattedMessage, { id: 'words.clear', defaultMessage: 'Clear' })
)
),
React.createElement(Autocomplete, {
disableClearable: true,
options: timezones,
getOptionLabel: (option) => option,
value: timezone,
onChange: (e, value) => {
onTimezoneSelected(value);
},
fullWidth: true,
renderInput: (params) =>
React.createElement(
TextField,
Object.assign({}, params, {
label: React.createElement(FormattedMessage, {
id: 'auditGrid.timezone',
defaultMessage: 'Timezone'
}),
variant: 'outlined'
})
)
})
)
),
['siteId', 'user', 'origin'].includes(filterId) &&
React.createElement(
Box,
{ display: 'flex', alignItems: 'center' },
React.createElement(
TextField,
{
fullWidth: true,
select: true,
label: formatMessage(translations[filterId]),
value: value ? value : 'all',
onChange: (e) => onFilterChange(filterId, e.target.value)
},
options.map((option) => React.createElement(MenuItem, { key: option.id, value: option.value }, option.name))
),
React.createElement(
Button,
{
className: classes.clearButton,
disabled: !value,
variant: 'text',
color: 'primary',
onClick: () => onResetFilter(filterId)
},
React.createElement(FormattedMessage, { id: 'words.clear', defaultMessage: 'Clear' })
)
),
filterId === 'operations' &&
React.createElement(
Box,
{ display: 'flex', alignItems: 'center' },
React.createElement(
TextField,
{
fullWidth: true,
select: true,
label: formatMessage(translations[filterId]),
value:
(_b = value === null || value === void 0 ? void 0 : value.split(',')) !== null && _b !== void 0
? _b
: ['all'],
SelectProps: { multiple: true },
onChange: onMultipleSelectChanges
},
options.map((option) => React.createElement(MenuItem, { key: option.id, value: option.value }, option.name))
),
React.createElement(
Button,
{
className: classes.clearButton,
disabled: !value,
variant: 'text',
color: 'primary',
onClick: () => onResetFilter(filterId)
},
React.createElement(FormattedMessage, { id: 'words.clear', defaultMessage: 'Clear' })
)
),
'target' === filterId &&
React.createElement(TextField, {
value: keyword,
label: formatMessage(translations[filterId]),
InputProps: {
endAdornment:
keyword &&
React.createElement(
Tooltip,
{ title: React.createElement(FormattedMessage, { id: 'words.clear', defaultMessage: 'Clear' }) },
React.createElement(
IconButton,
{ size: 'small', className: classes.clearButton, onClick: () => onClearTextField() },
React.createElement(ClearRoundedIcon, null)
)
)
},
fullWidth: true,
onChange: onTextFieldChanges
})
);
}
export default AuditGridFilterPopoverBody;