-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adopt the new classes for plot's big numbers #554
Changes from all commits
8145753
e611f92
a26fdd0
54eb832
55cf5ad
acd987c
b30b82a
8da625b
6537d9d
d335c5a
0b03f32
d15e6eb
65fb83b
edfacf1
27e6c01
bbd04c8
03920a6
ad9164f
0d9c5bc
09d3c89
5f4f6c7
da25240
7860c6b
1706dc4
f3b3f95
20ef431
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import * as d3 from "npm:d3"; | ||
import {html} from "npm:htl"; | ||
|
||
export function trend( | ||
value /*: number */, | ||
{ | ||
format = "+d", | ||
positive = "green", | ||
negative = "red", | ||
base = "muted", | ||
positiveSuffix = " ↗︎", | ||
negativeSuffix = " ↘︎", | ||
baseSuffix = "" | ||
} = {} /* | ||
as { | ||
format: string | ((x: number) => string); | ||
positive: string; | ||
negative: string; | ||
base: string; | ||
positiveSuffix: string; | ||
negativeSuffix: string; | ||
baseSuffix: string; | ||
} | ||
*/ | ||
) /*: Node */ { | ||
if (typeof format === "string") format = d3.format(format); | ||
if (typeof format !== "function") throw new Error(`unsupported format ${format}`); | ||
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${ | ||
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix | ||
}`; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ theme: dashboard | |
--- | ||
|
||
```js | ||
// Data | ||
const summary = FileAttachment("data/google-analytics-summary.csv").csv({typed: true}); | ||
const hourly = FileAttachment("data/google-analytics-time-of-day.csv").csv({typed: true}); | ||
const channels = FileAttachment("data/google-analytics-channels.csv").csv({typed: true}); | ||
|
@@ -13,16 +12,13 @@ const world = FileAttachment("data/countries-110m.json").json(); | |
``` | ||
|
||
```js | ||
// Imports | ||
import {svg} from "npm:htl"; | ||
import {BigNumber} from "./components/bigNumber.js"; | ||
import {Marimekko} from "./components/marimekko.js"; | ||
import {trend} from "./components/trend.js"; | ||
``` | ||
|
||
```js | ||
// Helpers | ||
const bigPercent = d3.format(".0%"); | ||
const percent = d3.format(".2%"); | ||
const bigNumber = d3.format(".3s"); | ||
const date = d3.utcFormat("%m/%d/%Y"); | ||
const color = Plot.scale({ | ||
|
@@ -55,11 +51,10 @@ function getCompareValue(data, metric) { | |
``` | ||
|
||
```js | ||
// Charts | ||
function lineChart(data, {width, height, metric}) { | ||
return Plot.plot({ | ||
width, | ||
height: 97, | ||
height: 94, | ||
axis: null, | ||
insetTop: 10, | ||
insetLeft: -15, | ||
|
@@ -78,11 +73,11 @@ function lineChart(data, {width, height, metric}) { | |
function areaChart(data, {width, height, metric}) { | ||
return Plot.plot({ | ||
width, | ||
height: 97, | ||
height: 94, | ||
axis: null, | ||
insetTop: 10, | ||
insetLeft: -15, | ||
insetRight: -16.5, | ||
insetRight: -17, | ||
marks: [ | ||
Plot.ruleY([0]), | ||
Plot.areaY(data, { | ||
|
@@ -276,42 +271,48 @@ function worldMap(data, {width, height, title, caption}) { | |
} | ||
``` | ||
|
||
<style> | ||
.bigNumber { | ||
overflow: hidden | ||
} | ||
</style> | ||
|
||
# Google analytics | ||
|
||
_Summary of metrics from the [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries), pulled on ${date(d3.max(summary, d => d.date))}_ | ||
|
||
<div class="grid grid-cols-4" style="grid-auto-rows: 165px;"> | ||
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber"> | ||
${resize((width) => BigNumber(`${summary[summary.length-1].active28d.toLocaleString("en-US")}`, {title: "Rolling 28-day Active users", plot: areaChart(summary, {width, metric: 'active28d'}), trend: getCompareValue(summary, 'active28d'), trendFormat: bigNumber}))} | ||
<div class="card"> | ||
<h2>Rolling 28-day Active users</h2> | ||
<span class="big">${summary[summary.length-1].active28d.toLocaleString("en-US")}</span> | ||
${trend(getCompareValue(summary, 'active28d'))} | ||
${resize((width) => areaChart(summary, {width, metric: 'active28d'}))} | ||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber"> | ||
${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].engagementRate)}`, {title: "Engagement Rate", plot: lineChart(summary, {width, metric: 'engagementRate'}), trend: getCompareValue(summary, 'engagementRate'), trendFormat: percent}))} | ||
<div class="card"> | ||
<h2>Engagement Rate</h2> | ||
<span class="big">${bigPercent(summary[summary.length-1].engagementRate)}</span> | ||
${trend(getCompareValue(summary, "engagementRate"), {format: "+.2%"})} | ||
${resize((width) => lineChart(summary, {width, metric: "engagementRate"}))} | ||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber"> | ||
${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].wauPerMau)}`, {title: "WAU to MAU ratio", plot: lineChart(summary, {width, metric: 'wauPerMau'}), trend: getCompareValue(summary, 'wauPerMau'), trendFormat: percent}))} | ||
<div class="card"> | ||
<h2>WAU to MAU ratio</h2> | ||
<span class="big">${bigPercent(summary[summary.length-1].wauPerMau)}</span> | ||
${trend(getCompareValue(summary, "wauPerMau"), {format: "+.2%"})} | ||
${resize((width) => lineChart(summary, {width, metric: 'wauPerMau'}))} | ||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber"> | ||
${resize((width) => BigNumber(`${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}`, {title: "Engaged Sessions", plot: areaChart(summary, {width, metric: 'engagedSessions'}), trend: getCompareValue(summary, 'engagedSessions'), trendFormat: bigNumber}))} | ||
<div class="card"> | ||
<h2>Engaged Sessions</h2> | ||
<span class="big">${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}</span> | ||
${trend(getCompareValue(summary, 'engagedSessions'))} | ||
${resize((width) => areaChart(summary, {width, metric: 'engagedSessions'}))} | ||
</div> | ||
</div> | ||
|
||
<div class="grid grid-cols-2" style="grid-auto-rows: 140px;"> | ||
<div class="card grid-colspan-1 grid-rowspan-4"> | ||
<div class="card grid-rowspan-4"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m not following why these need rowspan-4 and rowspan-2 given that there are only 4 elements total in the 2-column grid? (But this is a pre-existing column.) |
||
${resize((width, height) => horizonChart(channels, {width, height, metric:'active28d', title: 'Active users by channel', caption: 'Rolling 28-day active users', format: 's', z: 'channelGroup', color, order: color.domain.slice(1)}))} | ||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-3"> | ||
<div class="card grid-rowspan-2"> | ||
${resize((width, height) => worldMap(countryData, {width, height, title: "Active users by country", caption: 'Current rolling 28-day active users by country', lookup: countryLookup}))} | ||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-3"> | ||
${resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))} | ||
<div class="card grid-rowspan-4"> | ||
${resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height: height - 12, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are lots and lots of single quotes in this file that should be double quotes. 😞 |
||
</div> | ||
<div class="card grid-colspan-1 grid-rowspan-2"> | ||
<div class="card grid-rowspan-2"> | ||
${resize((width, height) => Punchcard(hourly, {width, height, label: "active users"}))} | ||
</div> | ||
</div> |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import * as d3 from "npm:d3"; | ||
import {html} from "npm:htl"; | ||
|
||
export function trend( | ||
value /*: number */, | ||
{ | ||
format = "+d", | ||
positive = "green", | ||
negative = "red", | ||
base = "muted", | ||
positiveSuffix = " ↗︎", | ||
negativeSuffix = " ↘︎", | ||
baseSuffix = "" | ||
} = {} /* | ||
as { | ||
format: string | ((x: number) => string); | ||
positive: string; | ||
negative: string; | ||
base: string; | ||
positiveSuffix: string; | ||
negativeSuffix: string; | ||
baseSuffix: string; | ||
} | ||
*/ | ||
) /*: Node */ { | ||
if (typeof format === "string") format = d3.format(format); | ||
if (typeof format !== "function") throw new Error(`unsupported format ${format}`); | ||
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${ | ||
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix | ||
}`; | ||
} |
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.