unpkg/modules/client/main/Stats.js

324 lines
9.6 KiB
JavaScript
Raw Normal View History

2018-12-17 17:38:05 +00:00
require('./Stats.css');
2018-04-04 05:16:09 +00:00
2018-12-17 17:38:05 +00:00
const React = require('react');
const PropTypes = require('prop-types');
const formatBytes = require('pretty-bytes');
const formatDate = require('date-fns/format');
const parseDate = require('date-fns/parse');
const { continents, countries } = require('countries-list');
2018-04-04 05:16:09 +00:00
2018-12-17 17:38:05 +00:00
const formatNumber = require('../utils/formatNumber');
const formatPercent = require('../utils/formatPercent');
2018-04-04 05:16:09 +00:00
function getCountriesByContinent(continent) {
return Object.keys(countries).filter(
2018-02-18 02:00:56 +00:00
country => countries[country].continent === continent
);
2018-04-04 05:16:09 +00:00
}
2018-04-04 05:16:09 +00:00
function sumKeyValues(hash, keys) {
return keys.reduce((n, key) => n + (hash[key] || 0), 0);
}
2018-04-04 05:16:09 +00:00
function sumValues(hash) {
return Object.keys(hash).reduce((memo, key) => memo + hash[key], 0);
}
2016-05-20 18:58:58 +00:00
class Stats extends React.Component {
2016-07-20 19:26:15 +00:00
static propTypes = {
data: PropTypes.object
2018-02-18 02:00:56 +00:00
};
2016-05-20 18:58:58 +00:00
state = {
minPackageRequests: 1000000,
minCountryRequests: 1000000
2018-02-18 02:00:56 +00:00
};
2017-04-15 04:01:23 +00:00
render() {
2018-02-18 02:00:56 +00:00
const { data } = this.props;
2018-02-18 02:00:56 +00:00
if (data == null) return null;
2018-02-18 02:00:56 +00:00
const totals = data.totals;
2016-05-20 18:58:58 +00:00
// Summary data
2018-02-18 02:00:56 +00:00
const since = parseDate(totals.since);
const until = parseDate(totals.until);
// Packages
2018-02-18 02:00:56 +00:00
const packageRows = [];
2017-11-08 16:57:15 +00:00
Object.keys(totals.requests.package)
.sort((a, b) => {
2018-02-18 02:00:56 +00:00
return totals.requests.package[b] - totals.requests.package[a];
2017-11-08 16:57:15 +00:00
})
.forEach(packageName => {
2018-02-18 02:00:56 +00:00
const requests = totals.requests.package[packageName];
const bandwidth = totals.bandwidth.package[packageName];
2017-11-08 16:57:15 +00:00
if (requests >= this.state.minPackageRequests) {
packageRows.push(
<tr key={packageName}>
<td>
<a
href={`https://npmjs.org/package/${packageName}`}
title={`${packageName} on npm`}
>
{packageName}
</a>
</td>
<td>
2018-12-17 17:38:05 +00:00
{formatNumber(requests)} (
{formatPercent(requests / totals.requests.all)}
%)
2017-11-08 16:57:15 +00:00
</td>
{bandwidth ? (
<td>
2018-12-17 17:38:05 +00:00
{formatBytes(bandwidth)} (
{formatPercent(bandwidth / totals.bandwidth.all)}
%)
2017-11-08 16:57:15 +00:00
</td>
) : (
<td>-</td>
)}
</tr>
2018-02-18 02:00:56 +00:00
);
2017-11-08 16:57:15 +00:00
}
2018-02-18 02:00:56 +00:00
});
2016-05-20 18:58:58 +00:00
// Regions
2018-02-18 02:00:56 +00:00
const regionRows = [];
2016-05-20 18:58:58 +00:00
const continentsData = Object.keys(continents).reduce((memo, continent) => {
2018-02-18 02:00:56 +00:00
const localCountries = getCountriesByContinent(continent);
2016-05-20 18:58:58 +00:00
memo[continent] = {
countries: localCountries,
requests: sumKeyValues(totals.requests.country, localCountries),
bandwidth: sumKeyValues(totals.bandwidth.country, localCountries)
2018-02-18 02:00:56 +00:00
};
2016-05-20 18:58:58 +00:00
2018-02-18 02:00:56 +00:00
return memo;
}, {});
2016-05-20 18:58:58 +00:00
const topContinents = Object.keys(continentsData).sort((a, b) => {
2018-02-18 02:00:56 +00:00
return continentsData[b].requests - continentsData[a].requests;
});
2016-05-20 18:58:58 +00:00
topContinents.forEach(continent => {
2018-02-18 02:00:56 +00:00
const continentName = continents[continent];
const continentData = continentsData[continent];
2016-05-20 18:58:58 +00:00
2018-02-18 02:00:56 +00:00
if (
continentData.requests > this.state.minCountryRequests &&
continentData.bandwidth !== 0
) {
2016-05-20 18:58:58 +00:00
regionRows.push(
<tr key={continent} className="continent-row">
2017-11-08 16:57:15 +00:00
<td>
2018-04-04 05:16:09 +00:00
<strong>{continentName}</strong>
2017-11-08 16:57:15 +00:00
</td>
<td>
2018-04-04 05:16:09 +00:00
<strong>
2018-12-17 17:38:05 +00:00
{formatNumber(continentData.requests)} (
{formatPercent(continentData.requests / totals.requests.all)}
%)
2018-04-04 05:16:09 +00:00
</strong>
</td>
<td>
<strong>
2018-12-17 17:38:05 +00:00
{formatBytes(continentData.bandwidth)} (
{formatPercent(continentData.bandwidth / totals.bandwidth.all)}
%)
2018-04-04 05:16:09 +00:00
</strong>
2017-11-08 16:57:15 +00:00
</td>
2016-05-20 18:58:58 +00:00
</tr>
2018-02-18 02:00:56 +00:00
);
2016-05-20 18:58:58 +00:00
const topCountries = continentData.countries.sort((a, b) => {
2018-02-18 02:00:56 +00:00
return totals.requests.country[b] - totals.requests.country[a];
});
2016-05-20 18:58:58 +00:00
topCountries.forEach(country => {
2018-02-18 02:00:56 +00:00
const countryRequests = totals.requests.country[country];
const countryBandwidth = totals.bandwidth.country[country];
2016-05-20 18:58:58 +00:00
if (countryRequests > this.state.minCountryRequests) {
2016-05-20 18:58:58 +00:00
regionRows.push(
<tr key={continent + country} className="country-row">
<td className="country-name">{countries[country].name}</td>
2017-11-08 16:57:15 +00:00
<td>
2018-12-17 17:38:05 +00:00
{formatNumber(countryRequests)} (
{formatPercent(countryRequests / totals.requests.all)}
%)
2017-11-08 16:57:15 +00:00
</td>
<td>
2018-12-17 17:38:05 +00:00
{formatBytes(countryBandwidth)} (
{formatPercent(countryBandwidth / totals.bandwidth.all)}
%)
2017-11-08 16:57:15 +00:00
</td>
2016-05-20 18:58:58 +00:00
</tr>
2018-02-18 02:00:56 +00:00
);
2016-05-20 18:58:58 +00:00
}
2018-02-18 02:00:56 +00:00
});
2016-05-20 18:58:58 +00:00
}
2018-02-18 02:00:56 +00:00
});
2016-05-20 18:58:58 +00:00
// Protocols
2017-11-08 16:57:15 +00:00
const protocolRows = Object.keys(totals.requests.protocol)
.sort((a, b) => {
2018-02-18 02:00:56 +00:00
return totals.requests.protocol[b] - totals.requests.protocol[a];
2017-11-08 16:57:15 +00:00
})
.map(protocol => {
2018-02-18 02:00:56 +00:00
const requests = totals.requests.protocol[protocol];
2017-11-08 16:57:15 +00:00
return (
<tr key={protocol}>
<td>{protocol}</td>
<td>
2018-12-17 17:38:05 +00:00
{formatNumber(requests)} (
{formatPercent(requests / sumValues(totals.requests.protocol))}
%)
2017-11-08 16:57:15 +00:00
</td>
</tr>
2018-02-18 02:00:56 +00:00
);
});
2016-05-20 18:58:58 +00:00
return (
<div className="wrapper">
2017-11-08 16:57:15 +00:00
<p>
2018-12-17 17:38:05 +00:00
From <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, 'MMM D')}</strong> unpkg served{' '}
2018-02-18 02:00:56 +00:00
<strong>{formatNumber(totals.requests.all)}</strong> requests and a
total of <strong>{formatBytes(totals.bandwidth.all)}</strong> of data
to <strong>{formatNumber(totals.uniques.all)}</strong> unique
2018-12-17 17:38:05 +00:00
visitors,{' '}
2018-02-18 02:00:56 +00:00
<strong>
{formatPercent(totals.requests.cached / totals.requests.all, 0)}%
2018-12-17 17:38:05 +00:00
</strong>{' '}
2018-02-18 02:00:56 +00:00
of which were served from the cache.
2017-11-08 16:57:15 +00:00
</p>
<h3>Packages</h3>
2017-11-08 16:57:15 +00:00
<p>
2018-12-17 17:38:05 +00:00
The table below shows the most popular packages served by unpkg from{' '}
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, 'MMM D')}</strong>. Only the top{' '}
2017-11-08 16:57:15 +00:00
{Object.keys(totals.requests.package).length} packages are shown.
</p>
2017-11-08 16:57:15 +00:00
<p className="table-filter">
2018-12-17 17:38:05 +00:00
Include only packages that received at least{' '}
2017-11-08 16:57:15 +00:00
<select
value={this.state.minPackageRequests}
2017-11-08 16:57:15 +00:00
onChange={event =>
this.setState({
minPackageRequests: parseInt(event.target.value, 10)
})
}
>
<option value="0">0</option>
<option value="1000">1,000</option>
<option value="10000">10,000</option>
<option value="100000">100,000</option>
<option value="1000000">1,000,000</option>
2017-08-22 16:30:57 +00:00
<option value="10000000">10,000,000</option>
2018-12-17 17:38:05 +00:00
</select>{' '}
2017-11-08 16:57:15 +00:00
requests.
</p>
2016-05-20 18:58:58 +00:00
2018-12-17 17:38:05 +00:00
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<thead>
<tr>
2018-04-04 05:16:09 +00:00
<th>
<strong>Package</strong>
</th>
<th>
<strong>Requests (% of total)</strong>
</th>
<th>
<strong>Bandwidth (% of total)</strong>
</th>
</tr>
</thead>
2017-11-08 16:57:15 +00:00
<tbody>{packageRows}</tbody>
</table>
2016-05-20 18:58:58 +00:00
<h3>Regions</h3>
2017-11-08 16:57:15 +00:00
<p>
2018-12-17 17:38:05 +00:00
The table below breaks down requests to unpkg from{' '}
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, 'MMM D')}</strong> by geographic region.
2017-11-08 16:57:15 +00:00
</p>
2017-11-08 16:57:15 +00:00
<p className="table-filter">
2018-12-17 17:38:05 +00:00
Include only countries that made at least{' '}
2017-11-08 16:57:15 +00:00
<select
value={this.state.minCountryRequests}
2017-11-08 16:57:15 +00:00
onChange={event =>
this.setState({
minCountryRequests: parseInt(event.target.value, 10)
})
}
>
<option value="0">0</option>
<option value="100000">100,000</option>
<option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option>
<option value="100000000">100,000,000</option>
2018-12-17 17:38:05 +00:00
</select>{' '}
2017-11-08 16:57:15 +00:00
requests.
</p>
2018-02-18 02:00:56 +00:00
<table
cellSpacing="0"
cellPadding="0"
2018-12-17 17:38:05 +00:00
style={{ width: '100%' }}
2018-02-18 02:00:56 +00:00
className="regions-table"
>
<thead>
<tr>
2018-04-04 05:16:09 +00:00
<th>
<strong>Region</strong>
</th>
<th>
<strong>Requests (% of total)</strong>
</th>
<th>
<strong>Bandwidth (% of total)</strong>
</th>
2016-05-20 18:58:58 +00:00
</tr>
</thead>
2017-11-08 16:57:15 +00:00
<tbody>{regionRows}</tbody>
2016-05-20 18:58:58 +00:00
</table>
<h3>Protocols</h3>
2017-11-08 16:57:15 +00:00
<p>
2018-12-17 17:38:05 +00:00
The table below breaks down requests to unpkg from{' '}
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, 'MMM D')}</strong> by HTTP protocol.
2017-11-08 16:57:15 +00:00
</p>
2018-12-17 17:38:05 +00:00
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<thead>
<tr>
2018-04-04 05:16:09 +00:00
<th>
<strong>Protocol</strong>
</th>
<th>
<strong>Requests (% of total)</strong>
</th>
</tr>
</thead>
2017-11-08 16:57:15 +00:00
<tbody>{protocolRows}</tbody>
</table>
2016-05-20 18:58:58 +00:00
</div>
2018-02-18 02:00:56 +00:00
);
2016-05-20 18:58:58 +00:00
}
}
module.exports = Stats;