import React from "react"; import { Link, withRouter } from 'react-router-dom' import Modal from './modal' import * as api from '../../api' import numberFormatter, { durationFormatter } from '../../util/number-formatter' import { parseQuery } from '../../query' const TITLES = { sources: 'Top Sources', utm_mediums: 'Top UTM mediums', utm_sources: 'Top UTM sources', utm_campaigns: 'Top UTM campaigns', utm_contents: 'Top UTM contents', utm_terms: 'Top UTM Terms' } class SourcesModal extends React.Component { constructor(props) { super(props) this.state = { loading: true, sources: [], query: parseQuery(props.location.search, props.site), page: 1, moreResultsAvailable: false } } loadSources() { const { site } = this.props const { query, page, sources } = this.state const detailed = this.showExtra() api.get(`/api/stats/${encodeURIComponent(site.domain)}/${this.currentFilter()}`, query, { limit: 100, page, detailed }) .then((res) => this.setState({ loading: false, sources: sources.concat(res), moreResultsAvailable: res.length === 100 })) } componentDidMount() { this.loadSources() } componentDidUpdate(prevProps) { if (this.props.location.pathname !== prevProps.location.pathname) { this.setState({ sources: [], loading: true }, this.loadSources.bind(this)) } } currentFilter() { const urlparts = this.props.location.pathname.split('/') return urlparts[urlparts.length - 1] } showExtra() { return this.state.query.period !== 'realtime' && !this.state.query.filters.goal } showConversionRate() { return !!this.state.query.filters.goal } loadMore() { this.setState({ loading: true, page: this.state.page + 1 }, this.loadSources.bind(this)) } formatBounceRate(page) { if (typeof (page.bounce_rate) === 'number') { return page.bounce_rate + '%' } else { return '-' } } formatDuration(source) { if (typeof (source.visit_duration) === 'number') { return durationFormatter(source.visit_duration) } else { return '-' } } icon(source) { if (this.currentFilter() === 'sources') { return ( ) } } renderSource(source) { const query = new URLSearchParams(window.location.search) const filter = this.currentFilter() if (filter === 'sources') query.set('source', source.name) if (filter === 'utm_mediums') query.set('utm_medium', source.name) if (filter === 'utm_sources') query.set('utm_source', source.name) if (filter === 'utm_campaigns') query.set('utm_campaign', source.name) if (filter === 'utm_contents') query.set('utm_content', source.name) if (filter === 'utm_terms') query.set('utm_term', source.name) return ( {this.icon(source)} {source.name} {this.showConversionRate() && {numberFormatter(source.total_visitors)}} {numberFormatter(source.visitors)} {this.showExtra() && {this.formatBounceRate(source)}} {this.showExtra() && {this.formatDuration(source)}} {this.showConversionRate() && {source.conversion_rate}%} ) } label() { if (this.state.query.period === 'realtime') { return 'Current visitors' } if (this.showConversionRate()) { return 'Conversions' } return 'Visitors' } renderLoading() { if (this.state.loading) { return
} else if (this.state.moreResultsAvailable) { return (
) } } title() { return TITLES[this.currentFilter()] } render() { return (

{this.title()}

{this.showConversionRate() && } {this.showExtra() && } {this.showExtra() && } {this.showConversionRate() && } {this.state.sources.map(this.renderSource.bind(this))}
SourceTotal visitors{this.label()}Bounce rateVisit durationCR
{this.renderLoading()}
) } } export default withRouter(SourcesModal)