import { faCircleNotch as preloader } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { isEmpty, mapObjIndexed, values } from 'ramda'; import React from 'react'; import { Card } from 'reactstrap'; import PropTypes from 'prop-types'; import qs from 'qs'; import DateRangeRow from '../utils/DateRangeRow'; import MutedMessage from '../utils/MuttedMessage'; import { formatDate } from '../utils/utils'; import SortableBarGraph from './SortableBarGraph'; import { shortUrlVisitsType } from './reducers/shortUrlVisits'; import VisitsHeader from './VisitsHeader'; import GraphCard from './GraphCard'; import { shortUrlDetailType } from './reducers/shortUrlDetail'; const ShortUrlVisits = ( { processStatsFromVisits }, OpenMapModalBtn ) => class ShortUrlVisits extends React.PureComponent { static propTypes = { match: PropTypes.shape({ params: PropTypes.object, }), location: PropTypes.shape({ search: PropTypes.string, }), getShortUrlVisits: PropTypes.func, shortUrlVisits: shortUrlVisitsType, getShortUrlDetail: PropTypes.func, shortUrlDetail: shortUrlDetailType, cancelGetShortUrlVisits: PropTypes.func, }; state = { startDate: undefined, endDate: undefined }; loadVisits = (loadDetail = false) => { const { match: { params }, location: { search }, getShortUrlVisits, getShortUrlDetail } = this.props; const { shortCode } = params; const dates = mapObjIndexed(formatDate(), this.state); const { startDate, endDate } = dates; const queryParams = qs.parse(search, { ignoreQueryPrefix: true }); const { domain } = queryParams; // While the "page" is loaded, use the timestamp + filtering dates as memoization IDs for stats calculations this.memoizationId = `${this.timeWhenMounted}_${shortCode}_${startDate}_${endDate}`; getShortUrlVisits(shortCode, { startDate, endDate, domain }); if (loadDetail) { getShortUrlDetail(shortCode, domain); } }; componentDidMount() { this.timeWhenMounted = new Date().getTime(); this.loadVisits(true); } componentWillUnmount() { this.props.cancelGetShortUrlVisits(); } render() { const { shortUrlVisits, shortUrlDetail } = this.props; const renderVisitsContent = () => { const { visits, loading, loadingLarge, error } = shortUrlVisits; if (loading) { const message = loadingLarge ? 'This is going to take a while... :S' : 'Loading...'; return {message}; } if (error) { return ( An error occurred while loading visits :( ); } if (isEmpty(visits)) { return There are no visits matching current filter :(; } const { os, browsers, referrers, countries, cities, citiesForMap } = processStatsFromVisits( { id: this.memoizationId, visits } ); const mapLocations = values(citiesForMap); return (
mapLocations.length > 0 && } sortingItems={{ name: 'City name', amount: 'Visits amount', }} />
); }; const setDate = (dateField) => (date) => this.setState({ [dateField]: date }, this.loadVisits); return (
{renderVisitsContent()}
); } }; export default ShortUrlVisits;