analytics/assets/js/dashboard/stats/locations/index.js
Uku Taht 05bf43c1be
City level location data (#1449)
* Merge branch 'plausible_master'

* Add City level details

* Add City level details

* Use ISO codes instead of geoname_id for subdivisions

* Add easier way to configure geolocation database

* Add workflow for dev branch

* Correct clickhouse migration

* Translate subdivision names

* Translate city names

* WIP

* Region and country filters

* Fix region filter

* Remove region_name when removing region filter

* Add modals for regions and cities

* Remove dead code

* WIP

* Revert "WIP"

This reverts commit 3202bf2fe9.

* Feature flag to hide cities when deployed

* Add changelog entry

* Remove unused code

* Remove unused variables

* Fix test

Co-authored-by: AymanTerra <aymanterra@yahoo.com>
2021-11-23 11:39:09 +02:00

131 lines
3.4 KiB
JavaScript

import React from 'react';
import * as storage from '../../storage'
import Countries from './countries';
import CountriesMap from './map'
import * as api from '../../api'
import {apiPath, sitePath} from '../../url'
import ListReport from '../reports/list'
function Regions({query, site}) {
function fetchData() {
return api.get(apiPath(site, '/regions'), query, {country_name: query.filters.country, limit: 9})
}
return (
<ListReport
title="Regions"
fetchData={fetchData}
filter={{region: 'code', region_name: 'name'}}
keyLabel="Region"
detailsLink={sitePath(site, '/regions')}
query={query}
/>
)
}
function Cities({query, site}) {
function fetchData() {
return api.get(apiPath(site, '/cities'), query, {limit: 9})
}
return (
<ListReport
title="Cities"
fetchData={fetchData}
filter={{city: 'code', city_name: 'name'}}
keyLabel="City"
detailsLink={sitePath(site, '/cities')}
query={query}
/>
)
}
const labelFor = {
'countries': 'Countries',
'regions': 'Regions',
'cities': 'Cities',
}
export default class Locations extends React.Component {
constructor(props) {
super(props)
this.tabKey = `geoTab__${ props.site.domain}`
const storedTab = storage.getItem(this.tabKey)
this.state = {
mode: storedTab || 'map'
}
}
setMode(mode) {
return () => {
storage.setItem(this.tabKey, mode)
this.setState({mode})
}
}
renderContent() {
switch(this.state.mode) {
case "cities":
return <Cities site={this.props.site} query={this.props.query} timer={this.props.timer}/>
case "regions":
return <Regions site={this.props.site} query={this.props.query} timer={this.props.timer}/>
case "countries":
return <Countries site={this.props.site} query={this.props.query} timer={this.props.timer}/>
case "map":
default:
return <CountriesMap site={this.props.site} query={this.props.query} timer={this.props.timer}/>
}
}
renderPill(name, mode) {
const isActive = this.state.mode === mode
if (isActive) {
return (
<li
className="inline-block h-5 text-indigo-700 dark:text-indigo-500 font-bold border-b-2 border-indigo-700 dark:border-indigo-500"
>
{name}
</li>
)
}
return (
<li
className="hover:text-indigo-600 cursor-pointer"
onClick={this.setMode(mode)}
>
{name}
</li>
)
}
render() {
return (
<div
className="stats-item flex flex-col w-full mt-6 stats-item--has-header"
>
<div
className="stats-item__header flex flex-col flex-grow bg-white dark:bg-gray-825 shadow-xl rounded p-4 relative"
>
<div className="w-full flex justify-between">
<h3 className="font-bold dark:text-gray-100">
{labelFor[this.state.mode] || 'Locations'}
</h3>
<ul className="flex font-medium text-xs text-gray-500 dark:text-gray-400 space-x-2">
{ this.renderPill('Map', 'map') }
{ this.renderPill('Countries', 'countries') }
{ this.props.site.cities && this.renderPill('Regions', 'regions') }
{ this.props.site.cities && this.renderPill('Cities', 'cities') }
</ul>
</div>
{ this.renderContent() }
</div>
</div>
)
}
}