import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { isEqual, sortBy, capitalize } from 'lodash'; import { shallowEqual, useSelector, useDispatch } from 'react-redux'; import { Link, useHistory } from 'react-router-dom'; import { Tooltip, Form, ActionGroup, Flex, FlexItem, Select, SelectOption, SelectVariant, ChipGroup, Chip, Tabs, Tab, TabTitleText, Button, DatePicker, Bullseye, Divider, Text, } from '@patternfly/react-core'; import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; import { translate as __ } from 'foremanReact/common/I18n'; import { selectCVFilterDetails } from '../ContentViewDetailSelectors'; import AffectedRepositoryTable from './AffectedRepositories/AffectedRepositoryTable'; import { editCVFilterRule } from '../ContentViewDetailActions'; import { hasPermission } from '../../helpers'; import { CONTENT_VIEW_NEEDS_PUBLISH } from '../../ContentViewsConstants'; export const dateFormat = date => `${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')}/${date.getFullYear()}`; export const convertAPIDateToUIFormat = (dateString) => { if (!dateString || dateString === '') return ''; return dateFormat(new Date(dateString)); }; export const dateParse = (date) => { if (!date || date === '') return new Date(); const split = date.split('/'); if (split.length !== 3) { return undefined; } const [month, day, year] = split; return new Date(`${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}T12:00:00Z`); }; export const isValidDate = date => date instanceof Date && !Number.isNaN(date.getTime()); const CVErrataDateFilterContent = ({ cvId, filterId, inclusion, showAffectedRepos, setShowAffectedRepos, details, }) => { const { push } = useHistory(); const filterDetails = useSelector(state => selectCVFilterDetails(state, cvId, filterId), shallowEqual); const { repositories = [], rules } = filterDetails; const [{ id, types, start_date: ruleStartDate, end_date: ruleEndDate, date_type: ruleDateType, } = {}] = rules; const { permissions } = details; const [startDate, setStartDate] = useState(convertAPIDateToUIFormat(ruleStartDate)); const [endDate, setEndDate] = useState(convertAPIDateToUIFormat(ruleEndDate)); const [dateType, setDateType] = useState(ruleDateType); const [dateTypeSelectOpen, setDateTypeSelectOpen] = useState(false); const [typeSelectOpen, setTypeSelectOpen] = useState(false); const [selectedTypes, setSelectedTypes] = useState(types); const dispatch = useDispatch(); const [activeTabKey, setActiveTabKey] = useState(0); const [startEntry, setStartEntry] = useState(false); const [endEntry, setEndEntry] = useState(false); const onSave = () => { dispatch(editCVFilterRule( filterId, { id, content_view_filter_id: filterId, start_date: startDate && startDate !== '' ? dateParse(startDate) : null, end_date: endDate && endDate !== '' ? dateParse(endDate) : null, types: selectedTypes, date_type: dateType, }, () => { dispatch({ type: CONTENT_VIEW_NEEDS_PUBLISH }); push('/filters'); }, )); }; const resetFilters = () => { setStartDate(convertAPIDateToUIFormat(ruleStartDate)); setEndDate(convertAPIDateToUIFormat(ruleEndDate)); setSelectedTypes(types); setDateType(ruleDateType); }; const onTypeSelect = (selection) => { if (selectedTypes.includes(selection)) { if (selectedTypes.length === 1) return; setSelectedTypes(selectedTypes.filter(e => e !== selection)); } else setSelectedTypes([...selectedTypes, selection]); }; const singleSelection = selection => (selectedTypes.length === 1 && selectedTypes.includes(selection)); const saveDisabled = !isValidDate(dateParse(startDate)) || !isValidDate(dateParse(endDate)) || ( isEqual(convertAPIDateToUIFormat(ruleStartDate), startDate) && isEqual(convertAPIDateToUIFormat(ruleEndDate), endDate) && isEqual(sortBy(types), sortBy(selectedTypes)) && isEqual(ruleDateType, dateType) ); useEffect(() => { if (!repositories.length && showAffectedRepos) { setActiveTabKey(1); } else { setActiveTabKey(0); } }, [showAffectedRepos, repositories.length]); const tabTitle = inclusion ? __('Included errata') : __('Excluded errata'); const invalidDateFormat = __('Enter a valid date: MM/DD/YYYY'); return ( setActiveTabKey(eventKey)} > {tabTitle}} >
{ e.preventDefault(); onSave(); }} > {(selectedTypes.length === 1) && } setStartEntry(true)} onBlur={() => setStartEntry(false)} > setStartDate(val)} dateParse={dateParse} placeholder={startEntry ? 'MM/DD/YYYY' : __('Start date')} isDisabled={!hasPermission(permissions, 'edit_content_views')} /> {__('to')} setEndEntry(true)} onBlur={() => setEndEntry(false)} > setEndDate(val)} dateParse={dateParse} placeholder={endEntry ? 'MM/DD/YYYY' : __('End date')} isDisabled={!hasPermission(permissions, 'edit_content_views')} /> {selectedTypes.map(type => ( onTypeSelect(type)} isReadOnly={singleSelection(type) || !hasPermission(permissions, 'edit_content_views')} > {capitalize(type)} ))} setStartDate('')} isReadOnly={!startDate || !hasPermission(permissions, 'edit_content_views')} > {startDate || __('ANY')} {__('to')} setEndDate('')} isReadOnly={!endDate || !hasPermission(permissions, 'edit_content_views')}> {endDate || __('ANY')} {hasPermission(permissions, 'edit_content_views') && } {hasPermission(permissions, 'edit_content_views') && }
{(repositories.length || showAffectedRepos) && {__('Affected repositories')}} >
}
); }; CVErrataDateFilterContent.propTypes = { cvId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), filterId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), inclusion: PropTypes.bool, showAffectedRepos: PropTypes.bool.isRequired, setShowAffectedRepos: PropTypes.func.isRequired, details: PropTypes.shape({ permissions: PropTypes.shape({}), }).isRequired, }; CVErrataDateFilterContent.defaultProps = { cvId: '', filterId: '', inclusion: false, }; export default CVErrataDateFilterContent;