Merge pull request #144 from Gaya/classnames

Use classnames lib for dynamic CSS classes. Thanks @Gaya!
This commit is contained in:
Danny van Kooten 2018-10-01 15:38:39 +02:00 committed by GitHub
commit c9b95fa728
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 26 deletions

View File

@ -3,6 +3,7 @@
import { h, Component } from 'preact'; import { h, Component } from 'preact';
import * as numbers from '../lib/numbers.js'; import * as numbers from '../lib/numbers.js';
import { bind } from 'decko'; import { bind } from 'decko';
import classNames from 'classnames';
const duration = 600; const duration = 600;
const easeOutQuint = function (t) { return 1+(--t)*t*t*t*t }; const easeOutQuint = function (t) { return 1+(--t)*t*t*t*t };
@ -17,8 +18,8 @@ class CountWidget extends Component {
} }
// TODO: Move to component of its own // TODO: Move to component of its own
@bind @bind
countUp(fromValue, toValue) { countUp(fromValue, toValue) {
const format = this.formatValue.bind(this); const format = this.formatValue.bind(this);
const startValue = isFinite(fromValue) ? fromValue : 0; const startValue = isFinite(fromValue) ? fromValue : 0;
const numberEl = this.numberEl; const numberEl = this.numberEl;
@ -34,7 +35,7 @@ class CountWidget extends Component {
window.requestAnimationFrame(tick); window.requestAnimationFrame(tick);
} }
} }
window.requestAnimationFrame(tick); window.requestAnimationFrame(tick);
} }
@ -46,7 +47,7 @@ class CountWidget extends Component {
switch(this.props.format) { switch(this.props.format) {
case "percentage": case "percentage":
formattedValue = numbers.formatPercentage(value) formattedValue = numbers.formatPercentage(value)
break; break;
default: default:
case "number": case "number":
@ -64,7 +65,7 @@ class CountWidget extends Component {
render(props, state) { render(props, state) {
return ( return (
<div class={"totals-detail " + ( props.loading ? "loading" : '')}> <div class={classNames("totals-detail", { loading: props.loading })}>
<div class="total-heading">{props.title}</div> <div class="total-heading">{props.title}</div>
<div class="total-numbers" ref={(e) => { this.numberEl = e; }}>{this.formatValue(props.value)}</div> <div class="total-numbers" ref={(e) => { this.numberEl = e; }}>{this.formatValue(props.value)}</div>
</div> </div>

View File

@ -3,6 +3,7 @@
import { h, Component } from 'preact'; import { h, Component } from 'preact';
import { bind } from 'decko'; import { bind } from 'decko';
import Pikadayer from './Pikadayer.js'; import Pikadayer from './Pikadayer.js';
import classNames from 'classnames';
const defaultPeriod = 'last-7-days'; const defaultPeriod = 'last-7-days';
const padZero = function(n){return n<10? '0'+n:''+n;} const padZero = function(n){return n<10? '0'+n:''+n;}
@ -24,7 +25,7 @@ function getNow() {
// today, yesterday, this week, last 7 days, last 30 days // today, yesterday, this week, last 7 days, last 30 days
const availablePeriods = { const availablePeriods = {
'today': { 'today': {
label: 'Today', label: 'Today',
start: function() { start: function() {
const now = getNow(); const now = getNow();
@ -35,7 +36,7 @@ const availablePeriods = {
return new Date(now.getFullYear(), now.getMonth(), now.getDate()); return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}, },
}, },
'last-7-days': { 'last-7-days': {
label: 'Last 7 days', label: 'Last 7 days',
start: function() { start: function() {
const now = getNow(); const now = getNow();
@ -46,7 +47,7 @@ const availablePeriods = {
return new Date(now.getFullYear(), now.getMonth(), now.getDate()); return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}, },
}, },
'last-30-days': { 'last-30-days': {
label: 'Last 30 days', label: 'Last 30 days',
start: function() { start: function() {
const now = getNow(); const now = getNow();
@ -57,7 +58,7 @@ const availablePeriods = {
return new Date(now.getFullYear(), now.getMonth(), now.getDate()); return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}, },
}, },
'this-year': { 'this-year': {
label: 'This year', label: 'This year',
start: function() { start: function() {
const now = getNow(); const now = getNow();
@ -117,7 +118,7 @@ class DatePicker extends Component {
period: period || '', period: period || '',
startDate: startDate, startDate: startDate,
endDate: endDate, endDate: endDate,
before: before, before: before,
after: after, after: after,
}); });
@ -127,7 +128,7 @@ class DatePicker extends Component {
this.props.onChange(this.state); this.props.onChange(this.state);
this.timeout = null; this.timeout = null;
window.localStorage.setItem('period', this.state.period) window.localStorage.setItem('period', this.state.period)
window.history.replaceState(this.state, null, `#!${this.state.period}`) window.history.replaceState(this.state, null, `#!${this.state.period}`)
}, 2) }, 2)
} }
@ -149,12 +150,12 @@ class DatePicker extends Component {
return date.getFullYear() + '-' + padZero(date.getMonth() + 1) + '-' + padZero(date.getDate()); return date.getFullYear() + '-' + padZero(date.getMonth() + 1) + '-' + padZero(date.getDate());
} }
@bind @bind
setStartDate(date) { setStartDate(date) {
this.setDateRange(date, this.state.endDate, '') this.setDateRange(date, this.state.endDate, '')
} }
@bind @bind
setEndDate(date) { setEndDate(date) {
this.setDateRange(this.state.startDate, date, '') this.setDateRange(this.state.startDate, date, '')
} }
@ -189,8 +190,11 @@ class DatePicker extends Component {
render(props, state) { render(props, state) {
const links = Object.keys(availablePeriods).map((id) => { const links = Object.keys(availablePeriods).map((id) => {
let p = availablePeriods[id]; let p = availablePeriods[id];
let className = ( id == state.period ) ? 'active' : ''; return (
return <li class={className} ><a href="#" data-value={id} onClick={this.setPeriod}>{p.label}</a></li> <li class={classNames({ active: id == state.period })}>
<a href="#" data-value={id} onClick={this.setPeriod}>{p.label}</a>
</li>
);
}); });
return ( return (
@ -198,7 +202,7 @@ class DatePicker extends Component {
{links} {links}
<li class="custom"> <li class="custom">
<Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} /> <Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} />
<span style="margin: 0 8px"> to </span> <span style="margin: 0 8px"> to </span>
<Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} /> <Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} />
</li> </li>
</ul> </ul>

View File

@ -4,6 +4,7 @@ import { h, Component } from 'preact';
import * as numbers from '../lib/numbers.js'; import * as numbers from '../lib/numbers.js';
import Client from '../lib/client.js'; import Client from '../lib/client.js';
import { bind } from 'decko'; import { bind } from 'decko';
import classNames from 'classnames';
const dayInSeconds = 60 * 60 * 24; const dayInSeconds = 60 * 60 * 24;
@ -31,7 +32,7 @@ class Table extends Component {
@bind @bind
fetchRecords(before, after) { fetchRecords(before, after) {
this.setState({ loading: true }); this.setState({ loading: true });
Client.request(`${this.props.endpoint}?before=${before}&after=${after}&limit=${this.state.limit}`) Client.request(`${this.props.endpoint}?before=${before}&after=${after}&limit=${this.state.limit}`)
.then((d) => { .then((d) => {
// request finished; check if timestamp range is still the one user wants to see // request finished; check if timestamp range is still the one user wants to see
@ -39,7 +40,7 @@ class Table extends Component {
return; return;
} }
this.setState({ this.setState({
loading: false, loading: false,
records: d, records: d,
}); });
@ -48,7 +49,7 @@ class Table extends Component {
// fetch totals too // fetch totals too
Client.request(`${this.props.endpoint}/pageviews?before=${before}&after=${after}`) Client.request(`${this.props.endpoint}/pageviews?before=${before}&after=${after}`)
.then((d) => { .then((d) => {
this.setState({ this.setState({
total: d total: d
}); });
}); });
@ -59,9 +60,9 @@ class Table extends Component {
const tableRows = state.records !== null && state.records.length > 0 ? state.records.map((p, i) => { const tableRows = state.records !== null && state.records.length > 0 ? state.records.map((p, i) => {
let href = (p.Hostname + p.Pathname) || p.URL; let href = (p.Hostname + p.Pathname) || p.URL;
let classes = "table-row"; let widthClass = "";
if(state.total > 0) { if(state.total > 0) {
classes += " w" + Math.min(98, Math.round(p.Pageviews / state.total * 100 * 2.5)); widthClass = "w" + Math.min(98, Math.round(p.Pageviews / state.total * 100 * 2.5));
} }
let label = p.Pathname let label = p.Pathname
@ -74,19 +75,19 @@ class Table extends Component {
} }
return( return(
<div class={classes}> <div class={classNames("table-row", widthClass)}>
<div class="cell main-col"><a href={href}>{label}</a></div> <div class="cell main-col"><a href={href}>{label}</a></div>
<div class="cell">{numbers.formatPretty(p.Pageviews)}</div> <div class="cell">{numbers.formatPretty(p.Pageviews)}</div>
<div class="cell">{numbers.formatPretty(p.Visitors)||"-"}</div> <div class="cell">{numbers.formatPretty(p.Visitors)||"-"}</div>
</div> </div>
)}) : <div class="table-row"><div class="cell main-col">Nothing here, yet.</div></div>; )}) : <div class="table-row"><div class="cell main-col">Nothing here, yet.</div></div>;
return ( return (
<div class={(state.loading ? "loading" : '')}> <div class={classNames({ loading: state.loading })}>
<div class="table-row header"> <div class="table-row header">
{props.headers.map((header, i) => { {props.headers.map((header, i) => {
return (<div class={i === 0 ? 'main-col cell' : 'cell'}>{header}</div>) return <div class={classNames("cell", { "main-col": i === 0 })}>{header}</div>
})} })}
</div> </div>
<div> <div>
{tableRows} {tableRows}

5
package-lock.json generated
View File

@ -1649,6 +1649,11 @@
} }
} }
}, },
"classnames": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"cliui": { "cliui": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",

View File

@ -22,6 +22,7 @@
"vinyl-source-stream": "^2.0.0" "vinyl-source-stream": "^2.0.0"
}, },
"dependencies": { "dependencies": {
"classnames": "^2.2.6",
"d3": "^5.4.0", "d3": "^5.4.0",
"d3-tip": "^0.9.1", "d3-tip": "^0.9.1",
"d3-transition": "^1.1.1", "d3-transition": "^1.1.1",