This commit is contained in:
MICHAEL JACKSON
2017-11-25 13:25:01 -08:00
parent f3974b5e2d
commit 3a309241da
64 changed files with 635 additions and 801 deletions

View File

@ -1,8 +1,6 @@
import React from 'react'
import contentHTML from './About.md'
import React from "react"
import contentHTML from "./About.md"
const About = () => (
<div className="wrapper" dangerouslySetInnerHTML={{ __html: contentHTML }} />
)
const About = () => <div className="wrapper" dangerouslySetInnerHTML={{ __html: contentHTML }} />
export default About

View File

@ -1,6 +1,6 @@
import React from 'react'
import { HashRouter } from 'react-router-dom'
import Layout from './Layout'
import React from "react"
import { HashRouter } from "react-router-dom"
import Layout from "./Layout"
const App = () => (
<HashRouter>

View File

@ -1,8 +1,6 @@
import React from 'react'
import contentHTML from './Home.md'
import React from "react"
import contentHTML from "./Home.md"
const Home = () => (
<div className="wrapper" dangerouslySetInnerHTML={{ __html: contentHTML }} />
)
const Home = () => <div className="wrapper" dangerouslySetInnerHTML={{ __html: contentHTML }} />
export default Home

View File

@ -1,11 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Motion, spring } from 'react-motion'
import { Switch, Route, Link, withRouter } from 'react-router-dom'
import WindowSize from './WindowSize'
import About from './About'
import Stats from './Stats'
import Home from './Home'
import React from "react"
import PropTypes from "prop-types"
import { Motion, spring } from "react-motion"
import { Switch, Route, Link, withRouter } from "react-router-dom"
import WindowSize from "./WindowSize"
import About from "./About"
import Stats from "./Stats"
import Home from "./Home"
class Layout extends React.Component {
static propTypes = {
@ -23,18 +23,18 @@ class Layout extends React.Component {
adjustUnderline = (useSpring = false) => {
let itemIndex
switch (this.props.location.pathname) {
case '/stats':
case "/stats":
itemIndex = 1
break
case '/about':
case "/about":
itemIndex = 2
break
case '/':
case "/":
default:
itemIndex = 0
}
const itemNodes = this.listNode.querySelectorAll('li')
const itemNodes = this.listNode.querySelectorAll("li")
const currentNode = itemNodes[itemIndex]
this.setState({
@ -47,7 +47,7 @@ class Layout extends React.Component {
componentDidMount() {
this.adjustUnderline()
fetch('/_stats?period=last-month')
fetch("/_stats?period=last-month")
.then(res => res.json())
.then(stats => this.setState({ stats }))
@ -63,17 +63,14 @@ class Layout extends React.Component {
}
componentDidUpdate(prevProps) {
if (prevProps.location.pathname !== this.props.location.pathname)
this.adjustUnderline(true)
if (prevProps.location.pathname !== this.props.location.pathname) this.adjustUnderline(true)
}
render() {
const { underlineLeft, underlineWidth, useSpring } = this.state
const style = {
left: useSpring
? spring(underlineLeft, { stiffness: 220 })
: underlineLeft,
left: useSpring ? spring(underlineLeft, { stiffness: 220 }) : underlineLeft,
width: useSpring ? spring(underlineWidth) : underlineWidth
}
@ -84,10 +81,7 @@ class Layout extends React.Component {
<header>
<h1 className="layout-title">unpkg</h1>
<nav className="layout-nav">
<ol
className="layout-nav-list"
ref={node => (this.listNode = node)}
>
<ol className="layout-nav-list" ref={node => (this.listNode = node)}>
<li>
<Link to="/">Home</Link>
</li>
@ -117,10 +111,7 @@ class Layout extends React.Component {
</div>
<Switch>
<Route
path="/stats"
render={() => <Stats data={this.state.stats} />}
/>
<Route path="/stats" render={() => <Stats data={this.state.stats} />} />
<Route path="/about" component={About} />
<Route path="/" component={Home} />
</Switch>

View File

@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { parseNumber, formatNumber } from './NumberUtils'
import React from "react"
import PropTypes from "prop-types"
import { parseNumber, formatNumber } from "./NumberUtils"
class NumberTextInput extends React.Component {
static propTypes = {
@ -37,14 +37,7 @@ class NumberTextInput extends React.Component {
const { parseNumber, formatNumber, ...props } = this.props // eslint-disable-line no-unused-vars
const displayValue = formatNumber(value)
return (
<input
{...props}
type="text"
value={displayValue}
onChange={this.handleChange}
/>
)
return <input {...props} type="text" value={displayValue} onChange={this.handleChange} />
}
}

View File

@ -1,23 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
import formatBytes from 'pretty-bytes'
import formatDate from 'date-fns/format'
import parseDate from 'date-fns/parse'
import formatNumber from './utils/formatNumber'
import formatPercent from './utils/formatPercent'
import React from "react"
import PropTypes from "prop-types"
import formatBytes from "pretty-bytes"
import formatDate from "date-fns/format"
import parseDate from "date-fns/parse"
import formatNumber from "./utils/formatNumber"
import formatPercent from "./utils/formatPercent"
import { continents, countries } from 'countries-list'
import { continents, countries } from "countries-list"
const getCountriesByContinent = continent =>
Object.keys(countries).filter(
country => countries[country].continent === continent
)
Object.keys(countries).filter(country => countries[country].continent === continent)
const sumKeyValues = (hash, keys) =>
keys.reduce((n, key) => n + (hash[key] || 0), 0)
const sumKeyValues = (hash, keys) => keys.reduce((n, key) => n + (hash[key] || 0), 0)
const sumValues = hash =>
Object.keys(hash).reduce((memo, key) => memo + hash[key], 0)
const sumValues = hash => Object.keys(hash).reduce((memo, key) => memo + hash[key], 0)
class Stats extends React.Component {
static propTypes = {
@ -63,15 +59,11 @@ class Stats extends React.Component {
</a>
</td>
<td>
{formatNumber(requests)} ({formatPercent(
requests / totals.requests.all
)}%)
{formatNumber(requests)} ({formatPercent(requests / totals.requests.all)}%)
</td>
{bandwidth ? (
<td>
{formatBytes(bandwidth)} ({formatPercent(
bandwidth / totals.bandwidth.all
)}%)
{formatBytes(bandwidth)} ({formatPercent(bandwidth / totals.bandwidth.all)}%)
</td>
) : (
<td>-</td>
@ -104,10 +96,7 @@ class Stats extends React.Component {
const continentName = continents[continent]
const continentData = continentsData[continent]
if (
continentData.requests > this.state.minCountryRequests &&
continentData.bandwidth !== 0
) {
if (continentData.requests > this.state.minCountryRequests && continentData.bandwidth !== 0) {
regionRows.push(
<tr key={continent} className="continent-row">
<td>{continentName}</td>
@ -176,29 +165,26 @@ class Stats extends React.Component {
return (
<div className="wrapper">
<p>
From <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, 'MMM D')}</strong> unpkg served{' '}
<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
visitors,{' '}
<strong>
{formatPercent(totals.requests.cached / totals.requests.all, 0)}%
</strong>{' '}
of which were served from the cache.
From <strong>{formatDate(since, "MMM D")}</strong> to{" "}
<strong>{formatDate(until, "MMM D")}</strong> unpkg served{" "}
<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 visitors,{" "}
<strong>{formatPercent(totals.requests.cached / totals.requests.all, 0)}%</strong> of
which were served from the cache.
</p>
<h3>Packages</h3>
<p>
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{' '}
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{" "}
{Object.keys(totals.requests.package).length} packages are shown.
</p>
<p className="table-filter">
Include only packages that received at least{' '}
Include only packages that received at least{" "}
<select
value={this.state.minPackageRequests}
onChange={event =>
@ -213,11 +199,11 @@ class Stats extends React.Component {
<option value="100000">100,000</option>
<option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option>
</select>{' '}
</select>{" "}
requests.
</p>
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}>
<thead>
<tr>
<th>Package</th>
@ -231,13 +217,13 @@ class Stats extends React.Component {
<h3>Regions</h3>
<p>
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.
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.
</p>
<p className="table-filter">
Include only countries that made at least{' '}
Include only countries that made at least{" "}
<select
value={this.state.minCountryRequests}
onChange={event =>
@ -251,16 +237,11 @@ class Stats extends React.Component {
<option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option>
<option value="100000000">100,000,000</option>
</select>{' '}
</select>{" "}
requests.
</p>
<table
cellSpacing="0"
cellPadding="0"
style={{ width: '100%' }}
className="regions-table"
>
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }} className="regions-table">
<thead>
<tr>
<th>Region</th>
@ -274,12 +255,12 @@ class Stats extends React.Component {
<h3>Protocols</h3>
<p>
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.
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.
</p>
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}>
<thead>
<tr>
<th>Protocol</th>

View File

@ -1,9 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import addEvent from './utils/addEvent'
import removeEvent from './utils/removeEvent'
import React from "react"
import PropTypes from "prop-types"
import addEvent from "./utils/addEvent"
import removeEvent from "./utils/removeEvent"
const ResizeEvent = 'resize'
const ResizeEvent = "resize"
class WindowSize extends React.Component {
static propTypes = {

View File

@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import "./index.css"
ReactDOM.render(<App />, document.getElementById('root'))
ReactDOM.render(<App />, document.getElementById("root"))

View File

@ -2,7 +2,7 @@ const addEvent = (node, type, handler) => {
if (node.addEventListener) {
node.addEventListener(type, handler, false)
} else if (node.attachEvent) {
node.attachEvent('on' + type, handler)
node.attachEvent("on" + type, handler)
}
}

View File

@ -1,10 +1,10 @@
const formatNumber = n => {
const digits = String(n).split('')
const digits = String(n).split("")
const groups = []
while (digits.length) groups.unshift(digits.splice(-3).join(''))
while (digits.length) groups.unshift(digits.splice(-3).join(""))
return groups.join(',')
return groups.join(",")
}
export default formatNumber

View File

@ -1,4 +1,3 @@
const formatPercent = (n, fixed = 1) =>
String((n.toPrecision(2) * 100).toFixed(fixed))
const formatPercent = (n, fixed = 1) => String((n.toPrecision(2) * 100).toFixed(fixed))
export default formatPercent

View File

@ -1,3 +1,3 @@
const parseNumber = s => parseInt(s.replace(/,/g, ''), 10) || 0
const parseNumber = s => parseInt(s.replace(/,/g, ""), 10) || 0
export default parseNumber

View File

@ -2,7 +2,7 @@ const removeEvent = (node, type, handler) => {
if (node.removeEventListener) {
node.removeEventListener(type, handler, false)
} else if (node.detachEvent) {
node.detachEvent('on' + type, handler)
node.detachEvent("on" + type, handler)
}
}