-
-
+
+
+
{propKey && renderBreakdown()}
diff --git a/assets/js/dashboard/stats/devices/index.js b/assets/js/dashboard/stats/devices/index.js
index cb668f7871c2..ddb2bcd7ca86 100644
--- a/assets/js/dashboard/stats/devices/index.js
+++ b/assets/js/dashboard/stats/devices/index.js
@@ -7,6 +7,38 @@ import * as url from '../../util/url'
import { VISITORS_METRIC, PERCENTAGE_METRIC, maybeWithCR } from '../reports/metrics';
import ImportedQueryUnsupportedWarning from '../imported-query-unsupported-warning';
+// Icons copied from https://github.com/alrra/browser-logos
+const BROWSER_ICONS = {
+ 'Chrome': 'chrome.svg',
+ 'Safari': 'safari.png',
+ 'Firefox': 'firefox.svg',
+ 'Microsoft Edge': 'edge.svg',
+ 'Vivaldi': 'vivaldi.svg',
+ 'Opera': 'opera.svg',
+ 'Samsung Browser': 'samsung-internet.svg',
+ 'Chromium': 'chromium.svg',
+ 'UC Browser': 'uc.svg',
+ 'Yandex Browser': 'yandex.png', // Only PNG available in browser-logos
+ // Logos underneath this line are not available in browser-logos. Grabbed from random places on the internets.
+ 'DuckDuckGo Privacy Browser': 'duckduckgo.svg',
+ 'MIUI Browser': 'miui.webp',
+ 'Huawei Browser Mobile': 'huawei.png',
+ 'QQ Browser': 'qq.png',
+ 'Ecosia': 'ecosia.png',
+ 'vivo Browser': 'vivo.png'
+}
+
+function browserIconFor(browser) {
+ const filename = BROWSER_ICONS[browser] || 'fallback.svg'
+
+ return (
+

+ )
+}
+
function Browsers({ query, site, afterFetchData }) {
function fetchData() {
return api.get(url.apiPath(site, '/browsers'), query)
@@ -19,6 +51,10 @@ function Browsers({ query, site, afterFetchData }) {
}
}
+ function renderIcon(listItem) {
+ return browserIconFor(listItem.name)
+ }
+
return (
)
}
@@ -34,6 +71,15 @@ function Browsers({ query, site, afterFetchData }) {
function BrowserVersions({ query, site, afterFetchData }) {
function fetchData() {
return api.get(url.apiPath(site, '/browser-versions'), query)
+ .then(res => {
+ return {...res, results: res.results.map((row => {
+ return {...row, name: `${row.browser} ${row.name}`, version: row.name}
+ }))}
+ })
+ }
+
+ function renderIcon(listItem) {
+ return browserIconFor(listItem.browser)
}
function getFilterFor(listItem) {
@@ -42,7 +88,7 @@ function BrowserVersions({ query, site, afterFetchData }) {
}
return {
prefix: 'browser_version',
- filter: ["is", "browser_version", [listItem['name']]]
+ filter: ["is", "browser_version", [listItem.version]]
}
}
@@ -53,6 +99,7 @@ function BrowserVersions({ query, site, afterFetchData }) {
getFilterFor={getFilterFor}
keyLabel="Browser version"
metrics={maybeWithCR([VISITORS_METRIC, PERCENTAGE_METRIC], query)}
+ renderIcon={renderIcon}
query={query}
/>
)
@@ -117,7 +164,9 @@ function ScreenSizes({ query, site, afterFetchData }) {
}
function renderIcon(screenSize) {
- return iconFor(screenSize.name)
+ return (
+
{iconFor(screenSize.name)}
+ )
}
function getFilterFor(listItem) {
diff --git a/assets/js/dashboard/stats/graph/stats-export.js b/assets/js/dashboard/stats/graph/stats-export.js
index 6716b2eb1eb6..0c3613a81767 100644
--- a/assets/js/dashboard/stats/graph/stats-export.js
+++ b/assets/js/dashboard/stats/graph/stats-export.js
@@ -2,7 +2,7 @@ import React, { useState } from "react"
import * as api from '../../api'
import { getCurrentInterval } from "./interval-picker"
-export default function StatsExport({site, query}) {
+export default function StatsExport({ site, query }) {
const [exporting, setExporting] = useState(false)
function startExport() {
@@ -50,4 +50,4 @@ export default function StatsExport({site, query}) {
{!exporting && renderExportLink()}
)
-}
\ No newline at end of file
+}
diff --git a/assets/js/dashboard/stats/locations/index.js b/assets/js/dashboard/stats/locations/index.js
index 7a229f449d0f..23f4a4bc2ded 100644
--- a/assets/js/dashboard/stats/locations/index.js
+++ b/assets/js/dashboard/stats/locations/index.js
@@ -4,108 +4,108 @@ import * as storage from '../../util/storage'
import CountriesMap from './map'
import * as api from '../../api'
-import {apiPath, sitePath} from '../../util/url'
+import { apiPath, sitePath } from '../../util/url'
import ListReport from '../reports/list'
import { VISITORS_METRIC, maybeWithCR } from '../reports/metrics';
import { getFiltersByKeyPrefix } from '../../util/filters';
import ImportedQueryUnsupportedWarning from '../imported-query-unsupported-warning';
-function Countries({query, site, onClick, afterFetchData}) {
- function fetchData() {
- return api.get(apiPath(site, '/countries'), query, { limit: 9 })
- }
-
- function renderIcon(country) {
- return
{country.flag}
- }
-
- function getFilterFor(listItem) {
- return {
- prefix: "country",
- filter: ["is", "country", [listItem['code']]],
- labels: { [listItem['code']]: listItem['name'] }
- }
- }
-
- return (
-
- )
+function Countries({ query, site, onClick, afterFetchData }) {
+ function fetchData() {
+ return api.get(apiPath(site, '/countries'), query, { limit: 9 })
+ }
+
+ function renderIcon(country) {
+ return
{country.flag}
+ }
+
+ function getFilterFor(listItem) {
+ return {
+ prefix: "country",
+ filter: ["is", "country", [listItem['code']]],
+ labels: { [listItem['code']]: listItem['name'] }
+ }
+ }
+
+ return (
+
+ )
}
-function Regions({query, site, onClick, afterFetchData}) {
- function fetchData() {
- return api.get(apiPath(site, '/regions'), query, {limit: 9})
- }
-
- function renderIcon(region) {
- return
{region.country_flag}
- }
-
- function getFilterFor(listItem) {
- return {
- prefix: "region",
- filter: ["is", "region", [listItem['code']]],
- labels: { [listItem['code']]: listItem['name'] }
- }
- }
-
- return (
-
- )
+function Regions({ query, site, onClick, afterFetchData }) {
+ function fetchData() {
+ return api.get(apiPath(site, '/regions'), query, { limit: 9 })
+ }
+
+ function renderIcon(region) {
+ return
{region.country_flag}
+ }
+
+ function getFilterFor(listItem) {
+ return {
+ prefix: "region",
+ filter: ["is", "region", [listItem['code']]],
+ labels: { [listItem['code']]: listItem['name'] }
+ }
+ }
+
+ return (
+
+ )
}
-function Cities({query, site, afterFetchData}) {
- function fetchData() {
- return api.get(apiPath(site, '/cities'), query, {limit: 9})
- }
-
- function renderIcon(city) {
- return
{city.country_flag}
- }
-
- function getFilterFor(listItem) {
- return {
- prefix: "city",
- filter: ["is", "city", [listItem['code']]],
- labels: { [listItem['code']]: listItem['name'] }
- }
- }
-
- return (
-
- )
+function Cities({ query, site, afterFetchData }) {
+ function fetchData() {
+ return api.get(apiPath(site, '/cities'), query, { limit: 9 })
+ }
+
+ function renderIcon(city) {
+ return
{city.country_flag}
+ }
+
+ function getFilterFor(listItem) {
+ return {
+ prefix: "city",
+ filter: ["is", "city", [listItem['code']]],
+ labels: { [listItem['code']]: listItem['name'] }
+ }
+ }
+
+ return (
+
+ )
}
@@ -117,116 +117,116 @@ const labelFor = {
export default class Locations extends React.Component {
constructor(props) {
- super(props)
- this.onCountryFilter = this.onCountryFilter.bind(this)
- this.onRegionFilter = this.onRegionFilter.bind(this)
- this.afterFetchData = this.afterFetchData.bind(this)
- this.tabKey = `geoTab__${ props.site.domain}`
- const storedTab = storage.getItem(this.tabKey)
- this.state = {
- mode: storedTab || 'map',
- loading: true,
- skipImportedReason: null
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- const isRemovingFilter = (filterName) => {
- return getFiltersByKeyPrefix(prevProps.query, filterName).length > 0 &&
- getFiltersByKeyPrefix(this.props.query, filterName).length == 0
- }
-
- if (this.state.mode === 'cities' && isRemovingFilter('region')) {
- this.setMode('regions')()
- }
-
- if (this.state.mode === 'regions' && isRemovingFilter('country')) {
- this.setMode(this.countriesRestoreMode || 'countries')()
- }
-
- if (this.props.query !== prevProps.query || this.state.mode !== prevState.mode) {
- this.setState({loading: true})
- }
- }
-
- setMode(mode) {
- return () => {
- storage.setItem(this.tabKey, mode)
- this.setState({mode})
- }
- }
-
- onCountryFilter(mode) {
- return () => {
- this.countriesRestoreMode = mode
- this.setMode('regions')()
- }
- }
-
- onRegionFilter() {
- this.setMode('cities')()
- }
-
- afterFetchData(apiResponse) {
- this.setState({loading: false, skipImportedReason: apiResponse.skip_imported_reason})
- }
+ super(props)
+ this.onCountryFilter = this.onCountryFilter.bind(this)
+ this.onRegionFilter = this.onRegionFilter.bind(this)
+ this.afterFetchData = this.afterFetchData.bind(this)
+ this.tabKey = `geoTab__${props.site.domain}`
+ const storedTab = storage.getItem(this.tabKey)
+ this.state = {
+ mode: storedTab || 'map',
+ loading: true,
+ skipImportedReason: null
+ }
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ const isRemovingFilter = (filterName) => {
+ return getFiltersByKeyPrefix(prevProps.query, filterName).length > 0 &&
+ getFiltersByKeyPrefix(this.props.query, filterName).length == 0
+ }
+
+ if (this.state.mode === 'cities' && isRemovingFilter('region')) {
+ this.setMode('regions')()
+ }
+
+ if (this.state.mode === 'regions' && isRemovingFilter('country')) {
+ this.setMode(this.countriesRestoreMode || 'countries')()
+ }
+
+ if (this.props.query !== prevProps.query || this.state.mode !== prevState.mode) {
+ this.setState({ loading: true })
+ }
+ }
+
+ setMode(mode) {
+ return () => {
+ storage.setItem(this.tabKey, mode)
+ this.setState({ mode })
+ }
+ }
+
+ onCountryFilter(mode) {
+ return () => {
+ this.countriesRestoreMode = mode
+ this.setMode('regions')()
+ }
+ }
+
+ onRegionFilter() {
+ this.setMode('cities')()
+ }
+
+ afterFetchData(apiResponse) {
+ this.setState({ loading: false, skipImportedReason: apiResponse.skip_imported_reason })
+ }
renderContent() {
- switch(this.state.mode) {
- case "cities":
- return
- case "regions":
- return
- case "countries":
- return
- case "map":
- default:
- return
- }
- }
+ switch (this.state.mode) {
+ case "cities":
+ return
+ case "regions":
+ return
+ case "countries":
+ return
+ case "map":
+ default:
+ return
+ }
+ }
renderPill(name, mode) {
- const isActive = this.state.mode === mode
-
- if (isActive) {
- return (
-
- )
- }
-
- return (
-
- )
- }
+ const isActive = this.state.mode === mode
+
+ if (isActive) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+ }
render() {
- return (
-
-
-
-
- {labelFor[this.state.mode] || 'Locations'}
-
-
-
-
- { this.renderPill('Map', 'map') }
- { this.renderPill('Countries', 'countries') }
- { this.renderPill('Regions', 'regions') }
- { this.renderPill('Cities', 'cities') }
-
-
- {this.renderContent()}
-
- )
- }
+ return (
+
+
+
+
+ {labelFor[this.state.mode] || 'Locations'}
+
+
+
+
+ {this.renderPill('Map', 'map')}
+ {this.renderPill('Countries', 'countries')}
+ {this.renderPill('Regions', 'regions')}
+ {this.renderPill('Cities', 'cities')}
+
+
+ {this.renderContent()}
+
+ )
+ }
}
diff --git a/assets/js/dashboard/stats/locations/map.js b/assets/js/dashboard/stats/locations/map.js
index 4006607c80ea..2cd09c8a340b 100644
--- a/assets/js/dashboard/stats/locations/map.js
+++ b/assets/js/dashboard/stats/locations/map.js
@@ -28,7 +28,7 @@ class Countries extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.query !== prevProps.query) {
// eslint-disable-next-line react/no-did-update-set-state
- this.setState({loading: true, countries: null})
+ this.setState({ loading: true, countries: null })
this.fetchCountries().then(this.drawMap)
}
}
@@ -49,19 +49,19 @@ class Countries extends React.Component {
getDataset() {
const dataset = {};
- var onlyValues = this.state.countries.map(function(obj){ return obj.visitors });
+ var onlyValues = this.state.countries.map(function(obj) { return obj.visitors });
var maxValue = Math.max.apply(null, onlyValues);
// eslint-disable-next-line no-undef
const paletteScale = d3.scale.linear()
- .domain([0,maxValue])
+ .domain([0, maxValue])
.range([
this.state.darkTheme ? "#2e3954" : "#f3ebff",
this.state.darkTheme ? "#6366f1" : "#a779e9"
])
- this.state.countries.forEach(function(item){
- dataset[item.alpha_3] = {numberOfThings: item.visitors, fillColor: paletteScale(item.visitors)};
+ this.state.countries.forEach(function(item) {
+ dataset[item.alpha_3] = { numberOfThings: item.visitors, fillColor: paletteScale(item.visitors) };
});
return dataset
@@ -69,18 +69,18 @@ class Countries extends React.Component {
updateCountries() {
this.fetchCountries().then(() => {
- this.map.updateChoropleth(this.getDataset(), {reset: true})
+ this.map.updateChoropleth(this.getDataset(), { reset: true })
})
}
fetchCountries() {
- return api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/countries`, this.props.query, {limit: 300})
+ return api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/countries`, this.props.query, { limit: 300 })
.then((response) => {
if (this.props.afterFetchData) {
this.props.afterFetchData(response)
}
- this.setState({loading: false, countries: response.results})
+ this.setState({ loading: false, countries: response.results })
})
}
@@ -154,9 +154,9 @@ class Countries extends React.Component {
if (this.state.countries) {
return (
<>
-
-
- { this.geolocationDbNotice() }
+
+
+ {this.geolocationDbNotice()}
>
)
}
@@ -167,9 +167,9 @@ class Countries extends React.Component {
render() {
return (
- { this.state.loading && }
+ {this.state.loading && }
- { this.renderBody() }
+ {this.renderBody()}
)
diff --git a/assets/js/dashboard/stats/modals/conversions.js b/assets/js/dashboard/stats/modals/conversions.js
index 1a245918cc2f..38efbfa7d032 100644
--- a/assets/js/dashboard/stats/modals/conversions.js
+++ b/assets/js/dashboard/stats/modals/conversions.js
@@ -69,7 +69,7 @@ function ConversionsModal(props) {
{listItem.name}
@@ -117,7 +117,7 @@ function ConversionsModal(props) {
}
return (
-
+
{renderBody()}
{loading && renderLoading()}
{!loading && moreResultsAvailable && renderLoadMore()}
diff --git a/assets/js/dashboard/stats/modals/entry-pages.js b/assets/js/dashboard/stats/modals/entry-pages.js
index 3c7004f42184..04007c6fd68c 100644
--- a/assets/js/dashboard/stats/modals/entry-pages.js
+++ b/assets/js/dashboard/stats/modals/entry-pages.js
@@ -81,7 +81,7 @@ class EntryPagesModal extends React.Component {
+
{this.renderBody()}
{this.renderLoading()}
diff --git a/assets/js/dashboard/stats/modals/exit-pages.js b/assets/js/dashboard/stats/modals/exit-pages.js
index 8dc82bec08ff..25be36b3ac23 100644
--- a/assets/js/dashboard/stats/modals/exit-pages.js
+++ b/assets/js/dashboard/stats/modals/exit-pages.js
@@ -4,7 +4,7 @@ import { withRouter } from 'react-router-dom'
import Modal from './modal'
import * as api from '../../api'
-import numberFormatter, {percentageFormatter} from '../../util/number-formatter'
+import numberFormatter, { percentageFormatter } from '../../util/number-formatter'
import { parseQuery } from '../../query'
import { trimURL, updatedQuery } from '../../util/url'
import { hasGoalFilter, replaceFilterByPrefix } from "../../util/filters";
@@ -62,7 +62,7 @@ class ExitPagesModal extends React.Component {
|
+
{this.renderBody()}
{this.renderLoading()}
diff --git a/assets/js/dashboard/stats/modals/filter-modal-group.js b/assets/js/dashboard/stats/modals/filter-modal-group.js
index b8eee128e4ba..3b1722f143e6 100644
--- a/assets/js/dashboard/stats/modals/filter-modal-group.js
+++ b/assets/js/dashboard/stats/modals/filter-modal-group.js
@@ -17,7 +17,6 @@ export default function FilterModalGroup({
() => Object.entries(filterState).filter(([_, filter]) => getFilterGroup(filter) == filterGroup).map(([id, filter]) => ({ id, filter })),
[filterGroup, filterState]
)
-
const disabledOptions = useMemo(
() => (filterGroup == 'props') ? rows.map(({ filter }) => ({ value: getPropertyKeyFromFilterKey(filter[1]) })) : null,
[filterGroup, rows]
@@ -28,7 +27,7 @@ export default function FilterModalGroup({
return (
<>
-
+
{showTitle && ( {formattedFilters[filterGroup]} )}
{rows.map(({ id, filter }) =>
filterGroup === 'props' ? (
@@ -55,7 +54,7 @@ export default function FilterModalGroup({
)}
{showAddRow && (
-
+
onAddRow(filterGroup)}>
+ Add another
diff --git a/assets/js/dashboard/stats/modals/filter-modal-props-row.js b/assets/js/dashboard/stats/modals/filter-modal-props-row.js
index 7f08be1f1a1c..09fb3e77ab07 100644
--- a/assets/js/dashboard/stats/modals/filter-modal-props-row.js
+++ b/assets/js/dashboard/stats/modals/filter-modal-props-row.js
@@ -33,7 +33,7 @@ export default function FilterModalPropsRow({
}
function fetchPropValueOptions(input) {
- if (operation === FILTER_OPERATIONS.contains) {return Promise.resolve([])}
+ if ([FILTER_OPERATIONS.contains, FILTER_OPERATIONS.does_not_contain].includes(operation)) {return Promise.resolve([])}
return fetchSuggestions(apiPath(site, `/suggestions/prop_value`), query, input, [
FILTER_OPERATIONS.isNot, filterKey, ['(none)']
])
diff --git a/assets/js/dashboard/stats/modals/filter-modal-row.js b/assets/js/dashboard/stats/modals/filter-modal-row.js
index 09c28781520f..dc4f85555f45 100644
--- a/assets/js/dashboard/stats/modals/filter-modal-row.js
+++ b/assets/js/dashboard/stats/modals/filter-modal-row.js
@@ -32,7 +32,7 @@ export default function FilterModalRow({
}
function fetchOptions(input) {
- if (operation === FILTER_OPERATIONS.contains) {
+ if ([FILTER_OPERATIONS.contains, FILTER_OPERATIONS.does_not_contain].includes(operation)) {
return Promise.resolve([])
}
@@ -43,14 +43,14 @@ export default function FilterModalRow({
return (
-
+
onUpdate([newOperation, filterKey, clauses], labels)}
selectedType={operation}
/>
-
+
{
- const filterState = {...prevState.filterState}
+ const filterState = { ...prevState.filterState }
delete filterState[id]
return { filterState }
})
@@ -133,7 +133,7 @@ class FilterModal extends React.Component {
render() {
return (
-
+
Filter by {formatFilterGroup(this.state.modalType)}
diff --git a/assets/js/dashboard/stats/modals/google-keywords.js b/assets/js/dashboard/stats/modals/google-keywords.js
index 39ba7f3b8fca..4dfd45972679 100644
--- a/assets/js/dashboard/stats/modals/google-keywords.js
+++ b/assets/js/dashboard/stats/modals/google-keywords.js
@@ -4,7 +4,7 @@ import { Link, withRouter } from 'react-router-dom'
import Modal from './modal'
import * as api from '../../api'
import numberFormatter, { percentageFormatter } from '../../util/number-formatter'
-import {parseQuery} from '../../query'
+import { parseQuery } from '../../query'
import RocketIcon from './rocket-icon'
class GoogleKeywordsModal extends React.Component {
@@ -17,7 +17,7 @@ class GoogleKeywordsModal extends React.Component {
}
componentDidMount() {
- api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/Google`, this.state.query, {limit: 100})
+ api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/Google`, this.state.query, { limit: 100 })
.then((res) => this.setState({
loading: false,
searchTerms: res.search_terms,
@@ -99,7 +99,7 @@ class GoogleKeywordsModal extends React.Component {
- { this.renderKeywords() }
+ {this.renderKeywords()}
)
@@ -108,8 +108,8 @@ class GoogleKeywordsModal extends React.Component {
render() {
return (
-
- { this.renderBody() }
+
+ {this.renderBody()}
)
}
diff --git a/assets/js/dashboard/stats/modals/modal.js b/assets/js/dashboard/stats/modals/modal.js
index 4b031f3600dc..a6cbbabded39 100644
--- a/assets/js/dashboard/stats/modals/modal.js
+++ b/assets/js/dashboard/stats/modals/modal.js
@@ -57,7 +57,7 @@ class Modal extends React.Component {
}
close() {
- this.props.history.push(`/${encodeURIComponent(this.props.site.domain)}${this.props.location.search}`)
+ this.props.history.push(`/${this.props.location.search}`)
}
/**
diff --git a/assets/js/dashboard/stats/modals/pages.js b/assets/js/dashboard/stats/modals/pages.js
index 643938352fde..d564a2689c54 100644
--- a/assets/js/dashboard/stats/modals/pages.js
+++ b/assets/js/dashboard/stats/modals/pages.js
@@ -65,7 +65,7 @@ class PagesModal extends React.Component {
- Top Pages
+ Top Pages hi
@@ -141,7 +141,7 @@ class PagesModal extends React.Component {
render() {
return (
-
+
{this.renderBody()}
{this.renderLoading()}
diff --git a/assets/js/dashboard/stats/modals/props.js b/assets/js/dashboard/stats/modals/props.js
index 0fcd1c04f562..64fe66a97b57 100644
--- a/assets/js/dashboard/stats/modals/props.js
+++ b/assets/js/dashboard/stats/modals/props.js
@@ -25,7 +25,8 @@ const Money = maybeRequire().default
function PropsModal(props) {
const site = props.site
const query = parseQuery(props.location.search, site)
- const propKey = props.location.pathname.split('/').pop()
+
+ const propKey = props.location.pathname.split('/').filter(i => i).pop()
const [loading, setLoading] = useState(true)
const [moreResultsAvailable, setMoreResultsAvailable] = useState(false)
@@ -71,7 +72,7 @@ function PropsModal(props) {
{url.trimURL(listItem.name, 30)}
@@ -125,7 +126,7 @@ function PropsModal(props) {
}
return (
-
+
{renderBody()}
{loading && renderLoading()}
{!loading && moreResultsAvailable && renderLoadMore()}
diff --git a/assets/js/dashboard/stats/modals/referrer-drilldown.js b/assets/js/dashboard/stats/modals/referrer-drilldown.js
index 49d33c547690..ff1e4caf5bf2 100644
--- a/assets/js/dashboard/stats/modals/referrer-drilldown.js
+++ b/assets/js/dashboard/stats/modals/referrer-drilldown.js
@@ -3,8 +3,8 @@ 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'
+import numberFormatter, { durationFormatter } from '../../util/number-formatter'
+import { parseQuery } from '../../query'
import { updatedQuery } from "../../util/url";
import { hasGoalFilter, replaceFilterByPrefix } from "../../util/filters";
@@ -20,8 +20,8 @@ class ReferrerDrilldownModal extends React.Component {
componentDidMount() {
const detailed = this.showExtra()
- api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/${this.props.match.params.referrer}`, this.state.query, {limit: 100, detailed})
- .then((response) => this.setState({loading: false, referrers: response.results}))
+ api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/${this.props.match.params.referrer}`, this.state.query, { limit: 100, detailed })
+ .then((response) => this.setState({ loading: false, referrers: response.results }))
}
showExtra() {
@@ -45,7 +45,7 @@ class ReferrerDrilldownModal extends React.Component {
}
formatBounceRate(ref) {
- if (typeof(ref.bounce_rate) === 'number') {
+ if (typeof (ref.bounce_rate) === 'number') {
return ref.bounce_rate + '%'
} else {
return '-'
@@ -53,7 +53,7 @@ class ReferrerDrilldownModal extends React.Component {
}
formatDuration(referrer) {
- if (typeof(referrer.visit_duration) === 'number') {
+ if (typeof (referrer.visit_duration) === 'number') {
return durationFormatter(referrer.visit_duration)
} else {
return '-'
@@ -77,12 +77,12 @@ class ReferrerDrilldownModal extends React.Component {
{referrer.name}
- { this.renderExternalLink(referrer.name) }
+ {this.renderExternalLink(referrer.name)}
)
}
@@ -91,13 +91,13 @@ class ReferrerDrilldownModal extends React.Component {
return (
- { this.renderReferrerName(referrer) }
+ {this.renderReferrerName(referrer)}
|
- {this.showConversionRate() && {numberFormatter(referrer.total_visitors)} | }
+ {this.showConversionRate() && {numberFormatter(referrer.total_visitors)} | }
{numberFormatter(referrer.visitors)} |
- {this.showExtra() && {this.formatBounceRate(referrer)} | }
- {this.showExtra() && {this.formatDuration(referrer)} | }
- {this.showConversionRate() && {referrer.conversion_rate}% | }
+ {this.showExtra() && {this.formatBounceRate(referrer)} | }
+ {this.showExtra() && {this.formatDuration(referrer)} | }
+ {this.showConversionRate() && {referrer.conversion_rate}% | }
)
}
@@ -126,7 +126,7 @@ class ReferrerDrilldownModal extends React.Component {
|
- { this.state.referrers.map(this.renderReferrer.bind(this)) }
+ {this.state.referrers.map(this.renderReferrer.bind(this))}
@@ -137,8 +137,8 @@ class ReferrerDrilldownModal extends React.Component {
render() {
return (
-
- { this.renderBody() }
+
+ {this.renderBody()}
)
}
diff --git a/assets/js/dashboard/stats/modals/sources.js b/assets/js/dashboard/stats/modals/sources.js
index 2f272f19e017..8e9efa068dc9 100644
--- a/assets/js/dashboard/stats/modals/sources.js
+++ b/assets/js/dashboard/stats/modals/sources.js
@@ -152,7 +152,7 @@ class SourcesModal extends React.Component {
render() {
return (
-
+
{this.title()}
diff --git a/assets/js/dashboard/stats/modals/table.js b/assets/js/dashboard/stats/modals/table.js
index 20eea170c3bd..fc4861776a10 100644
--- a/assets/js/dashboard/stats/modals/table.js
+++ b/assets/js/dashboard/stats/modals/table.js
@@ -4,7 +4,7 @@ import { Link, withRouter } from 'react-router-dom'
import Modal from './modal'
import * as api from '../../api'
import numberFormatter from '../../util/number-formatter'
-import {parseQuery} from '../../query'
+import { parseQuery } from '../../query'
import { cleanLabels, hasGoalFilter, replaceFilterByPrefix } from "../../util/filters";
import { updatedQuery } from "../../util/url";
@@ -18,8 +18,8 @@ class ModalTable extends React.Component {
}
componentDidMount() {
- api.get(this.props.endpoint, this.state.query, {limit: 100})
- .then((response) => this.setState({loading: false, list: response.results}))
+ api.get(this.props.endpoint, this.state.query, { limit: 100 })
+ .then((response) => this.setState({ loading: false, list: response.results }))
}
showConversionRate() {
@@ -56,7 +56,7 @@ class ModalTable extends React.Component {
className="hover:underline"
to={{
search: updatedQuery({ filters, labels }),
- pathname: `/${encodeURIComponent(this.props.site.domain)}`
+ pathname: `/`
}}
>
{this.props.renderIcon && this.props.renderIcon(tableItem)}
@@ -97,7 +97,7 @@ class ModalTable extends React.Component {
| | |
- { this.state.list.map(this.renderTableItem.bind(this)) }
+ {this.state.list.map(this.renderTableItem.bind(this))}
@@ -110,8 +110,8 @@ class ModalTable extends React.Component {
render() {
return (
-
- { this.renderBody() }
+
+ {this.renderBody()}
)
}
diff --git a/assets/js/dashboard/stats/more-link.js b/assets/js/dashboard/stats/more-link.js
index 95dfdf284e8b..3940cbbc5050 100644
--- a/assets/js/dashboard/stats/more-link.js
+++ b/assets/js/dashboard/stats/more-link.js
@@ -5,7 +5,7 @@ function detailsIcon() {
return (